[FIX] point_of_sale: fixing potential timeout issues when sending orders over bad connection
bzr revid: fva@openerp.com-20130328150718-zj91ljrlkvv59tkj
This commit is contained in:
parent
74b3538dd1
commit
0fdf9066dd
|
@ -267,11 +267,12 @@ function openerp_pos_db(instance, module){
|
|||
return results;
|
||||
},
|
||||
add_order: function(order){
|
||||
var last_id = this.load('last_order_id',0);
|
||||
var order_id = this.load('last_order_id',0) + 1;
|
||||
var orders = this.load('orders',[]);
|
||||
orders.push({id: last_id + 1, data: order});
|
||||
this.save('last_order_id',last_id+1);
|
||||
orders.push({id: order_id, data: order});
|
||||
this.save('last_order_id', order_id);
|
||||
this.save('orders',orders);
|
||||
return order_id;
|
||||
},
|
||||
remove_order: function(order_id){
|
||||
var orders = this.load('orders',[]);
|
||||
|
@ -283,5 +284,14 @@ function openerp_pos_db(instance, module){
|
|||
get_orders: function(){
|
||||
return this.load('orders',[]);
|
||||
},
|
||||
get_order: function(order_id){
|
||||
var orders = this.get_orders();
|
||||
for(var i = 0, len = orders.length; i < len; i++){
|
||||
if(orders[i].id === order_id){
|
||||
return orders[i];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -120,7 +120,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
|
||||
return self.fetch('res.currency',['symbol','position','rounding','accuracy'],[['id','=',self.get('company').currency_id[0]]]);
|
||||
}).then(function(currencies){
|
||||
console.log('Currency:',currencies[0]);
|
||||
self.set('currency',currencies[0]);
|
||||
|
||||
return self.fetch('product.uom', null, null);
|
||||
|
@ -256,12 +255,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
}
|
||||
},
|
||||
|
||||
// saves the order locally and try to send it to the backend. 'record' is a bizzarely defined JSON version of the Order
|
||||
push_order: function(record) {
|
||||
this.db.add_order(record);
|
||||
this.flush();
|
||||
},
|
||||
|
||||
//creates a new empty order and sets it as the current order
|
||||
add_new_order: function(){
|
||||
var order = new module.Order({pos:this});
|
||||
|
@ -269,45 +262,111 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
|||
this.set('selectedOrder', order);
|
||||
},
|
||||
|
||||
// saves the order locally and try to send it to the backend. 'record' is a bizzarely defined JSON version of the Order
|
||||
// it returns a deferred that succeeds or fail when the pushed order is successfully posted on the server, previously failed orders
|
||||
// will try to be re-sent but don't make this method return false if they fail. ( So that in the unlikely case of an order making
|
||||
// the server crash, the other orders can still be sent )
|
||||
// payment process )
|
||||
push_order: function(record) {
|
||||
var self = this;
|
||||
var order_id = this.db.add_order(record);
|
||||
var pushed = new $.Deferred();
|
||||
|
||||
this.set('nbr_pending_operations',self.db.get_orders().length);
|
||||
|
||||
this.flush_mutex.exec(function(){
|
||||
|
||||
//first we try to push all orders (the one we added and the one that were not sent)
|
||||
var tried_all = self._flush_all_orders();
|
||||
var done = new $.Deferred();
|
||||
|
||||
tried_all.always(function(){
|
||||
// then we verify that the one we just added has been sent successfuly.
|
||||
self._flush_order(order_id)
|
||||
.done( function(){ pushed.resolve();})
|
||||
.fail( function(){ pushed.reject(); })
|
||||
.always( function(){ done.resolve(); });
|
||||
});
|
||||
|
||||
return done;
|
||||
});
|
||||
|
||||
return pushed;
|
||||
},
|
||||
|
||||
|
||||
// attemps to send all pending orders ( stored in the pos_db ) to the server,
|
||||
// and remove the successfully sent ones from the db once
|
||||
// it has been confirmed that they have been sent correctly.
|
||||
flush: function() {
|
||||
//TODO make the mutex work
|
||||
//this makes sure only one _int_flush is called at the same time
|
||||
/*
|
||||
return this.flush_mutex.exec(_.bind(function() {
|
||||
return this._flush(0);
|
||||
}, this));
|
||||
*/
|
||||
this._flush(0);
|
||||
var self = this;
|
||||
var flushed = new $.Deferred();
|
||||
|
||||
this.flush_mutex.exec(function(){
|
||||
var done = new $.Deferred();
|
||||
|
||||
self._flush_all_orders()
|
||||
.done( function(){ flushed.resolve();})
|
||||
.fail( function(){ flushed.reject(); })
|
||||
.always(function(){ done.resolve(); });
|
||||
|
||||
return done;
|
||||
});
|
||||
|
||||
return flushed;
|
||||
},
|
||||
// attempts to send an order of index 'index' in the list of order to send. The index
|
||||
// is used to skip orders that failed. do not call this method outside the mutex provided
|
||||
// by flush()
|
||||
_flush: function(index){
|
||||
|
||||
// attempts to send the locally stored order of id 'order_id'
|
||||
// the sending is asynchronous and can take a long time to decide if it is successful or not (60s)
|
||||
// it is therefore important to only call this method from inside a mutex
|
||||
// this method returns a deferred indicating wether the sending was successful or not
|
||||
_flush_order: function(order_id){
|
||||
var self = this;
|
||||
var order = this.db.get_order(order_id);
|
||||
|
||||
if(!order){
|
||||
// flushing a non existing order always succeeds
|
||||
return (new $.Deferred()).resolve();
|
||||
}
|
||||
|
||||
//we try to send the order. shadow prevents a spinner if it takes too long.
|
||||
var rpc = (new instance.web.Model('pos.order')).call('create_from_ui',[[order]],undefined,{shadow: true, timeout: 2000});
|
||||
|
||||
rpc.fail(function(unused,event){
|
||||
//prevent an error popup creation by the rpc failure
|
||||
event.preventDefault();
|
||||
console.error('Failed to send order:',order);
|
||||
});
|
||||
|
||||
rpc.done(function(){
|
||||
self.db.remove_order(order_id);
|
||||
self.set('nbr_pending_operations',self.db.get_orders().length);
|
||||
});
|
||||
|
||||
return rpc;
|
||||
},
|
||||
|
||||
// attempts to send all the locally stored orders. As with _flush_order, it should only be
|
||||
// called from within a mutex.
|
||||
// this method returns a deferred that always succeeds when all orders have been tried to be sent,
|
||||
// even if none of them could actually be sent.
|
||||
_flush_all_orders: function(){
|
||||
var self = this;
|
||||
var orders = this.db.get_orders();
|
||||
self.set('nbr_pending_operations',orders.length);
|
||||
var tried_all = new $.Deferred();
|
||||
|
||||
var order = orders[index];
|
||||
if(!order){
|
||||
return;
|
||||
function rec_flush(index){
|
||||
if(index < orders.length){
|
||||
self._flush_order(orders[index].id).always(function(){
|
||||
rec_flush(index+1);
|
||||
})
|
||||
}else{
|
||||
tried_all.resolve();
|
||||
}
|
||||
}
|
||||
//try to push an order to the server
|
||||
// shadow : true is to prevent a spinner to appear in case of timeout
|
||||
(new instance.web.Model('pos.order')).call('create_from_ui',[[order]],undefined,{ shadow:true })
|
||||
.fail(function(unused, event){
|
||||
//don't show error popup if it fails
|
||||
event.preventDefault();
|
||||
console.error('Failed to send order:',order);
|
||||
self._flush(index+1);
|
||||
})
|
||||
.done(function(){
|
||||
//remove from db if success
|
||||
self.db.remove_order(order.id);
|
||||
self._flush(index);
|
||||
});
|
||||
rec_flush(0);
|
||||
|
||||
return tried_all;
|
||||
},
|
||||
|
||||
scan_product: function(parsed_ean){
|
||||
|
|
Loading…
Reference in New Issue