diff --git a/addons/point_of_sale/controllers/main.py b/addons/point_of_sale/controllers/main.py index de757238d6f..419f5bc2efa 100644 --- a/addons/point_of_sale/controllers/main.py +++ b/addons/point_of_sale/controllers/main.py @@ -82,7 +82,7 @@ class PointOfSaleController(http.Controller): """ print 'scan_item_success: ' + str(ean) - @http.route('/pos/scan_item_error_unrecognized') + @http.route('/pos/scan_item_error_unrecognized', type='json', auth='admin') def scan_item_error_unrecognized(self, ean): """ A product has been scanned without success diff --git a/addons/point_of_sale/static/src/js/db.js b/addons/point_of_sale/static/src/js/db.js index bb0acfb285c..66791bb3c8b 100644 --- a/addons/point_of_sale/static/src/js/db.js +++ b/addons/point_of_sale/static/src/js/db.js @@ -43,6 +43,7 @@ function openerp_pos_db(instance, module){ this.product_by_id = {}; this.product_by_ean13 = {}; this.product_by_category_id = {}; + this.product_by_reference = {}; this.category_by_id = {}; this.root_category_id = 0; @@ -197,6 +198,9 @@ function openerp_pos_db(instance, module){ if(product.ean13){ this.product_by_ean13[product.ean13] = product; } + if(product.default_code){ + this.product_by_reference[product.default_code] = product; + } } }, add_packagings: function(packagings){ @@ -241,6 +245,9 @@ function openerp_pos_db(instance, module){ } return undefined; }, + get_product_by_reference: function(ref){ + return this.product_by_reference[ref]; + }, get_product_by_category: function(category_id){ var product_ids = this.product_by_category_id[category_id]; var list = []; diff --git a/addons/point_of_sale/static/src/js/devices.js b/addons/point_of_sale/static/src/js/devices.js index 1d35a0cc08b..a34714bad3e 100644 --- a/addons/point_of_sale/static/src/js/devices.js +++ b/addons/point_of_sale/static/src/js/devices.js @@ -450,7 +450,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal // it will check its validity then return an object containing various // information about the ean. // most importantly : - // - ean : the ean + // - code : the ean // - type : the type of the ean: // 'price' | 'weight' | 'unit' | 'cashier' | 'client' | 'discount' | 'error' // @@ -460,13 +460,16 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal // - unit : if the encoded value has a unit, it will be put there. // not to be confused with the 'unit' type, which represent an unit of a // unique product + // - base_code : the ean code with all the encoding parts set to zero; the one put on + // the product in the backend parse_ean: function(ean){ var parse_result = { - type:'unknown', // + encoding: 'ean13', + type:'unknown', prefix:'', - ean:ean, - base_ean: ean, + code:ean, + base_code: ean, id:'', value: 0, unit: 'none', @@ -487,13 +490,13 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal parse_result.type = 'error'; } else if( match_prefix(this.price_prefix_set,'price')){ parse_result.id = ean.substring(0,7); - parse_result.base_ean = this.sanitize_ean(ean.substring(0,7)); + parse_result.base_code = this.sanitize_ean(ean.substring(0,7)); parse_result.value = Number(ean.substring(7,12))/100.0; parse_result.unit = 'euro'; } else if( match_prefix(this.weight_prefix_set,'weight')){ parse_result.id = ean.substring(0,7); parse_result.value = Number(ean.substring(7,12))/1000.0; - parse_result.base_ean = this.sanitize_ean(ean.substring(0,7)); + parse_result.base_code = this.sanitize_ean(ean.substring(0,7)); parse_result.unit = 'Kg'; } else if( match_prefix(this.client_prefix_set,'client')){ parse_result.id = ean.substring(0,7); @@ -502,7 +505,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal parse_result.id = ean.substring(0,7); } else if( match_prefix(this.discount_prefix_set,'discount')){ parse_result.id = ean.substring(0,7); - parse_result.base_ean = this.sanitize_ean(ean.substring(0,7)); + parse_result.base_code = this.sanitize_ean(ean.substring(0,7)); parse_result.value = Number(ean.substring(7,12))/100.0; parse_result.unit = '%'; } else { @@ -512,9 +515,19 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal } return parse_result; }, - - on_ean: function(ean){ - var parse_result = this.parse_ean(ean); + + scan: function(type,code){ + console.log('scan',type,code); + if (type === 'ean13'){ + var parse_result = this.parse_ean(code); + }else if(type === 'reference'){ + var parse_result = { + encoding: 'reference', + type: 'unit', + code: code, + prefix: '', + }; + } if (parse_result.type === 'error') { //most likely a checksum error, raise warning console.warn('WARNING: barcode checksum error:',parse_result); @@ -522,7 +535,6 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal if(this.action_callback['product']){ this.action_callback['product'](parse_result); } - //this.trigger("codebar",parse_result ); }else{ if(this.action_callback[parse_result.type]){ this.action_callback[parse_result.type](parse_result); @@ -530,41 +542,43 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal } }, + on_reference: function(code){ + if(this.action_callback['reference']){ + this.action_callback['reference'](code); + } + }, + // starts catching keyboard events and tries to interpret codebar // calling the callbacks when needed. connect: function(){ + var self = this; - var codeNumbers = []; - var timeStamp = 0; - var lastTimeStamp = 0; + var code = ""; + var timeStamp = 0; + var onlynumbers = true; - // 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. this.handler = function(e){ - //We only care about numbers - if (e.which >= 48 && e.which < 58){ + if(timeStamp + 50 < new Date().getTime()){ + code = ""; + onlynumbers = true; + } - // 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.which - 48); - lastTimeStamp = new Date().getTime(); - if (codeNumbers.length === 13) { - //We have found what seems to be a valid codebar - self.on_ean(codeNumbers.join('')); - codeNumbers = []; - } - } else { - // NaN - codeNumbers = []; + timeStamp = new Date().getTime(); + + if( e.which < 48 || e.which >= 58 ){ // not a number + onlynumbers = false; + } + + code += String.fromCharCode(e.which); + + if(code.length >= 2 && self.pos.db.get_product_by_reference(code)){ + self.scan('reference',code); + code = ""; + onlynumbers = true; + }else if(code.length === 13 && onlynumbers){ + self.scan('ean13',code); + code = ""; + onlynumbers = true; } }; $('body').on('keypress', this.handler); diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index f0200bf434c..e47101ce27d 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -428,19 +428,23 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal return tried_all; }, - scan_product: function(parsed_ean){ + scan_product: function(parsed_code){ var self = this; - var product = this.db.get_product_by_ean13(parsed_ean.base_ean); var selectedOrder = this.get('selectedOrder'); + if(parsed_code.encoding === 'ean13'){ + var product = this.db.get_product_by_ean13(parsed_code.base_code); + }else if(parsed_code.encoding === 'reference'){ + var product = this.db.get_product_by_reference(parsed_code.code); + } if(!product){ return false; } - if(parsed_ean.type === 'price'){ - selectedOrder.addProduct(new module.Product(product), {price:parsed_ean.value}); - }else if(parsed_ean.type === 'weight'){ - selectedOrder.addProduct(new module.Product(product), {quantity:parsed_ean.value, merge:false}); + if(parsed_code.type === 'price'){ + selectedOrder.addProduct(new module.Product(product), {price:parsed_code.value}); + }else if(parsed_code.type === 'weight'){ + selectedOrder.addProduct(new module.Product(product), {quantity:parsed_code.value, merge:false}); }else{ selectedOrder.addProduct(new module.Product(product)); } diff --git a/addons/point_of_sale/static/src/js/screens.js b/addons/point_of_sale/static/src/js/screens.js index 4d453099690..77a542ff93c 100644 --- a/addons/point_of_sale/static/src/js/screens.js +++ b/addons/point_of_sale/static/src/js/screens.js @@ -160,29 +160,29 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa // what happens when a product is scanned : // it will add the product to the order and go to barcode_product_screen. Or show barcode_product_error_popup if // there's an error. - barcode_product_action: function(ean){ + barcode_product_action: function(code){ var self = this; - if(self.pos.scan_product(ean)){ - self.pos.proxy.scan_item_success(ean); + if(self.pos.scan_product(code)){ + self.pos.proxy.scan_item_success(code); if(self.barcode_product_screen){ self.pos_widget.screen_selector.set_current_screen(self.barcode_product_screen); } }else{ - self.pos.proxy.scan_item_error_unrecognized(ean); + self.pos.proxy.scan_item_error_unrecognized(code); if(self.barcode_product_error_popup && self.pos_widget.screen_selector.get_user_mode() !== 'cashier'){ self.pos_widget.screen_selector.show_popup(self.barcode_product_error_popup); } } }, - + // what happens when a cashier id barcode is scanned. // the default behavior is the following : // - if there's a user with a matching ean, put it as the active 'cashier', go to cashier mode, and return true // - else : do nothing and return false. You probably want to extend this to show and appropriate error popup... - barcode_cashier_action: function(ean){ + barcode_cashier_action: function(code){ var users = this.pos.get('user_list'); for(var i = 0, len = users.length; i < len; i++){ - if(users[i].ean13 === ean.ean){ + if(users[i].ean13 === code.code){ this.pos.set('cashier',users[i]); this.pos_widget.username.refresh(); this.pos.proxy.cashier_mode_activated(); @@ -190,7 +190,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa return true; } } - this.pos.proxy.scan_item_error_unrecognized(ean); + this.pos.proxy.scan_item_error_unrecognized(code); return false; }, @@ -198,28 +198,28 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa // the default behavior is the following : // - if there's a user with a matching ean, put it as the active 'client' and return true // - else : return false. - barcode_client_action: function(ean){ + barcode_client_action: function(code){ var partners = this.pos.get('partner_list'); for(var i = 0, len = partners.length; i < len; i++){ - if(partners[i].ean13 === ean.ean){ + if(partners[i].ean13 === code.code){ this.pos.get('selectedOrder').set_client(partners[i]); this.pos_widget.username.refresh(); - this.pos.proxy.scan_item_success(ean); + this.pos.proxy.scan_item_success(code); return true; } } - this.pos.proxy.scan_item_error_unrecognized(ean); + this.pos.proxy.scan_item_error_unrecognized(code); return false; //TODO start the transaction }, // what happens when a discount barcode is scanned : the default behavior // is to set the discount on the last order. - barcode_discount_action: function(ean){ - this.pos.proxy.scan_item_success(ean); + barcode_discount_action: function(code){ + this.pos.proxy.scan_item_success(code); var last_orderline = this.pos.get('selectedOrder').getLastOrderline(); if(last_orderline){ - last_orderline.set_discount(ean.value) + last_orderline.set_discount(code.value) } }, @@ -292,10 +292,10 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.pos_widget.username.set_user_mode(this.pos_widget.screen_selector.get_user_mode()); this.pos.barcode_reader.set_action_callback({ - 'cashier': self.barcode_cashier_action ? function(ean){ self.barcode_cashier_action(ean); } : undefined , - 'product': self.barcode_product_action ? function(ean){ self.barcode_product_action(ean); } : undefined , - 'client' : self.barcode_client_action ? function(ean){ self.barcode_client_action(ean); } : undefined , - 'discount': self.barcode_discount_action ? function(ean){ self.barcode_discount_action(ean); } : undefined, + 'cashier': self.barcode_cashier_action ? function(code){ self.barcode_cashier_action(code); } : undefined , + 'product': self.barcode_product_action ? function(code){ self.barcode_product_action(code); } : undefined , + 'client' : self.barcode_client_action ? function(code){ self.barcode_client_action(code); } : undefined , + 'discount': self.barcode_discount_action ? function(code){ self.barcode_discount_action(code); } : undefined, }); }, @@ -405,7 +405,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa this.pos.barcode_reader.save_callbacks(); this.pos.barcode_reader.reset_action_callbacks(); this.pos.barcode_reader.set_action_callback({ - 'cashier': function(ean){ + 'cashier': function(code){ clearInterval(this.intervalID); self.pos.proxy.cashier_mode_activated(); self.pos_widget.screen_selector.set_user_mode('cashier'); @@ -683,14 +683,14 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa show_numpad: false, show_leftpane: false, - barcode_product_action: function(ean){ + barcode_product_action: function(code){ this.pos.proxy.transaction_start(); - this._super(ean); + this._super(code); }, - barcode_client_action: function(ean){ + barcode_client_action: function(code){ this.pos.proxy.transaction_start(); - this._super(ean); + this._super(code); $('.goodbye-message').addClass('oe_hidden'); this.pos_widget.screen_selector.show_popup('choose-receipt'); }, diff --git a/addons/point_of_sale/static/src/js/widgets.js b/addons/point_of_sale/static/src/js/widgets.js index b83da0ac8ab..291c8bfdaae 100644 --- a/addons/point_of_sale/static/src/js/widgets.js +++ b/addons/point_of_sale/static/src/js/widgets.js @@ -744,12 +744,15 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa this.$('.button.custom_ean').click(function(){ var ean = self.pos.barcode_reader.sanitize_ean(self.$('input.ean').val() || '0'); self.$('input.ean').val(ean); - self.pos.barcode_reader.on_ean(ean); + self.pos.barcode_reader.scan('ean13',ean); + }); + this.$('.button.reference').click(function(){ + self.pos.barcode_reader.scan('reference',self.$('input.ean').val()); }); _.each(this.eans, function(ean, name){ self.$('.button.'+name).click(function(){ self.$('input.ean').val(ean); - self.pos.barcode_reader.on_ean(ean); + self.pos.barcode_reader.scan('ean13',ean); }); }); _.each(this.events, function(name){ diff --git a/addons/point_of_sale/static/src/xml/pos.xml b/addons/point_of_sale/static/src/xml/pos.xml index d9f021fc219..d5f57e099f7 100644 --- a/addons/point_of_sale/static/src/xml/pos.xml +++ b/addons/point_of_sale/static/src/xml/pos.xml @@ -494,6 +494,7 @@
Hardware Status