[IMP] point_of_sale: support for non ean13 barcodes using the Internal Reference...
authorFrédéric van der Essen <fva@openerp.com>
Mon, 23 Sep 2013 14:51:39 +0000 (16:51 +0200)
committerFrédéric van der Essen <fva@openerp.com>
Mon, 23 Sep 2013 14:51:39 +0000 (16:51 +0200)
bzr revid: fva@openerp.com-20130923145139-iu3ds9tcfzy1ffcf

addons/point_of_sale/controllers/main.py
addons/point_of_sale/static/src/js/db.js
addons/point_of_sale/static/src/js/devices.js
addons/point_of_sale/static/src/js/models.js
addons/point_of_sale/static/src/js/screens.js
addons/point_of_sale/static/src/js/widgets.js
addons/point_of_sale/static/src/xml/pos.xml

index de75723..419f5bc 100644 (file)
@@ -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
index bb0acfb..66791bb 100644 (file)
@@ -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 = [];
index 1d35a0c..a34714b 100644 (file)
@@ -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){
-
-                    // 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 = [];
+                if(timeStamp + 50 < new Date().getTime()){
+                    code = "";
+                    onlynumbers = true;
+                }
+
+                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);
index f0200bf..e47101c 100644 (file)
@@ -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));
             }
index 4d45309..77a542f 100644 (file)
@@ -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');
         },
index e36161e..5f03ef5 100644 (file)
@@ -753,12 +753,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){
index d9f021f..d5f57e0 100644 (file)
                     <li class="button lemon_price">1.54€ Lemon</li>
                     <li class="button unknown_product">Unknown Product</li>
                     <li class="button invalid_ean">Invalid Ean</li>
+                    <li class="button reference">Reference</li>
                 </ul>
 
                 <p class="category">Hardware Status</p>