From befafc71d54b9a2ac0226f97520da5b918b4e465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Mon, 19 Mar 2012 12:20:15 +0100 Subject: [PATCH 001/322] [imp] add required jquery plugin bzr revid: rlo@openerp.com-20120319112015-788gds4aioshyvco --- .../src/js/jquery.barcodelistener-1.1-min.js | 1 + .../src/js/jquery.barcodelistener-1.1.js | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1-min.js create mode 100644 addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1.js diff --git a/addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1-min.js b/addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1-min.js new file mode 100644 index 00000000000..f3b7c205dbf --- /dev/null +++ b/addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1-min.js @@ -0,0 +1 @@ +(function(a){jQuery.fn.BarcodeListener=function(b,c){char0=new Array("","32");char1=new Array("~","732");settings=new Array(char0,char1);if(b){jQuery.extend(settings,b)}a("body").append('
');a(document).keypress(function(d){if(d.which==settings[0][1]){if(settings.length-1>0){wlBUJTIw=1;xaWi4Y4y=true;while((wlBUJTIw"); + + // intercetta barcode reader con sequenza di caratteri ~ + $(document).keypress(function(e) { + if (e.which == settings[0][1]) { + if(settings.length-1>0) { + wlBUJTIw = 1; + xaWi4Y4y = true; + while ((wlBUJTIw < settings.length) && (xaWi4Y4y == true)) { + $(document).keypress(function(e) { + if (e.which == settings[wlBUJTIw][1]) { + xaWi4Y4y = true; + } else { + xaWi4Y4y = false; + } + }); + wlBUJTIw++; + } + if (xaWi4Y4y == true) { + $("#L3ZitQdL").val("").focus(); + } + } else { + $("#L3ZitQdL").val("").focus(); + } + + // event propagation + e.cancelBubble = true; + e.returnValue = false; + + if (e.stopPropagation) { + e.stopPropagation(); + e.preventDefault(); + } + + } + }); + + // intercetta invio del form + $("#29LLRUZk").submit(function() { + code = $("#L3ZitQdL").val(); + for (i=0; i Date: Tue, 20 Mar 2012 09:47:05 +0100 Subject: [PATCH 002/322] [fix] move jquery.barcodelistener bzr revid: rlo@openerp.com-20120320084705-2s7lewxb8x2hkg0z --- addons/point_of_sale/__openerp__.py | 2 +- .../src/js/jquery.barcodelistener-1.1-min.js | 1 - .../src/js/jquery.barcodelistener-1.1.js | 79 ------------------- addons/point_of_sale/static/src/js/pos.js | 9 +++ 4 files changed, 10 insertions(+), 81 deletions(-) delete mode 100644 addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1-min.js delete mode 100644 addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1.js diff --git a/addons/point_of_sale/__openerp__.py b/addons/point_of_sale/__openerp__.py index 911ccf24bb5..43376663170 100644 --- a/addons/point_of_sale/__openerp__.py +++ b/addons/point_of_sale/__openerp__.py @@ -82,7 +82,7 @@ Main features : 'application': True, 'certificate' : '001156338024966477869', # Web client - 'js': ['static/lib/backbone/backbone-0.5.3.js', 'static/src/js/pos.js'], + 'js': ['static/lib/backbone/backbone-0.5.3.js', 'static/src/js/pos.js', 'static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js'], 'css': ['static/src/css/pos.css'], 'qweb': ['static/src/xml/pos.xml'], } diff --git a/addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1-min.js b/addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1-min.js deleted file mode 100644 index f3b7c205dbf..00000000000 --- a/addons/point_of_sale/static/src/js/jquery.barcodelistener-1.1-min.js +++ /dev/null @@ -1 +0,0 @@ -(function(a){jQuery.fn.BarcodeListener=function(b,c){char0=new Array("","32");char1=new Array("~","732");settings=new Array(char0,char1);if(b){jQuery.extend(settings,b)}a("body").append('
');a(document).keypress(function(d){if(d.which==settings[0][1]){if(settings.length-1>0){wlBUJTIw=1;xaWi4Y4y=true;while((wlBUJTIw"); - - // intercetta barcode reader con sequenza di caratteri ~ - $(document).keypress(function(e) { - if (e.which == settings[0][1]) { - if(settings.length-1>0) { - wlBUJTIw = 1; - xaWi4Y4y = true; - while ((wlBUJTIw < settings.length) && (xaWi4Y4y == true)) { - $(document).keypress(function(e) { - if (e.which == settings[wlBUJTIw][1]) { - xaWi4Y4y = true; - } else { - xaWi4Y4y = false; - } - }); - wlBUJTIw++; - } - if (xaWi4Y4y == true) { - $("#L3ZitQdL").val("").focus(); - } - } else { - $("#L3ZitQdL").val("").focus(); - } - - // event propagation - e.cancelBubble = true; - e.returnValue = false; - - if (e.stopPropagation) { - e.stopPropagation(); - e.preventDefault(); - } - - } - }); - - // intercetta invio del form - $("#29LLRUZk").submit(function() { - code = $("#L3ZitQdL").val(); - for (i=0; i Date: Tue, 20 Mar 2012 09:47:29 +0100 Subject: [PATCH 003/322] [fix] move jquery.barcodelistener bzr revid: rlo@openerp.com-20120320084729-x2zo7n01jamsfkt5 --- .../jquery.barcodelistener-1.1-min.js | 1 + .../jquery.barcodelistener-1.1.js | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js create mode 100644 addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1.js diff --git a/addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js b/addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js new file mode 100644 index 00000000000..f3b7c205dbf --- /dev/null +++ b/addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js @@ -0,0 +1 @@ +(function(a){jQuery.fn.BarcodeListener=function(b,c){char0=new Array("","32");char1=new Array("~","732");settings=new Array(char0,char1);if(b){jQuery.extend(settings,b)}a("body").append('
');a(document).keypress(function(d){if(d.which==settings[0][1]){if(settings.length-1>0){wlBUJTIw=1;xaWi4Y4y=true;while((wlBUJTIw"); + + // intercetta barcode reader con sequenza di caratteri ~ + $(document).keypress(function(e) { + if (e.which == settings[0][1]) { + if(settings.length-1>0) { + wlBUJTIw = 1; + xaWi4Y4y = true; + while ((wlBUJTIw < settings.length) && (xaWi4Y4y == true)) { + $(document).keypress(function(e) { + if (e.which == settings[wlBUJTIw][1]) { + xaWi4Y4y = true; + } else { + xaWi4Y4y = false; + } + }); + wlBUJTIw++; + } + if (xaWi4Y4y == true) { + $("#L3ZitQdL").val("").focus(); + } + } else { + $("#L3ZitQdL").val("").focus(); + } + + // event propagation + e.cancelBubble = true; + e.returnValue = false; + + if (e.stopPropagation) { + e.stopPropagation(); + e.preventDefault(); + } + + } + }); + + // intercetta invio del form + $("#29LLRUZk").submit(function() { + code = $("#L3ZitQdL").val(); + for (i=0; i Date: Tue, 20 Mar 2012 09:51:11 +0100 Subject: [PATCH 004/322] [fix] move jquery.barcodelistener bzr revid: rlo@openerp.com-20120320085111-s9i0l92u9vkushrh --- addons/point_of_sale/static/src/js/pos.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index e64f0232d62..e90b524960f 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1328,11 +1328,10 @@ openerp.point_of_sale = function(db) { pos.app = new App(self.$element); - $.getScript('/point_of_sale/static/src/js/jquery.barcodelistener-1.1-min.js'); char0 = new Array("§", "32"); char1 = new Array("˜", "732"); characters = new Array(char0, char1); - new jQuery.fn.BarcodeListener(characters, function(code) {console.log('<<<<<<<<<<<<<<<');}); + db.webclient.BarcodeListener(characters, function(code) {console.log('<<<<<<<<<<<<<<<');}); db.webclient.set_content_full_screen(true); From 0f0ecfd90f341deb47b1f06d21821089db5b76e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Tue, 20 Mar 2012 16:46:20 +0100 Subject: [PATCH 005/322] [imp] bzr revid: rlo@openerp.com-20120320154620-c5f5o2og5dmai7je --- .../jquery.barcodelistener-1.1-min.js | 1 - .../jquery.barcodelistener-1.1.js | 79 ------------------- addons/point_of_sale/static/src/js/pos.js | 34 ++++++-- 3 files changed, 28 insertions(+), 86 deletions(-) delete mode 100644 addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js delete mode 100644 addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1.js diff --git a/addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js b/addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js deleted file mode 100644 index f3b7c205dbf..00000000000 --- a/addons/point_of_sale/static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js +++ /dev/null @@ -1 +0,0 @@ -(function(a){jQuery.fn.BarcodeListener=function(b,c){char0=new Array("","32");char1=new Array("~","732");settings=new Array(char0,char1);if(b){jQuery.extend(settings,b)}a("body").append('
');a(document).keypress(function(d){if(d.which==settings[0][1]){if(settings.length-1>0){wlBUJTIw=1;xaWi4Y4y=true;while((wlBUJTIw"); - - // intercetta barcode reader con sequenza di caratteri ~ - $(document).keypress(function(e) { - if (e.which == settings[0][1]) { - if(settings.length-1>0) { - wlBUJTIw = 1; - xaWi4Y4y = true; - while ((wlBUJTIw < settings.length) && (xaWi4Y4y == true)) { - $(document).keypress(function(e) { - if (e.which == settings[wlBUJTIw][1]) { - xaWi4Y4y = true; - } else { - xaWi4Y4y = false; - } - }); - wlBUJTIw++; - } - if (xaWi4Y4y == true) { - $("#L3ZitQdL").val("").focus(); - } - } else { - $("#L3ZitQdL").val("").focus(); - } - - // event propagation - e.cancelBubble = true; - e.returnValue = false; - - if (e.stopPropagation) { - e.stopPropagation(); - e.preventDefault(); - } - - } - }); - - // intercetta invio del form - $("#29LLRUZk").submit(function() { - code = $("#L3ZitQdL").val(); - for (i=0; i= 48 && e.keyCode <= 57) { + // a number + if (codeNumbers.length==0) { + codeNumbers.timeStamp = new Date().getTime() + } else { + if (codeNumbers.lastTimeStamp + 30 < new Date().getTime()) { + // not a barcode reader + console.log(e) + codeNumbers = [] + codeNumbers.timeStamp = new Date().getTime() + } + } + codeNumbers.push(e.keyCode - 48) + codeNumbers.lastTimeStamp = new Date().getTime() + if (codeNumbers.length == 13) { + // a barcode reader + console.log('barcode: ' + codeNumbers.join()) + codeNumbers = [] + } + } else { + // NaN + codeNumbers = [] + } + }) $('.searchbox input').keyup(function() { var m, s; s = $(this).val().toLowerCase(); @@ -1323,15 +1351,9 @@ openerp.point_of_sale = function(db) { this.$element.find("#loggedas button").click(function() { self.try_close(); }); - // TODO bind barcode reader event - console.log('--------------------'); pos.app = new App(self.$element); - char0 = new Array("§", "32"); - char1 = new Array("˜", "732"); - characters = new Array(char0, char1); - db.webclient.BarcodeListener(characters, function(code) {console.log('<<<<<<<<<<<<<<<');}); db.webclient.set_content_full_screen(true); From 2f0d87381b85b2fe3f21c68450a8375c7507be60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Wed, 21 Mar 2012 10:43:11 +0100 Subject: [PATCH 006/322] [imp] barcode reader events are successfully delegated bzr revid: rlo@openerp.com-20120321094311-bb12qnp46ch29pt1 --- addons/point_of_sale/static/src/js/pos.js | 50 +++++++++++------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 83fb7b31930..0ee945a2130 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1259,34 +1259,34 @@ openerp.point_of_sale = function(db) { }); (this.shop.get('products')).reset(products); var self = this; - // bind barcode reader event - codeNumbers = [] - $('.openerp').keypress(function (e){ - console.log('keyup!!!') - if (e.keyCode >= 48 && e.keyCode <= 57) { - // a number - if (codeNumbers.length==0) { - codeNumbers.timeStamp = new Date().getTime() - } else { - if (codeNumbers.lastTimeStamp + 30 < new Date().getTime()) { - // not a barcode reader - console.log(e) - codeNumbers = [] - codeNumbers.timeStamp = new Date().getTime() - } - } - codeNumbers.push(e.keyCode - 48) - codeNumbers.lastTimeStamp = new Date().getTime() - if (codeNumbers.length == 13) { - // a barcode reader - console.log('barcode: ' + codeNumbers.join()) - codeNumbers = [] - } + // bind barcode reader event + codeNumbers = [] + $('body').delegate('','keyup', function (e){ + console.log('keyup!!!') + if (e.keyCode >= 48 && e.keyCode <= 57) { + // a number + if (codeNumbers.length==0) { + codeNumbers.timeStamp = new Date().getTime() } else { - // NaN + if (codeNumbers.lastTimeStamp + 30 < new Date().getTime()) { + // not a barcode reader + console.log(e) + codeNumbers = [] + codeNumbers.timeStamp = new Date().getTime() + } + } + codeNumbers.push(e.keyCode - 48) + codeNumbers.lastTimeStamp = new Date().getTime() + if (codeNumbers.length == 13) { + // a barcode reader + console.log('barcode: ' + codeNumbers.join()) codeNumbers = [] } - }) + } else { + // NaN + codeNumbers = [] + } + }) $('.searchbox input').keyup(function() { var m, s; s = $(this).val().toLowerCase(); From 1677026b0bd5b605db675b06adebe7f37f5fb758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Wed, 21 Mar 2012 11:04:14 +0100 Subject: [PATCH 007/322] [imp] unbind barcode reader events when closing point of sale bzr revid: rlo@openerp.com-20120321100414-h5qsu1qumbil8uks --- addons/point_of_sale/static/src/js/pos.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 0ee945a2130..90aa47f4be6 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1403,6 +1403,9 @@ openerp.point_of_sale = function(db) { }, this)); }, close: function() { + // remove barcode reader event listener + $('body').undelegate('', 'keyup') + return new db.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_pos_close_statement']], ['res_id']).pipe( _.bind(function(res) { return this.rpc('/web/action/load', {'action_id': res[0]['res_id']}).pipe(_.bind(function(result) { From 8cab1f54c21cb808a7c6afb0d4f1c63ce2c35fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Wed, 21 Mar 2012 14:33:29 +0100 Subject: [PATCH 008/322] [imp] barcode tooltip bzr revid: rlo@openerp.com-20120321133329-h447mmid36nekbak --- addons/product/product.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/product/product.py b/addons/product/product.py index 0d5fa31ac11..8408909b57e 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -517,7 +517,7 @@ class product_product(osv.osv): 'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the product without removing it."), 'variants': fields.char('Variants', size=64), 'product_tmpl_id': fields.many2one('product.template', 'Product Template', required=True, ondelete="cascade"), - 'ean13': fields.char('EAN13', size=13), + 'ean13': fields.char('EAN13', size=13, help='Barcode'), 'packaging' : fields.one2many('product.packaging', 'product_id', 'Logistical Units', help="Gives the different ways to package the same product. This has no impact on the picking order and is mainly used if you use the EDI module."), 'price_extra': fields.float('Variant Price Extra', digits_compute=dp.get_precision('Sale Price')), 'price_margin': fields.float('Variant Price Margin', digits_compute=dp.get_precision('Sale Price')), From 3b81d145b4256dca9fe5b793d7431112cf857b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 22 Mar 2012 10:25:58 +0100 Subject: [PATCH 009/322] [imp] get the barcode of each product during the init method of the point of sale. Thus, the product can be detected using its barcode. Insertion into the current order still pending bzr revid: rlo@openerp.com-20120322092558-sw7pll78qim6v51q --- addons/point_of_sale/static/src/js/pos.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 90aa47f4be6..4a5a3952603 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -85,7 +85,7 @@ openerp.point_of_sale = function(db) { }, this)); }, this)); $.when(this.fetch('pos.category', ['name', 'parent_id', 'child_id']), - this.fetch('product.product', ['name', 'list_price', 'pos_categ_id', 'taxes_id', 'product_image_small'], [['pos_categ_id', '!=', 'false']]), + this.fetch('product.product', ['name', 'list_price', 'pos_categ_id', 'taxes_id', 'product_image_small', 'ean13'], [['pos_categ_id', '!=', 'false']]), this.fetch('account.bank.statement', ['account_id', 'currency', 'journal_id', 'state', 'name'], [['state', '=', 'open'], ['user_id', '=', this.session.uid]]), this.fetch('account.journal', ['auto_cash', 'check_dtls', 'currency', 'name', 'type']), @@ -1280,6 +1280,11 @@ openerp.point_of_sale = function(db) { if (codeNumbers.length == 13) { // a barcode reader console.log('barcode: ' + codeNumbers.join()) + selectedOrder = self.shop.get('selectedOrder') + products = pos.store.get('product.product') + scannedProduct = _.detect(products, function(el){return el.ean13 === codeNumbers.join('')}) + //TODO INSERT THE scannedProduct into the selectedOrder + codeNumbers = [] } } else { From 315a75679b534a1ed579cc54707c9ed484b5f5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 22 Mar 2012 11:27:24 +0100 Subject: [PATCH 010/322] [imp] working integration barcode reader - point of sale order bzr revid: rlo@openerp.com-20120322102724-nfakdy4ug5pnm6he --- addons/point_of_sale/static/src/js/pos.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 4a5a3952603..6549a4f6678 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1262,7 +1262,6 @@ openerp.point_of_sale = function(db) { // bind barcode reader event codeNumbers = [] $('body').delegate('','keyup', function (e){ - console.log('keyup!!!') if (e.keyCode >= 48 && e.keyCode <= 57) { // a number if (codeNumbers.length==0) { @@ -1281,9 +1280,9 @@ openerp.point_of_sale = function(db) { // a barcode reader console.log('barcode: ' + codeNumbers.join()) selectedOrder = self.shop.get('selectedOrder') - products = pos.store.get('product.product') - scannedProduct = _.detect(products, function(el){return el.ean13 === codeNumbers.join('')}) - //TODO INSERT THE scannedProduct into the selectedOrder + productsCollection = self.shop.get('products') + scannedProductModel = _.detect(productsCollection.models, function(pc) { return pc.attributes.ean13 === codeNumbers.join('')}) + selectedOrder.addProduct(scannedProductModel) codeNumbers = [] } From 9e5f88c24351bd275b45e7b48fa1ef9c5551a76e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 22 Mar 2012 11:57:20 +0100 Subject: [PATCH 011/322] [imp] add demo data bzr revid: rlo@openerp.com-20120322105720-o9ygtir59x3lokv7 --- addons/point_of_sale/point_of_sale_demo.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/point_of_sale/point_of_sale_demo.xml b/addons/point_of_sale/point_of_sale_demo.xml index 1e4b2ec7c35..3638b0faa72 100644 --- a/addons/point_of_sale/point_of_sale_demo.xml +++ b/addons/point_of_sale/point_of_sale_demo.xml @@ -672,6 +672,7 @@ 0.83 Belle-Vue Kriek 25cl + 5410228193449 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 @@ -679,6 +680,7 @@ 1.00 Leffe Brune 33cl + 5410228142164 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 From cc3e6d9b172564ecf3fa8eeb7c1c5a202c7dcd3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 22 Mar 2012 13:20:29 +0100 Subject: [PATCH 012/322] [fix] remove unused js import bzr revid: rlo@openerp.com-20120322122029-5sy4luezyaf8c57m --- addons/point_of_sale/__openerp__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/point_of_sale/__openerp__.py b/addons/point_of_sale/__openerp__.py index 43376663170..911ccf24bb5 100644 --- a/addons/point_of_sale/__openerp__.py +++ b/addons/point_of_sale/__openerp__.py @@ -82,7 +82,7 @@ Main features : 'application': True, 'certificate' : '001156338024966477869', # Web client - 'js': ['static/lib/backbone/backbone-0.5.3.js', 'static/src/js/pos.js', 'static/lib/jquery-barcodelistener/jquery.barcodelistener-1.1-min.js'], + 'js': ['static/lib/backbone/backbone-0.5.3.js', 'static/src/js/pos.js'], 'css': ['static/src/css/pos.css'], 'qweb': ['static/src/xml/pos.xml'], } From 36e5619bf3e63cface457ecd265464fe8ffcbf5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 22 Mar 2012 14:05:19 +0100 Subject: [PATCH 013/322] [fix] clean debug output and improve digits detection bzr revid: rlo@openerp.com-20120322130519-0zxr8wif2sl3nr47 --- addons/point_of_sale/static/src/js/pos.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 6549a4f6678..b3d737dfb87 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1262,14 +1262,13 @@ openerp.point_of_sale = function(db) { // bind barcode reader event codeNumbers = [] $('body').delegate('','keyup', function (e){ - if (e.keyCode >= 48 && e.keyCode <= 57) { + if (!isNaN(Number(String.fromCharCode(e.keyCode)))) { // a number if (codeNumbers.length==0) { codeNumbers.timeStamp = new Date().getTime() } else { if (codeNumbers.lastTimeStamp + 30 < new Date().getTime()) { // not a barcode reader - console.log(e) codeNumbers = [] codeNumbers.timeStamp = new Date().getTime() } From 337fe0c8eef34ac72ee6a90b71f1e934807662e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 22 Mar 2012 15:08:14 +0100 Subject: [PATCH 014/322] [fix] bzr revid: rlo@openerp.com-20120322140814-mvo7e1qh4svom3tw --- addons/point_of_sale/static/src/js/pos.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index b3d737dfb87..9c92e5233d0 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1356,8 +1356,6 @@ openerp.point_of_sale = function(db) { }); pos.app = new App(self.$element); - - db.webclient.set_content_full_screen(true); if (pos.store.get('account.bank.statement').length === 0) From 7fc89ff1d8b30117284cfb0d829b39a02df06d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 23 Mar 2012 15:31:36 +0100 Subject: [PATCH 015/322] =?UTF-8?q?[imp]=20modified=20code=20after=20St?= =?UTF-8?q?=C3=A9phane=20instructions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bzr revid: rlo@openerp.com-20120323143136-0qhzjnttnxei7xpi --- addons/point_of_sale/static/src/js/pos.js | 33 +++++++++++++++++++---- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 9c92e5233d0..53b7b01037e 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1260,7 +1260,7 @@ openerp.point_of_sale = function(db) { (this.shop.get('products')).reset(products); var self = this; // bind barcode reader event - codeNumbers = [] + var codeNumbers = [] $('body').delegate('','keyup', function (e){ if (!isNaN(Number(String.fromCharCode(e.keyCode)))) { // a number @@ -1277,10 +1277,33 @@ openerp.point_of_sale = function(db) { codeNumbers.lastTimeStamp = new Date().getTime() if (codeNumbers.length == 13) { // a barcode reader - console.log('barcode: ' + codeNumbers.join()) - selectedOrder = self.shop.get('selectedOrder') - productsCollection = self.shop.get('products') - scannedProductModel = _.detect(productsCollection.models, function(pc) { return pc.attributes.ean13 === codeNumbers.join('')}) + var barcode = codeNumbers.join('') + console.log('barcode: ' + barcode) + var selectedOrder = self.shop.get('selectedOrder') + var productsCollection = self.shop.get('products') + if (barcode.substring(0,2) in ['02', '22', '24', '26', '28']) { + // product with a specific price - specified into the barcode + barcode = barcode.substring(2,5) + // TODO conversion euro - old local currencies + price = Number(barcode.substring(7,5))/100 + weight = '' + } else if (barcode.substring(0,2) in ['21','23','27','29','25']) { + // product sold by weight + barcode = barcode.substring(2,5) + weight = Number(barcode.substring(7,5))/1000 + price = '' + } else { + // product unit + weight = '' + price = '' + } + var scannedProductModel = _.detect(productsCollection.models, function(pc) { return pc.attributes.ean13 === barcode}) + if (weight === '' and price !== '') { + scannedProductModel.price = price + } else if (weight !== '' and price === '') { + // TODO sell by weight: how to calculate the price? + scannedProductModel.price *= weight + } selectedOrder.addProduct(scannedProductModel) codeNumbers = [] From e398d3aa1207cb58f6d4ecede27747cfe62ba1d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Mon, 26 Mar 2012 11:36:05 +0200 Subject: [PATCH 016/322] [fix] correct js syntax bzr revid: rlo@openerp.com-20120326093605-72k4ewcnw4xzmnid --- addons/point_of_sale/static/src/js/pos.js | 52 +++++++++++------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 53b7b01037e..84c4d695829 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1260,57 +1260,57 @@ openerp.point_of_sale = function(db) { (this.shop.get('products')).reset(products); var self = this; // bind barcode reader event - var codeNumbers = [] + var codeNumbers = []; $('body').delegate('','keyup', function (e){ if (!isNaN(Number(String.fromCharCode(e.keyCode)))) { // a number if (codeNumbers.length==0) { - codeNumbers.timeStamp = new Date().getTime() + codeNumbers.timeStamp = new Date().getTime(); } else { if (codeNumbers.lastTimeStamp + 30 < new Date().getTime()) { // not a barcode reader - codeNumbers = [] - codeNumbers.timeStamp = new Date().getTime() + codeNumbers = []; + codeNumbers.timeStamp = new Date().getTime(); } } - codeNumbers.push(e.keyCode - 48) - codeNumbers.lastTimeStamp = new Date().getTime() + codeNumbers.push(e.keyCode - 48); + codeNumbers.lastTimeStamp = new Date().getTime(); if (codeNumbers.length == 13) { // a barcode reader - var barcode = codeNumbers.join('') - console.log('barcode: ' + barcode) - var selectedOrder = self.shop.get('selectedOrder') - var productsCollection = self.shop.get('products') + var barcode = codeNumbers.join(''); + console.log('barcode: ' + barcode); + var selectedOrder = self.shop.get('selectedOrder'); + var productsCollection = self.shop.get('products'); if (barcode.substring(0,2) in ['02', '22', '24', '26', '28']) { // product with a specific price - specified into the barcode - barcode = barcode.substring(2,5) + barcode = barcode.substring(2,5); // TODO conversion euro - old local currencies - price = Number(barcode.substring(7,5))/100 - weight = '' + price = Number(barcode.substring(7,5))/100; + weight = ''; } else if (barcode.substring(0,2) in ['21','23','27','29','25']) { // product sold by weight - barcode = barcode.substring(2,5) - weight = Number(barcode.substring(7,5))/1000 - price = '' + barcode = barcode.substring(2,5); + weight = Number(barcode.substring(7,5))/1000; + price = ''; } else { // product unit - weight = '' - price = '' + weight = ''; + price = ''; } - var scannedProductModel = _.detect(productsCollection.models, function(pc) { return pc.attributes.ean13 === barcode}) - if (weight === '' and price !== '') { - scannedProductModel.price = price - } else if (weight !== '' and price === '') { + var scannedProductModel = _.detect(productsCollection.models, function(pc) { return pc.attributes.ean13 === barcode;}); + if (weight === '' && price !== '') { + scannedProductModel.price = price; + } else if (weight !== '' && price === '') { // TODO sell by weight: how to calculate the price? - scannedProductModel.price *= weight + scannedProductModel.price *= weight; } - selectedOrder.addProduct(scannedProductModel) + selectedOrder.addProduct(scannedProductModel); - codeNumbers = [] + codeNumbers = []; } } else { // NaN - codeNumbers = [] + codeNumbers = []; } }) $('.searchbox input').keyup(function() { From 08e30b83bf5759d7c75848ab8585e22f78f6fdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Mon, 26 Mar 2012 14:27:43 +0200 Subject: [PATCH 017/322] [imp] warning product not recognized bzr revid: rlo@openerp.com-20120326122743-3m6c24j0dnb9c1yq --- addons/point_of_sale/static/src/js/pos.js | 18 +++++++++++++++++- addons/point_of_sale/static/src/xml/pos.xml | 3 +++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 84c4d695829..70de88dd93e 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1298,10 +1298,26 @@ openerp.point_of_sale = function(db) { price = ''; } var scannedProductModel = _.detect(productsCollection.models, function(pc) { return pc.attributes.ean13 === barcode;}); + if (scannedProductModel == undefined) { + // product not recognized, raise warning + $(QWeb.render('pos-scan-warning')).dialog({ + resizable: false, + height:160, + modal: true, + title: "Warning", + buttons: { + "OK": function() { + $( this ).dialog( "close" ); + }, + } + }); + } if (weight === '' && price !== '') { + // product sold by price scannedProductModel.price = price; } else if (weight !== '' && price === '') { - // TODO sell by weight: how to calculate the price? + // product sold by weight + // TODO check how to calculate the price scannedProductModel.price *= weight; } selectedOrder.addProduct(scannedProductModel); diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index d24d16713d8..16192f208c8 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -141,6 +141,9 @@ + +
The product could not be recognized. Please contact an employee.
+
There are pending operations that could not be saved into the database, are you sure you want to exit?
From d849defd2a2cb0aa2827970e88e413fedc98ed01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Mon, 26 Mar 2012 16:39:00 +0200 Subject: [PATCH 018/322] [imp] dialog height bzr revid: rlo@openerp.com-20120326143900-qb6g01z9wsdzuyac --- addons/point_of_sale/static/src/js/pos.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 70de88dd93e..18c6511629f 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1302,7 +1302,7 @@ openerp.point_of_sale = function(db) { // product not recognized, raise warning $(QWeb.render('pos-scan-warning')).dialog({ resizable: false, - height:160, + height:220, modal: true, title: "Warning", buttons: { From e70087c87451593d897d2aa3cf98a65ce538c596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Tue, 27 Mar 2012 08:53:22 +0200 Subject: [PATCH 019/322] [imp] add control digit bzr revid: rlo@openerp.com-20120327065322-a7gegbmtrtjexn41 --- addons/point_of_sale/static/src/js/pos.js | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 18c6511629f..369c7fbc032 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1281,6 +1281,7 @@ openerp.point_of_sale = function(db) { console.log('barcode: ' + barcode); var selectedOrder = self.shop.get('selectedOrder'); var productsCollection = self.shop.get('products'); + var controlDigit = Number(barcode.charAt(12)); if (barcode.substring(0,2) in ['02', '22', '24', '26', '28']) { // product with a specific price - specified into the barcode barcode = barcode.substring(2,5); From b6fa154cbc153aef1db14cc44c5ecc15443a7b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Tue, 27 Mar 2012 10:25:45 +0200 Subject: [PATCH 020/322] [imp] add control digit bzr revid: rlo@openerp.com-20120327082545-y3fzc2rysefx0k2q --- addons/point_of_sale/static/src/js/pos.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 369c7fbc032..ecaecdf91d5 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1281,7 +1281,28 @@ openerp.point_of_sale = function(db) { console.log('barcode: ' + barcode); var selectedOrder = self.shop.get('selectedOrder'); var productsCollection = self.shop.get('products'); - var controlDigit = Number(barcode.charAt(12)); + // EAN digit control calculation, based on http://es.wikipedia.org/wiki/EAN#Javascript , licensed under Creative Commons Attribution-Share-Alike License 3.0 + var checksum = 0; + ean13Reversed = codeNumbers.reverse(); + for (var pos in ean13Reversed) { + checksum += ean13Reversed[pos] * (3 - 2 * (pos % 2)); + } + checksum = (10 - (checksum % 10)) % 10; + // End of EAN digit control calculation + if (Number(barcode.charAt(12)) !== checksum) { + // barcode read error, raise warning + $(QWeb.render('pos-scan-warning')).dialog({ + resizable: false, + height:220, + modal: true, + title: "Warning", + buttons: { + "OK": function() { + $( this ).dialog( "close" ); + }, + } + }); + } if (barcode.substring(0,2) in ['02', '22', '24', '26', '28']) { // product with a specific price - specified into the barcode barcode = barcode.substring(2,5); From e5150890236f42e48e4055dcba8aef39e093c8a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Tue, 27 Mar 2012 16:14:22 +0200 Subject: [PATCH 021/322] [imp] currency conversion - yet incomplete bzr revid: rlo@openerp.com-20120327141422-9grv8dw70q89ayx5 --- addons/point_of_sale/__openerp__.py | 2 +- addons/point_of_sale/static/src/js/pos.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/addons/point_of_sale/__openerp__.py b/addons/point_of_sale/__openerp__.py index 911ccf24bb5..f39c05c5e7d 100644 --- a/addons/point_of_sale/__openerp__.py +++ b/addons/point_of_sale/__openerp__.py @@ -40,7 +40,7 @@ Main features : """, 'author': 'OpenERP SA', 'images': ['images/cash_registers.jpeg', 'images/pos_analysis.jpeg','images/register_analysis.jpeg','images/sale_order_pos.jpeg','images/product_pos.jpeg'], - 'depends': ['sale'], + 'depends': ['sale','account'], 'init_xml': [], 'update_xml': [ diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index ecaecdf91d5..77b38d9b872 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1249,6 +1249,7 @@ openerp.point_of_sale = function(db) { id = 0; } c = pos.categories[id]; + currency = pos.get('currency'); this.categoryView.ancestors = c.ancestors; this.categoryView.children = c.children; this.categoryView.renderElement(); @@ -1307,6 +1308,7 @@ openerp.point_of_sale = function(db) { // product with a specific price - specified into the barcode barcode = barcode.substring(2,5); // TODO conversion euro - old local currencies + new db.web.Model('res.currency').get_func('_get_conversion_rate')(['FRF', 'EUR']).pipe(function(result){}); price = Number(barcode.substring(7,5))/100; weight = ''; } else if (barcode.substring(0,2) in ['21','23','27','29','25']) { From ce55e113ed3b01506664b9b59b0d9c9999a24ee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Wed, 28 Mar 2012 12:03:37 +0200 Subject: [PATCH 022/322] [imp] control digit check + more demo data bzr revid: rlo@openerp.com-20120328100337-aypdlk8o9revqpm6 --- addons/point_of_sale/point_of_sale_demo.xml | 1 + addons/point_of_sale/static/src/js/pos.js | 40 ++++++++++++++------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/addons/point_of_sale/point_of_sale_demo.xml b/addons/point_of_sale/point_of_sale_demo.xml index 3638b0faa72..95c0192f6c7 100644 --- a/addons/point_of_sale/point_of_sale_demo.xml +++ b/addons/point_of_sale/point_of_sale_demo.xml @@ -687,6 +687,7 @@ 1.00 Leffe Blonde 33cl + 5410228142218 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 diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 77b38d9b872..238366163d9 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1266,31 +1266,46 @@ openerp.point_of_sale = function(db) { if (!isNaN(Number(String.fromCharCode(e.keyCode)))) { // a number if (codeNumbers.length==0) { - codeNumbers.timeStamp = new Date().getTime(); + timeStamp = new Date().getTime(); } else { - if (codeNumbers.lastTimeStamp + 30 < new Date().getTime()) { + if (lastTimeStamp + 30 < new Date().getTime()) { // not a barcode reader codeNumbers = []; - codeNumbers.timeStamp = new Date().getTime(); + timeStamp = new Date().getTime(); } } codeNumbers.push(e.keyCode - 48); - codeNumbers.lastTimeStamp = new Date().getTime(); + lastTimeStamp = new Date().getTime(); if (codeNumbers.length == 13) { // a barcode reader var barcode = codeNumbers.join(''); console.log('barcode: ' + barcode); var selectedOrder = self.shop.get('selectedOrder'); var productsCollection = self.shop.get('products'); - // EAN digit control calculation, based on http://es.wikipedia.org/wiki/EAN#Javascript , licensed under Creative Commons Attribution-Share-Alike License 3.0 - var checksum = 0; - ean13Reversed = codeNumbers.reverse(); - for (var pos in ean13Reversed) { - checksum += ean13Reversed[pos] * (3 - 2 * (pos % 2)); - } - checksum = (10 - (checksum % 10)) % 10; + // EAN digit control calculation + var st1 = codeNumbers; + var st2 = st1.slice(0,12).reverse(); + var countSt3 = 1; + var st3 = 0; + $.each(st2, function() { + if (countSt3%2 === 1) { + st3 += this; + } + countSt3 ++; + }); + st3 *= 3; + var st4 = 0; + var countSt4 = 1; + $.each(st2, function() { + if (countSt4%2 === 0) { + st4 += this; + } + countSt4 ++; + }); + var st5 = st3 + st4; + var dc = (10 - (st5%10)) % 10; // End of EAN digit control calculation - if (Number(barcode.charAt(12)) !== checksum) { + if (Number(barcode.charAt(12)) !== dc) { // barcode read error, raise warning $(QWeb.render('pos-scan-warning')).dialog({ resizable: false, @@ -1332,6 +1347,7 @@ openerp.point_of_sale = function(db) { buttons: { "OK": function() { $( this ).dialog( "close" ); + return; }, } }); From 6178afe4be0a386022e02d22ee099517f3b88f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Wed, 28 Mar 2012 15:46:56 +0200 Subject: [PATCH 023/322] [imp] unit barcode bzr revid: rlo@openerp.com-20120328134656-zxxdpa861q2qk3r5 --- addons/point_of_sale/static/src/js/pos.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 238366163d9..ec6726a42ef 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1254,6 +1254,7 @@ openerp.point_of_sale = function(db) { this.categoryView.children = c.children; this.categoryView.renderElement(); this.categoryView.start(); + allProducts = pos.store.get('product.product'); products = pos.store.get('product.product').filter( function(p) { var _ref; return _ref = p.pos_categ_id[0], _.indexOf(c.subtree, _ref) >= 0; @@ -1279,9 +1280,7 @@ openerp.point_of_sale = function(db) { if (codeNumbers.length == 13) { // a barcode reader var barcode = codeNumbers.join(''); - console.log('barcode: ' + barcode); var selectedOrder = self.shop.get('selectedOrder'); - var productsCollection = self.shop.get('products'); // EAN digit control calculation var st1 = codeNumbers; var st2 = st1.slice(0,12).reverse(); @@ -1315,6 +1314,7 @@ openerp.point_of_sale = function(db) { buttons: { "OK": function() { $( this ).dialog( "close" ); + return; }, } }); @@ -1336,7 +1336,7 @@ openerp.point_of_sale = function(db) { weight = ''; price = ''; } - var scannedProductModel = _.detect(productsCollection.models, function(pc) { return pc.attributes.ean13 === barcode;}); + var scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === barcode;}); if (scannedProductModel == undefined) { // product not recognized, raise warning $(QWeb.render('pos-scan-warning')).dialog({ @@ -1360,7 +1360,7 @@ openerp.point_of_sale = function(db) { // TODO check how to calculate the price scannedProductModel.price *= weight; } - selectedOrder.addProduct(scannedProductModel); + selectedOrder.addProduct(new Product(scannedProductModel)); codeNumbers = []; } @@ -1368,7 +1368,7 @@ openerp.point_of_sale = function(db) { // NaN codeNumbers = []; } - }) + }); $('.searchbox input').keyup(function() { var m, s; s = $(this).val().toLowerCase(); From c67aea4ed7e61eed9fd02835cf0ade4d883e1f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 29 Mar 2012 12:04:27 +0200 Subject: [PATCH 024/322] [imp] improved dc check bzr revid: rlo@openerp.com-20120329100427-r5pk59e5dnne99ou --- addons/point_of_sale/static/src/js/pos.js | 57 +++++++++++++---------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index ec6726a42ef..81ac6cff516 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1260,6 +1260,38 @@ openerp.point_of_sale = function(db) { return _ref = p.pos_categ_id[0], _.indexOf(c.subtree, _ref) >= 0; }); (this.shop.get('products')).reset(products); + var checkEan = function(code) { + // EAN control digit calculation + var st1 = code.slice(); + var st2 = st1.slice(0,st1.length-1).reverse(); + // some EAN13 barcodes have a length of 12, as they start by 0 + while (st2.length < 12) { + st2.push(0); + } + console.log('code: '+code.join(',')); + console.log('st1: '+st1.join(',')); + console.log('st2: '+st2.join(',')); + var countSt3 = 1; + var st3 = 0; + $.each(st2, function() { + if (countSt3%2 === 1) { + st3 += this; + } + countSt3 ++; + }); + st3 *= 3; + var st4 = 0; + var countSt4 = 1; + $.each(st2, function() { + if (countSt4%2 === 0) { + st4 += this; + } + countSt4 ++; + }); + var st5 = st3 + st4; + var cd = (10 - (st5%10)) % 10; + return code[code.length-1] === cd; + } var self = this; // bind barcode reader event var codeNumbers = []; @@ -1281,30 +1313,7 @@ openerp.point_of_sale = function(db) { // a barcode reader var barcode = codeNumbers.join(''); var selectedOrder = self.shop.get('selectedOrder'); - // EAN digit control calculation - var st1 = codeNumbers; - var st2 = st1.slice(0,12).reverse(); - var countSt3 = 1; - var st3 = 0; - $.each(st2, function() { - if (countSt3%2 === 1) { - st3 += this; - } - countSt3 ++; - }); - st3 *= 3; - var st4 = 0; - var countSt4 = 1; - $.each(st2, function() { - if (countSt4%2 === 0) { - st4 += this; - } - countSt4 ++; - }); - var st5 = st3 + st4; - var dc = (10 - (st5%10)) % 10; - // End of EAN digit control calculation - if (Number(barcode.charAt(12)) !== dc) { + if (!checkEan(codeNumbers)) { // barcode read error, raise warning $(QWeb.render('pos-scan-warning')).dialog({ resizable: false, From d9c673d586e58ee56bc29f2d6df8e4101383ba9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 29 Mar 2012 12:24:46 +0200 Subject: [PATCH 025/322] [imp] add method to get exchange rates from the client bzr revid: rlo@openerp.com-20120329102446-wzg853rgzd11f4yg --- addons/account/res_currency.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/account/res_currency.py b/addons/account/res_currency.py index 8c9c6a8b103..6381ca258de 100644 --- a/addons/account/res_currency.py +++ b/addons/account/res_currency.py @@ -25,6 +25,11 @@ from osv import osv class res_currency_account(osv.osv): _inherit = "res.currency" + def get_conversion_rate(self, cr, uid, from_currency, to_currency, context=None): + if context is None: + context = {} + return self._get_conversion_rate(cr, uid, from_currency, to_currency, context=context) + def _get_conversion_rate(self, cr, uid, from_currency, to_currency, context=None): if context is None: context = {} @@ -44,4 +49,4 @@ class res_currency_account(osv.osv): res_currency_account() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 646e0334c83bd636868ea7d772352ee546859a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 29 Mar 2012 12:25:48 +0200 Subject: [PATCH 026/322] [fix] fix 'in' expression when reading a price or weight barcode bzr revid: rlo@openerp.com-20120329102548-gnffz8am3m755agq --- addons/point_of_sale/static/src/js/pos.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 81ac6cff516..17c9da5e92c 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1328,14 +1328,14 @@ openerp.point_of_sale = function(db) { } }); } - if (barcode.substring(0,2) in ['02', '22', '24', '26', '28']) { + if (barcode.substring(0,2) in {'02':'', '22':'', '24':'', '26':'', '28':''}) { // product with a specific price - specified into the barcode barcode = barcode.substring(2,5); // TODO conversion euro - old local currencies new db.web.Model('res.currency').get_func('_get_conversion_rate')(['FRF', 'EUR']).pipe(function(result){}); price = Number(barcode.substring(7,5))/100; weight = ''; - } else if (barcode.substring(0,2) in ['21','23','27','29','25']) { + } else if (barcode.substring(0,2) in {'21':'','23':'','27':'','29':'','25':''}) { // product sold by weight barcode = barcode.substring(2,5); weight = Number(barcode.substring(7,5))/1000; From 0a77d53dea33d0b66d631d21e62a095bc0e22d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Thu, 29 Mar 2012 14:12:23 +0200 Subject: [PATCH 027/322] [imp] currency conversion (partial) bzr revid: rlo@openerp.com-20120329121223-gb0d9sbpdjijaf0t --- addons/point_of_sale/static/src/js/pos.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 17c9da5e92c..95c8bfa1d32 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1268,9 +1268,6 @@ openerp.point_of_sale = function(db) { while (st2.length < 12) { st2.push(0); } - console.log('code: '+code.join(',')); - console.log('st1: '+st1.join(',')); - console.log('st2: '+st2.join(',')); var countSt3 = 1; var st3 = 0; $.each(st2, function() { @@ -1330,15 +1327,15 @@ openerp.point_of_sale = function(db) { } if (barcode.substring(0,2) in {'02':'', '22':'', '24':'', '26':'', '28':''}) { // product with a specific price - specified into the barcode - barcode = barcode.substring(2,5); + price = Number(barcode.substring(7,12))/100; + barcode = barcode.substring(2,7); // TODO conversion euro - old local currencies - new db.web.Model('res.currency').get_func('_get_conversion_rate')(['FRF', 'EUR']).pipe(function(result){}); - price = Number(barcode.substring(7,5))/100; + new db.web.Model('res.currency').get_func('get_conversion_rate')([pos.session.uid,'FRF', pos.get('currency'), {}]).pipe(function(result){}); weight = ''; } else if (barcode.substring(0,2) in {'21':'','23':'','27':'','29':'','25':''}) { // product sold by weight - barcode = barcode.substring(2,5); - weight = Number(barcode.substring(7,5))/1000; + weight = Number(barcode.substring(7,12))/1000; + barcode = barcode.substring(2,7); price = ''; } else { // product unit From 09506d254af19e1a626413d0eab3f4a043cc0d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 30 Mar 2012 12:02:21 +0200 Subject: [PATCH 028/322] [imp] partially working price/weight barcodes bzr revid: rlo@openerp.com-20120330100221-tjzbpqfp1wzv9n6w --- addons/point_of_sale/static/src/js/pos.js | 54 ++++++++++++----------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 95c8bfa1d32..6c86194201c 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -85,7 +85,8 @@ openerp.point_of_sale = function(db) { }, this)); }, this)); $.when(this.fetch('pos.category', ['name', 'parent_id', 'child_id']), - this.fetch('product.product', ['name', 'list_price', 'pos_categ_id', 'taxes_id', 'product_image_small', 'ean13'], [['pos_categ_id', '!=', 'false']]), + this.fetch('product.product', ['name', 'list_price', 'pos_categ_id', 'taxes_id', 'product_image_small', 'ean13', 'id'], [['pos_categ_id', '!=', 'false']]), + this.fetch('product.packaging', ['product_id', 'ean']), this.fetch('account.bank.statement', ['account_id', 'currency', 'journal_id', 'state', 'name'], [['state', '=', 'open'], ['user_id', '=', this.session.uid]]), this.fetch('account.journal', ['auto_cash', 'check_dtls', 'currency', 'name', 'type']), @@ -1255,6 +1256,7 @@ openerp.point_of_sale = function(db) { this.categoryView.renderElement(); this.categoryView.start(); allProducts = pos.store.get('product.product'); + allPackages = pos.store.get('product.packaging'); products = pos.store.get('product.product').filter( function(p) { var _ref; return _ref = p.pos_categ_id[0], _.indexOf(c.subtree, _ref) >= 0; @@ -1308,8 +1310,6 @@ openerp.point_of_sale = function(db) { lastTimeStamp = new Date().getTime(); if (codeNumbers.length == 13) { // a barcode reader - var barcode = codeNumbers.join(''); - var selectedOrder = self.shop.get('selectedOrder'); if (!checkEan(codeNumbers)) { // barcode read error, raise warning $(QWeb.render('pos-scan-warning')).dialog({ @@ -1325,25 +1325,36 @@ openerp.point_of_sale = function(db) { } }); } + var barcode = codeNumbers.join(''); + var selectedOrder = self.shop.get('selectedOrder'); if (barcode.substring(0,2) in {'02':'', '22':'', '24':'', '26':'', '28':''}) { - // product with a specific price - specified into the barcode + // PRICE barcode price = Number(barcode.substring(7,12))/100; - barcode = barcode.substring(2,7); - // TODO conversion euro - old local currencies - new db.web.Model('res.currency').get_func('get_conversion_rate')([pos.session.uid,'FRF', pos.get('currency'), {}]).pipe(function(result){}); - weight = ''; + barcode = barcode.substring(0,7); + var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === barcode;}); + if (scannedPackaging !== undefined) { + var scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];}); + console.log(scannedProductModel.price); + scannedProductModel.price = price; + console.log('price: '+price); + } } else if (barcode.substring(0,2) in {'21':'','23':'','27':'','29':'','25':''}) { - // product sold by weight + // WEIGHT barcode weight = Number(barcode.substring(7,12))/1000; - barcode = barcode.substring(2,7); - price = ''; + console.log(weight); + barcode = barcode.substring(0,7); + var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === barcode;}); + if (scannedPackaging !== undefined) { + var scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === scannedPackaging.product_id[0];}); + console.log(scannedProductModel.price); + scannedProductModel.price *= weight; + console.log(weight); + } } else { - // product unit - weight = ''; - price = ''; + // UNIT barcode + var scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === barcode;}); } - var scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === barcode;}); - if (scannedProductModel == undefined) { + if (scannedProductModel === undefined) { // product not recognized, raise warning $(QWeb.render('pos-scan-warning')).dialog({ resizable: false, @@ -1357,16 +1368,9 @@ openerp.point_of_sale = function(db) { }, } }); + } else { + selectedOrder.addProduct(new Product(scannedProductModel)); } - if (weight === '' && price !== '') { - // product sold by price - scannedProductModel.price = price; - } else if (weight !== '' && price === '') { - // product sold by weight - // TODO check how to calculate the price - scannedProductModel.price *= weight; - } - selectedOrder.addProduct(new Product(scannedProductModel)); codeNumbers = []; } From de6a9009725afe731ce682b5b65a6a62215d3578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 30 Mar 2012 13:16:17 +0200 Subject: [PATCH 029/322] [imp] working price barcodes bzr revid: rlo@openerp.com-20120330111617-fnc85bpk26eevicc --- addons/point_of_sale/static/src/js/pos.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 6c86194201c..98930e284cd 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1334,9 +1334,7 @@ openerp.point_of_sale = function(db) { var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === barcode;}); if (scannedPackaging !== undefined) { var scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];}); - console.log(scannedProductModel.price); - scannedProductModel.price = price; - console.log('price: '+price); + scannedProductModel.list_price = price; } } else if (barcode.substring(0,2) in {'21':'','23':'','27':'','29':'','25':''}) { // WEIGHT barcode From caba6de06e850006689ea4d318807057e97bae85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 30 Mar 2012 13:42:25 +0200 Subject: [PATCH 030/322] [imp] working weight barcodes bzr revid: rlo@openerp.com-20120330114225-iouhxmyv3hb3xbcd --- addons/point_of_sale/static/src/js/pos.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 98930e284cd..4b63740c9f9 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1339,14 +1339,12 @@ openerp.point_of_sale = function(db) { } else if (barcode.substring(0,2) in {'21':'','23':'','27':'','29':'','25':''}) { // WEIGHT barcode weight = Number(barcode.substring(7,12))/1000; - console.log(weight); barcode = barcode.substring(0,7); var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === barcode;}); if (scannedPackaging !== undefined) { - var scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === scannedPackaging.product_id[0];}); - console.log(scannedProductModel.price); - scannedProductModel.price *= weight; - console.log(weight); + var scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];}); + scannedProductModel.list_price *= weight; + scannedProductModel.name += ' - ' + weight + ' Kg.' } } else { // UNIT barcode From e3a06211124d62b1b0f8e5b62a767960c0cd0737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 30 Mar 2012 14:42:07 +0200 Subject: [PATCH 031/322] [fix] fix search field 'clear' button bzr revid: rlo@openerp.com-20120330124207-5c4lb61al2c1q8s2 --- addons/point_of_sale/static/src/js/pos.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 4b63740c9f9..d845fe06679 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1390,7 +1390,7 @@ openerp.point_of_sale = function(db) { return (self.shop.get('products')).reset(m); }); return $('.search-clear').click( function() { - (this.shop.get('products')).reset(products); + (self.shop.get('products')).reset(products); $('.searchbox input').val('').focus(); return $('.search-clear').fadeOut(); }); From 2d672a4089587934baf092b9b367d46df0dfc6e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 30 Mar 2012 15:23:04 +0200 Subject: [PATCH 032/322] [fix] remove some useless changes after review bzr revid: rlo@openerp.com-20120330132304-6kyfsir5efcp9kig --- addons/account/res_currency.py | 5 ----- addons/point_of_sale/__openerp__.py | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/addons/account/res_currency.py b/addons/account/res_currency.py index 6381ca258de..ce781a1e11a 100644 --- a/addons/account/res_currency.py +++ b/addons/account/res_currency.py @@ -25,11 +25,6 @@ from osv import osv class res_currency_account(osv.osv): _inherit = "res.currency" - def get_conversion_rate(self, cr, uid, from_currency, to_currency, context=None): - if context is None: - context = {} - return self._get_conversion_rate(cr, uid, from_currency, to_currency, context=context) - def _get_conversion_rate(self, cr, uid, from_currency, to_currency, context=None): if context is None: context = {} diff --git a/addons/point_of_sale/__openerp__.py b/addons/point_of_sale/__openerp__.py index f39c05c5e7d..911ccf24bb5 100644 --- a/addons/point_of_sale/__openerp__.py +++ b/addons/point_of_sale/__openerp__.py @@ -40,7 +40,7 @@ Main features : """, 'author': 'OpenERP SA', 'images': ['images/cash_registers.jpeg', 'images/pos_analysis.jpeg','images/register_analysis.jpeg','images/sale_order_pos.jpeg','images/product_pos.jpeg'], - 'depends': ['sale','account'], + 'depends': ['sale'], 'init_xml': [], 'update_xml': [ From c82330ccb63d598792b17415308316659d3df079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Fri, 30 Mar 2012 15:30:01 +0200 Subject: [PATCH 033/322] [fix] remove some useless changes after review bzr revid: rlo@openerp.com-20120330133001-8l5w5d7nsy2vpyh9 --- addons/account/res_currency.py | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/account/res_currency.py b/addons/account/res_currency.py index ce781a1e11a..8e02836274a 100644 --- a/addons/account/res_currency.py +++ b/addons/account/res_currency.py @@ -45,3 +45,4 @@ class res_currency_account(osv.osv): res_currency_account() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + From c053aab30edb3bff9e741653352165bc730bfa4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Mon, 2 Apr 2012 11:13:43 +0200 Subject: [PATCH 034/322] [fix] remove unused code bzr revid: rlo@openerp.com-20120402091343-8dltnmyld7yk2yo2 --- addons/point_of_sale/static/src/js/pos.js | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index d845fe06679..3253fe85bd9 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1250,7 +1250,6 @@ openerp.point_of_sale = function(db) { id = 0; } c = pos.categories[id]; - currency = pos.get('currency'); this.categoryView.ancestors = c.ancestors; this.categoryView.children = c.children; this.categoryView.renderElement(); From c407affde98d46158e8f8a85745e25863ed8749f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Mon, 2 Apr 2012 16:25:13 +0200 Subject: [PATCH 035/322] [IMP]Cleaned syntax of the Backbone models bzr revid: fva@openerp.com-20120402142513-funzsxkit810c3q2 --- addons/point_of_sale/static/src/js/pos.js | 232 ++++++++-------------- 1 file changed, 88 insertions(+), 144 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 3253fe85bd9..85aaacc8621 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -224,57 +224,29 @@ openerp.point_of_sale = function(db) { Models --- */ - var CashRegister = (function() { - __extends(CashRegister, Backbone.Model); - function CashRegister() { - CashRegister.__super__.constructor.apply(this, arguments); - } + console.log("Fva Tools Reloaded"); - return CashRegister; - })(); - var CashRegisterCollection = (function() { - __extends(CashRegisterCollection, Backbone.Collection); - function CashRegisterCollection() { - CashRegisterCollection.__super__.constructor.apply(this, arguments); - } + var CashRegister = Backbone.Model.extend({ + }); - CashRegisterCollection.prototype.model = CashRegister; - return CashRegisterCollection; - })(); - var Product = (function() { - __extends(Product, Backbone.Model); - function Product() { - Product.__super__.constructor.apply(this, arguments); - } + var CashRegisterCollection = Backbone.Collection.extend({ + model: CashRegister, + }); - return Product; - })(); - var ProductCollection = (function() { - __extends(ProductCollection, Backbone.Collection); - function ProductCollection() { - ProductCollection.__super__.constructor.apply(this, arguments); - } + var Product = Backbone.Model.extend({ + }); - ProductCollection.prototype.model = Product; - return ProductCollection; - })(); - var Category = (function() { - __extends(Category, Backbone.Model); - function Category() { - Category.__super__.constructor.apply(this, arguments); - } + var ProductCollection = Backbone.Collection.extend({ + model: Product, + }); - return Category; - })(); - var CategoryCollection = (function() { - __extends(CategoryCollection, Backbone.Collection); - function CategoryCollection() { - CategoryCollection.__super__.constructor.apply(this, arguments); - } + var Category = Backbone.Model.extend({ + }); + + var CategoryCollection = Backbone.Collection.extend({ + model: Category, + }); - CategoryCollection.prototype.model = Category; - return CategoryCollection; - })(); /* Each Order contains zero or more Orderlines (i.e. the content of the "shopping cart".) There should only ever be one Orderline per distinct product in an Order. @@ -352,91 +324,73 @@ openerp.point_of_sale = function(db) { }; }, exportAsJSON: function() { - var result; - result = { + return { qty: this.get('quantity'), price_unit: this.get('list_price'), discount: this.get('discount'), product_id: this.get('id') }; - return result; }, }); + var OrderlineCollection = Backbone.Collection.extend({ model: Orderline, }); - /* - Every PaymentLine has all the attributes of the corresponding CashRegister. - */ - var Paymentline = (function() { - __extends(Paymentline, Backbone.Model); - function Paymentline() { - Paymentline.__super__.constructor.apply(this, arguments); - } - Paymentline.prototype.defaults = { - amount: 0 - }; - Paymentline.prototype.getAmount = function() { + // Every PaymentLine has all the attributes of the corresponding CashRegister. + var Paymentline = Backbone.Model.extend({ + defaults: { + amount: 0, + }, + initialize: function(attributes) { + Backbone.Model.prototype.initialize.apply(this, arguments); + }, + getAmount: function(){ return this.get('amount'); - }; - Paymentline.prototype.exportAsJSON = function() { - var result; - result = { + }, + exportAsJSON: function(){ + return { name: db.web.datetime_to_str(new Date()), statement_id: this.get('id'), account_id: (this.get('account_id'))[0], journal_id: (this.get('journal_id'))[0], amount: this.getAmount() }; - return result; - }; - return Paymentline; - })(); - var PaymentlineCollection = (function() { - __extends(PaymentlineCollection, Backbone.Collection); - function PaymentlineCollection() { - PaymentlineCollection.__super__.constructor.apply(this, arguments); - } + }, + }); - PaymentlineCollection.prototype.model = Paymentline; - return PaymentlineCollection; - })(); - var Order = (function() { - __extends(Order, Backbone.Model); - function Order() { - Order.__super__.constructor.apply(this, arguments); - } - - Order.prototype.defaults = { + var PaymentlineCollection = Backbone.Collection.extend({ + model: Paymentline, + }); + + var Order = Backbone.Model.extend({ + defaults:{ validated: false, step: 'products', - }; - Order.prototype.initialize = function() { - this.set({creationDate: new Date}); + }, + initialize: function(attributes){ + Backbone.Model.prototype.initialize.apply(this, arguments); this.set({ - orderLines: new OrderlineCollection - }); - this.set({ - paymentLines: new PaymentlineCollection + creationDate: new Date, + orderLines: new OrderlineCollection, + paymentLines: new PaymentlineCollection, + name: "Order " + this.generateUniqueId(), }); this.bind('change:validated', this.validatedChanged); - return this.set({ - name: "Order " + this.generateUniqueId() - }); - }; - Order.prototype.events = { + return this; + }, + events: { 'change:validated': 'validatedChanged' - }; - Order.prototype.validatedChanged = function() { + }, + validatedChanged: function() { if (this.get("validated") && !this.previous("validated")) { this.set({'step': 'receipt'}); } - } - Order.prototype.generateUniqueId = function() { + }, + generateUniqueId: function() { return new Date().getTime(); - }; - Order.prototype.addProduct = function(product) { + }, + addProduct: function(product) { var existing; existing = (this.get('orderLines')).get(product.id); if (existing != null) { @@ -448,8 +402,8 @@ openerp.point_of_sale = function(db) { this.get('orderLines').remove(line); }, this); } - }; - Order.prototype.addPaymentLine = function(cashRegister) { + }, + addPaymentLine: function(cashRegister) { var newPaymentline; newPaymentline = new Paymentline(cashRegister); /* TODO: Should be 0 for cash-like accounts */ @@ -457,38 +411,38 @@ openerp.point_of_sale = function(db) { amount: this.getDueLeft() }); return (this.get('paymentLines')).add(newPaymentline); - }; - Order.prototype.getName = function() { + }, + getName: function() { return this.get('name'); - }; - Order.prototype.getTotal = function() { + }, + getTotal: function() { return (this.get('orderLines')).reduce((function(sum, orderLine) { return sum + orderLine.getPriceWithTax(); }), 0); - }; - Order.prototype.getTotalTaxExcluded = function() { + }, + getTotalTaxExcluded: function() { return (this.get('orderLines')).reduce((function(sum, orderLine) { return sum + orderLine.getPriceWithoutTax(); }), 0); - }; - Order.prototype.getTax = function() { + }, + getTax: function() { return (this.get('orderLines')).reduce((function(sum, orderLine) { return sum + orderLine.getTax(); }), 0); - }; - Order.prototype.getPaidTotal = function() { + }, + getPaidTotal: function() { return (this.get('paymentLines')).reduce((function(sum, paymentLine) { return sum + paymentLine.getAmount(); }), 0); - }; - Order.prototype.getChange = function() { + }, + getChange: function() { return this.getPaidTotal() - this.getTotal(); - }; - Order.prototype.getDueLeft = function() { + }, + getDueLeft: function() { return this.getTotal() - this.getPaidTotal(); - }; - Order.prototype.exportAsJSON = function() { - var orderLines, paymentLines, result; + }, + exportAsJSON: function() { + var orderLines, paymentLines; orderLines = []; (this.get('orderLines')).each(_.bind( function(item) { return orderLines.push([0, 0, item.exportAsJSON()]); @@ -497,7 +451,7 @@ openerp.point_of_sale = function(db) { (this.get('paymentLines')).each(_.bind( function(item) { return paymentLines.push([0, 0, item.exportAsJSON()]); }, this)); - result = { + return { name: this.getName(), amount_paid: this.getPaidTotal(), amount_total: this.getTotal(), @@ -506,26 +460,15 @@ openerp.point_of_sale = function(db) { lines: orderLines, statement_ids: paymentLines }; - return result; - }; - return Order; - })(); - var OrderCollection = (function() { - __extends(OrderCollection, Backbone.Collection); - function OrderCollection() { - OrderCollection.__super__.constructor.apply(this, arguments); - } + }, + }); - OrderCollection.prototype.model = Order; - return OrderCollection; - })(); - var Shop = (function() { - __extends(Shop, Backbone.Model); - function Shop() { - Shop.__super__.constructor.apply(this, arguments); - } + var OrderCollection = Backbone.Collection.extend({ + model: Order, + }); - Shop.prototype.initialize = function() { + var Shop = Backbone.Model.extend({ + initialize: function() { this.set({ orders: new OrderCollection(), products: new ProductCollection() @@ -543,15 +486,15 @@ openerp.point_of_sale = function(db) { }); } }, this)); - }; - Shop.prototype.addAndSelectOrder = function(newOrder) { + }, + addAndSelectOrder: function(newOrder) { (this.get('orders')).add(newOrder); return this.set({ selectedOrder: newOrder }); - }; - return Shop; - })(); + }, + }); + /* The numpad handles both the choice of the property currently being modified (quantity, price or discount) and the edition of the corresponding numeric value. @@ -618,6 +561,7 @@ openerp.point_of_sale = function(db) { } }, }); + /* --- Views From d7d7500588993348edf3c97b70f2aae7236e32fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Mon, 2 Apr 2012 17:50:05 +0200 Subject: [PATCH 036/322] [IMP]Cleaned more syntax, added comments, removed __extends() bzr revid: fva@openerp.com-20120402155005-6rpin43aho26h1yz --- addons/point_of_sale/static/src/js/pos.js | 53 ++++++++++++----------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 85aaacc8621..e6868519c55 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -2,22 +2,6 @@ openerp.point_of_sale = function(db) { db.point_of_sale = {}; - var __extends = function(child, parent) { - var __hasProp = Object.prototype.hasOwnProperty; - for (var key in parent) { - if (__hasProp.call(parent, key)) - child[key] = parent[key]; - } - function ctor() { - this.constructor = child; - } - - ctor.prototype = parent.prototype; - child.prototype = new ctor; - child.__super__ = parent.prototype; - return child; - }; - var QWeb = db.web.qweb; var qweb_template = function(template) { return function(ctx) { @@ -719,6 +703,7 @@ openerp.point_of_sale = function(db) { }, on_selected: function() {}, }); + var OrderWidget = db.web.OldWidget.extend({ init: function(parent, options) { this._super(parent); @@ -800,6 +785,7 @@ openerp.point_of_sale = function(db) { $('#total').html(total.toFixed(2)).hide().fadeIn(); }, }); + /* "Products" step. */ @@ -838,6 +824,7 @@ openerp.point_of_sale = function(db) { }, on_change_category: function(id) {}, }); + var ProductWidget = db.web.OldWidget.extend({ tagName:'li', template_fct: qweb_template('pos-product-template'), @@ -860,6 +847,7 @@ openerp.point_of_sale = function(db) { return this; }, }); + var ProductListWidget = db.web.OldWidget.extend({ init: function(parent, options) { this._super(parent); @@ -1011,6 +999,7 @@ openerp.point_of_sale = function(db) { this.currentPaymentLines.last().set({amount: val}); }, }); + var ReceiptWidget = db.web.OldWidget.extend({ init: function(parent, options) { this._super(parent); @@ -1053,6 +1042,7 @@ openerp.point_of_sale = function(db) { $('.pos-receipt-container', this.$element).html(qweb_template('pos-ticket')({widget:this})); }, }); + var OrderButtonWidget = db.web.OldWidget.extend({ tagName: 'li', template_fct: qweb_template('pos-order-selector-button-template'), @@ -1092,6 +1082,7 @@ openerp.point_of_sale = function(db) { this.$element.addClass('order-selector-button'); } }); + var ShopWidget = db.web.OldWidget.extend({ init: function(parent, options) { this._super(parent); @@ -1172,7 +1163,9 @@ openerp.point_of_sale = function(db) { } }, }); + var App = (function() { + function App($element) { this.initialize($element); } @@ -1188,16 +1181,18 @@ openerp.point_of_sale = function(db) { this.categoryView.on_change_category.add_last(_.bind(this.category, this)); this.category(); }; + App.prototype.category = function(id) { - var c, products; - if (id == null) { - id = 0; - } + var c, products, self = this; + + id = !id ? 0 : id; + c = pos.categories[id]; this.categoryView.ancestors = c.ancestors; this.categoryView.children = c.children; this.categoryView.renderElement(); this.categoryView.start(); + allProducts = pos.store.get('product.product'); allPackages = pos.store.get('product.packaging'); products = pos.store.get('product.product').filter( function(p) { @@ -1205,8 +1200,9 @@ openerp.point_of_sale = function(db) { return _ref = p.pos_categ_id[0], _.indexOf(c.subtree, _ref) >= 0; }); (this.shop.get('products')).reset(products); + + //returns true if the code is a valid EAN codebar number by checking the control digit. var checkEan = function(code) { - // EAN control digit calculation var st1 = code.slice(); var st2 = st1.slice(0,st1.length-1).reverse(); // some EAN13 barcodes have a length of 12, as they start by 0 @@ -1234,12 +1230,18 @@ openerp.point_of_sale = function(db) { var cd = (10 - (st5%10)) % 10; return code[code.length-1] === cd; } - var self = this; - // bind barcode reader event + + // The barcode readers acts as a keyboard, we catch all keyup events and try to find a + // barcode sequence in the typed keys, then act accordingly. + var codeNumbers = []; $('body').delegate('','keyup', function (e){ + + //We only care about numbers if (!isNaN(Number(String.fromCharCode(e.keyCode)))) { - // a number + + // The barcode reader sends keystrokes with a specific interval. + // We look if the typed keys fit in the interval. if (codeNumbers.length==0) { timeStamp = new Date().getTime(); } else { @@ -1291,7 +1293,7 @@ openerp.point_of_sale = function(db) { } } else { // UNIT barcode - var scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === barcode;}); + var scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === barcode;}); //TODO DOES NOT SCALE } if (scannedProductModel === undefined) { // product not recognized, raise warning @@ -1318,6 +1320,7 @@ openerp.point_of_sale = function(db) { codeNumbers = []; } }); + $('.searchbox input').keyup(function() { var m, s; s = $(this).val().toLowerCase(); From a7bdd4e172657f2b5962e13c3eadafa759c12d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Mon, 2 Apr 2012 18:17:54 +0200 Subject: [PATCH 037/322] [FIX] Remove debug console.log bzr revid: fva@openerp.com-20120402161754-dmhty19ag58aow2q --- addons/point_of_sale/static/src/js/pos.js | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index e6868519c55..cf8c066c249 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -208,7 +208,6 @@ openerp.point_of_sale = function(db) { Models --- */ - console.log("Fva Tools Reloaded"); var CashRegister = Backbone.Model.extend({ }); From 34610c1e61c5de6759b82e51fcafcb8f26e88697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20L=C3=B3pez=20L=C3=B3pez=20=28OpenERP=29?= Date: Tue, 3 Apr 2012 10:28:03 +0200 Subject: [PATCH 038/322] [fix] modify according to review: split functionalities into different functions bzr revid: rlo@openerp.com-20120403082803-hvvd65cl64qmzvms --- addons/point_of_sale/static/src/js/pos.js | 54 +++++++++++++---------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index cf8c066c249..2ec692618f0 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1234,6 +1234,35 @@ openerp.point_of_sale = function(db) { // barcode sequence in the typed keys, then act accordingly. var codeNumbers = []; + + var getProductByEAN = function(ean) { + var prefix = ean.substring(0,2); + var scannedProductModel = undefined; + if (prefix in {'02':'', '22':'', '24':'', '26':'', '28':''}) { + // PRICE barcode + var itemCode = ean.substring(0,7); + var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === itemCode;}); + if (scannedPackaging !== undefined) { + scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];}); + scannedProductModel.list_price = Number(ean.substring(7,12))/100; + } + } else if (prefix in {'21':'','23':'','27':'','29':'','25':''}) { + // WEIGHT barcode + var weight = Number(barcode.substring(7,12))/1000; + var itemCode = ean.substring(0,7); + var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === itemCode;}); + if (scannedPackaging !== undefined) { + scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];}); + scannedProductModel.list_price *= weight; + scannedProductModel.name += ' - ' + weight + ' Kg.'; + } + } else { + // UNIT barcode + scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === ean;}); //TODO DOES NOT SCALE + } + return scannedProductModel; + } + $('body').delegate('','keyup', function (e){ //We only care about numbers @@ -1269,31 +1298,8 @@ openerp.point_of_sale = function(db) { } }); } - var barcode = codeNumbers.join(''); var selectedOrder = self.shop.get('selectedOrder'); - if (barcode.substring(0,2) in {'02':'', '22':'', '24':'', '26':'', '28':''}) { - // PRICE barcode - price = Number(barcode.substring(7,12))/100; - barcode = barcode.substring(0,7); - var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === barcode;}); - if (scannedPackaging !== undefined) { - var scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];}); - scannedProductModel.list_price = price; - } - } else if (barcode.substring(0,2) in {'21':'','23':'','27':'','29':'','25':''}) { - // WEIGHT barcode - weight = Number(barcode.substring(7,12))/1000; - barcode = barcode.substring(0,7); - var scannedPackaging = _.detect(allPackages, function(pack) { return pack.ean !== undefined && pack.ean.substring(0,7) === barcode;}); - if (scannedPackaging !== undefined) { - var scannedProductModel = _.detect(allProducts, function(pc) { return pc.id === scannedPackaging.product_id[0];}); - scannedProductModel.list_price *= weight; - scannedProductModel.name += ' - ' + weight + ' Kg.' - } - } else { - // UNIT barcode - var scannedProductModel = _.detect(allProducts, function(pc) { return pc.ean13 === barcode;}); //TODO DOES NOT SCALE - } + var scannedProductModel = getProductByEAN(codeNumbers.join('')); if (scannedProductModel === undefined) { // product not recognized, raise warning $(QWeb.render('pos-scan-warning')).dialog({ From ef10d28de963cabf8eb5e636b6b726159f4bbf11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Tue, 3 Apr 2012 10:46:58 +0200 Subject: [PATCH 039/322] [FIX] Comment in the wrong place bzr revid: fva@openerp.com-20120403084658-j19s285vjd307ag7 --- addons/point_of_sale/static/src/js/pos.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos.js b/addons/point_of_sale/static/src/js/pos.js index 2ec692618f0..a03e34a3e53 100644 --- a/addons/point_of_sale/static/src/js/pos.js +++ b/addons/point_of_sale/static/src/js/pos.js @@ -1230,11 +1230,10 @@ openerp.point_of_sale = function(db) { return code[code.length-1] === cd; } - // The barcode readers acts as a keyboard, we catch all keyup events and try to find a - // barcode sequence in the typed keys, then act accordingly. - var codeNumbers = []; + // returns a product that has a packaging with an EAN matching to provided ean string. + // returns undefined if no such product is found. var getProductByEAN = function(ean) { var prefix = ean.substring(0,2); var scannedProductModel = undefined; @@ -1263,6 +1262,8 @@ openerp.point_of_sale = function(db) { return scannedProductModel; } + // The barcode readers acts as a keyboard, we catch all keyup events and try to find a + // barcode sequence in the typed keys, then act accordingly. $('body').delegate('','keyup', function (e){ //We only care about numbers From bc05498416ae2fce7625d7f5d842ed0c38fb60a9 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Wed, 4 Apr 2012 14:31:14 +0200 Subject: [PATCH 040/322] [IMP] point_of_sale: Add the POS Config object bzr revid: stw@openerp.com-20120404123114-e557auyszvy4uy3a --- addons/point_of_sale/point_of_sale.py | 57 ++++++++++++++++ addons/point_of_sale/point_of_sale_view.xml | 76 +++++++++++++++++++++ 2 files changed, 133 insertions(+) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 5af78b131b2..012de387776 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -33,6 +33,63 @@ import decimal_precision as dp _logger = logging.getLogger(__name__) +class pos_config(osv.osv): + _name = 'pos.config' + + POS_CONFIG_STATE = [('draft', 'Draft'),('active', 'Active'),('inactive', 'Inactive'),('deprecated', 'Deprecated')] + + _columns = { + 'name' : fields.char('Name', size=32, select=1, required=True), + 'journal_ids' : fields.many2many('account.journal', 'pos_config_journal_rel', 'pos_config_id', 'journal_id', 'Payment Methods'), + 'shop_id' : fields.many2one('sale.shop', 'Shop', required=True, select=1), + 'journal_id' : fields.many2one('account.journal', 'Journal', required=True, select=1), + 'profit_account_id' : fields.many2one('account.account', 'Profit Account', required=True, select=1), + 'loss_account_id' : fields.many2one('account.account', 'Loss Account', required=True, select=1), + + 'authorized_cashbox_diff' : fields.integer('Authorized Cashbox Difference (%)'), + 'authorized_cashbox_diff_fixed' : fields.integer('Authorized Cashbox Difference (Fixed Amount)'), + + + 'iface_self_checkout' : fields.boolean('Self Checkout Mode'), + 'iface_websql' : fields.boolean('WebSQL (to store data)'), + 'iface_led' : fields.boolean('LED Interface'), + 'iface_cashdrawer' : fields.boolean('Cashdrawer Interface'), + 'iface_payment_terminal' : fields.boolean('Payment Terminal Interface'), + 'iface_electronic_scale' : fields.boolean('Electronic Scale Interface'), + 'iface_barscan' : fields.boolean('BarScan Interface'), + 'iface_vkeyboard' : fields.boolean('Virtual KeyBoard Interface'), + + 'state' : fields.selection(POS_CONFIG_STATE, 'State', required=True, readonly=True), + + } + + _defaults = { + 'state' : 'draft', + } + + def set_draft(self, cr, uid, ids, context=None): + return self.write(cr, uid, ids, {'state' : 'draft'}, context=context) + + def set_active(self, cr, uid, ids, context=None): + return self.write(cr, uid, ids, {'state' : 'active'}, context=context) + + def set_inactive(self, cr, uid, ids, context=None): + return self.write(cr, uid, ids, {'state' : 'inactive'}, context=context) + + def set_deprecate(self, cr, uid, ids, context=None): + return self.write(cr, uid, ids, {'state' : 'deprecated'}, context=context) + +pos_config() + +class pos_session(osv.osv): + _name = 'pos.session' + + _columns = { + 'config_id' : fields.many2one('pos.config', 'Configuration', required=True, select=1), + } + +pos_session() + class pos_config_journal(osv.osv): """ Point of Sale journal configuration""" _name = 'pos.config.journal' diff --git a/addons/point_of_sale/point_of_sale_view.xml b/addons/point_of_sale/point_of_sale_view.xml index b397bd826cc..4e1fcc7c6db 100644 --- a/addons/point_of_sale/point_of_sale_view.xml +++ b/addons/point_of_sale/point_of_sale_view.xml @@ -790,5 +790,81 @@ + + pos.config.form.view + pos.config + form + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

Receipt

+
+
+
+
+ + +
+
+
+
@@ -229,20 +265,6 @@ - - -
+ + + + +
+

WELCUM

+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+
From 05535cf4e961080a74726c000963c9eca5d7e9f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Thu, 3 May 2012 18:27:46 +0200 Subject: [PATCH 076/322] Added a few more screens bzr revid: fva@openerp.com-20120503162746-lo7m3qno48jcanyz --- addons/point_of_sale/__openerp__.py | 1 + .../static/src/js/pos_devices.js | 31 +- .../point_of_sale/static/src/js/pos_main.js | 2 + .../static/src/js/pos_widgets.js | 369 +++--------------- addons/point_of_sale/static/src/xml/pos.xml | 24 +- 5 files changed, 102 insertions(+), 325 deletions(-) diff --git a/addons/point_of_sale/__openerp__.py b/addons/point_of_sale/__openerp__.py index c159193e299..2c356ab4f31 100644 --- a/addons/point_of_sale/__openerp__.py +++ b/addons/point_of_sale/__openerp__.py @@ -87,6 +87,7 @@ Main features : 'static/src/js/pos_models.js', 'static/src/js/pos_widgets.js', 'static/src/js/pos_devices.js', + 'static/src/js/pos_screens.js', 'static/src/js/pos_main.js' ], 'css': ['static/src/css/pos.css'], diff --git a/addons/point_of_sale/static/src/js/pos_devices.js b/addons/point_of_sale/static/src/js/pos_devices.js index f87754c92c7..86c5bcda635 100644 --- a/addons/point_of_sale/static/src/js/pos_devices.js +++ b/addons/point_of_sale/static/src/js/pos_devices.js @@ -1,72 +1,97 @@ function openerp_pos_devices(module, instance){ //module is instance.point_of_sale - // this module interfaces with the local proxy to communicate to the various hardware devices + window.debug_devices = new (instance.web.Class.extend({ + payment_status: 'waiting_for_payment', + weight: 0, + accept_payment: function(){ this.payment_status = 'payment_accepted'; }, + reject_payment: function(){ this.payment_status = 'payment_rejected'; }, + delay_payment: function(){ this.payment_status = 'waiting_for_payment'; }, + }))(); + + // 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. + module.ProxyDevice = instance.web.Class.extend({ //a product has been scanned and recognized with success scan_item_succes: function(){ + console.log('PROXY: scan item success'); }, //a product has been scanned but not recognized scan_item_error_unrecognized: function(){ + console.log('PROXY: scan item error'); }, //the client is asking for help help_needed: function(){ + console.log('PROXY: help needed'); }, //the client does not need help anymore help_canceled: function(){ + console.log('PROXY: help canceled'); }, //the client is starting to weight weighting_start: function(){ + console.log('PROXY: weighting start'); }, //returns the weight on the scale. // is called at regular interval (up to 10x/sec) between a weighting_start() // and a weighting_end() weighting_read_kg: function(){ - return Math.random() + 0.1; + console.log('PROXY: weighting read'); + //return Math.random() + 0.1; + return window.debug_devices.weight; }, // the client has finished weighting products weighting_end: function(){ + console.log('PROXY: weighting end'); }, // the pos asks the client to pay 'price' units // method: 'mastercard' | 'cash' | ... ? TBD // info: 'extra information to display on the payment terminal' ... ? TBD payment_request: function(price, method, info){ + console.log('PROXY: payment request:',price,method,info); }, // is called at regular interval after a payment request to see if the client // has paid the required money // returns 'waiting_for_payment' | 'payment_accepted' | 'payment_rejected' is_payment_accepted: function(){ - return 'waiting_for_payment'; // 'payment_accepted' | 'payment_rejected' + console.log('PROXY: is payment accepted ?'); + //return 'waiting_for_payment'; // 'payment_accepted' | 'payment_rejected' + return window.debug_devices.payment_status; }, // the client cancels his payment payment_canceled: function(){ + console.log('PROXY: payment canceled by client'); }, // called when the client logs in or starts to scan product transation_start: function(){ + console.log('PROXY: transaction start'); }, // called when the clients has finished his interaction with the machine transaction_end: function(){ + console.log('PROXY: transaction end'); }, // called when the POS turns to cashier mode cashier_mode_activated: function(){ + console.log('PROXY:'); }, // called when the POS turns to client mode cashier_mode_deactivated: function(){ + console.log('PROXY:'); }, }); diff --git a/addons/point_of_sale/static/src/js/pos_main.js b/addons/point_of_sale/static/src/js/pos_main.js index 09e51dd41e1..a358639e2e3 100644 --- a/addons/point_of_sale/static/src/js/pos_main.js +++ b/addons/point_of_sale/static/src/js/pos_main.js @@ -6,6 +6,8 @@ openerp.point_of_sale = function(instance) { var module = instance.point_of_sale; openerp_pos_models(module,instance); // import pos_models.js + + openerp_pos_screens(module,instance); // import pos_screens.js openerp_pos_widgets(module,instance); // import pos_widgets.js diff --git a/addons/point_of_sale/static/src/js/pos_widgets.js b/addons/point_of_sale/static/src/js/pos_widgets.js index ae17c6dbbc4..09f56573bf6 100644 --- a/addons/point_of_sale/static/src/js/pos_widgets.js +++ b/addons/point_of_sale/static/src/js/pos_widgets.js @@ -357,278 +357,27 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa template:'pos-actionbar', init: function(parent, options){ this._super(parent,options); - this.left_button_list = []; - this.right_button_list = []; + this.button_list = []; }, - start: function(){ - window.actionbarwidget = this; - }, - destroyButtons:function(position){ - var button_list; - if(position === 'left'){ - button_list = this.left_button_list; - this.left_button_list = []; - }else if (position === 'right'){ - button_list = this.right_button_list; - this.right_button_list = []; - }else{ - return this; - } - for(var i = 0; i < button_list.length; i++){ - button_list[i].destroy(); + destroy_buttons:function(){ + for(var i = 0; i < this.button_list.length; i++){ + this.button_list[i].destroy(); } + this.button_list = []; return this; }, - addNewButton: function(position,button_options){ - if(arguments.length == 2){ - var button_list; - var $button_list; - if(position === 'left'){ - button_list = this.left_button_list; - $button_list = $('.pos-actionbar-left-region'); - }else if(position === 'right'){ - button_list = this.right_button_list; - $button_list = $('.pos-actionbar-right-region'); - } + add_new_button: function(button_options){ + if(arguments.length == 1){ var button = new module.ActionButtonWidget(this,button_options); - button_list.push(button); - button.appendTo($button_list); + this.button_list.push(button); + button.appendTo($('.pos-actionbar-right-region')); }else{ - for(var i = 1; i < arguments.length; i++){ - this.addNewButton(position,arguments[i]); + for(var i = 0; i < arguments.length; i++){ + this.add_new_button(arguments[i]); } } return this; } - /* - renderElement: function() { - //this.$element.html(this.template_fct()); - },*/ - }); - -// ---------- Screens Widgets ---------- - - module.ScreenWidget = instance.web.Widget.extend({ - init: function(parent, options){ - this._super(parent, options); - }, - show: function(){ - if(this.$element){ - this.$element.show(); - } - }, - hide: function(){ - if(this.$element){ - this.$element.hide(); - } - }, - }); - - module.ScreenSelector = instance.web.Class.extend({ - init: function(options){ - this.pos = options.pos; - this.screen_set = options.screen_set || {}; - this.current_screen = options.current_screen ? this.screen_set[options.current_screen] : undefined; - this.default_screen = options.default_screen; - - var current = null; - for(screen_name in this.screen_set){ - var screen = this.screen_set[screen_name]; - if(screen === this.current_screen){ - current = screen; - }else{ - screen.hide(); - } - } - if(current){ - current.show(); - } - - this.selected_order = this.pos.get('selectedOrder'); - this.pos.bind('change:selectedOrder', this.load_saved_screen, this); - }, - add_screen: function(screen_name, screen){ - screen.hide(); - this.screen_set[screen_name] = screen; - return this; - }, - load_saved_screen: function(){ - if(this.selected_order != this.pos.get('selectedOrder')){ - var screen = this.pos.get('selectedOrder').get('screen') || this.default_screen; - this.selected_order = this.pos.get('selectedOrder'); - this.set_current_screen(screen); - } - }, - set_current_screen: function(screen_name){ - var screen = this.screen_set[screen_name]; - - this.pos.get('selectedOrder').set({'screen':screen_name}); - - console.log('Set Current Screen: '+screen_name+' :',screen,'old:',this.current_screen); - if(screen && screen !== this.current_screen){ - if(this.current_screen){ - this.current_screen.hide(); - } - this.current_screen = screen; - this.current_screen.show(); - } - }, - }); - - module.PaymentScreenWidget = module.ScreenWidget.extend({ - template_fct: qweb_template('PaymentScreenWidget'), - init: function(parent, options) { - this._super(parent); - this.model = options.model; - this.pos = options.pos; - this.pos_widget = options.pos_widget; - this.pos.bind('change:selectedOrder', this.changeSelectedOrder, this); - this.bindPaymentLineEvents(); - this.bindOrderLineEvents(); - }, - show: function(){ - this._super(); - this.setNumpadState(this.pos_widget.numpadView.state); - }, - hide: function(){ - this._super(); - this.pos_widget.orderView.setNumpadState(null); - this.pos_widget.payment_screen.setNumpadState(null); - }, - paymentLineList: function() { - return this.$element.find('#paymentlines'); - }, - back: function() { - console.log('back'); - this.pos.screen_selector.set_current_screen('products'); - }, - validateCurrentOrder: function() { - var callback, currentOrder; - currentOrder = this.pos.get('selectedOrder'); - $('button#validate-order', this.$element).attr('disabled', 'disabled'); - this.pos.push_order(currentOrder.exportAsJSON()).then(_.bind(function() { - $('button#validate-order', this.$element).removeAttr('disabled'); - return currentOrder.set({ - validated: true - }); - }, this)); - }, - bindPaymentLineEvents: function() { - this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines'); - this.currentPaymentLines.bind('add', this.addPaymentLine, this); - this.currentPaymentLines.bind('remove', this.renderElement, this); - this.currentPaymentLines.bind('all', this.updatePaymentSummary, this); - }, - bindOrderLineEvents: function() { - this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines'); - this.currentOrderLines.bind('all', this.updatePaymentSummary, this); - }, - changeSelectedOrder: function() { - this.currentPaymentLines.unbind(); - this.bindPaymentLineEvents(); - this.currentOrderLines.unbind(); - this.bindOrderLineEvents(); - this.renderElement(); - }, - addPaymentLine: function(newPaymentLine) { - var x = new module.PaymentlineWidget(null, { - model: newPaymentLine - }); - x.on_delete.add(_.bind(this.deleteLine, this, x)); - x.appendTo(this.paymentLineList()); - }, - renderElement: function() { - this._super(); - this.$element.html(this.template_fct()); - this.paymentLineList().empty(); - this.currentPaymentLines.each(_.bind( function(paymentLine) { - this.addPaymentLine(paymentLine); - }, this)); - this.updatePaymentSummary(); - $('button#validate-order', this.$element).click(_.bind(this.validateCurrentOrder, this)); - $('.oe-back-to-products', this.$element).click(_.bind(this.back, this)); - }, - deleteLine: function(lineWidget) { - this.currentPaymentLines.remove([lineWidget.model]); - }, - updatePaymentSummary: function() { - var currentOrder, dueTotal, paidTotal, remaining, remainingAmount; - currentOrder = this.pos.get('selectedOrder'); - paidTotal = currentOrder.getPaidTotal(); - dueTotal = currentOrder.getTotal(); - this.$element.find('#payment-due-total').html(dueTotal.toFixed(2)); - this.$element.find('#payment-paid-total').html(paidTotal.toFixed(2)); - remainingAmount = dueTotal - paidTotal; - remaining = remainingAmount > 0 ? 0 : (-remainingAmount).toFixed(2); - $('#payment-remaining').html(remaining); - }, - setNumpadState: function(numpadState) { - if (this.numpadState) { - this.numpadState.unbind('setValue', this.setValue); - this.numpadState.unbind('change:mode', this.setNumpadMode); - } - this.numpadState = numpadState; - if (this.numpadState) { - this.numpadState.bind('setValue', this.setValue, this); - this.numpadState.bind('change:mode', this.setNumpadMode, this); - this.numpadState.reset(); - this.setNumpadMode(); - } - }, - setNumpadMode: function() { - this.numpadState.set({mode: 'payment'}); - }, - setValue: function(val) { - this.currentPaymentLines.last().set({amount: val}); - }, - }); - - module.ReceiptScreenWidget = module.ScreenWidget.extend({ - template: 'ReceiptScreenWidget', - init: function(parent, options) { - this._super(parent); - this.model = options.model; - this.pos = options.pos; - this.pos = options.pos; - this.user = this.pos.get('user'); - this.company = this.pos.get('company'); - this.shop_obj = this.pos.get('shop'); - }, - start: function() { - this.pos.bind('change:selectedOrder', this.changeSelectedOrder, this); - this.changeSelectedOrder(); - $('button#pos-finish-order', this.$element).click(_.bind(this.finishOrder, this)); - $('button#print-the-ticket', this.$element).click(_.bind(this.print, this)); - }, - print: function() { - window.print(); - }, - finishOrder: function() { - this.pos.get('selectedOrder').destroy(); - }, - changeSelectedOrder: 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.$element).html(qweb_template('pos-ticket')({widget:this})); - }, - }); - - module.WelcomeScreenWidget = module.ScreenWidget.extend({ - }); - - module.ScanProductScreenWidget = module.ScreenWidget.extend({ }); module.ProductCategoriesWidget = instance.web.Widget.extend({ @@ -743,45 +492,6 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa }, }); - module.SearchProductScreenWidget = module.ScreenWidget.extend({ - template:'SearchProductScreenWidget', - init: function(parent, options){ - this._super(parent,options); - options = options || {}; - this.pos = options.pos; - this.pos_widget = options.pos_widget; - }, - start: function(){ - this.product_categories_widget = new module.ProductCategoriesWidget(null,{ - pos:this.pos, - }); - this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget')); - - this.product_list_widget = new module.ProductListWidget(null,{ - pos:this.pos, - }); - this.product_list_widget.replace($('.placeholder-ProductListWidget')); - }, - show: function(){ - this._super(); - this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state); - }, - hide: function(){ - this._super(); - this.pos_widget.orderView.setNumpadState(null); - this.pos_widget.payment_screen.setNumpadState(null); - }, - - }); - - module.ScaleInviteScreenWidget = module.ScreenWidget.extend({ - }); - - module.ScaleProductSelectionScreenWidget = module.ScreenWidget.extend({ - }); - - module.AskForMoneyScreenWidget = module.ScreenWidget.extend({ - }); // ---------- PopUp Widgets ---------- @@ -799,6 +509,8 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa module.TicketOrInvoicePopUp = module.PopUp.extend({ }); +// ---------- OnScreen Keyboard Widget ---------- + // A Widget that displays an onscreen keyboard. // There are two options when creating the widget : // @@ -994,6 +706,8 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa }, }); +// ---------- Main Point of Sale Widget ---------- + module.SynchNotification = instance.web.OldWidget.extend({ template: "pos-synch-notification", init: function() { @@ -1061,6 +775,11 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa }); this.search_product_screen.appendTo($('#rightpane')); + this.scan_product_screen = new module.ScanProductScreenWidget(this,{ + pos: this.pos, + pos_widget: this, + }); + this.scan_product_screen.appendTo($('#rightpane')); this.receipt_screen = new module.ReceiptScreenWidget(this, { pos: this.pos, @@ -1068,13 +787,30 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa }); this.receipt_screen.appendTo($('#rightpane')); - this.payment_screen = new module.PaymentScreenWidget(this, { pos: this.pos, pos_widget: this, }); this.payment_screen.appendTo($('#rightpane')); + this.welcome_screen = new module.WelcomeScreenWidget(this,{ + pos:this.pos, + pos_widget: this, + }); + this.welcome_screen.appendTo($('#rightpane')); + + this.client_payment_screen = new module.ClientPaymentScreenWidget(this, { + pos: this.pos, + pos_widget: this, + }); + this.client_payment_screen.appendTo($('#rightpane')); + + this.scale_invite_screen = new module.ScaleInviteScreenWidget(this, { + pos: this.pos, + pos_widget: this, + }); + this.scale_invite_screen.appendTo($('#rightpane')); + this.paypadView = new module.PaypadWidget(null, { pos: this.pos }); @@ -1089,29 +825,28 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa }); this.orderView.$element = $('#current-order-content'); this.orderView.start(); + + this.action_bar = new module.ActionbarWidget(null); + this.action_bar.appendTo($(".point-of-sale #content")); + + this.onscreen_keyboard = new module.OnscreenKeyboardWidget(null, { + 'keyboard_model': 'simple' + }); + this.onscreen_keyboard.appendTo($(".point-of-sale #content")); this.pos.screen_selector = new module.ScreenSelector({ pos: this.pos, screen_set:{ 'products': this.search_product_screen, + 'scan': this.scan_product_screen, 'payment' : this.payment_screen, + 'client_payment' : this.client_payment_screen, + 'scale_invite' : this.scale_invite_screen, 'receipt' : this.receipt_screen, + 'welcome' : this.welcome_screen, }, - current_screen: 'products', - default_screen: 'products', - }); - - this.onscreenKeyboard = new module.OnscreenKeyboardWidget(null, { - 'keyboard_model': 'simple' - }); - this.onscreenKeyboard.appendTo($(".point-of-sale #content")); - - this.action_bar = new module.ActionbarWidget(null); - this.action_bar.appendTo($(".point-of-sale #content")); - this.action_bar.addNewButton('left',{ - label : 'Hello World', - icon : '/point_of_sale/static/src/img/icons/png48/face-monkey.png', - click : function(){ console.log("Hello World!"); } + current_screen: 'welcome', + default_screen: 'welcome', }); this.pos.barcode_reader.connect(); diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index 7abd08f1974..e8ca9202a08 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -218,26 +218,40 @@
- -
+

WELCUM

+

plz scan ur card or thingie

- -
+ + +
+

SCAN YOUR PRODUCT

+

please scan another product ! fun !

+
+
+ + +
+

GIMME UR MONEY!!!11

+

It's a rubbery

-
+
+

Put ur loot on the scale

+

Is it worth a ton ?

+ +
From 850ed87082a8cf3756d22f0f07ab8c7271e93763 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Thu, 3 May 2012 18:40:32 +0200 Subject: [PATCH 077/322] Draft of the product scale screen bzr revid: fva@openerp.com-20120503164032-zoe5rini8lj7kw1i --- addons/point_of_sale/static/src/js/pos_widgets.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/point_of_sale/static/src/js/pos_widgets.js b/addons/point_of_sale/static/src/js/pos_widgets.js index 09f56573bf6..a4c12e8ccb2 100644 --- a/addons/point_of_sale/static/src/js/pos_widgets.js +++ b/addons/point_of_sale/static/src/js/pos_widgets.js @@ -811,6 +811,12 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa }); this.scale_invite_screen.appendTo($('#rightpane')); + this.scale_product_screen = new module.ScaleProductScreenWidget(this, { + pos: this.pos, + pos_widget: this, + }); + this.scale_product_screen.appendTo($('#rightpane')); + this.paypadView = new module.PaypadWidget(null, { pos: this.pos }); @@ -842,6 +848,7 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa 'payment' : this.payment_screen, 'client_payment' : this.client_payment_screen, 'scale_invite' : this.scale_invite_screen, + 'scale_product' : this.scale_product_screen, 'receipt' : this.receipt_screen, 'welcome' : this.welcome_screen, }, From fa4b14487d374c390bdb1c8ced70b43a360445e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Thu, 3 May 2012 19:15:23 +0200 Subject: [PATCH 078/322] Forgot to add pos_screens.js bzr revid: fva@openerp.com-20120503171523-rmew4wbblrw3hpyk --- .../static/src/js/pos_screens.js | 543 ++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 addons/point_of_sale/static/src/js/pos_screens.js diff --git a/addons/point_of_sale/static/src/js/pos_screens.js b/addons/point_of_sale/static/src/js/pos_screens.js new file mode 100644 index 00000000000..29c92d85792 --- /dev/null +++ b/addons/point_of_sale/static/src/js/pos_screens.js @@ -0,0 +1,543 @@ + +// this file contains the screens definitions. Screens are the +// content of the right pane of the pos, containing the main functionalities. +// screens are contained in the PosWidget, in pos_widget.js +// all screens are present in the dom at all time, but only one is shown at the +// same time. +// +// transition between screens is made possible by the use of the screen_selector, +// which is responsible of hiding and showing the screens, as well as maintaining +// the state of the screens between different orders. +// +// all screens inherit from ScreenWidget. the only addition from the base widgets +// are show() and hide() which shows and hides the screen but are also used to +// bind and unbind actions on widgets and devices. The screen_selector guarantees +// that only one screen is shown at the same time and that show() is called after all +// hide()s + +function openerp_pos_screens(module, instance){ //module is instance.point_of_sale + var QWeb = instance.web.qweb; + + var qweb_template = function(template,pos){ + return function(ctx){ + if(!pos){ //this is a huge hack that needs to be removed ... TODO + var HackPosModel = Backbone.Model.extend({ + initialize:function(){ + this.set({ + 'currency': {symbol: '$', position: 'after'}, + }); + }, + }); + pos = new HackPosModel(); + } + return QWeb.render(template, _.extend({}, ctx,{ + 'currency': pos.get('currency'), + 'format_amount': function(amount) { + if (pos.get('currency').position == 'after') { + return amount + ' ' + pos.get('currency').symbol; + } else { + return pos.get('currency').symbol + ' ' + amount; + } + }, + })); + }; + }; + + module.ScreenSelector = instance.web.Class.extend({ + init: function(options){ + this.pos = options.pos; + this.screen_set = options.screen_set || {}; + this.current_screen = options.current_screen ? this.screen_set[options.current_screen] : undefined; + this.default_screen = options.default_screen; + + var current = null; + for(screen_name in this.screen_set){ + var screen = this.screen_set[screen_name]; + if(screen === this.current_screen){ + current = screen; + }else{ + screen.hide(); + } + } + if(current){ + current.show(); + } + + this.selected_order = this.pos.get('selectedOrder'); + this.pos.bind('change:selectedOrder', this.load_saved_screen, this); + }, + add_screen: function(screen_name, screen){ + screen.hide(); + this.screen_set[screen_name] = screen; + return this; + }, + load_saved_screen: function(){ + if(this.selected_order != this.pos.get('selectedOrder')){ + var screen = this.pos.get('selectedOrder').get('screen') || this.default_screen; + this.selected_order = this.pos.get('selectedOrder'); + this.set_current_screen(screen); + } + }, + set_current_screen: function(screen_name){ + var screen = this.screen_set[screen_name]; + + this.pos.get('selectedOrder').set({'screen':screen_name}); + + console.log('Set Current Screen: '+screen_name+' :',screen,'old:',this.current_screen); + if(screen && screen !== this.current_screen){ + if(this.current_screen){ + this.current_screen.hide(); + } + this.current_screen = screen; + this.current_screen.show(); + } + }, + }); + + module.ScreenWidget = instance.web.Widget.extend({ + init: function(parent, options){ + this._super(parent, options); + options = options || {}; + this.pos = options.pos; + this.pos_widget = options.pos_widget; + }, + show: function(){ + if(this.$element){ + this.$element.show(); + } + }, + hide: function(){ + if(this.$element){ + this.$element.hide(); + } + if(this.pos.barcode_reader){ + this.pos.barcode_reader.reset_action_callbacks(); + } + if(this.pos_widget.action_bar){ + this.pos_widget.action_bar.destroy_buttons(); + } + }, + }); + + module.ScaleInviteScreenWidget = module.ScreenWidget.extend({ + template:'ScaleInviteScreenWidget', + show: function(){ + this._super(); + var self = this; + + self.pos.proxy.weighting_start(); + + var intervalID = setInterval(function(){ + var weight = self.pos.proxy.weighting_read_kg(); + if(weight > 0.001){ + clearInterval(intervalID); + self.pos.screen_selector.set_current_screen('scale_product'); + } + },500); + + this.pos_widget.action_bar.add_new_button( + { + label: 'help', + click: function(){ //TODO Show help popup + } + },{ + label: 'back', + click: function(){ //TODO Go to ask for weighting screen + clearInterval(intervalID); + self.pos.proxy.weighting_end(); + self.pos.screen_selector.set_current_screen('scan'); + } + } + ); + }, + }); + + module.ScaleProductScreenWidget = module.ScreenWidget.extend({ + template:'ScaleProductSelectionScreenWidget', + start: function(){ + this.product_categories_widget = new module.ProductCategoriesWidget(null,{ + pos:this.pos, + }); + this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget')); + + this.product_list_widget = new module.ProductListWidget(null,{ + pos:this.pos, + }); + this.product_list_widget.replace($('.placeholder-ProductListWidget')); + }, + show: function(){ + this._super(); + var self = this; + this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state); + this.pos_widget.action_bar.add_new_button( + { + label: 'help', + click: function(){ //TODO Show help popup + } + },{ + label: 'back', + click: function(){ + self.pos.screen_selector.set_current_screen('scan'); + } + } + ); + this.pos.barcode_reader.set_action_callbacks({ + 'cashier': function(ean){ + //TODO 'switch to cashier mode' + self.proxy.cashier_mode_activated(); + }, + }); + }, + hide: function(){ + this._super(); + this.pos_widget.orderView.setNumpadState(null); + this.pos_widget.payment_screen.setNumpadState(null); + }, + + }); + + module.ClientPaymentScreenWidget = module.ScreenWidget.extend({ + template:'ClientPaymentScreenWidget', + show: function(){ + this._super(); + var self = this; + + this.pos.proxy.payment_request(0,'card','info'); //TODO TOTAL + + var intervalID = setInterval(function(){ + var payment = self.pos.proxy.is_payment_accepted(); + if(payment === 'payment_accepted'){ + clearInterval(intervalID); + //TODO process the payment stuff + self.pos.proxy.transaction_end(); + self.pos.screen_selector.set_current_screen('welcome'); + }else if(payment === 'payment_rejected'){ + clearInterval(intervalID); + //TODO show a tryagain thingie ? + } + },500); + + this.pos_widget.action_bar.add_new_button( + { + label: 'help', + click: function(){ //TODO Show help popup + } + },{ + label: 'back', + click: function(){ //TODO Go to ask for weighting screen + clearInterval(intervalID); + self.pos.proxy.payment_canceled(); + self.pos.screen_selector.set_current_screen('scan'); + } + } + ); + + this.pos.barcode_reader.set_action_callbacks({ + 'cashier': function(ean){ + //TODO 'switch to cashier mode' + clearInterval(intervalID); + self.proxy.cashier_mode_activated(); + self.pos.screen_selector.set_current_screen('products'); + }, + }); + }, + }); + + module.WelcomeScreenWidget = module.ScreenWidget.extend({ + template:'WelcomeScreenWidget', + show: function(){ + this._super(); + var self = this; + this.pos_widget.action_bar.add_new_button( + { + label:'scan', + click: function(){ + self.pos.screen_selector.set_current_screen('scan'); + } + },{ + label: 'help', + click: function(){ //TODO Show help popup + } + },{ + label: 'peser', + click: function(){ //TODO Go to ask for weighting screen + self.pos.screen_selector.set_current_screen('scale_invite'); + } + } + ); + this.pos.barcode_reader.set_action_callbacks({ + 'product': function(ean){ + self.proxy.transaction_start(); + self.pos.barcode_reader.scan_product_callback(ean); + self.pos.screen_selector.set_current_screen('products'); + }, + 'cashier': function(ean){ + //TODO 'switch to cashier mode' + self.proxy.cashier_mode_activated(); + self.pos.screen_selector.set_current_screen('products'); + }, + 'client': function(ean){ + self.proxy.transaction_start(); + //TODO 'log the client' + self.pos.screen_selector.set_current_screen('products'); + }, + 'discount': function(ean){ + // TODO : what to do in this case ???? + }, + }); + }, + hide: function(){ + this._super(); + this.pos.barcode_reader.reset_action_callbacks(); + this.pos_widget.action_bar.destroy_buttons(); + }, + }); + + module.ScanProductScreenWidget = module.ScreenWidget.extend({ + template:'ScanProductScreenWidget', + show: function(){ + this._super(); + var self = this; + this.pos_widget.action_bar.add_new_button( + { + label: 'help', + click: function(){ //TODO Show help popup + } + },{ + label: 'weight', + click: function(){ //TODO Go to ask for weighting screen + self.pos.screen_selector.set_current_screen('scale_invite'); + } + },{ + label: 'pay', + click: function(){ + self.pos.screen_selector.set_current_screen('client_payment'); //TODO what stuff ? + } + } + ); + this.pos.barcode_reader.set_action_callbacks({ + 'product': function(ean){ + var success = self.pos.barcode_reader.scan_product_callback(ean); + if(success){ + self.proxy.scan_item_success(); + }else{ + self.proxy.scan_item_error_unrecognized(); + } + }, + 'cashier': function(ean){ + //TODO 'switch to cashier mode' + self.proxy.cashier_mode_activated(); + }, + 'discount': function(ean){ + // TODO : handle the discount + }, + }); + }, + }); + + module.SearchProductScreenWidget = module.ScreenWidget.extend({ + template:'SearchProductScreenWidget', + start: function(){ + this.product_categories_widget = new module.ProductCategoriesWidget(null,{ + pos:this.pos, + }); + this.product_categories_widget.replace($('.placeholder-ProductCategoriesWidget')); + + this.product_list_widget = new module.ProductListWidget(null,{ + pos:this.pos, + }); + this.product_list_widget.replace($('.placeholder-ProductListWidget')); + }, + show: function(){ + this._super(); + var self = this; + this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state); + this.pos_widget.action_bar.add_new_button( + { + label: 'help', + click: function(){ //TODO Show help popup + } + },{ + label: 'weight', + click: function(){ //TODO Go to ask for weighting screen + } + },{ + label: 'pay', + click: function(){ + self.pos.screen_selector.set_current_screen('payment'); //TODO what stuff ? + } + } + ); + this.pos.barcode_reader.set_action_callbacks({ + 'product': function(ean){ + var success = self.pos.barcode_reader.scan_product_callback(ean); + if(success){ + self.proxy.scan_item_success(); + }else{ + self.proxy.scan_item_error_unrecognized(); + } + }, + 'cashier': function(ean){ + //TODO 'switch to cashier mode' + self.proxy.cashier_mode_activated(); + }, + 'discount': function(ean){ + // TODO : handle the discount + }, + }); + }, + hide: function(){ + this._super(); + this.pos_widget.orderView.setNumpadState(null); + this.pos_widget.payment_screen.setNumpadState(null); + }, + + }); + + module.ReceiptScreenWidget = module.ScreenWidget.extend({ + template: 'ReceiptScreenWidget', + 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'); + }, + start: function() { + this.pos.bind('change:selectedOrder', this.changeSelectedOrder, this); + this.changeSelectedOrder(); + $('button#pos-finish-order', this.$element).click(_.bind(this.finishOrder, this)); + $('button#print-the-ticket', this.$element).click(_.bind(this.print, this)); + }, + print: function() { + window.print(); + }, + finishOrder: function() { + this.pos.get('selectedOrder').destroy(); + }, + changeSelectedOrder: 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.$element).html(qweb_template('pos-ticket')({widget:this})); + }, + }); + + module.PaymentScreenWidget = module.ScreenWidget.extend({ + template_fct: qweb_template('PaymentScreenWidget'), + init: function(parent, options) { + this._super(parent,options); + this.model = options.model; + this.pos.bind('change:selectedOrder', this.changeSelectedOrder, this); + this.bindPaymentLineEvents(); + this.bindOrderLineEvents(); + }, + show: function(){ + this._super(); + this.setNumpadState(this.pos_widget.numpadView.state); + }, + hide: function(){ + this._super(); + this.pos_widget.orderView.setNumpadState(null); + this.pos_widget.payment_screen.setNumpadState(null); + }, + paymentLineList: function() { + return this.$element.find('#paymentlines'); + }, + back: function() { + console.log('back'); + this.pos.screen_selector.set_current_screen('products'); + }, + validateCurrentOrder: function() { + var callback, currentOrder; + currentOrder = this.pos.get('selectedOrder'); + $('button#validate-order', this.$element).attr('disabled', 'disabled'); + this.pos.push_order(currentOrder.exportAsJSON()).then(_.bind(function() { + $('button#validate-order', this.$element).removeAttr('disabled'); + return currentOrder.set({ + validated: true + }); + }, this)); + }, + bindPaymentLineEvents: function() { + this.currentPaymentLines = (this.pos.get('selectedOrder')).get('paymentLines'); + this.currentPaymentLines.bind('add', this.addPaymentLine, this); + this.currentPaymentLines.bind('remove', this.renderElement, this); + this.currentPaymentLines.bind('all', this.updatePaymentSummary, this); + }, + bindOrderLineEvents: function() { + this.currentOrderLines = (this.pos.get('selectedOrder')).get('orderLines'); + this.currentOrderLines.bind('all', this.updatePaymentSummary, this); + }, + changeSelectedOrder: function() { + this.currentPaymentLines.unbind(); + this.bindPaymentLineEvents(); + this.currentOrderLines.unbind(); + this.bindOrderLineEvents(); + this.renderElement(); + }, + addPaymentLine: function(newPaymentLine) { + var x = new module.PaymentlineWidget(null, { + model: newPaymentLine + }); + x.on_delete.add(_.bind(this.deleteLine, this, x)); + x.appendTo(this.paymentLineList()); + }, + renderElement: function() { + this._super(); + this.$element.html(this.template_fct()); + this.paymentLineList().empty(); + this.currentPaymentLines.each(_.bind( function(paymentLine) { + this.addPaymentLine(paymentLine); + }, this)); + this.updatePaymentSummary(); + $('button#validate-order', this.$element).click(_.bind(this.validateCurrentOrder, this)); + $('.oe-back-to-products', this.$element).click(_.bind(this.back, this)); + }, + deleteLine: function(lineWidget) { + this.currentPaymentLines.remove([lineWidget.model]); + }, + updatePaymentSummary: function() { + var currentOrder, dueTotal, paidTotal, remaining, remainingAmount; + currentOrder = this.pos.get('selectedOrder'); + paidTotal = currentOrder.getPaidTotal(); + dueTotal = currentOrder.getTotal(); + this.$element.find('#payment-due-total').html(dueTotal.toFixed(2)); + this.$element.find('#payment-paid-total').html(paidTotal.toFixed(2)); + remainingAmount = dueTotal - paidTotal; + remaining = remainingAmount > 0 ? 0 : (-remainingAmount).toFixed(2); + $('#payment-remaining').html(remaining); + }, + setNumpadState: function(numpadState) { + if (this.numpadState) { + this.numpadState.unbind('setValue', this.setValue); + this.numpadState.unbind('change:mode', this.setNumpadMode); + } + this.numpadState = numpadState; + if (this.numpadState) { + this.numpadState.bind('setValue', this.setValue, this); + this.numpadState.bind('change:mode', this.setNumpadMode, this); + this.numpadState.reset(); + this.setNumpadMode(); + } + }, + setNumpadMode: function() { + this.numpadState.set({mode: 'payment'}); + }, + setValue: function(val) { + this.currentPaymentLines.last().set({amount: val}); + }, + }); + +} From 22c0ae2d8b9bc5cd94d628469287c52a7a3a18d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Fri, 4 May 2012 11:48:25 +0200 Subject: [PATCH 079/322] Client and cashier mode bzr revid: fva@openerp.com-20120504094825-fb0ku12w3kq1ubcf --- .../static/src/js/pos_screens.js | 81 ++++++++++++++++--- .../static/src/js/pos_widgets.js | 6 +- 2 files changed, 74 insertions(+), 13 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos_screens.js b/addons/point_of_sale/static/src/js/pos_screens.js index 29c92d85792..0f8cdaadbb4 100644 --- a/addons/point_of_sale/static/src/js/pos_screens.js +++ b/addons/point_of_sale/static/src/js/pos_screens.js @@ -46,9 +46,22 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa module.ScreenSelector = instance.web.Class.extend({ init: function(options){ this.pos = options.pos; + this.screen_set = options.screen_set || {}; - this.current_screen = options.current_screen ? this.screen_set[options.current_screen] : undefined; - this.default_screen = options.default_screen; + + this.default_client_screen = options.default_client_screen; + this.default_cashier_screen = options.default_cashier_screen; + + this.current_client_screen = this.screen_set[this.default_client_screen]; + + this.current_cashier_screen = this.screen_set[this.default_client_screen]; + + this.default_mode = options.default_mode || 'client'; + this.current_mode = this.default_mode; + + this.current_screen = this.current_mode === 'client' ? + this.current_client_screen: + this.current_cashier_screen; var current = null; for(screen_name in this.screen_set){ @@ -64,6 +77,12 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa } this.selected_order = this.pos.get('selectedOrder'); + this.selected_order.set({ + user_mode : this.current_mode, + client_screen: this.default_client_screen, + cashier_screen: this.default_cashier_screen, + }); + this.pos.bind('change:selectedOrder', this.load_saved_screen, this); }, add_screen: function(screen_name, screen){ @@ -72,18 +91,54 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa return this; }, load_saved_screen: function(){ - if(this.selected_order != this.pos.get('selectedOrder')){ - var screen = this.pos.get('selectedOrder').get('screen') || this.default_screen; - this.selected_order = this.pos.get('selectedOrder'); - this.set_current_screen(screen); + console.log('load_saved_screen'); + if(true || this.selected_order != this.pos.get('selectedOrder')){ + var selectedOrder = this.pos.get('selectedOrder'); + + var user_mode = selectedOrder.get('user_mode'); + console.log('user mode:',user_mode); + + if(user_mode === 'client'){ + this.current_mode = 'client'; + this.set_current_screen(selectedOrder.get('client_screen') || this.default_client_screen); + }else if(user_mode === 'cashier'){ + this.current_mode = 'cashier'; + console.log('default_cashier_screen:',this.default_cashier_screen); + this.set_current_screen(selectedOrder.get('cashier_screen') || this.default_cashier_screen); + }else{ + this.current_mode = this.default_mode; + selectedOrder.set({ user_mode: this.current_mode }); + if(this.current_mode === 'client'){ + this.set_current_screen(this.default_client_screen); + }else{ + this.set_current_screen(this.default_cashier_screen); + } + } + this.selected_order = selectedOrder; + // var screen = this.pos.get('selectedOrder').get('screen') || this.default_screen; + // this.selected_order = this.pos.get('selectedOrder'); + // this.set_current_screen(screen); + } + }, + set_user_mode: function(user_mode){ + console.log('set user mode:',user_mode); + if(user_mode !== this.current_mode){ + this.current_mode = user_mode; + this.pos.get('selectedOrder').set({ user_mode : this.current_mode }); + this.load_saved_screen(); } }, set_current_screen: function(screen_name){ var screen = this.screen_set[screen_name]; - - this.pos.get('selectedOrder').set({'screen':screen_name}); - console.log('Set Current Screen: '+screen_name+' :',screen,'old:',this.current_screen); + var selectedOrder = this.pos.get('selectedOrder'); + if(this.current_mode === 'client'){ + selectedOrder.set({'client_screen': screen_name}); + }else{ + selectedOrder.set({'cashier_screen': screen_name}); + } + + console.log('Set Current Screen: '+screen_name+' :',screen,'old:',this.current_screen, 'mode:',this.current_mode); if(screen && screen !== this.current_screen){ if(this.current_screen){ this.current_screen.hide(); @@ -127,7 +182,7 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa self.pos.proxy.weighting_start(); - var intervalID = setInterval(function(){ + this.intervalID = setInterval(function(){ var weight = self.pos.proxy.weighting_read_kg(); if(weight > 0.001){ clearInterval(intervalID); @@ -143,13 +198,17 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa },{ label: 'back', click: function(){ //TODO Go to ask for weighting screen - clearInterval(intervalID); + clearInterval(this.intervalID); self.pos.proxy.weighting_end(); self.pos.screen_selector.set_current_screen('scan'); } } ); }, + hide: function(){ + this._super(); + clearInterval(this.intervalID); + }, }); module.ScaleProductScreenWidget = module.ScreenWidget.extend({ diff --git a/addons/point_of_sale/static/src/js/pos_widgets.js b/addons/point_of_sale/static/src/js/pos_widgets.js index a4c12e8ccb2..91e4e7b9d40 100644 --- a/addons/point_of_sale/static/src/js/pos_widgets.js +++ b/addons/point_of_sale/static/src/js/pos_widgets.js @@ -852,9 +852,11 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa 'receipt' : this.receipt_screen, 'welcome' : this.welcome_screen, }, - current_screen: 'welcome', - default_screen: 'welcome', + default_client_screen: 'welcome', + default_cashier_screen: 'products', + default_mode: 'client', }); + window.screen_selector = this.pos.screen_selector; this.pos.barcode_reader.connect(); From bf9fc9b13c856b874f4ae6719cf4aab116885a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Fri, 4 May 2012 12:27:37 +0200 Subject: [PATCH 080/322] Showing and hiding widgets in different screens and modes bzr revid: fva@openerp.com-20120504102737-gfi4kggapocpnxrk --- .../static/src/js/pos_screens.js | 40 ++++++++++++++++++ .../static/src/js/pos_widgets.js | 41 +++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/addons/point_of_sale/static/src/js/pos_screens.js b/addons/point_of_sale/static/src/js/pos_screens.js index 0f8cdaadbb4..4c11770151d 100644 --- a/addons/point_of_sale/static/src/js/pos_screens.js +++ b/addons/point_of_sale/static/src/js/pos_screens.js @@ -180,6 +180,10 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa this._super(); var self = this; + this.pos_widget.set_numpad_visible(false); + this.pos_widget.set_leftpane_visible(true); + this.pos_widget.set_cashier_controls_visible(false); + self.pos.proxy.weighting_start(); this.intervalID = setInterval(function(){ @@ -227,6 +231,11 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa show: function(){ this._super(); var self = this; + + this.pos_widget.set_numpad_visible(false); + this.pos_widget.set_leftpane_visible(true); + this.pos_widget.set_cashier_controls_visible(false); + this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state); this.pos_widget.action_bar.add_new_button( { @@ -261,6 +270,10 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa this._super(); var self = this; + this.pos_widget.set_numpad_visible(false); + this.pos_widget.set_leftpane_visible(true); + this.pos_widget.set_cashier_controls_visible(false); + this.pos.proxy.payment_request(0,'card','info'); //TODO TOTAL var intervalID = setInterval(function(){ @@ -307,6 +320,11 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa show: function(){ this._super(); var self = this; + + this.pos_widget.set_numpad_visible(false); + this.pos_widget.set_leftpane_visible(false); + this.pos_widget.set_cashier_controls_visible(false); + this.pos_widget.action_bar.add_new_button( { label:'scan', @@ -357,6 +375,11 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa show: function(){ this._super(); var self = this; + + this.pos_widget.set_numpad_visible(false); + this.pos_widget.set_leftpane_visible(true); + this.pos_widget.set_cashier_controls_visible(false); + this.pos_widget.action_bar.add_new_button( { label: 'help', @@ -410,6 +433,11 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa show: function(){ this._super(); var self = this; + + this.pos_widget.set_numpad_visible(true); + this.pos_widget.set_leftpane_visible(true); + this.pos_widget.set_cashier_controls_visible(true); + this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state); this.pos_widget.action_bar.add_new_button( { @@ -468,6 +496,13 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa $('button#pos-finish-order', this.$element).click(_.bind(this.finishOrder, this)); $('button#print-the-ticket', this.$element).click(_.bind(this.print, this)); }, + show: function(){ + this._super(); + + this.pos_widget.set_numpad_visible(true); + this.pos_widget.set_leftpane_visible(true); + this.pos_widget.set_cashier_controls_visible(true); + }, print: function() { window.print(); }, @@ -504,6 +539,11 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa }, show: function(){ this._super(); + + this.pos_widget.set_numpad_visible(true); + this.pos_widget.set_leftpane_visible(true); + this.pos_widget.set_cashier_controls_visible(true); + this.setNumpadState(this.pos_widget.numpadView.state); }, hide: function(){ diff --git a/addons/point_of_sale/static/src/js/pos_widgets.js b/addons/point_of_sale/static/src/js/pos_widgets.js index 91e4e7b9d40..2d0fad64748 100644 --- a/addons/point_of_sale/static/src/js/pos_widgets.js +++ b/addons/point_of_sale/static/src/js/pos_widgets.js @@ -729,6 +729,10 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa init: function() { this._super.apply(this, arguments); this.pos = new module.PosModel(this.session); + this.numpad_visible = true; + this.leftpane_visible = true; + this.leftpane_width = '440px'; + this.cashier_controls_visible = true; }, start: function() { var self = this; @@ -882,6 +886,43 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa var self = this; this.synch_notification.on_change_nbr_pending(self.pos.get('nbr_pending_operations').length); }, + set_numpad_visible: function(visible){ + if(visible != this.numpad_visible){ + this.numpad_visible = visible; + if(visible){ + $('#numpad').show(); + $('#paypad').show(); + }else{ + $('#numpad').hide(); + $('#paypad').hide(); + } + } + }, + set_leftpane_visible: function(visible){ + if(visible != this.leftpane_visible){ + this.leftpane_visible = visible; + if(visible){ + $('#leftpane').show().animate({'width':this.leftpane_width},500,'swing'); + $('#rightpane').animate({'left':this.leftpane_width},500,'swing'); + }else{ + var leftpane = $('#leftpane'); + $('#leftpane').animate({'width':'0px'},500,'swing', function(){ leftpane.hide(); }); + $('#rightpane').animate({'left':'0px'},500,'swing'); + } + } + }, + set_cashier_controls_visible: function(visible){ + if(visible != this.cashier_controls_visible){ + this.cashier_controls_visible = visible; + if(visible){ + $('#loggedas').show(); + $('#rightheader').show(); + }else{ + $('#loggedas').hide(); + $('#rightheader').hide(); + } + } + }, try_close: function() { var self = this; self.pos.flush().then(_.bind(function() { From 5fafeb4c89e8b35ccf04af216797167eef4fafe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Fri, 4 May 2012 14:24:48 +0200 Subject: [PATCH 081/322] New action bar draft bzr revid: fva@openerp.com-20120504122448-bhs06j1lgoauss58 --- addons/point_of_sale/static/src/css/pos.css | 6 ++---- .../point_of_sale/static/src/js/pos_widgets.js | 8 ++++---- addons/point_of_sale/static/src/xml/pos.xml | 18 ++++++++++-------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/addons/point_of_sale/static/src/css/pos.css b/addons/point_of_sale/static/src/css/pos.css index 3769417995b..067f1368d71 100644 --- a/addons/point_of_sale/static/src/css/pos.css +++ b/addons/point_of_sale/static/src/css/pos.css @@ -510,7 +510,7 @@ body{ list-style: none; } -.point-of-sale .pos-actionbar-left-region{ +.point-of-sale .pos-actionbar-left-pane{ height: 100%; width: 434px; margin: 0px; @@ -520,7 +520,7 @@ body{ float: left; } -.point-of-sale .pos-actionbar-right-region{ +.point-of-sale .pos-actionbar-button-list{ height: 100%; margin: 0px; padding-left:3px; @@ -534,8 +534,6 @@ body{ text-align:center; margin:3px; margin-top:6px; - //line-height: 90px; - //vertical-align:center; float:left; font-size: 14px; diff --git a/addons/point_of_sale/static/src/js/pos_widgets.js b/addons/point_of_sale/static/src/js/pos_widgets.js index 2d0fad64748..899221a009a 100644 --- a/addons/point_of_sale/static/src/js/pos_widgets.js +++ b/addons/point_of_sale/static/src/js/pos_widgets.js @@ -353,8 +353,8 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa }, }); - module.ActionbarWidget = instance.web.Widget.extend({ - template:'pos-actionbar', + module.ActionBarWidget = instance.web.Widget.extend({ + template:'ActionBarWidget', init: function(parent, options){ this._super(parent,options); this.button_list = []; @@ -370,7 +370,7 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa if(arguments.length == 1){ var button = new module.ActionButtonWidget(this,button_options); this.button_list.push(button); - button.appendTo($('.pos-actionbar-right-region')); + button.appendTo($('.pos-actionbar-button-list')); }else{ for(var i = 0; i < arguments.length; i++){ this.add_new_button(arguments[i]); @@ -836,7 +836,7 @@ function openerp_pos_widgets(module, instance){ //module is instance.point_of_sa this.orderView.$element = $('#current-order-content'); this.orderView.start(); - this.action_bar = new module.ActionbarWidget(null); + this.action_bar = new module.ActionBarWidget(null); this.action_bar.appendTo($(".point-of-sale #content")); this.onscreen_keyboard = new module.OnscreenKeyboardWidget(null, { diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index e8ca9202a08..dd5412dcaf9 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -354,15 +354,17 @@
- +
-
    - -
- -
    +
    +
    + Help +
    +

    + Total: 1234 +

    +
    +
      From e56de26bcc14532ef8d38d29d88f9046c649bc60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20van=20der=20Essen?= Date: Fri, 4 May 2012 14:30:33 +0200 Subject: [PATCH 082/322] removed custom help buttons bzr revid: fva@openerp.com-20120504123033-mffgt1x9swahq5oe --- .../static/src/js/pos_screens.js | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/addons/point_of_sale/static/src/js/pos_screens.js b/addons/point_of_sale/static/src/js/pos_screens.js index 4c11770151d..083f415669e 100644 --- a/addons/point_of_sale/static/src/js/pos_screens.js +++ b/addons/point_of_sale/static/src/js/pos_screens.js @@ -196,10 +196,6 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa this.pos_widget.action_bar.add_new_button( { - label: 'help', - click: function(){ //TODO Show help popup - } - },{ label: 'back', click: function(){ //TODO Go to ask for weighting screen clearInterval(this.intervalID); @@ -239,10 +235,6 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state); this.pos_widget.action_bar.add_new_button( { - label: 'help', - click: function(){ //TODO Show help popup - } - },{ label: 'back', click: function(){ self.pos.screen_selector.set_current_screen('scan'); @@ -291,10 +283,6 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa this.pos_widget.action_bar.add_new_button( { - label: 'help', - click: function(){ //TODO Show help popup - } - },{ label: 'back', click: function(){ //TODO Go to ask for weighting screen clearInterval(intervalID); @@ -331,10 +319,6 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa click: function(){ self.pos.screen_selector.set_current_screen('scan'); } - },{ - label: 'help', - click: function(){ //TODO Show help popup - } },{ label: 'peser', click: function(){ //TODO Go to ask for weighting screen @@ -382,10 +366,6 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa this.pos_widget.action_bar.add_new_button( { - label: 'help', - click: function(){ //TODO Show help popup - } - },{ label: 'weight', click: function(){ //TODO Go to ask for weighting screen self.pos.screen_selector.set_current_screen('scale_invite'); @@ -441,10 +421,6 @@ function openerp_pos_screens(module, instance){ //module is instance.point_of_sa this.pos_widget.orderView.setNumpadState(this.pos_widget.numpadView.state); this.pos_widget.action_bar.add_new_button( { - label: 'help', - click: function(){ //TODO Show help popup - } - },{ label: 'weight', click: function(){ //TODO Go to ask for weighting screen } From ec308a08e73dc07a71216a7127ffd74160e80c55 Mon Sep 17 00:00:00 2001 From: Stephane Wirtel Date: Fri, 4 May 2012 14:51:58 +0200 Subject: [PATCH 083/322] [IMP] account: Add new wizard for the cash register "Take Money Out", "Put Money In" [FIX] point_of_sale: Fix some bugs bzr revid: stw@openerp.com-20120504125158-p45qfzo8mif6x9xe --- addons/account/__openerp__.py | 1 + addons/account/account.py | 4 + addons/account/account_cash_statement.py | 41 +++++++++- addons/account/account_view.xml | 18 +++-- addons/account/wizard/__init__.py | 2 + addons/account/wizard/pos_box.py | 80 +++++++++++++++++++ addons/account/wizard/pos_box.xml | 62 ++++++++++++++ addons/point_of_sale/__openerp__.py | 3 +- .../point_of_sale/account_bank_statement.py | 5 +- .../point_of_sale/account_statement_view.xml | 1 - addons/point_of_sale/point_of_sale.py | 20 ++--- addons/point_of_sale/point_of_sale_view.xml | 35 ++++---- addons/point_of_sale/wizard/__init__.py | 4 +- addons/point_of_sale/wizard/pos_box.py | 26 ++++++ addons/point_of_sale/wizard/pos_box.xml | 22 +++++ .../point_of_sale/wizard/pos_box_entries.py | 22 ++++- addons/point_of_sale/wizard/pos_payment.py | 22 ++++- addons/point_of_sale/wizard/pos_payment.xml | 3 +- 18 files changed, 327 insertions(+), 44 deletions(-) create mode 100644 addons/account/wizard/pos_box.py create mode 100644 addons/account/wizard/pos_box.xml create mode 100644 addons/point_of_sale/wizard/pos_box.py create mode 100644 addons/point_of_sale/wizard/pos_box.xml diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py index 221a58e35d1..e6f356e0a44 100644 --- a/addons/account/__openerp__.py +++ b/addons/account/__openerp__.py @@ -100,6 +100,7 @@ module named account_voucher. 'wizard/account_reconcile_partner_process_view.xml', 'wizard/account_automatic_reconcile_view.xml', 'wizard/account_financial_report_view.xml', + 'wizard/pos_box.xml', 'project/wizard/project_account_analytic_line_view.xml', 'account_end_fy.xml', 'account_invoice_view.xml', diff --git a/addons/account/account.py b/addons/account/account.py index 75bfc891980..df446abc3bc 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -739,6 +739,10 @@ class account_journal(osv.osv): 'entry_posted': fields.boolean('Skip \'Draft\' State for Manual Entries', help='Check this box if you don\'t want new journal entries to pass through the \'draft\' state and instead goes directly to the \'posted state\' without any manual validation. \nNote that journal entries that are automatically created by the system are always skipping that state.'), 'company_id': fields.many2one('res.company', 'Company', required=True, select=1, help="Company related to this journal"), 'allow_date':fields.boolean('Check Date in Period', help= 'If set to True then do not accept the entry if the entry date is not into the period dates'), + + 'profit_account_id' : fields.many2one('account.account', 'Profit Account'), + 'loss_account_id' : fields.many2one('account.account', 'Loss Account'), + 'internal_account_id' : fields.many2one('account.account', 'Internal Transfers Account', select=1), } _defaults = { diff --git a/addons/account/account_cash_statement.py b/addons/account/account_cash_statement.py index f21bd7e9a36..9cec8dfc723 100644 --- a/addons/account/account_cash_statement.py +++ b/addons/account/account_cash_statement.py @@ -188,6 +188,14 @@ class account_cash_statement(osv.osv): result[line.statement_id.id] = True return result.keys() + def _compute_difference(self, cr, uid, ids, fieldnames, args, context=None): + result = dict.fromkeys(ids, 0.0) + + for obj in self.browse(cr, uid, ids, context=context): + result[obj.id] = obj.balance_end - obj.balance_end_cash + + return result + _columns = { 'total_entry_encoding': fields.function(_get_sum_entry_encoding, string="Cash Transaction", help="Total cash transactions", store = { @@ -198,6 +206,7 @@ class account_cash_statement(osv.osv): 'balance_end_cash': fields.function(_balance_end_cash, store=False, string='Closing Balance', help="Closing balance based on cashBox"), 'details_ids' : fields.one2many('account.cashbox.line', 'bank_statement_id', string='CashBox Lines'), 'user_id': fields.many2one('res.users', 'Responsible', required=False), + 'difference' : fields.function(_compute_difference, method=True, string="Difference", type="float"), } _defaults = { @@ -234,7 +243,8 @@ class account_cash_statement(osv.osv): for line in vals.get('details_ids',[]): print "line: %r" % (line,) if line and len(line)==3 and line[2]: - amount_total+= line[2]['pieces'] * line[2]['number_opening'] + # FIXME: If there is no piece # does not work with GTK + amount_total+= line[2].get('pieces', 0) * line[2]['number_opening'] vals.update(balance_start= amount_total) vals.update(balance_end_real=self._compute_balance_end_real(cr, uid, vals['journal_id'], context=context)) @@ -287,7 +297,7 @@ class account_cash_statement(osv.osv): balance_start = 0.0 if journal_id: count = self.search_count(cr, uid, [('journal_id', '=', journal_id),('state', '=', 'open')], context=None) - if count: + if 0: # count: journal = self.pool.get('account.journal').browse(cr, uid, journal_id, context=context) raise osv.except_osv(_('Error !'), (_('The Account Journal %s is opened by an other Cash Register !') % (journal.name,))) else: @@ -380,6 +390,33 @@ class account_cash_statement(osv.osv): def button_confirm_cash(self, cr, uid, ids, context=None): super(account_cash_statement, self).button_confirm_bank(cr, uid, ids, context=context) + absl_proxy = self.pool.get('account.bank.statement.line') + + TABLES = (('Profit', 'profit_account_id'), ('Loss', 'loss_account_id'),) + + for obj in self.browse(cr, uid, ids, context=context): + if obj.difference == 0.0: + continue + + for item_label, item_account in TALBES: + if getattr(obj.journal_id, item_account): + raise osv.except_osv(_('Error !'), + _('There is no %s Account on the Journal %s') % (item_label, obj.journal_id.name,)) + + is_profit = obj.difference < 0.0 + + account = getattr(obj.journal_id, TABLES[is_profit][1]) + + values = { + 'statement_id' : obj.id, + 'journal_id' : obj.journal_id.id, + 'account_id' : account.id, + 'amount' : obj.difference, + 'name' : 'Exceptional %s' % TABLES[is_profit][0], + } + + absl_proxy.create(cr, uid, values, context=context) + return self.write(cr, uid, ids, {'closing_date': time.strftime("%Y-%m-%d %H:%M:%S")}, context=context) def button_cancel(self, cr, uid, ids, context=None): diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml index 5258b876ad2..273035fbc2a 100644 --- a/addons/account/account_view.xml +++ b/addons/account/account_view.xml @@ -505,11 +505,17 @@ - + + + + + + + @@ -2659,12 +2665,13 @@ action = pool.get('res.config').next(cr, uid, [], context) - + + - + - + @@ -2677,7 +2684,7 @@ action = pool.get('res.config').next(cr, uid, [], context) - + @@ -2690,6 +2697,7 @@ action = pool.get('res.config').next(cr, uid, [], context) + diff --git a/addons/account/wizard/__init__.py b/addons/account/wizard/__init__.py index a78cf12050b..87a053d558c 100644 --- a/addons/account/wizard/__init__.py +++ b/addons/account/wizard/__init__.py @@ -64,6 +64,8 @@ import account_report_account_balance import account_change_currency +import pos_box; + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/wizard/pos_box.py b/addons/account/wizard/pos_box.py new file mode 100644 index 00000000000..a9e752397e0 --- /dev/null +++ b/addons/account/wizard/pos_box.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +from osv import osv, fields +import decimal_precision as dp + +class CashBox(osv.osv_memory): + _register = False + _columns = { + 'name' : fields.char('Reason', size=64, required=True), + # Attention, we don't set a domain, because there is a journal_type key + # in the context of the action + 'amount' : fields.float('Amount', + digits_compute = dp.get_precision('Account'), + required=True), + } + + def run(self, cr, uid, ids, context=None): + if not context: + context = dict() + + active_model = context.get('active_model', False) or False + active_ids = context.get('active_ids', []) or [] + + records = self.pool.get(active_model).browse(cr, uid, active_ids, context=context) + + return self._run(cr, uid, ids, records, context=None) + + def _run(self, cr, uid, ids, records, context=None): + for box in self.browse(cr, uid, ids, context=context): + for record in records: + if not record.journal_id.internal_account_id: + raise osv.except_osv(_('Error !'), + _('Please check that internal account is set to %s') % (record.journal_id.name,)) + + self._create_bank_statement_line(cr, uid, box, record, context=context) + + return {} + + +class CashBoxIn(CashBox): + _name = 'cash.box.in' + + _columns = CashBox._columns.copy() + _columns.update({ + 'ref' : fields.char('Reference', size=32), + }) + + def _create_bank_statement_line(self, cr, uid, box, record, context=None): + absl_proxy = self.pool.get('account.bank.statement.line') + + values = { + 'statement_id' : record.id, + 'journal_id' : record.journal_id.id, + 'account_id' : record.journal_id.internal_account_id.id, + 'amount' : box.amount or 0.0, + 'ref' : "%s" % (box.ref or ''), + 'name' : box.name, + } + + return absl_proxy.create(cr, uid, values, context=context) + +CashBoxIn() + +class CashBoxOut(CashBox): + _name = 'cash.box.out' + + def _create_bank_statement_line(self, cr, uid, box, record, context=None): + absl_proxy = self.pool.get('account.bank.statement.line') + + amount = box.amount or 0.0 + values = { + 'statement_id' : record.id, + 'journal_id' : record.journal_id.id, + 'account_id' : record.journal_id.internal_account_id.id, + 'amount' : -amount if amount > 0.0 else amount, + 'name' : box.name, + } + + return absl_proxy.create(cr, uid, values, context=context) + +CashBoxOut() diff --git a/addons/account/wizard/pos_box.xml b/addons/account/wizard/pos_box.xml new file mode 100644 index 00000000000..6136cca06ad --- /dev/null +++ b/addons/account/wizard/pos_box.xml @@ -0,0 +1,62 @@ + + + + + cash_box_in + cash.box.in + form + +
      + + + + + + + +
+ + + + @@ -407,7 +423,7 @@

- Total: 1234 € + Total: 0