diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 970eb1fbed7..8e47d83aa24 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -853,8 +853,7 @@ class pos_order(osv.osv): inv_line['price_unit'] = line.price_unit inv_line['discount'] = line.discount inv_line['name'] = inv_name - inv_line['invoice_line_tax_id'] = ('invoice_line_tax_id' in inv_line)\ - and [(6, 0, inv_line['invoice_line_tax_id'])] or [] + inv_line['invoice_line_tax_id'] = [(6, 0, [x.id for x in line.product_id.taxes_id] )] inv_line_ref.create(cr, uid, inv_line, context=context) inv_ref.button_reset_taxes(cr, uid, [inv_id], context=context) wf_service.trg_validate(uid, 'pos.order', order.id, 'invoice', cr) @@ -1156,7 +1155,6 @@ class pos_order_line(osv.osv): prod = self.pool.get('product.product').browse(cr, uid, product, context=context) - taxes = prod.taxes_id price = price_unit * (1 - (discount or 0.0) / 100.0) taxes = account_tax_obj.compute_all(cr, uid, prod.taxes_id, price, qty, product=prod, partner=False) diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css index 2c086032ec3..d9a4d6d00a9 100644 --- a/addons/point_of_sale/static/src/css/pos.css +++ b/addons/point_of_sale/static/src/css/pos.css @@ -233,7 +233,9 @@ font-style: italic; cursor:pointer; } - +.point-of-sale .oe_pos_synch-notification.oe_inactive{ + cursor: default; +} .point-of-sale .oe_pos_synch-notification .oe_status_red{ display:inline-block; cursor:pointer; @@ -542,7 +544,9 @@ background: -webkit-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); background: -moz-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); background: -ms-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); - background: linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); + /* for some reason the -90deg orientation doesn't match the -webkit-linear-gradient. It should be 180deg here. + * webkit also insists on rendering *both* gradients instead of only the native one. So it doesn't looks right. ugh. + background: linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); */ /*background:#FFF;*/ padding: 3px; padding-top: 15px; @@ -607,7 +611,9 @@ background: -webkit-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); background: -moz-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); background: -ms-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); + /* troublesome in latest webkit background: linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); + */ /*background:#FFF;*/ padding: 3px; padding-top:15px; @@ -991,12 +997,20 @@ margin-bottom:10px; } .point-of-sale .order .summary .line{ + float: right; margin-right:15px; + margin-left: 15px; padding-top:5px; border-top: solid 2px; border-color:#777; } +.point-of-sale .order .summary .line .subentry{ + font-size: 10px; + font-weight: normal; + text-align: center; +} .point-of-sale .order .summary .line.empty{ + text-align: right; border-color:#BBB; color:#999; } diff --git a/addons/point_of_sale/static/src/js/db.js b/addons/point_of_sale/static/src/js/db.js index 666c61919da..2be58d6ce97 100644 --- a/addons/point_of_sale/static/src/js/db.js +++ b/addons/point_of_sale/static/src/js/db.js @@ -40,6 +40,10 @@ function openerp_pos_db(instance, module){ //cache the data in memory to avoid roundtrips to the localstorage this.cache = {}; + this.product_by_id = {}; + this.product_by_ean13 = {}; + this.product_by_category_id = {}; + this.category_by_id = {}; this.root_category_id = 0; this.category_products = {}; @@ -49,6 +53,7 @@ function openerp_pos_db(instance, module){ this.category_search_string = {}; this.packagings_by_id = {}; this.packagings_by_product_id = {}; + this.packagings_by_ean13 = {}; }, /* returns the category object from its id. If you pass a list of id as parameters, you get * a list of category objects. @@ -137,7 +142,6 @@ function openerp_pos_db(instance, module){ /* saves a record store to the database */ save: function(store,data){ var str_data = JSON.stringify(data); - console.log('Storing '+ Math.round(str_data.length/1024.0)+' KB of data to store: '+store); localStorage[this.name + '_' + store] = JSON.stringify(data); this.cache[store] = data; }, @@ -153,8 +157,7 @@ function openerp_pos_db(instance, module){ return str + '\n'; }, add_products: function(products){ - var stored_products = this.load('products',{}); - var stored_categories = this.load('categories',{}); + var stored_categories = this.product_by_category_id; if(!products instanceof Array){ products = [products]; @@ -187,10 +190,11 @@ function openerp_pos_db(instance, module){ } this.category_search_string[ancestor] += search_string; } - stored_products[product.id] = product; + this.product_by_id[product.id] = product; + if(product.ean13){ + this.product_by_ean13[product.ean13] = product; + } } - this.save('products',stored_products); - this.save('categories',stored_categories); }, add_packagings: function(packagings){ for(var i = 0, len = packagings.length; i < len; i++){ @@ -200,6 +204,9 @@ function openerp_pos_db(instance, module){ this.packagings_by_product_id[pack.product_id[0]] = []; } this.packagings_by_product_id[pack.product_id[0]].push(pack); + if(pack.ean13){ + this.packagings_by_ean13[pack.ean13] = pack; + } } }, /* removes all the data from the database. TODO : being able to selectively remove data */ @@ -219,31 +226,24 @@ function openerp_pos_db(instance, module){ return count; }, get_product_by_id: function(id){ - return this.load('products',{})[id]; + return this.product_by_id[id]; }, get_product_by_ean13: function(ean13){ - var products = this.load('products',{}); - for(var i in products){ - if( products[i] && products[i].ean13 === ean13){ - return products[i]; - } + if(this.product_by_ean13[ean13]){ + return this.product_by_ean13[ean13]; } - for(var p in this.packagings_by_id){ - var pack = this.packagings_by_id[p]; - if( pack.ean === ean13){ - return products[pack.product_id[0]]; - } + var pack = this.packagings_by_ean13[ean13]; + if(pack){ + return this.product_by_id[pack.product_id[0]]; } return undefined; }, get_product_by_category: function(category_id){ - var stored_categories = this.load('categories',{}); - var stored_products = this.load('products',{}); - var product_ids = stored_categories[category_id]; + var product_ids = this.product_by_category_id[category_id]; var list = []; if (product_ids) { for (var i = 0, len = Math.min(product_ids.length, this.limit); i < len; i++) { - list.push(stored_products[product_ids[i]]); + list.push(this.product_by_id[product_ids[i]]); } } return list; @@ -275,12 +275,9 @@ function openerp_pos_db(instance, module){ }, remove_order: function(order_id){ var orders = this.load('orders',[]); - console.log('Remove order:',order_id); - console.log('Order count:',orders.length); orders = _.filter(orders, function(order){ return order.id !== order_id; }); - console.log('Order count:',orders.length); this.save('orders',orders); }, get_orders: function(){ diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 556ea482aad..d2cf15b54f3 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -1,6 +1,24 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sale var QWeb = instance.web.qweb; + // rounds a value with a fixed number of decimals. + // round(3.141492,2) -> 3.14 + function round(value,decimals){ + var mult = Math.pow(10,decimals || 0); + return Math.round(value*mult)/mult; + } + window.round = round; + + // rounds a value with decimal form precision + // round(3.141592,0.025) ->3.125 + function round_pr(value,precision){ + if(!precision || precision < 0){ + throw new Error('round_pr(): needs a precision greater than zero, got '+precision+' instead'); + } + return Math.round(value / precision) * precision; + } + window.round_pr = round_pr; + // The PosModel contains the Point Of Sale's representation of the backend. // Since the PoS must work in standalone ( Without connection to the server ) @@ -24,8 +42,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.proxy = new module.ProxyDevice(); // used to communicate to the hardware devices via a local 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 - + this.debug = jQuery.deparam(jQuery.param.querystring()).debug !== undefined; //debug mode // default attributes values. If null, it will be loaded below. this.set({ @@ -101,8 +118,9 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal }).then(function(company_partners){ self.get('company').contact_address = company_partners[0].contact_address; - return self.fetch('res.currency',['symbol','position'],[['id','=',self.get('company').currency_id[0]]]); + 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); @@ -117,7 +135,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal return self.fetch('product.packaging', null, null); }).then(function(packagings){ self.set('product.packaging',packagings); - + return self.fetch('res.users', ['name','ean13'], [['ean13', '!=', false]]); }).then(function(users){ self.set('user_list',users); @@ -211,7 +229,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal // logs the usefull posmodel data to the console for debug purposes log_loaded_data: function(){ console.log('PosModel data has been loaded:'); - console.log('PosModel: categories:',this.get('categories')); console.log('PosModel: units:',this.get('units')); console.log('PosModel: bank_statements:',this.get('bank_statements')); console.log('PosModel: journals:',this.get('journals')); @@ -339,19 +356,26 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.product = options.product; this.price = options.product.get('price'); this.quantity = 1; + this.quantityStr = '1'; this.discount = 0; + this.discountStr = '0'; this.type = 'unit'; this.selected = false; }, // sets a discount [0,100]% set_discount: function(discount){ - this.discount = Math.max(0,Math.min(100,discount)); + var disc = Math.min(Math.max(parseFloat(discount) || 0, 0),100); + this.discount = disc; + this.discountStr = '' + disc; this.trigger('change'); }, // returns the discount [0,100]% get_discount: function(){ return this.discount; }, + get_discount_str: function(){ + return this.discountStr; + }, get_product_type: function(){ return this.type; }, @@ -359,13 +383,18 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal // product's unity of measure properties. Quantities greater than zero will not get // rounded to zero set_quantity: function(quantity){ - if(_.isNaN(quantity)){ + if(quantity === 'remove'){ this.order.removeOrderline(this); - }else if(quantity !== undefined){ - this.quantity = Math.max(0,quantity); + return; + }else{ + var quant = Math.max(parseFloat(quantity) || 0, 0); var unit = this.get_unit(); - if(unit && this.quantity > 0 ){ - this.quantity = Math.max(unit.rounding, Math.round(quantity / unit.rounding) * unit.rounding); + if(unit){ + this.quantity = Math.max(unit.rounding, Math.round(quant / unit.rounding) * unit.rounding); + this.quantityStr = this.quantity.toFixed(Math.max(0,Math.ceil(Math.log(1.0 / unit.rounding) / Math.log(10)))); + }else{ + this.quantity = quant; + this.quantityStr = '' + this.quantity; } } this.trigger('change'); @@ -374,6 +403,17 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal get_quantity: function(){ return this.quantity; }, + get_quantity_str: function(){ + return this.quantityStr; + }, + get_quantity_str_with_unit: function(){ + var unit = this.get_unit(); + if(unit && unit.name !== 'Unit(s)'){ + return this.quantityStr + ' ' + unit.name; + }else{ + return this.quantityStr; + } + }, // return the unit of measure of the product get_unit: function(){ var unit_id = (this.product.get('uos_id') || this.product.get('uom_id')); @@ -390,15 +430,6 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal get_product: function(){ return this.product; }, - // return the base price of this product (for this orderline) - get_price: function(){ - return this.price; - }, - // changes the base price of the product for this orderline - set_price: function(price){ - this.price = price; - this.trigger('change'); - }, // selects or deselects this orderline set_selected: function(selected){ this.selected = selected; @@ -429,7 +460,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal export_as_JSON: function() { return { qty: this.get_quantity(), - price_unit: this.get_price(), + price_unit: this.get_unit_price(), discount: this.get_discount(), product_id: this.get_product().get('id'), }; @@ -439,9 +470,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal return { quantity: this.get_quantity(), unit_name: this.get_unit().name, - price: this.get_price(), + price: this.get_unit_price(), discount: this.get_discount(), product_name: this.get_product().get('name'), + price_display : this.get_display_price(), price_with_tax : this.get_price_with_tax(), price_without_tax: this.get_price_without_tax(), tax: this.get_tax(), @@ -449,6 +481,19 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal product_description_sale: this.get_product().get('description_sale'), }; }, + // changes the base price of the product for this orderline + set_unit_price: function(price){ + this.price = round(parseFloat(price) || 0, 2); + this.trigger('change'); + }, + get_unit_price: function(){ + var rounding = this.pos.get('currency').rounding; + return round_pr(this.price,rounding); + }, + get_display_price: function(){ + var rounding = this.pos.get('currency').rounding; + return round_pr(round_pr(this.get_unit_price() * this.get_quantity(),rounding) * (1- this.get_discount()/100.0),rounding); + }, get_price_without_tax: function(){ return this.get_all_prices().priceWithoutTax; }, @@ -458,9 +503,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal get_tax: function(){ return this.get_all_prices().tax; }, - get_all_prices: function() { + get_all_prices: function(){ var self = this; - var base = this.get_quantity() * this.price * (1 - (this.get_discount() / 100)); + var currency_rounding = this.pos.get('currency').rounding; + var base = round_pr(this.get_quantity() * this.get_unit_price() * (1.0 - (this.get_discount() / 100.0)), currency_rounding); var totalTax = base; var totalNoTax = base; @@ -474,12 +520,13 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal if (tax.price_include) { var tmp; if (tax.type === "percent") { - tmp = base - (base / (1 + tax.amount)); + tmp = base - round_pr(base / (1 + tax.amount),currency_rounding); } else if (tax.type === "fixed") { - tmp = tax.amount * self.get_quantity(); + tmp = round_pr(tax.amount * self.get_quantity(),currency_rounding); } else { throw "This type of tax is not supported by the point of sale: " + tax.type; } + tmp = round_pr(tmp,currency_rounding); taxtotal += tmp; totalNoTax -= tmp; } else { @@ -491,6 +538,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal } else { throw "This type of tax is not supported by the point of sale: " + tax.type; } + tmp = round_pr(tmp,currency_rounding); taxtotal += tmp; totalTax += tmp; } @@ -515,7 +563,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal }, //sets the amount of money on this payment line set_amount: function(value){ - this.amount = value; + this.amount = parseFloat(value) || 0; this.trigger('change'); }, // returns the amount of money on this paymentline @@ -584,7 +632,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal line.set_quantity(options.quantity); } if(options.price !== undefined){ - line.set_price(options.price); + line.set_unit_price(options.price); } var last_orderline = this.getLastOrderline(); @@ -613,14 +661,19 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal getName: function() { return this.get('name'); }, - getTotal: function() { + getSubtotal : function(){ + return (this.get('orderLines')).reduce((function(sum, orderLine){ + return sum + orderLine.get_display_price(); + }), 0); + }, + getTotalTaxIncluded: function() { return (this.get('orderLines')).reduce((function(sum, orderLine) { return sum + orderLine.get_price_with_tax(); }), 0); }, getDiscountTotal: function() { return (this.get('orderLines')).reduce((function(sum, orderLine) { - return sum + (orderLine.get_price() * (orderLine.get_discount()/100) * orderLine.get_quantity()); + return sum + (orderLine.get_unit_price() * (orderLine.get_discount()/100) * orderLine.get_quantity()); }), 0); }, getTotalTaxExcluded: function() { @@ -639,10 +692,10 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal }), 0); }, getChange: function() { - return this.getPaidTotal() - this.getTotal(); + return this.getPaidTotal() - this.getTotalTaxIncluded(); }, getDueLeft: function() { - return this.getTotal() - this.getPaidTotal(); + return this.getTotalTaxIncluded() - this.getPaidTotal(); }, // sets the type of receipt 'receipt'(default) or 'invoice' set_receipt_type: function(type){ @@ -698,10 +751,12 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal return { orderlines: orderlines, paymentlines: paymentlines, - total_with_tax: this.getTotal(), + subtotal: this.getSubtotal(), + total_with_tax: this.getTotalTaxIncluded(), total_without_tax: this.getTotalTaxExcluded(), total_tax: this.getTax(), total_paid: this.getPaidTotal(), + total_discount: this.getDiscountTotal(), change: this.getChange(), name : this.getName(), client: client ? client.name : null , @@ -743,7 +798,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal return { name: this.getName(), amount_paid: this.getPaidTotal(), - amount_total: this.getTotal(), + amount_total: this.getTotalTaxIncluded(), amount_tax: this.getTax(), amount_return: this.getChange(), lines: orderLines, @@ -800,20 +855,19 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal buffer: (this.get('buffer')) + newChar }); } - this.updateTarget(); + this.trigger('set_value',this.get('buffer')); }, deleteLastChar: function() { - var tempNewBuffer = this.get('buffer').slice(0, -1); - - if(!tempNewBuffer){ - this.set({ buffer: "0" }); - this.killTarget(); - }else{ - if (isNaN(tempNewBuffer)) { - tempNewBuffer = "0"; + if(this.get('buffer') === ""){ + if(this.get('mode') === 'quantity'){ + this.trigger('set_value','remove'); + }else{ + this.trigger('set_value',this.get('buffer')); } - this.set({ buffer: tempNewBuffer }); - this.updateTarget(); + }else{ + var newBuffer = this.get('buffer').slice(0,-1) || ""; + this.set({ buffer: newBuffer }); + this.trigger('set_value',this.get('buffer')); } }, switchSign: function() { @@ -822,7 +876,7 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal this.set({ buffer: oldBuffer[0] === '-' ? oldBuffer.substr(1) : "-" + oldBuffer }); - this.updateTarget(); + this.trigger('set_value',this.get('buffer')); }, changeMode: function(newMode) { this.set({ @@ -836,15 +890,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal mode: "quantity" }); }, - updateTarget: function() { - var bufferContent, params; - bufferContent = this.get('buffer'); - if (bufferContent && !isNaN(bufferContent)) { - this.trigger('set_value', parseFloat(bufferContent)); - } - }, - killTarget: function(){ - this.trigger('set_value',Number.NaN); + resetValue: function(){ + this.set({buffer:'0'}); }, }); } diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index f8e3382c242..eca4a3c5915 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -368,7 +368,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa module.ChooseReceiptPopupWidget = module.PopUpWidget.extend({ template:'ChooseReceiptPopupWidget', show: function(){ - console.log('show'); this._super(); this.renderElement(); var self = this; @@ -603,7 +602,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa // initiates the connection to the payment terminal and starts the update requests this.start = function(){ var def = new $.Deferred(); - console.log("START"); self.pos.proxy.payment_request(self.pos.get('selectedOrder').getDueLeft()) .done(function(ack){ if(ack === 'ok'){ @@ -613,7 +611,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }else{ console.error('unknown payment request return value:',ack); } - console.log("START_END"); def.resolve(); }); return def; @@ -621,10 +618,8 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa // gets updated status from the payment terminal and performs the appropriate consequences this.update = function(){ - console.log("UPDATE"); var def = new $.Deferred(); if(self.canceled){ - console.log("UPDATE_END"); return def.resolve(); } self.pos.proxy.payment_status() @@ -656,7 +651,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }else{ console.error('unknown status value:',status.status); } - console.log("UPDATE_END"); def.resolve(); }); return def; @@ -664,14 +658,12 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa // cancels a payment. this.cancel = function(){ - console.log("CANCEL"); if(!self.paid && !self.canceled){ self.canceled = true; self.pos.proxy.payment_cancel(); self.pos_widget.screen_selector.set_current_screen(self.previous_screen); self.queue.clear(); } - console.log("CANCEL_END"); return (new $.Deferred()).resolve(); } @@ -865,6 +857,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.bindPaymentLineEvents(); this.bind_orderline_events(); this.paymentlinewidgets = []; + this.focusedLine = null; }, show: function(){ this._super(); @@ -894,6 +887,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }); this.updatePaymentSummary(); + this.line_refocus(); }, close: function(){ this._super(); @@ -931,17 +925,30 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa 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(); + } + }, addPaymentLine: function(newPaymentLine) { var self = this; - var l = new module.PaymentlineWidget(null, { - payment_line: newPaymentLine + 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); - this.$('.paymentline-amount input:last').focus(); + if(this.numpadState){ + this.numpadState.resetValue(); + } + this.line_refocus(l); }, renderElement: function() { this._super(); @@ -958,25 +965,26 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa }, deleteLine: function(lineWidget) { this.currentPaymentLines.remove([lineWidget.payment_line]); + lineWidget.destroy(); }, updatePaymentSummary: function() { var currentOrder = this.pos.get('selectedOrder'); var paidTotal = currentOrder.getPaidTotal(); - var dueTotal = currentOrder.getTotal(); + var dueTotal = currentOrder.getTotalTaxIncluded(); var remaining = dueTotal > paidTotal ? dueTotal - paidTotal : 0; var change = paidTotal > dueTotal ? paidTotal - dueTotal : 0; - this.$('#payment-due-total').html(dueTotal.toFixed(2)); - this.$('#payment-paid-total').html(paidTotal.toFixed(2)); - this.$('#payment-remaining').html(remaining.toFixed(2)); - this.$('#payment-change').html(change.toFixed(2)); - if((currentOrder.selected_orderline == undefined)) - remaining = 1 + 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', remaining > 0); } - this.$('.paymentline-amount input:last').focus(); }, set_numpad_state: function(numpadState) { if (this.numpadState) { @@ -998,5 +1006,4 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.currentPaymentLines.last().set_amount(val); }, }); - } diff --git a/addons/point_of_sale/static/src/js/widget_base.js b/addons/point_of_sale/static/src/js/widget_base.js index 0aa0a44e7e7..124be4e9f82 100644 --- a/addons/point_of_sale/static/src/js/widget_base.js +++ b/addons/point_of_sale/static/src/js/widget_base.js @@ -22,14 +22,20 @@ function openerp_pos_basewidget(instance, module){ //module is instance.point_of if(this.pos && this.pos.get('currency')){ this.currency = this.pos.get('currency'); }else{ - this.currency = {symbol: '$', position: 'after'}; + this.currency = {symbol: '$', position: 'after', rounding: 0.01}; } + var decimals = Math.max(0,Math.ceil(Math.log(1.0 / this.currency.rounding) / Math.log(10))); + this.format_currency = function(amount){ + if(typeof amount === 'number'){ + amount = Math.round(amount*100)/100; + amount = amount.toFixed(decimals); + } if(this.currency.position === 'after'){ - return Math.round(amount*100)/100 + ' ' + this.currency.symbol; + return amount + ' ' + this.currency.symbol; }else{ - return this.currency.symbol + ' ' + Math.round(amount*100)/100; + return this.currency.symbol + ' ' + amount; } } diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js index 39ac2529a76..874c387ea23 100644 --- a/addons/point_of_sale/static/src/js/widgets.js +++ b/addons/point_of_sale/static/src/js/widgets.js @@ -186,7 +186,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }else if( mode === 'discount'){ order.getSelectedLine().set_discount(val); }else if( mode === 'price'){ - order.getSelectedLine().set_price(val); + order.getSelectedLine().set_unit_price(val); } } else { this.pos.get('selectedOrder').destroy(); @@ -269,8 +269,10 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }, update_summary: function(){ var order = this.pos.get('selectedOrder'); - var total = order ? order.getTotal() : 0; - this.$('.summary .value.total').html(this.format_currency(total)); + var total = order ? order.getTotalTaxIncluded() : 0; + var taxes = order ? total - order.getTotalTaxExcluded() : 0; + this.$('.summary .total > .value').html(this.format_currency(total)); + this.$('.summary .total .subentry .value').html(this.format_currency(taxes)); }, set_display_mode: function(mode){ if(this.display_mode !== mode){ @@ -311,24 +313,34 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa }, changeAmount: function(event) { var newAmount = event.currentTarget.value; - if (newAmount && !isNaN(newAmount)) { - this.amount = parseFloat(newAmount); - this.payment_line.set_amount(this.amount); + var amount = parseFloat(newAmount); + if(!isNaN(amount)){ + this.amount = amount; + this.payment_line.set_amount(amount); } }, changedAmount: function() { - if (this.amount !== this.payment_line.get_amount()) + 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').keyup(_.bind(this.changeAmount, this)); + this.$('input').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(); + this.$('input')[0].value = val; + this.$('input')[0].select(); + }, }); module.OrderButtonWidget = module.PosBaseWidget.extend({ @@ -606,20 +618,15 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa if(this.scrollbar){ this.scrollbar.destroy(); } - - this.pos.get('products') - .chain() - .map(function(product) { - var product = new module.ProductWidget(self, { - model: product, - weight: self.weight, - click_product_action: self.click_product_action, - }) - self.productwidgets.push(product); - return product; - }) - .invoke('appendTo', this.$('.product-list')); - + var products = this.pos.get('products').models || []; + for(var i = 0, len = products.length; i < len; i++){ + var product = new module.ProductWidget(self, { + model: products[i], + click_product_action: this.click_product_action, + }); + this.productwidgets.push(product); + product.appendTo(this.$('.product-list')); + } this.scrollbar = new module.ScrollbarWidget(this,{ target_widget: this, target_selector: '.product-list-scroller', diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index 41a061e78b4..3da76ec12d8 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -48,11 +48,17 @@ -
- -
-
-
+ +
+ +
+
+
+ +
+
+
+
@@ -214,11 +220,7 @@ Total: - - - - - +
@@ -227,31 +229,19 @@ Paid: - - - - - +
Remaining: - - - - - +
Change: - - - - - +
@@ -431,9 +421,13 @@
- - Total: 0.00 € - +
+
+ Total: 0.00 € +
Taxes: 0.00€
+
+
+
@@ -500,26 +494,26 @@ - +