From e92963fb78ca093f5acdad8e436a133e35399fbe Mon Sep 17 00:00:00 2001 From: Frederic van der Essen Date: Wed, 1 Oct 2014 00:37:04 +0200 Subject: [PATCH] [WIP] pos_barcodes: initial commit of the barcode nomenclature addon for the point of sale --- addons/point_of_sale/static/src/js/devices.js | 2 +- addons/pos_barcodes/__init__.py | 25 ++++ addons/pos_barcodes/__openerp__.py | 51 ++++++++ addons/pos_barcodes/barcodes.py | 64 +++++++++ addons/pos_barcodes/barcodes_view.xml | 80 ++++++++++++ addons/pos_barcodes/static/src/js/barcodes.js | 123 ++++++++++++++++++ addons/pos_barcodes/views/templates.xml | 14 ++ 7 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 addons/pos_barcodes/__init__.py create mode 100644 addons/pos_barcodes/__openerp__.py create mode 100644 addons/pos_barcodes/barcodes.py create mode 100644 addons/pos_barcodes/barcodes_view.xml create mode 100644 addons/pos_barcodes/static/src/js/barcodes.js create mode 100644 addons/pos_barcodes/views/templates.xml diff --git a/addons/point_of_sale/static/src/js/devices.js b/addons/point_of_sale/static/src/js/devices.js index 5e813b9d73c..09595c087dc 100644 --- a/addons/point_of_sale/static/src/js/devices.js +++ b/addons/point_of_sale/static/src/js/devices.js @@ -635,7 +635,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal if( p === 'N'){ value *= 10; value += v; - }else if( p === 'D'){ + }else if( p === 'D'){ // FIXME precision .... decimals += 1; value += v * Math.pow(10,-decimals); } diff --git a/addons/pos_barcodes/__init__.py b/addons/pos_barcodes/__init__.py new file mode 100644 index 00000000000..e69cfb845e3 --- /dev/null +++ b/addons/pos_barcodes/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import barcodes + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/addons/pos_barcodes/__openerp__.py b/addons/pos_barcodes/__openerp__.py new file mode 100644 index 00000000000..afd208fe0a9 --- /dev/null +++ b/addons/pos_barcodes/__openerp__.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'Advanced Barcodes', + 'version': '1.0', + 'category': 'Point of Sale', + 'sequence': 6, + 'summary': 'Advanced Barcode Setup for the Point of Sale', + 'description': """ + +======================= + +This module unlocks several advanced barcode features for the point of sale: + +- Barcode aliases allows you to identify the same product with different barcodes +- Barcode patterns to identify customers, employees, weighted, discounted, and custom priced products +- Unlimited barcode patterns and definitions. + +""", + 'author': 'OpenERP SA', + 'depends': ['point_of_sale'], + 'website': 'https://www.odoo.com/page/point-of-sale', + 'data': [ + 'barcodes_view.xml', + 'views/templates.xml', + ], + 'installable': True, + 'auto_install': False, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/pos_barcodes/barcodes.py b/addons/pos_barcodes/barcodes.py new file mode 100644 index 00000000000..492f573e86f --- /dev/null +++ b/addons/pos_barcodes/barcodes.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import logging + +import openerp +from openerp import tools +from openerp.osv import fields, osv +from openerp.tools.translate import _ + +_logger = logging.getLogger(__name__) + +class barcode_nomenclature(osv.osv): + _name = 'barcode.nomenclature' + _columns = { + 'name': fields.char('Nomenclature Name', size=32, required=True, help='An internal identification of the barcode nomenclature'), + #'convert_to_ean13': fields.boolean('Convert to EAN-13',help='Numerical Barcodes shorter than EAN-13 will be automatically converted to EAN-13'), + 'pos_config_ids': fields.one2many('pos.config','barcode_nomenclature_id','Point of Sale', help='The Point of Sales using this barcode nomenclature'), + 'rule_ids': fields.one2many('barcode.rule','barcode_nomenclature_id','Rules', help='The list of barcode rules'), + } + +class barcode_rule(osv.osv): + _name = 'barcode.rule' + _columns = { + 'name': fields.char('Rule Name', size=32, required=True, help='An internal identification for this barcode nomenclature rule'), + 'barcode_nomenclature_id': fields.many2one('barcode.nomenclature','Barcode Nomenclature'), + 'priority': fields.float('Priority', help='Rules with a higher priority match first'), + #'encoding': fields.selection([('any','Any'),('ean13','EAN-13'),('ean8','EAN-8'),('codabar','Codabar'),('upca','UPC-A'),('upce','UPC-E')],'Encoding',help='This rule will apply only if the barcode is encoded with the specified encoding'), + 'type': fields.selection([('unit','Unit Product'),('weight','Weighted Product'),('price','Priced Product'),('discount','Discounted Product'),('client','Client'),('cashier','Cashier')],'Type', required=True), + 'pattern': fields.char('Barcode Pattern', size=32, help="The barcode matching pattern"), + #'alias': fields.char('Alias',size=32,help='The matched pattern will alias to this barcode'), + } + + _defaults = { + 'type': 'unit', + 'pattern': '*', + #'encoding': 'any', + } + +class pos_config(osv.osv): + _inherit = 'pos.config' + _columns = { + 'barcode_nomenclature_id': fields.many2one('barcode.nomenclature','Barcode Nomenclature', help='A barcode nomenclature'), + } + + diff --git a/addons/pos_barcodes/barcodes_view.xml b/addons/pos_barcodes/barcodes_view.xml new file mode 100644 index 00000000000..30e6b237bce --- /dev/null +++ b/addons/pos_barcodes/barcodes_view.xml @@ -0,0 +1,80 @@ + + + + + + + + Barcode Nomenclatures + barcode.nomenclature + +
+ + + + + + + + + + + + + +
+
+
+ + + Barcode Nomenclatures + barcode.nomenclature + + + + + + + + + Barcode Nomenclatures + ir.actions.act_window + barcode.nomenclature + form + tree,form + +

+ Click to add a Barcode Nomenclature . +

+ A barcode nomenclature defines how the point of sale identify and interprets barcodes +

+
+
+ + + Barcode Rule + barcode.rule + +
+ + + + + + + + +
+
+
+ + + + +
+
diff --git a/addons/pos_barcodes/static/src/js/barcodes.js b/addons/pos_barcodes/static/src/js/barcodes.js new file mode 100644 index 00000000000..460a12c7e97 --- /dev/null +++ b/addons/pos_barcodes/static/src/js/barcodes.js @@ -0,0 +1,123 @@ +openerp.pos_barcodes = function(instance){ + var module = instance.point_of_sale; + var _t = instance.web._t; + + // At POS Startup, load the barcode nomenclature and add it to the pos model + module.PosModel.prototype.models.push({ + model: 'barcode.nomenclature', + fields: ['name','rule_ids'], + domain: function(self){ return [] }, + loaded: function(self,nomenclatures){ + if (self.config.barcode_nomenclature_id) { + for (var i = 0; i < nomenclatures.length; i++) { + if (nomenclatures[i].id === self.config.barcode_nomenclature_id[0]) { + self.nomenclature = nomenclatures[i]; + } + } + } + self.nomenclature = self.nomenclature || null; + }, + }); + + module.PosModel.prototype.models.push({ + model: 'barcode.rule', + fields: ['name','priority','type','pattern'], + domain: function(self){ return [['barcode_nomenclature_id','=',self.nomenclature ? self.nomenclature.id : 0]]; }, + loaded: function(self,rules){ + rules = rules.sort(function(a,b){ return b.priority - a.priority; }); + self.nomenclature.rules = rules; + for (var i = 0; i < rules.length; i++) { + var pattern = rules[i].pattern; + pattern = pattern.replace(/[x\*]/gi,'x'); + + while (pattern.length < 12) { + pattern += 'x'; + } + + rules[i].pattern = pattern; + } + }, + }); + + module.BarcodeReader.include({ + parse_ean: function(ean) { + var self = this; + var parse_result = { + encoding: 'ean13', + type: 'error', + code: ean, + base_code: ean, + value: 0, + }; + + if (!this.pos.nomenclature) { + return this._super(ean); + } + + if (!this.check_ean(ean)) { + return parse_result; + } + + function is_number(char) { + n = char.charCodeAt(0); + return n >= 48 && n <= 57; + } + + function match_pattern(ean,pattern) { + for (var i = 0; i < pattern.length; i++) { + var p = pattern[i]; + var e = ean[i]; + if( is_number(p) && p !== e ){ + return false; + } + } + return true; + } + + function get_value(ean,pattern){ + var value = 0; + var decimals = 0; + for(var i = 0; i < pattern.length; i++){ + var p = pattern[i]; + var v = parseInt(ean[i]); + if( p === 'N'){ + value *= 10; + value += v; + }else if( p === 'D'){ // FIXME precision ... + decimals += 1; + value += v * Math.pow(10,-decimals); + } + } + return value; + } + + function get_basecode(ean,pattern){ + var base = ''; + for(var i = 0; i < pattern.length; i++){ + var p = pattern[i]; + var v = ean[i]; + if( p === 'x' || is_number(p)){ + base += v; + }else{ + base += '0'; + } + } + return self.sanitize_ean(base); + } + + var rules = this.pos.nomenclature.rules; + + for (var i = 0; i < rules.length; i++) { + if (match_pattern(ean,rules[i].pattern)) { + parse_result.type = rules[i].type; + parse_result.value = get_value(ean,patterns[i].pattern); + parse_result.base_code = get_basecode(ean,patterns[i].pattern); + return parse_result; + } + } + + return parse_result; + }, + }); + +}; diff --git a/addons/pos_barcodes/views/templates.xml b/addons/pos_barcodes/views/templates.xml new file mode 100644 index 00000000000..9f2b3575cbd --- /dev/null +++ b/addons/pos_barcodes/views/templates.xml @@ -0,0 +1,14 @@ + + + + + + + + +