From b671824048969f2c42806076f96377f3e36ca2a1 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Fri, 14 Nov 2014 12:39:31 +0100 Subject: [PATCH] [FIX] barcodes, stock, point_of_sale: parse_barcode function uses regex, pattern and barcodes may now contain special characters \ { and ., special character * replaced by . --- addons/barcodes/barcodes.py | 94 +++++---------- addons/barcodes/data/barcodes_data.xml | 2 +- .../barcodes/static/src/js/barcode_parser.js | 114 ++++++------------ .../data/default_barcode_patterns.xml | 6 +- addons/point_of_sale/static/src/js/devices.js | 2 +- .../stock/data/default_barcode_patterns.xml | 8 +- 6 files changed, 82 insertions(+), 144 deletions(-) diff --git a/addons/barcodes/barcodes.py b/addons/barcodes/barcodes.py index 60a8d4c78fc..53be165c84b 100644 --- a/addons/barcodes/barcodes.py +++ b/addons/barcodes/barcodes.py @@ -88,69 +88,37 @@ class barcode_nomenclature(osv.osv): 'base_code': barcode, 'value': 0} - def match_pattern(barcode,pattern): - if(len(barcode) < len(pattern.replace('{','').replace('}',''))): - return False # match of this pattern is impossible - numerical_content = False - j=0 - for i in range(len(pattern)): - p = pattern[i] - if p == '{' or p == '}': - numerical_content = not numerical_content - continue + def match_pattern(barcode, pattern): + match = { + "value": 0, + "base_code": barcode, + "match": False, + } - if not numerical_content and p != '*' and p != barcode[j]: - return False - j+=1 - return True + barcode = barcode.replace("\\", "\\\\").replace("{", '\{').replace("}", "\}").replace(".", "\.") + numerical_content = re.search("[{][N]*[D]*[}]", pattern) - def get_value(barcode,pattern): - value = 0 - decimals = 0 - numerical_content = False - j = 0 - for i in range(len(pattern)): - p = pattern[i] - if not numerical_content and p != "{": - j+=1 - continue - elif p == "{": - numerical_content = True - continue - elif p == "}": - break; + if numerical_content: + num_start = numerical_content.start() + num_end = numerical_content.end() + value_string = barcode[num_start:num_end-2] - v = int(barcode[j]) - if p == 'N': - value *= 10 - value += v - elif p == 'D': #FIXME precision .... - decimals += 1 - value += v * pow(10,-decimals) - j+=1 - return value + whole_part_match = re.search("[{][N]*[D}]", numerical_content.group()) + decimal_part_match = re.search("[{N][D]*[}]", numerical_content.group()) + whole_part = value_string[:whole_part_match.end()-2] + decimal_part = "0." + value_string[decimal_part_match.start():decimal_part_match.end()-1] + if whole_part == '': + whole_part = '0' + match['value'] = int(whole_part) + float(decimal_part) - def get_basecode(barcode,pattern,encoding): - base = '' - numerical_content = False - j = 0 - for i in range(len(pattern)): - p = pattern[i] - if p == '{' or p == '}': - numerical_content = not numerical_content - continue + match['base_code'] = barcode[:num_start] + (num_end-num_start-2)*"0" + barcode[num_end-2:] + match['base_code'] = match['base_code'].replace("\\\\", "\\").replace("\{", "{").replace("\}","}").replace("\.",".") + pattern = pattern[:num_start] + (num_end-num_start-2)*"0" + pattern[num_end:] - if numerical_content: - base += '0' - else: - base += barcode[j] - j+=1 + match['match'] = re.match(pattern, match['base_code'][:len(pattern)]) + + return match - for i in range(j, len(barcode)): # Read the rest of the barcode - base += barcode[i] - if encoding == "ean13": - base = self.sanitize_ean(base) - return base rules = [] for rule in self.rule_ids: @@ -166,16 +134,21 @@ class barcode_nomenclature(osv.osv): cur_barcode = barcode if prepend_zero and rule['encoding'] == "ean13": cur_barcode = '0'+cur_barcode - if match_pattern(cur_barcode, rule['pattern']): + + match = match_pattern(cur_barcode, rule['pattern']) + if match['match']: if rule['type'] == 'alias': barcode = rule['alias'] parsed_result['code'] = barcode else: parsed_result['encoding'] = rule['encoding'] parsed_result['type'] = rule['type'] - parsed_result['value'] = get_value(cur_barcode, rule['pattern']) + parsed_result['value'] = match['value'] parsed_result['code'] = cur_barcode - parsed_result['base_code'] = get_basecode(cur_barcode, rule['pattern'], parsed_result['encoding']) + if rule['encoding'] == "ean13": + parsed_result['base_code'] = self.sanitize_ean(match['base_code']) + else: + parsed_result['base_code'] = match['base_code'] return parsed_result return parsed_result @@ -193,7 +166,6 @@ class barcode_rule(models.Model): 'barcode_nomenclature_id': fields.many2one('barcode.nomenclature','Barcode Nomenclature'), 'sequence': fields.integer('Sequence', help='Used to order rules such that rules with a smaller sequence match first'), 'encoding': fields.selection([('any','Any'),('ean13','EAN-13')],'Encoding',required=True,help='This rule will apply only if the barcode is encoded with the specified encoding'), - #'type': fields.selection([('alias','Alias'),('product','Unit Product')],'Type', required=True), 'type': fields.selection('_get_type_selection','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',required=True), diff --git a/addons/barcodes/data/barcodes_data.xml b/addons/barcodes/data/barcodes_data.xml index 4ad60aa7fec..8d33995669a 100644 --- a/addons/barcodes/data/barcodes_data.xml +++ b/addons/barcodes/data/barcodes_data.xml @@ -11,7 +11,7 @@ 90 product ean13 - * + . \ No newline at end of file diff --git a/addons/barcodes/static/src/js/barcode_parser.js b/addons/barcodes/static/src/js/barcode_parser.js index 18823d645de..3d9a5eb2907 100644 --- a/addons/barcodes/static/src/js/barcode_parser.js +++ b/addons/barcodes/static/src/js/barcode_parser.js @@ -162,81 +162,41 @@ openerp.barcodes = function(instance) { return parsed_result; } - function match_pattern(barcode,pattern){ - if(barcode.length < pattern.replace(/[{}]/g, '').length){ - return false; // Match of this pattern is impossible - } - var numerical_content = false; // Used to detect when we are between { } - for(var i = 0, j = 0; i < pattern.length; i++, j++){ - var p = pattern[i]; - if(p === "{" || p === "}"){ - numerical_content = !numerical_content; - j--; - continue; - } - - if(!numerical_content && p !== '*' && p !== barcode[j]){ - return false; - } - } - return true; - } - - function get_value(barcode,pattern){ - var value = 0; - var decimals = 0; - var numerical_content = false; - for(var i = 0, j = 0; i < pattern.length; i++, j++){ - var p = pattern[i]; - if(!numerical_content && p !== "{"){ - continue; - } - else if(p === "{"){ - numerical_content = true; - j--; - continue; - } - else if(p === "}"){ - break; - } + function match_pattern(barcode, pattern){ + var match = { + value: 0, + base_code: barcode, + match: false, + }; + barcode = barcode.replace("\\", "\\\\").replace("{", '\{').replace("}", "\}").replace(".", "\."); - var v = parseInt(barcode[j]); - if(p === 'N'){ - value *= 10; - value += v; - }else if(p === 'D'){ // FIXME precision .... - decimals += 1; - value += v * Math.pow(10,-decimals); + var numerical_content = pattern.match(/[{][N]*[D]*[}]/); + var base_pattern = pattern; + if(numerical_content){ + var num_start = numerical_content.index; + var num_length = numerical_content[0].length; + var value_string = barcode.substr(num_start, num_length-2); + var whole_part_match = numerical_content[0].match("[{][N]*[D}]"); + var decimal_part_match = numerical_content[0].match("[{N][D]*[}]"); + var whole_part = value_string.substr(0, whole_part_match.index+whole_part_match[0].length-2); + var decimal_part = "0." + value_string.substr(decimal_part_match.index, decimal_part_match[0].length-1); + if (whole_part === ''){ + whole_part = '0'; } + match['value'] = parseInt(whole_part) + parseFloat(decimal_part); + match['base_code'] = barcode.substr(0,num_start); + var base_pattern = pattern.substr(0,num_start); + for(var i=0;i<(num_length-2);i++) { + match['base_code'] += "0"; + base_pattern += "0"; + } + match['base_code'] += barcode.substr(num_start+num_length-2,barcode.length-1); + base_pattern += pattern.substr(num_start+num_length,pattern.length-1); + match['base_code'] = match['base_code'].replace("\\\\", "\\").replace("\{", "{").replace("\}","}").replace("\.","."); } - return value; - } - function get_basecode(barcode,pattern,encoding){ - var base = ''; - var numerical_content = false; - for(var i = 0, j = 0; i < pattern.length; i++, j++){ - var p = pattern[i]; - if(p === "{" || p === "}"){ - numerical_content = !numerical_content; - j--; - continue; - } - - if(numerical_content){ - base += '0'; - } - else{ - base += barcode[j]; - } - } - for(i=j; i36 weight ean13 - 21*****{NNDDD}* + 21.....{NNDDD}. @@ -34,7 +34,7 @@ 20 discount any - 22{NN}* + 22{NN}. @@ -43,7 +43,7 @@ 14 price ean13 - 23*****{NNNDD}* + 23.....{NNNDD}. \ No newline at end of file diff --git a/addons/point_of_sale/static/src/js/devices.js b/addons/point_of_sale/static/src/js/devices.js index 4e2cce1c0e9..1b4202676de 100644 --- a/addons/point_of_sale/static/src/js/devices.js +++ b/addons/point_of_sale/static/src/js/devices.js @@ -515,7 +515,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal this.action_callback['product'](parsed_result); } } - else if (parsed_result.type in {'cashier':'', 'client':''}){ + else if (parsed_result.type in {'cashier':'', 'client':'', 'discount':''}){ if(this.action_callback[parsed_result.type]){ this.action_callback[parsed_result.type](parsed_result); } diff --git a/addons/stock/data/default_barcode_patterns.xml b/addons/stock/data/default_barcode_patterns.xml index 5d62bcd1861..a9eed0f27cc 100644 --- a/addons/stock/data/default_barcode_patterns.xml +++ b/addons/stock/data/default_barcode_patterns.xml @@ -7,7 +7,7 @@ 36 weight ean13 - 21*****{NNDDD}* + 21.....{NNDDD}. @@ -16,7 +16,7 @@ 70 package any - PACK* + PACK. @@ -25,7 +25,7 @@ 80 lot any - 10* + 10. @@ -34,7 +34,7 @@ 60 location any - 414* + 414. \ No newline at end of file