From d4e7b6eb962d38349ac62676c79c0467e9a80d2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Wed, 4 Dec 2013 18:21:22 +0100 Subject: [PATCH] [WIP] point_of_sale: more perf improvement, this time on the receipt and payment screen + lots of usability improvements and cleanups bzr revid: fva@openerp.com-20131204172122-mzl4wg4uw51uzdfv --- addons/point_of_sale/__openerp__.py | 2 - .../lib/mousewheel/jquery.mousewheel-3.0.6.js | 84 ---- addons/point_of_sale/static/src/css/pos.css | 102 ++--- addons/point_of_sale/static/src/js/main.js | 2 - addons/point_of_sale/static/src/js/models.js | 49 ++- addons/point_of_sale/static/src/js/screens.js | 358 ++++++++++++------ addons/point_of_sale/static/src/js/widgets.js | 69 +--- addons/point_of_sale/static/src/xml/pos.xml | 91 ++--- 8 files changed, 378 insertions(+), 379 deletions(-) delete mode 100644 addons/point_of_sale/static/lib/mousewheel/jquery.mousewheel-3.0.6.js diff --git a/addons/point_of_sale/__openerp__.py b/addons/point_of_sale/__openerp__.py index d963144ceca..44ceb83b02d 100644 --- a/addons/point_of_sale/__openerp__.py +++ b/addons/point_of_sale/__openerp__.py @@ -89,13 +89,11 @@ Main Features 'installable': True, 'application': True, 'js': [ - 'static/lib/mousewheel/jquery.mousewheel-3.0.6.js', 'static/lib/fastclick.js', 'static/src/js/db.js', 'static/src/js/models.js', 'static/src/js/widget_base.js', 'static/src/js/widget_keyboard.js', - 'static/src/js/widget_scrollbar.js', 'static/src/js/widgets.js', 'static/src/js/devices.js', 'static/src/js/screens.js', diff --git a/addons/point_of_sale/static/lib/mousewheel/jquery.mousewheel-3.0.6.js b/addons/point_of_sale/static/lib/mousewheel/jquery.mousewheel-3.0.6.js deleted file mode 100644 index 38b60951b20..00000000000 --- a/addons/point_of_sale/static/lib/mousewheel/jquery.mousewheel-3.0.6.js +++ /dev/null @@ -1,84 +0,0 @@ -/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) - * Licensed under the MIT License (LICENSE.txt). - * - * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. - * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. - * Thanks to: Seamus Leahy for adding deltaX and deltaY - * - * Version: 3.0.6 - * - * Requires: 1.2.2+ - */ - -(function($) { - -var types = ['DOMMouseScroll', 'mousewheel']; - -if ($.event.fixHooks) { - for ( var i=types.length; i; ) { - $.event.fixHooks[ types[--i] ] = $.event.mouseHooks; - } -} - -$.event.special.mousewheel = { - setup: function() { - if ( this.addEventListener ) { - for ( var i=types.length; i; ) { - this.addEventListener( types[--i], handler, false ); - } - } else { - this.onmousewheel = handler; - } - }, - - teardown: function() { - if ( this.removeEventListener ) { - for ( var i=types.length; i; ) { - this.removeEventListener( types[--i], handler, false ); - } - } else { - this.onmousewheel = null; - } - } -}; - -$.fn.extend({ - mousewheel: function(fn) { - return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); - }, - - unmousewheel: function(fn) { - return this.unbind("mousewheel", fn); - } -}); - - -function handler(event) { - var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0; - event = $.event.fix(orgEvent); - event.type = "mousewheel"; - - // Old school scrollwheel delta - if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta/120; } - if ( orgEvent.detail ) { delta = -orgEvent.detail/3; } - - // New school multidimensional scroll (touchpads) deltas - deltaY = delta; - - // Gecko - if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { - deltaY = 0; - deltaX = -1*delta; - } - - // Webkit - if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; } - if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; } - - // Add event and delta to the front of the arguments - args.unshift(event, delta, deltaX, deltaY); - - return ($.event.dispatch || $.event.handle).apply(this, args); -} - -})(jQuery); diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css index 9d728f8c7da..18673ec1cc2 100644 --- a/addons/point_of_sale/static/src/css/pos.css +++ b/addons/point_of_sale/static/src/css/pos.css @@ -705,37 +705,60 @@ /* b) The payment screen */ -.pos .pos-step-container { - display: inline-block; - font-size: 1.5em; -} -.pos .greyed-out{ - color: #AAA; -} -.pos .pos-step-container input{ - font-size: 1em; - outline: none; - border: none; - padding: 0px 8px; - padding-top: 8px; - margin-left: 16px; - background: white; - color: #4c4c4c; - box-shadow: 0px 2px rgba(143, 143, 143, 0.3) inset; - -webkit-animation: all 250ms linear; -} - -.pos .pos-step-container input:focus{ - color: rgb(130, 124, 255); - box-shadow: 0px 2px rgba(130, 124, 255, 0.3) inset; - -webkit-animation: all 250ms linear; -} .pos .pos-payment-container { + display: inline-block; + font-size: 16px; text-align: left; - min-width: 320px; - margin-top: 40px; + width: 360px; } +.pos .payment-due-total { + text-align: center; + font-weight: bold; + font-size: 48px; + margin: 27px; + text-shadow: 0px 2px rgb(202, 202, 202); +} +.pos .paymentline{ + position: relative; + padding: 8px; + border-box: 3px; + box-sizing: border-box; + border-radius: 3px; +} +.pos .paymentline-input{ + font-size: 20px; + font-family: Lato; + display: block; + width: 100%; + box-sizing: border-box; + outline: none; + border: none; + padding: 6px 8px; + background: white; + color: #484848; + text-align: right; + box-shadow: 0px 2px rgba(143, 143, 143, 0.3) inset; +} + +.pos .paymentline-input:focus{ + color: rgb(130, 124, 255); + box-shadow: 0px 2px rgba(219, 219, 219, 0.3) inset; + -webkit-animation: all 250ms linear; +} + +.paymentline-delete { + width: 32px; + height: 32px; + padding: 5px; + text-align: center; + box-sizing: border-box; + position: absolute; + bottom: 10px; + left: 8px; + cursor: pointer; +} + .pos .pos-payment-container .left-block{ display: inline-block; width:49%; @@ -743,14 +766,15 @@ padding:0; text-align:left; } -.pos .pos-payment-container .header{ - margin-top: 0px; - margin-bottom:20px; - font-weight: bold; -} .pos .pos-payment-container .infoline{ margin-top:5px; margin-bottom:5px; + padding: 0px 8px; + opacity: 0.5; +} +.pos .pos-payment-container .infoline.bigger{ + opacity: 1; + font-size: 20px; } .pos .pos-payment-container .right-block{ display: inline-block; @@ -759,17 +783,8 @@ padding:0; text-align:right; } -.pos .pos-payment-container table { - width: 100%; - margin-bottom: 20px; -} -.pos .pos-payment-container td { - vertical-align: middle; -} -.pos .pos-payment-container .paymentline-type { - font-size: 1em; - font-weight: bold; - margin-right:10px; +.pos .paymentline.selected{ + background: rgb(220,220,220); } /* c) The receipt screen */ @@ -784,6 +799,7 @@ background-color: white; margin: 20px; padding: 15px; + font-size: 14px; padding-bottom:30px; display: inline-block; font-family: "Inconsolata"; diff --git a/addons/point_of_sale/static/src/js/main.js b/addons/point_of_sale/static/src/js/main.js index 55f0bbd1f61..90fa3567cda 100644 --- a/addons/point_of_sale/static/src/js/main.js +++ b/addons/point_of_sale/static/src/js/main.js @@ -13,8 +13,6 @@ openerp.point_of_sale = function(instance) { openerp_pos_keyboard(instance,module); // import pos_keyboard_widget.js - openerp_pos_scrollbar(instance,module); // import pos_scrollbar_widget.js - openerp_pos_screens(instance,module); // import pos_screens.js openerp_pos_devices(instance,module); // import pos_devices.js diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index bd32e040304..20fcc5e553f 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -669,25 +669,30 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal model: module.Orderline, }); - // Every PaymentLine contains a cashregister and an amount of money. + // Every Paymentline contains a cashregister and an amount of money. module.Paymentline = Backbone.Model.extend({ initialize: function(attributes, options) { this.amount = 0; this.cashregister = options.cashRegister; + this.name = this.cashregister.get('journal_id')[1]; + this.selected = false; }, //sets the amount of money on this payment line set_amount: function(value){ - this.amount = parseFloat(value) || 0; - this.trigger('change'); + this.amount = round_di(parseFloat(value) || 0, 2); + this.trigger('change:amount',this); }, // returns the amount of money on this paymentline get_amount: function(){ return this.amount; }, - // returns the associated cashRegister - get_cashregister: function(){ - return this.cashregister; + set_selected: function(selected){ + if(this.selected !== selected){ + this.selected = selected; + this.trigger('change:selected',this); + } }, + // returns the associated cashRegister //exports as JSON for server communication export_as_JSON: function(){ return { @@ -713,7 +718,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal // An order more or less represents the content of a client's shopping cart (the OrderLines) - // plus the associated payment information (the PaymentLines) + // plus the associated payment information (the Paymentlines) // there is always an active ('selected') order in the Pos, a new one is created // automaticaly once an order is completed and sent to the server. module.Order = Backbone.Model.extend({ @@ -727,8 +732,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal name: "Order " + this.uid, client: null, }); - this.pos = attributes.pos; - this.selected_orderline = undefined; + this.pos = attributes.pos; + this.selected_orderline = undefined; + this.selected_paymentline = undefined; this.screen_data = {}; // see ScreenSelector this.receipt_type = 'receipt'; // 'receipt' || 'invoice' return this; @@ -765,13 +771,21 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal getLastOrderline: function(){ return this.get('orderLines').at(this.get('orderLines').length -1); }, - addPaymentLine: function(cashRegister) { + addPaymentline: function(cashRegister) { var paymentLines = this.get('paymentLines'); var newPaymentline = new module.Paymentline({},{cashRegister:cashRegister}); if(cashRegister.get('journal').type !== 'cash'){ - newPaymentline.set_amount( this.getDueLeft() ); + newPaymentline.set_amount( Math.max(this.getDueLeft(),0) ); } paymentLines.add(newPaymentline); + this.selectPaymentline(newPaymentline); + + }, + removePaymentline: function(line){ + if(this.selected_paymentline === line){ + this.selectPaymentline(undefined); + } + this.get('paymentLines').remove(line); }, getName: function() { return this.get('name'); @@ -946,6 +960,19 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.selected_orderline = undefined; } }, + selectPaymentline: function(line){ + console.log("SELECT_PAYMENTLINE",line); + if(line !== this.selected_paymentline){ + if(this.selected_paymentline){ + this.selected_paymentline.set_selected(false); + } + this.selected_paymentline = line; + if(this.selected_paymentline){ + this.selected_paymentline.set_selected(true); + } + this.trigger('change:selected_paymentline',this.selected_paymentline); + } + }, }); module.OrderCollection = Backbone.Collection.extend({ diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 965451ee0eb..c182d9d06b2 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -157,6 +157,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa barcode_product_screen: 'products', //if defined, this screen will be loaded when a product is scanned barcode_product_error_popup: 'error-product', //if defined, this popup will be loaded when there's an error in the popup + hotkeys_handlers: {}, + // what happens when a product is scanned : // it will add the product to the order and go to barcode_product_screen. Or show barcode_product_error_popup if // there's an error. @@ -634,7 +636,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa } var cashregister = selfCheckoutRegisters[0] || self.pos.get('cashRegisters').models[0]; - currentOrder.add_payment_line(cashregister); + currentOrder.addPaymentline(cashregister); self.pos.push_order(currentOrder) currentOrder.destroy(); self.pos.proxy.transaction_end(); @@ -802,15 +804,12 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa init: function(parent, options) { this._super(parent,options); - this.model = options.model; this.user = this.pos.get('user'); this.company = this.pos.get('company'); this.shop_obj = this.pos.get('shop'); }, renderElement: function() { this._super(); - this.pos.bind('change:selectedOrder', this.change_selected_order, this); - this.change_selected_order(); }, show: function(){ this._super(); @@ -828,6 +827,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa click: function() { self.finishOrder(); }, }); + this.refresh(); this.print(); // THIS IS THE HACK OF THE CENTURY @@ -859,22 +859,14 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa finishOrder: function() { this.pos.get('selectedOrder').destroy(); }, - change_selected_order: function() { - if (this.currentOrderLines) - this.currentOrderLines.unbind(); - this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines'); - this.currentOrderLines.bind('add', this.refresh, this); - this.currentOrderLines.bind('change', this.refresh, this); - this.currentOrderLines.bind('remove', this.refresh, this); - if (this.currentPaymentLines) - this.currentPaymentLines.unbind(); - this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines'); - this.currentPaymentLines.bind('all', this.refresh, this); - this.refresh(); - }, refresh: function() { - this.currentOrder = this.pos.get('selectedOrder'); - $('.pos-receipt-container', this.$el).html(QWeb.render('PosTicket',{widget:this})); + var order = this.pos.get('selectedOrder'); + $('.pos-receipt-container', this.$el).html(QWeb.render('PosTicket',{ + widget:this, + order: order, + orderlines: order.get('orderLines').models, + paymentlines: order.get('paymentLines').models, + })); }, close: function(){ this._super(); @@ -886,17 +878,68 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa back_screen: 'products', next_screen: 'receipt', init: function(parent, options) { + var self = this; this._super(parent,options); - this.model = options.model; - this.pos.bind('change:selectedOrder', this.change_selected_order, this); - this.bind_payment_line_events(); - this.bind_orderline_events(); - this.paymentlinewidgets = []; - this.focusedLine = null; + + this.pos.bind('change:selectedOrder',function(){ + this.bind_events(); + this.renderElement(); + },this); + + this.bind_events(); + + this.line_delete_handler = function(event){ + var node = this; + while(node && !node.classList.contains('paymentline')){ + node = node.parentNode; + } + if(node){ + self.pos.get('selectedOrder').removePaymentline(node.line) + } + event.stopPropagation(); + }; + + this.line_change_handler = function(event){ + var node = this; + while(node && !node.classList.contains('paymentline')){ + node = node.parentNode; + } + if(node){ + node.line.set_amount(this.value); + } + + }; + + this.line_click_handler = function(event){ + console.log('click'); + var node = this; + while(node && !node.classList.contains('paymentline')){ + node = node.parentNode; + } + if(node){ + self.pos.get('selectedOrder').selectPaymentline(node.line); + } + }; + }, show: function(){ this._super(); var self = this; + + this.enable_numpad(); + this.update_payment_summary(); + this.focus_selected_line(); + window.removeall = function(){ + self.remove_empty_lines(); + }; + window.listlines = function(){ + var lines = self.pos.get('selectedOrder').get('paymentLines').models; + for(var i = 0; i < lines.length; i++){ + console.log('LINE:',lines[i]); + } + }; + + /* this.hotkey_handler = function(event){ if(event.which === 13){ @@ -907,13 +950,16 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }; $('body').on('keyup',this.hotkey_handler); + + */ - - if( this.pos.iface_cashdrawer && this.pos.get('selectedOrder').get('paymentLines').find( function(pl){ return pl.cashregister.get('journal').type === 'cash'; })){ + if( this.pos.iface_cashdrawer + && this.pos.get('selectedOrder').get('paymentLines').find( function(pl){ + return pl.cashregister.get('journal').type === 'cash'; + })){ this.pos.proxy.open_cashbox(); } - this.enable_numpad(); this.add_action_button({ label: _t('Back'), @@ -928,17 +974,17 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa name: 'validation', icon: '/point_of_sale/static/src/img/icons/png48/validate.png', click: function(){ - self.validate(); + self.validate_order(); }, }); - if(this.pos.iface_invoicing){ + if( this.pos.iface_invoicing ){ this.add_action_button({ label: 'Invoice', name: 'invoice', icon: '/point_of_sale/static/src/img/icons/png48/invoice.png', click: function(){ - self.validate({invoice: true}); + self.validate_order({invoice: true}); }, }); } @@ -954,23 +1000,163 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }); } - this.update_payment_summary(); - this.line_refocus(); }, close: function(){ this._super(); this.disable_numpad(); - $('body').off('keyup',this.hotkey_handler); + //$('body').off('keyup',this.hotkey_handler); + }, + remove_empty_lines: function(){ + var order = this.pos.get('selectedOrder'); + var lines = order.get('paymentLines').models.slice(0); + for(var i = 0; i < lines.length; i++){ + var line = lines[i]; + if(line.get_amount() === 0){ + order.removePaymentline(line); + } + } }, back: function() { - _.each(this.paymentlinewidgets, function(widget){ - if( widget.payment_line.get_amount() === 0 ){ - widget.payment_line.destroy(); - } - }); + this.remove_empty_lines(); this.pos_widget.screen_selector.set_current_screen(this.back_screen); }, - validate: function(options) { + bind_events: function() { + if(this.old_order){ + this.old_order.unbind(null,null,this); + } + var order = this.pos.get('selectedOrder'); + order.bind('change:selected_paymentline',this.focus_selected_line,this); + + this.old_order = order; + + if(this.old_paymentlines){ + this.old_paymentlines.unbind(null,null,this); + } + var paymentlines = order.get('paymentLines'); + paymentlines.bind('add', this.add_paymentline, this); + paymentlines.bind('change:selected', this.rerender_paymentline, this); + paymentlines.bind('change:amount', function(line){ + if(!line.selected && line.node){ + line.node.value = line.amount.toFixed(2); + } + this.update_payment_summary(); + },this); + paymentlines.bind('remove', this.remove_paymentline, this); + paymentlines.bind('all', this.update_payment_summary, this); + + this.old_paymentlines = paymentlines; + + if(this.old_orderlines){ + this.old_orderlines.unbind(null,null,this); + } + var orderlines = order.get('orderLines'); + orderlines.bind('all', this.update_payment_summary, this); + + this.old_orderlines = orderlines; + }, + focus_selected_line: function(){ + var line = this.pos.get('selectedOrder').selected_paymentline; + if(line){ + debugger; + if(!line.node){ + debugger; + } + var input = line.node.querySelector('input'); + if(!input){ + return; + } + var value = input.value; + input.focus(); + + if(this.numpad_state){ + this.numpad_state.reset(); + } + + if(Number(value) === 0){ + input.value = ''; + }else{ + input.value = value; + input.select(); + } + } + }, + add_paymentline: function(line) { + var list_container = this.el.querySelector('.payment-lines'); + list_container.appendChild(this.render_paymentline(line)); + + if(this.numpad_state){ + this.numpad_state.reset(); + } + }, + render_paymentline: function(line){ + var el_html = openerp.qweb.render('Paymentline',{widget: this, line: line}); + el_html = _.str.trim(el_html); + + var el_node = document.createElement('tbody'); + el_node.innerHTML = el_html; + el_node = el_node.childNodes[0]; + el_node.line = line; + el_node.querySelector('.paymentline-delete') + .addEventListener('click', this.line_delete_handler); + el_node.addEventListener('click', this.line_click_handler); + el_node.querySelector('input') + .addEventListener('keyup', this.line_change_handler); + + line.node = el_node; + + return el_node; + }, + rerender_paymentline: function(line){ + var old_node = line.node; + var new_node = this.render_paymentline(line); + + old_node.parentNode.replaceChild(new_node,old_node); + console.log('RERENDER',line); + }, + remove_paymentline: function(line){ + console.log('Removing line from DOM:',line); + line.node.parentNode.removeChild(line.node); + line.node = undefined; + }, + renderElement: function(){ + this._super(); + + var paymentlines = this.pos.get('selectedOrder').get('paymentLines').models; + var list_container = this.el.querySelector('.payment-lines'); + + for(var i = 0; i < paymentlines.length; i++){ + list_container.appendChild(this.render_paymentline(paymentlines[i])); + } + + //this.update_payment_summary(); + }, + update_payment_summary: function() { + var currentOrder = this.pos.get('selectedOrder'); + var paidTotal = currentOrder.getPaidTotal(); + var dueTotal = currentOrder.getTotalTaxIncluded(); + var remaining = dueTotal > paidTotal ? dueTotal - paidTotal : 0; + var change = paidTotal > dueTotal ? paidTotal - dueTotal : 0; + + this.$('.payment-due-total').html(this.format_currency(dueTotal)); + this.$('.payment-paid-total').html(this.format_currency(paidTotal)); + this.$('.payment-remaining').html(this.format_currency(remaining)); + this.$('.payment-change').html(this.format_currency(change)); + if(currentOrder.selected_orderline === undefined){ + remaining = 1; // What is this ? + } + + if(this.pos_widget.action_bar){ + this.pos_widget.action_bar.set_button_disabled('validation', !this.is_paid()); + this.pos_widget.action_bar.set_button_disabled('invoice', !this.is_paid()); + } + }, + is_paid: function(){ + var currentOrder = this.pos.get('selectedOrder'); + return (currentOrder.getTotalTaxIncluded() >= 0.000001 + && currentOrder.getPaidTotal() + 0.000001 >= currentOrder.getTotalTaxIncluded()); + + }, + validate_order: function(options) { var self = this; options = options || {}; @@ -1012,97 +1198,13 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.pos_widget.screen_selector.set_current_screen(this.next_screen); } } + // hide onscreen (iOS) keyboard setTimeout(function(){ document.activeElement.blur(); $("input").blur(); },250); }, - bind_payment_line_events: function() { - this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines'); - this.currentPaymentLines.bind('add', this.add_payment_line, this); - this.currentPaymentLines.bind('remove', this.renderElement, this); - this.currentPaymentLines.bind('all', this.update_payment_summary, this); - }, - bind_orderline_events: function() { - this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines'); - this.currentOrderLines.bind('all', this.update_payment_summary, this); - }, - change_selected_order: function() { - this.currentPaymentLines.unbind(); - this.bind_payment_line_events(); - this.currentOrderLines.unbind(); - this.bind_orderline_events(); - this.renderElement(); - }, - line_refocus: function(lineWidget){ - if(lineWidget){ - if(this.focusedLine !== lineWidget){ - this.focusedLine = lineWidget; - } - } - if(this.focusedLine){ - this.focusedLine.focus(); - } - }, - add_payment_line: function(newPaymentLine) { - var self = this; - var l = new module.PaymentlineWidget(this, { - payment_line: newPaymentLine, - }); - l.on('delete_payment_line', self, function(r) { - self.deleteLine(r); - }); - l.appendTo(this.$('.paymentlines')); - this.paymentlinewidgets.push(l); - if(this.numpadState){ - this.numpadState.resetValue(); - } - this.line_refocus(l); - }, - renderElement: function() { - this._super(); - this.$('.paymentlines').empty(); - for(var i = 0, len = this.paymentlinewidgets.length; i < len; i++){ - this.paymentlinewidgets[i].destroy(); - } - this.paymentlinewidgets = []; - - this.currentPaymentLines.each(_.bind( function(paymentLine) { - this.add_payment_line(paymentLine); - }, this)); - this.update_payment_summary(); - }, - deleteLine: function(lineWidget) { - this.currentPaymentLines.remove([lineWidget.payment_line]); - lineWidget.destroy(); - }, - is_paid: function(){ - var currentOrder = this.pos.get('selectedOrder'); - return (currentOrder.getTotalTaxIncluded() >= 0.000001 - && currentOrder.getPaidTotal() + 0.000001 >= currentOrder.getTotalTaxIncluded()); - - }, - update_payment_summary: function() { - var currentOrder = this.pos.get('selectedOrder'); - var paidTotal = currentOrder.getPaidTotal(); - var dueTotal = currentOrder.getTotalTaxIncluded(); - var remaining = dueTotal > paidTotal ? dueTotal - paidTotal : 0; - var change = paidTotal > dueTotal ? paidTotal - dueTotal : 0; - - this.$('.payment-due-total').html(this.format_currency(dueTotal)); - this.$('.payment-paid-total').html(this.format_currency(paidTotal)); - this.$('.payment-remaining').html(this.format_currency(remaining)); - this.$('.payment-change').html(this.format_currency(change)); - if(currentOrder.selected_orderline === undefined){ - remaining = 1; // What is this ? - } - - if(this.pos_widget.action_bar){ - this.pos_widget.action_bar.set_button_disabled('validation', !this.is_paid()); - this.pos_widget.action_bar.set_button_disabled('invoice', !this.is_paid()); - } - }, enable_numpad: function(){ this.disable_numpad(); //ensure we don't register the callbacks twice this.numpad_state = this.pos_widget.numpad.state; @@ -1124,7 +1226,11 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.numpad_state.set({mode: 'payment'}); }, set_value: function(val) { - this.currentPaymentLines.last().set_amount(val); + var selected_line =this.pos.get('selectedOrder').selected_paymentline; + if(selected_line){ + selected_line.set_amount(val); + selected_line.node.querySelector('input').value = selected_line.amount.toFixed(2); + } }, }); } diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js index 438dbc4bc00..90787f9f610 100644 --- a/addons/point_of_sale/static/src/js/widgets.js +++ b/addons/point_of_sale/static/src/js/widgets.js @@ -60,9 +60,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.state = new module.NumpadState(); window.numpadstate = this.state; var self = this; - this.state.bind('change:buffer',function(){ - console.log('BUFFER:',self.state.get('buffer')); - }) }, start: function() { this.state.bind('change:mode', this.changedMode, this); @@ -128,7 +125,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa console.warn('TODO should not get there...?'); return; } - self.pos.get('selectedOrder').addPaymentLine(self.cashRegister); + self.pos.get('selectedOrder').addPaymentline(self.cashRegister); self.pos_widget.screen_selector.set_current_screen('payment'); }); }, @@ -208,11 +205,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.update_summary(); },this); }, - update_numpad: function() { - this.selected_line = this.pos.get('selectedOrder').getSelectedLine(); - if (this.numpadState) - this.numpadState.reset(); - }, render_orderline: function(orderline){ var el_str = openerp.qweb.render('Orderline',{widget:this, line:orderline}); var el_node = document.createElement('div'); @@ -236,6 +228,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa var replacement_line = this.render_orderline(order_line); node.parentNode.replaceChild(replacement_line,node); }, + // overriding the openerp framework replace method for performance reasons replace: function($target){ this.renderElement(); var target = $target[0]; @@ -278,58 +271,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }, }); - module.PaymentlineWidget = module.PosBaseWidget.extend({ - template: 'PaymentlineWidget', - init: function(parent, options) { - this._super(parent,options); - this.payment_line = options.payment_line; - this.payment_line.bind('change', this.changedAmount, this); - }, - changeAmount: function(event) { - var newAmount = event.currentTarget.value; - var amount = parseFloat(newAmount); - if(!isNaN(amount)){ - this.amount = amount; - this.payment_line.set_amount(amount); - } - }, - checkAmount: function(e){ - if (e.which !== 0 && e.charCode !== 0) { - if(isNaN(String.fromCharCode(e.charCode))){ - return (String.fromCharCode(e.charCode) === "." && e.currentTarget.value.toString().split(".").length < 2)?true:false; - } - } - return true - }, - changedAmount: function() { - if (this.amount !== this.payment_line.get_amount()){ - this.renderElement(); - } - }, - renderElement: function() { - var self = this; - this.name = this.payment_line.get_cashregister().get('journal_id')[1]; - this._super(); - this.$('input').keypress(_.bind(this.checkAmount, this)) - .keyup(function(event){ - self.changeAmount(event); - }); - this.$('.delete-payment-line').click(function() { - self.trigger('delete_payment_line', self); - }); - }, - focus: function(){ - var val = this.$('input')[0].value; - this.$('input')[0].focus(); - if(Number(val) === 0){ - this.$('input')[0].value = ''; - }else{ - this.$('input')[0].value = val; - this.$('input')[0].select(); - } - }, - }); - module.OrderButtonWidget = module.PosBaseWidget.extend({ template:'OrderButtonWidget', init: function(parent, options) { @@ -918,12 +859,6 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa self.pos.delete_current_order(); }); - $('body').on('keyup',function(event){ - if(event.which === 13){ - self.set_fullscreen(); - } - }); - //when a new order is created, add an order button widget self.pos.get('orders').bind('add', function(new_order){ var new_order_button = new module.OrderButtonWidget(null, { diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index 941fdc8c80b..5591acf0ac7 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -246,41 +246,32 @@

Payment

-
-
-
-
- - Total: +
+
+
+
+
+ + Paid: - +
- -
-
- +
@@ -556,14 +547,26 @@ - - + +
+
+ +
+ + + + +
+
+ + + - + - - + + @@ -590,7 +593,7 @@
+ Date.CultureInfo.formatPatterns.longTime)"/>


Phone:
@@ -603,7 +606,7 @@ - + @@ -623,33 +626,33 @@
Subtotal: - +
Tax: - +
Discount: - +
Total: - +

- +
- + - +

Change: - +