From 05ffbd28a13bb0a01fde7bb86241fc961f17d42e Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Tue, 3 Apr 2012 15:05:28 +0200 Subject: [PATCH] [MERGE] point_of_sale barcode scanning (manual merge) bzr revid: al@openerp.com-20120403130528-8awtj91yoa64gi61 --- addons/account/res_currency.py | 3 +- addons/point_of_sale/point_of_sale_demo.xml | 3 + addons/point_of_sale/static/src/js/pos.js | 405 ++++++++++++-------- addons/point_of_sale/static/src/xml/pos.xml | 3 + addons/product/product.py | 2 +- 5 files changed, 247 insertions(+), 169 deletions(-) diff --git a/addons/account/res_currency.py b/addons/account/res_currency.py index 8c9c6a8b103..8e02836274a 100644 --- a/addons/account/res_currency.py +++ b/addons/account/res_currency.py @@ -44,4 +44,5 @@ 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: + diff --git a/addons/point_of_sale/point_of_sale_demo.xml b/addons/point_of_sale/point_of_sale_demo.xml index d86d27e04dd..1ec37579ed2 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,12 +680,14 @@ 1.00 Leffe Brune 33cl + 5410228142164 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 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 359173e2261..574af72eecd 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) { @@ -85,7 +69,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'], [['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']), @@ -223,57 +208,28 @@ openerp.point_of_sale = function(db) { Models --- */ - var CashRegister = (function() { - __extends(CashRegister, Backbone.Model); - function CashRegister() { - CashRegister.__super__.constructor.apply(this, arguments); - } - 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. @@ -351,91 +307,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) { @@ -447,8 +385,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 */ @@ -456,38 +394,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()]); @@ -496,7 +434,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(), @@ -505,26 +443,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() @@ -542,15 +469,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. @@ -617,6 +544,7 @@ openerp.point_of_sale = function(db) { } }, }); + /* --- Views @@ -774,6 +702,7 @@ openerp.point_of_sale = function(db) { }, on_selected: function() {}, }); + var OrderWidget = db.web.OldWidget.extend({ init: function(parent, options) { this._super(parent); @@ -855,6 +784,7 @@ openerp.point_of_sale = function(db) { $('#total').html(total.toFixed(2)).hide().fadeIn(); }, }); + /* "Products" step. */ @@ -893,6 +823,7 @@ openerp.point_of_sale = function(db) { }, on_change_category: function(id) {}, }); + var ProductWidget = db.web.OldWidget.extend({ tag_name:'li', template_fct: qweb_template('pos-product-template'), @@ -915,6 +846,7 @@ openerp.point_of_sale = function(db) { return this; }, }); + var ProductListWidget = db.web.OldWidget.extend({ init: function(parent, options) { this._super(parent); @@ -1066,6 +998,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); @@ -1108,6 +1041,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({ tag_name: 'li', template_fct: qweb_template('pos-order-selector-button-template'), @@ -1147,6 +1081,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); @@ -1227,7 +1162,9 @@ openerp.point_of_sale = function(db) { } }, }); + var App = (function() { + function App($element) { this.initialize($element); } @@ -1243,22 +1180,153 @@ 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.render_element(); 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; }); (this.shop.get('products')).reset(products); - var self = this; + + + //returns true if the code is a valid EAN codebar number by checking the control digit. + var checkEan = function(code) { + 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); + } + 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 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; + 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; + } + + // 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 + if (!isNaN(Number(String.fromCharCode(e.keyCode)))) { + + // 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 { + if (lastTimeStamp + 30 < new Date().getTime()) { + // not a barcode reader + codeNumbers = []; + timeStamp = new Date().getTime(); + } + } + codeNumbers.push(e.keyCode - 48); + lastTimeStamp = new Date().getTime(); + if (codeNumbers.length == 13) { + // a barcode reader + if (!checkEan(codeNumbers)) { + // 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" ); + return; + }, + } + }); + } + var selectedOrder = self.shop.get('selectedOrder'); + var scannedProductModel = getProductByEAN(codeNumbers.join('')); + if (scannedProductModel === undefined) { + // product not recognized, raise warning + $(QWeb.render('pos-scan-warning')).dialog({ + resizable: false, + height:220, + modal: true, + title: "Warning", + buttons: { + "OK": function() { + $( this ).dialog( "close" ); + return; + }, + } + }); + } else { + selectedOrder.addProduct(new Product(scannedProductModel)); + } + + codeNumbers = []; + } + } else { + // NaN + codeNumbers = []; + } + }); + $('.searchbox input').keyup(function() { var m, s; s = $(this).val().toLowerCase(); @@ -1274,7 +1342,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(); }); @@ -1374,6 +1442,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) { 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?
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')),