diff --git a/addons/point_of_sale/controllers/main.py b/addons/point_of_sale/controllers/main.py index db5d5a25018..e0bd19545a6 100644 --- a/addons/point_of_sale/controllers/main.py +++ b/addons/point_of_sale/controllers/main.py @@ -3,12 +3,17 @@ import logging import simplejson import os import openerp +import time +import random from openerp.addons.web import http from openerp.addons.web.http import request from openerp.addons.web.controllers.main import manifest_list, module_boot, html_template class PointOfSaleController(http.Controller): + def __init__(self): + self.scale = 'closed' + self.scale_weight = 0.0 @http.route('/pos/app', type='http', auth='admin') def app(self): @@ -64,6 +69,10 @@ class PointOfSaleController(http.Controller): return m + @http.route('/pos/test_connection', type='json', auth='admin') + def test_connection(self): + return + @http.route('/pos/scan_item_success', type='json', auth='admin') def scan_item_success(self, ean): """ @@ -98,18 +107,38 @@ class PointOfSaleController(http.Controller): @http.route('/pos/weighting_start', type='json', auth='admin') def weighting_start(self): - print "weighting_start" + if self.scale == 'closed': + print "Opening (Fake) Connection to Scale..." + self.scale = 'open' + self.scale_weight = 0.0 + time.sleep(0.1) + print "... Scale Open." + else: + print "WARNING: Scale already Connected !!!" return @http.route('/pos/weighting_read_kg', type='json', auth='admin') def weighting_read_kg(self): - print "weighting_read_kg" - return 3.14 + if self.scale == 'open': + print "Reading Scale..." + time.sleep(0.025) + self.scale_weight += 0.01 + print "... Done." + return self.scale_weight + else: + print "WARNING: Reading closed scale !!!" + return 0.0 @http.route('/pos/weighting_end', type='json', auth='admin') def weighting_end(self): - print "weighting_end" - return + if self.scale == 'open': + print "Closing Connection to Scale ..." + self.scale = 'closed' + self.scale_weight = 0.0 + time.sleep(0.1) + print "... Scale Closed." + else: + print "WARNING: Scale already Closed !!!" @http.route('/pos/payment_request', type='json', auth='admin') def payment_request(self, price): diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css index e328054aa28..d78276b2b97 100644 --- a/addons/point_of_sale/static/src/css/pos.css +++ b/addons/point_of_sale/static/src/css/pos.css @@ -175,10 +175,9 @@ background: linear-gradient(#b2b3d7, #7f82ac); } -.point-of-sale #rightheader button.neworder-button { +.point-of-sale #rightheader button.square{ width: 32px; margin-left:4px; - margin-right:4px; } .point-of-sale div#order-selector { @@ -186,12 +185,20 @@ } .point-of-sale ol#orders { display: inline; + margin-left: 8px; } .point-of-sale li.order-selector-button { display: inline; } .point-of-sale li.selected-order button { font-weight: 900; + background: #7174A8 !important; + color: rgb(236, 237, 255) !important; + text-shadow: 0px 1px rgba(0, 0, 0, 0.31); + -webkit-box-shadow: 0px 1px 2px rgb(63, 66, 139) inset; + -moz-box-shadow: 0px 1px 2px rgb(63, 66, 139) inset; + -ms-box-shadow: 0px 1px 2px rgb(63, 66, 139) inset; + box-shadow: 0px 1px 2px rgb(63, 66, 139) inset; } /* c) The session buttons */ @@ -215,7 +222,7 @@ .point-of-sale #rightheader .header-button:last-child{ border-left: 1px solid #3a3a3a; } -.point-of-sale #rightheader .header-button:hover{ +.point-of-sale #rightheader .header-button:active{ background: rgba(0,0,0,0.2); text-shadow: #000 0px 0px 3px; color:#EEE; @@ -307,18 +314,10 @@ border-top: 1px solid #efefef; font-size: 14px; } -.point-of-sale #paypad button, .point-of-sale #numpad button, .point-of-sale .popup button{ - position: relative; - top: 0; - -webkit-transition: top 150ms linear; - -moz-transition: top 150ms linear; - -ms-transition: top 150ms linear; - transition: top 150ms linear; -} -.point-of-sale #paypad button:active, .point-of-sale #numpad button:active, .point-of-sale .popup button:active{ - top:3px; -} -.point-of-sale #paypad button:hover, .point-of-sale #numpad button:hover, .point-of-sale #numpad .selected-mode, .point-of-sale .popup button:hover { +.point-of-sale #paypad button:active, +.point-of-sale #numpad button:active, +.point-of-sale #numpad .selected-mode, +.point-of-sale .popup button:active{ border: none; color: white; background: #7f82ac; @@ -518,7 +517,7 @@ -moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.1); box-shadow: 0px 2px 2px rgba(0,0,0, 0.1); } -.point-of-sale .category-simple-button:hover { +.point-of-sale .category-simple-button:active{ color: white; background: #7f82ac; border: 1px solid #7f82ac; @@ -1049,13 +1048,13 @@ -moz-transition: background 250ms ease-in-out; transition: background 250ms ease-in-out; } -.point-of-sale .order .orderline:hover{ +.point-of-sale .order .orderline:active{ background: rgba(140,143,183,0.05); -webkit-transition: background 50ms ease-in-out; -moz-transition: background 50ms ease-in-out; transition: background 50ms ease-in-out; } -.point-of-sale .order .orderline.empty:hover{ +.point-of-sale .order .orderline.empty:active{ background: transparent; cursor: default; } @@ -1156,7 +1155,7 @@ .point-of-sale .pos-actionbar .button .icon{ margin-top: 10px; } -.point-of-sale .pos-actionbar .button:hover { +.point-of-sale .pos-actionbar .button:active{ color: white; background: #7f82ac; border: 1px solid #7f82ac; @@ -1173,7 +1172,7 @@ .point-of-sale .pos-actionbar .button.disabled *{ opacity: 0.5; } -.point-of-sale .pos-actionbar .button.disabled:hover{ +.point-of-sale .pos-actionbar .button.disabled:active{ border: 1px solid #cacaca; border-radius: 4px; color: #555; @@ -1242,7 +1241,7 @@ display: block; cursor:pointer; } -.point-of-sale .debug-widget .button:hover{ +.point-of-sale .debug-widget .button:active{ background: rgba(96,21,177,0.45); } .point-of-sale .debug-widget input{ @@ -1330,7 +1329,7 @@ -moz-box-shadow: 0px 2px 2px rgba(0,0,0, 0.3); box-shadow: 0px 2px 2px rgba(0,0,0, 0.3); } -.point-of-sale .popup .button:hover { +.point-of-sale .popup .button:active{ color: white; background: #7f82ac; border: 1px solid #7f82ac; @@ -1398,7 +1397,7 @@ -moz-transition: all 250ms ease-in-out; transition: all 250ms ease-in-out; } -.point-of-sale .scrollbar .button:hover{ +.point-of-sale .scrollbar .button:active{ text-shadow: rgba(255,255,255,0.8) 0px 0px 15px; } .point-of-sale .scrollbar .button.disabled{ diff --git a/addons/point_of_sale/static/src/js/devices.js b/addons/point_of_sale/static/src/js/devices.js index 300bc46b093..0c737ec1e1a 100644 --- a/addons/point_of_sale/static/src/js/devices.js +++ b/addons/point_of_sale/static/src/js/devices.js @@ -1,6 +1,81 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sale + // the JobQueue schedules a sequence of 'jobs'. each job is + // a function returning a deferred. the queue waits for each job to finish + // before launching the next. Each job can also be scheduled with a delay. + // the is used to prevent parallel requests to the proxy. + + module.JobQueue = function(){ + var queue = []; + var running = false; + var scheduled_end_time = 0; + var end_of_queue = (new $.Deferred()).resolve(); + var stoprepeat = false; + + var run = function(){ + if(end_of_queue.state() === 'resolved'){ + end_of_queue = new $.Deferred(); + } + if(queue.length > 0){ + running = true; + var job = queue[0]; + if(!job.opts.repeat || stoprepeat){ + queue.shift(); + stoprepeat = false; + } + + // the time scheduled for this job + scheduled_end_time = (new Date()).getTime() + (job.opts.duration || 0); + + // we run the job and put in def when it finishes + var def = job.fun() || (new $.Deferred()).resolve(); + + // we don't care if a job fails ... + def.always(function(){ + // we run the next job after the scheduled_end_time, even if it finishes before + setTimeout(function(){ + run(); + }, Math.max(0, scheduled_end_time - (new Date()).getTime()) ); + }); + }else{ + running = false; + end_of_queue.resolve(); + } + }; + + // adds a job to the schedule. + // opts : { + // duration : the job is guaranteed to finish no quicker than this (milisec) + // repeat : if true, the job will be endlessly repeated + // important : if true, the scheduled job cannot be canceled by a queue.clear() + // } + this.schedule = function(fun, opts){ + queue.push({fun:fun, opts:opts || {}}); + if(!running){ + run(); + } + } + + // remove all jobs from the schedule (except the ones marked as important) + this.clear = function(){ + queue = _.filter(queue,function(job){job.opts.important === true}); + }; + + // end the repetition of the current job + this.stoprepeat = function(){ + stoprepeat = true; + }; + + // returns a deferred that resolves when all scheduled + // jobs have been run. + // ( jobs added after the call to this method are considered as well ) + this.finished = function(){ + return end_of_queue; + } + + }; + // this object interfaces with the local proxy to communicate to the various hardware devices // connected to the Point of Sale. As the communication only goes from the POS to the proxy, // methods are used both to signal an event, and to fetch information. @@ -10,7 +85,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal options = options || {}; url = options.url || 'http://localhost:8069'; - this.weight = 0; this.weighting = false; this.debug_weight = 0; this.use_debug_weight = false; @@ -35,18 +109,11 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal this.connection.destroy(); }, message : function(name,params){ - var ret = new $.Deferred(); var callbacks = this.notifications[name] || []; for(var i = 0; i < callbacks.length; i++){ callbacks[i](params); } - - this.connection.rpc('/pos/' + name, params || {}).done(function(result) { - ret.resolve(result); - }).fail(function(error) { - ret.reject(error); - }); - return ret; + return this.connection.rpc('/pos/' + name, params || {}); }, // this allows the client to be notified when a proxy call is made. The notification @@ -82,13 +149,32 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal //the client is starting to weight weighting_start: function(){ + var ret = new $.Deferred(); if(!this.weighting){ this.weighting = true; - if(!this.bypass_proxy){ - this.weight = 0; - return this.message('weighting_start'); - } + this.message('weighting_start').always(function(){ + ret.resolve(); + }); + }else{ + console.error('Weighting already started!!!'); + ret.resolve(); } + return ret; + }, + + // the client has finished weighting products + weighting_end: function(){ + var ret = new $.Deferred(); + if(this.weighting){ + this.weighting = false; + this.message('weighting_end').always(function(){ + ret.resolve(); + }); + }else{ + console.error('Weighting already ended !!!'); + ret.resolve(); + } + return ret; }, //returns the weight on the scale. @@ -96,17 +182,14 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal // and a weighting_end() weighting_read_kg: function(){ var self = this; + var ret = new $.Deferred(); this.message('weighting_read_kg',{}) - .done(function(weight){ - if(self.weighting){ - if(self.use_debug_weight){ - self.weight = self.debug_weight; - }else{ - self.weight = weight; - } - } + .then(function(weight){ + ret.resolve(self.use_debug_weight ? self.debug_weight : weight); + }, function(){ //failed to read weight + ret.resolve(self.use_debug_weight ? self.debug_weight : 0.0); }); - return this.weight; + return ret; }, // sets a custom weight, ignoring the proxy returned value. @@ -121,12 +204,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal this.debug_weight = 0; }, - // the client has finished weighting products - weighting_end: function(){ - this.weight = 0; - this.weighting = false; - this.message('weighting_end'); - }, // the pos asks the client to pay 'price' units payment_request: function(price){ diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index e4d69bca26f..fbbb15af9c7 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -24,6 +24,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.barcode_reader = new module.BarcodeReader({'pos': this}); // used to read barcodes this.proxy = new module.ProxyDevice(); // used to communicate to the hardware devices via a local proxy + this.proxy_queue = new module.JobQueue(); // used to prevent parallels communications to the proxy this.db = new module.PosLS(); // a database used to store the products and categories this.db.clear('products','categories'); this.debug = jQuery.deparam(jQuery.param.querystring()).debug !== undefined; //debug mode @@ -55,7 +56,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal 'selectedOrder': null, }); - this.get('orders').bind('remove', function(){ self.on_removed_order(); }); + this.get('orders').bind('remove', function(order,_unused_,options){ + self.on_removed_order(order,options.index,options.reason); + }); // We fetch the backend data on the server asynchronously. this is done only when the pos user interface is launched, // Any change on this data made on the server is thus not reflected on the point of sale until it is relaunched. @@ -239,11 +242,14 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal // this is called when an order is removed from the order collection. It ensures that there is always an existing // order and a valid selected order - on_removed_order: function(removed_order){ - if( this.get('orders').isEmpty()){ - this.add_new_order(); + on_removed_order: function(removed_order,index,reason){ + if(reason === 'abandon' && this.get('orders').size() > 0){ + // when we intentionally remove an unfinished order, and there is another existing one + this.set({'selectedOrder' : this.get('orders').at(index) || this.get('orders').last()}); }else{ - this.set({ selectedOrder: this.get('orders').last() }); + // when the order was automatically removed after completion, + // or when we intentionally delete the only concurrent order + this.add_new_order(); } }, @@ -254,6 +260,12 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.set('selectedOrder', order); }, + //removes the current order + delete_current_order: function(){ + this.get('selectedOrder').destroy({'reason':'abandon'}); + console.log('coucou!'); + }, + // saves the order locally and try to send it to the backend. // it returns a deferred that succeeds after having tried to send the order and all the other pending orders. push_order: function(order) { diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 8c588adadf3..854c1e1adec 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -271,19 +271,19 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }); var self = this; - var cashier_mode = this.pos_widget.screen_selector.get_user_mode() === 'cashier'; + this.cashier_mode = this.pos_widget.screen_selector.get_user_mode() === 'cashier'; - this.pos_widget.set_numpad_visible(this.show_numpad && cashier_mode); + this.pos_widget.set_numpad_visible(this.show_numpad && this.cashier_mode); this.pos_widget.set_leftpane_visible(this.show_leftpane); - this.pos_widget.set_left_action_bar_visible(this.show_leftpane && !cashier_mode); - this.pos_widget.set_cashier_controls_visible(cashier_mode); + this.pos_widget.set_left_action_bar_visible(this.show_leftpane && !this.cashier_mode); + this.pos_widget.set_cashier_controls_visible(this.cashier_mode); - if(cashier_mode && this.pos.iface_self_checkout){ + if(this.cashier_mode && this.pos.iface_self_checkout){ this.pos_widget.client_button.show(); }else{ this.pos_widget.client_button.hide(); } - if(cashier_mode){ + if(this.cashier_mode){ this.pos_widget.close_button.show(); }else{ this.pos_widget.close_button.hide(); @@ -441,7 +441,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa module.ErrorInvoiceTransferPopupWidget = module.ErrorPopupWidget.extend({ template: 'ErrorInvoiceTransferPopupWidget', }); - + module.ScaleInviteScreenWidget = module.ScreenWidget.extend({ template:'ScaleInviteScreenWidget', @@ -451,30 +451,35 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa show: function(){ this._super(); var self = this; + var queue = this.pos.proxy_queue; - self.pos.proxy.weighting_start(); - - this.intervalID = setInterval(function(){ - var weight = self.pos.proxy.weighting_read_kg(); - if(weight > 0.001){ - clearInterval(this.intervalID); - self.pos_widget.screen_selector.set_current_screen(self.next_screen); - } - },100); + queue.schedule(function(){ + return self.pos.proxy.weighting_start(); + },{ unclearable: true }); + + queue.schedule(function(){ + return self.pos.proxy.weighting_read_kg().then(function(weight){ + if(weight > 0.001){ + self.pos_widget.screen_selector.set_current_screen(self.next_screen); + } + }); + },{duration: 100, repeat: true}); this.add_action_button({ label: _t('Back'), icon: '/point_of_sale/static/src/img/icons/png48/go-previous.png', click: function(){ - clearInterval(this.intervalID); self.pos_widget.screen_selector.set_current_screen(self.previous_screen); } }); }, close: function(){ this._super(); - clearInterval(this.intervalID); - this.pos.proxy.weighting_end(); + var self = this; + this.pos.proxy_queue.clear(); + this.pos.proxy_queue.schedule(function(){ + return self.pos.proxy.weighting_end(); + },{ unclearable: true }); }, }); @@ -486,9 +491,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa show: function(){ this._super(); - this.renderElement(); var self = this; + var queue = this.pos.proxy_queue; + this.set_weight(0); + this.renderElement(); this.add_action_button({ label: _t('Back'), @@ -507,14 +514,16 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }, }); - this.pos.proxy.weighting_start(); - this.intervalID = setInterval(function(){ - var weight = self.pos.proxy.weighting_read_kg(); - if(weight != self.weight){ - self.weight = weight; - self.renderElement(); - } - },100); + queue.schedule(function(){ + return self.pos.proxy.weighting_start() + },{ unclearable: true }); + + queue.schedule(function(){ + return self.pos.proxy.weighting_read_kg().then(function(weight){ + self.set_weight(weight); + }); + },{duration:50, repeat: true}); + }, renderElement: function(){ var self = this; @@ -544,54 +553,24 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa var product = this.get_product(); return (product ? product.get('price') : 0) || 0; }, - get_product_weight: function(){ - return this.weight || 0; + set_weight: function(weight){ + this.weight = weight; + this.$('.js-weight').text(this.get_product_weight_string()); + }, + get_product_weight_string: function(){ + return (this.weight || 0).toFixed(3) + ' Kg'; }, close: function(){ + var self = this; this._super(); - clearInterval(this.intervalID); - this.pos.proxy.weighting_end(); + + this.pos.proxy_queue.clear(); + this.pos.proxy_queue.schedule(function(){ + self.pos.proxy.weighting_end(); + },{ unclearable: true }); }, }); - // the JobQueue schedules a sequence of 'jobs'. each job is - // a function returning a deferred. the queue waits for each job to finish - // before launching the next. Each job can also be scheduled with a delay. - // the queue jobqueue is used to prevent parallel requests to the payment terminal. - - module.JobQueue = function(){ - var queue = []; - var running = false; - var run = function(){ - if(queue.length > 0){ - running = true; - var job = queue.shift(); - setTimeout(function(){ - var def = job.fun(); - if(def){ - def.done(run); - }else{ - run(); - } - },job.delay || 0); - }else{ - running = false; - } - }; - - // adds a job to the schedule. - this.schedule = function(fun, delay){ - queue.push({fun:fun, delay:delay}); - if(!running){ - run(); - } - } - - // remove all jobs from the schedule - this.clear = function(){ - queue = []; - }; - }; module.ClientPaymentScreenWidget = module.ScreenWidget.extend({ template:'ClientPaymentScreenWidget', @@ -740,7 +719,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa module.ProductScreenWidget = module.ScreenWidget.extend({ template:'ProductScreenWidget', - scale_screen: 'scale_invite', + scale_screen: 'scale', + client_scale_screen : 'scale_invite', client_next_screen: 'client_payment', show_numpad: true, @@ -754,7 +734,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.product_list_widget = new module.ProductListWidget(this,{ click_product_action: function(product){ if(product.get('to_weight') && self.pos.iface_electronic_scale){ - self.pos_widget.screen_selector.set_current_screen(self.scale_screen, {product: product}); + self.pos_widget.screen_selector.set_current_screen( self.cashier_mode ? self.scale_screen : self.client_scale_screen, {product: product}); }else{ self.pos.get('selectedOrder').addProduct(product); } diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js index bf7cf4d13af..8afd3df6255 100644 --- a/addons/point_of_sale/static/src/js/widgets.js +++ b/addons/point_of_sale/static/src/js/widgets.js @@ -62,10 +62,10 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa start: function() { this.state.bind('change:mode', this.changedMode, this); this.changedMode(); - this.$el.find('button#numpad-backspace').click(_.bind(this.clickDeleteLastChar, this)); - this.$el.find('button#numpad-minus').click(_.bind(this.clickSwitchSign, this)); - this.$el.find('button.number-char').click(_.bind(this.clickAppendNewChar, this)); - this.$el.find('button.mode-button').click(_.bind(this.clickChangeMode, this)); + this.$el.find('.numpad-backspace').click(_.bind(this.clickDeleteLastChar, this)); + this.$el.find('.numpad-minus').click(_.bind(this.clickSwitchSign, this)); + this.$el.find('.number-char').click(_.bind(this.clickAppendNewChar, this)); + this.$el.find('.mode-button').click(_.bind(this.clickChangeMode, this)); }, clickDeleteLastChar: function() { return this.state.deleteLastChar(); @@ -189,8 +189,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }else if( mode === 'price'){ order.getSelectedLine().set_unit_price(val); } - } else { - this.pos.get('selectedOrder').destroy(); } }, change_selected_order: function() { @@ -362,28 +360,23 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.order = options.order; this.order.bind('destroy',function(){ self.destroy(); }); this.order.bind('change', function(){ self.renderElement(); }); - this.pos.bind('change:selectedOrder', _.bind( function(pos) { - var selectedOrder; - selectedOrder = pos.get('selectedOrder'); - if (this.order === selectedOrder) { - this.setButtonSelected(); - } - }, this)); + this.pos.bind('change:selectedOrder', function() { + self.renderElement(); + }, this); }, renderElement:function(){ this._super(); this.$('button.select-order').off('click').click(_.bind(this.selectOrder, this)); this.$('button.close-order').off('click').click(_.bind(this.closeOrder, this)); + if( this.order === this.pos.get('selectedOrder') ){ + this.$el.addClass('selected-order'); + } }, selectOrder: function(event) { this.pos.set({ selectedOrder: this.order }); }, - setButtonSelected: function() { - $('.selected-order').removeClass('selected-order'); - this.$el.addClass('selected-order'); - }, closeOrder: function(event) { this.order.destroy(); }, @@ -848,17 +841,24 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.leftpane_width = '440px'; this.cashier_controls_visible = true; this.image_cache = new module.ImageCache(); // for faster products image display + }, start: function() { var self = this; return self.pos.ready.done(function() { + $('.oe_tooltip').remove(); // remove tooltip from the start session button + self.build_currency_template(); self.renderElement(); self.$('.neworder-button').click(function(){ self.pos.add_new_order(); }); + + self.$('.deleteorder-button').click(function(){ + self.pos.delete_current_order(); + }); //when a new order is created, add an order button widget self.pos.get('orders').bind('add', function(new_order){ diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index e28ea1c06b0..5c5faf3fc82 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -12,7 +12,8 @@
- + +
    @@ -93,10 +94,10 @@
    - + -
    @@ -191,8 +192,9 @@

    - - Kg + + +

    diff --git a/addons/web/static/src/js/data.js b/addons/web/static/src/js/data.js index a4fbb364a21..04f657d91f7 100644 --- a/addons/web/static/src/js/data.js +++ b/addons/web/static/src/js/data.js @@ -451,7 +451,7 @@ instance.web.DataSet = instance.web.Class.extend(instance.web.PropertiesMixin, // TODO: reorder results to match ids list return this._model.call('read', [ids, fields || false], - {context: this._model.context(options.context)}); + {context: this.get_context(options.context)}); }, /** * Read a slice of the records represented by this DataSet, based on its diff --git a/addons/web/static/src/js/view_tree.js b/addons/web/static/src/js/view_tree.js index 0c101e330c9..2f92042c4d0 100644 --- a/addons/web/static/src/js/view_tree.js +++ b/addons/web/static/src/js/view_tree.js @@ -166,13 +166,13 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie var is_loaded = 0, $this = $(this), record_id = $this.data('id'), - parent_id = $this.data('parent-id'), + row_parent_id = $this.data('row-parent-id'), record = self.records[record_id], children_ids = record[self.children_field]; _(children_ids).each(function(childid) { - if (self.$el.find('[id=treerow_' + childid + '][data-parent-id='+ record_id +']').length ) { - if (self.$el.find('[id=treerow_' + childid + '][data-parent-id='+ record_id +']').is(':hidden')) { + if (self.$el.find('[id=treerow_' + childid + '][data-row-parent-id='+ record_id +']').length ) { + if (self.$el.find('[id=treerow_' + childid + '][data-row-parent-id='+ record_id +']').is(':hidden')) { is_loaded = -1; } else { is_loaded++; @@ -196,7 +196,6 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie _(records).each(function (record) { self.records[record.id] = record; }); - var $curr_node = self.$el.find('#treerow_' + id); var children_rows = QWeb.render('TreeView.rows', { 'records': records, @@ -206,7 +205,7 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie 'level': $curr_node.data('level') || 0, 'render': instance.web.format_value, 'color_for': self.color_for, - 'parent_id': id + 'row_parent_id': id }); if ($curr_node.length) { $curr_node.addClass('oe_open'); @@ -250,7 +249,7 @@ instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeVie showcontent: function (curnode,record_id, show) { curnode.parent('tr').toggleClass('oe_open', show); _(this.records[record_id][this.children_field]).each(function (child_id) { - var $child_row = this.$el.find('[id=treerow_' + child_id + '][data-parent-id='+ curnode.data('id') +']'); + var $child_row = this.$el.find('[id=treerow_' + child_id + '][data-row-parent-id='+ curnode.data('id') +']'); if ($child_row.hasClass('oe_open')) { $child_row.toggleClass('oe_open',show); this.showcontent($child_row, child_id, false); diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index d21318799c9..ee87237d045 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -685,7 +685,7 @@ t-foreach="records" t-as="record" t-att-id="'treerow_' + record.id" t-att-data-id="record.id" t-att-data-level="level + 1" - t-att-data-parent-id="parent_id"> + t-att-data-row-parent-id="row_parent_id">