[FIX] barcodes, stock, point_of_sale: parse_barcode function uses regex, pattern and barcodes may now contain special characters \ { and ., special character * replaced by .

This commit is contained in:
Aaron Bohy
2014-11-26 12:11:51 +01:00
committed by Frédéric van der Essen
parent f250013329
commit b671824048
6 changed files with 82 additions and 144 deletions
+33 -61
View File
@@ -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),
+1 -1
View File
@@ -11,7 +11,7 @@
<field name="sequence">90</field>
<field name="type">product</field>
<field name="encoding">ean13</field>
<field name="pattern">*</field>
<field name="pattern">.</field>
</record>
</data>
</openerp>
+40 -74
View File
@@ -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; i<barcode.length; i++){ // Read the rest of the barcode
base += barcode[i];
}
if(encoding === "ean13"){
base = self.sanitize_ean(base);
}
return base;
match['match'] = match['base_code'].substr(0,base_pattern.length).match(base_pattern);
return match;
}
// If the nomenclature does not use strict EAN, prepend the barcode with a 0 if it seems
@@ -251,7 +211,8 @@ openerp.barcodes = function(instance) {
if (prepend_zero && rules[i].encoding == 'ean13'){
cur_barcode = '0'+cur_barcode;
}
if (match_pattern(cur_barcode,rules[i].pattern)) {
var match = match_pattern(cur_barcode,rules[i].pattern);
if (match.match) {
if(rules[i].type === 'alias') {
barcode = rules[i].alias;
parsed_result.code = barcode;
@@ -260,9 +221,14 @@ openerp.barcodes = function(instance) {
else {
parsed_result.encoding = rules[i].encoding;
parsed_result.type = rules[i].type;
parsed_result.value = get_value(cur_barcode,rules[i].pattern);
parsed_result.value = match.value
parsed_result.code = cur_barcode;
parsed_result.base_code = get_basecode(cur_barcode,rules[i].pattern,parsed_result.encoding);
if (rules[i].encoding === "ean13"){
parsed_result.base_code = this.sanitize_ean(match.base_code);
}
else{
parsed_result.base_code = match.base_code;
}
return parsed_result;
}
}
@@ -25,7 +25,7 @@
<field name="sequence">36</field>
<field name="type">weight</field>
<field name="encoding">ean13</field>
<field name="pattern">21*****{NNDDD}*</field>
<field name="pattern">21.....{NNDDD}.</field>
</record>
<record id="barcode_rule_discount" model="barcode.rule">
@@ -34,7 +34,7 @@
<field name="sequence">20</field>
<field name="type">discount</field>
<field name="encoding">any</field>
<field name="pattern">22{NN}*</field>
<field name="pattern">22{NN}.</field>
</record>
<record id="barcode_rule_price_two_dec" model="barcode.rule">
@@ -43,7 +43,7 @@
<field name="sequence">14</field>
<field name="type">price</field>
<field name="encoding">ean13</field>
<field name="pattern">23*****{NNNDD}*</field>
<field name="pattern">23.....{NNNDD}.</field>
</record>
</data>
</openerp>
@@ -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);
}
@@ -7,7 +7,7 @@
<field name="sequence">36</field>
<field name="type">weight</field>
<field name="encoding">ean13</field>
<field name="pattern">21*****{NNDDD}*</field>
<field name="pattern">21.....{NNDDD}.</field>
</record>
<record id="barcode_rule_package" model="barcode.rule">
@@ -16,7 +16,7 @@
<field name="sequence">70</field>
<field name="type">package</field>
<field name="encoding">any</field>
<field name="pattern">PACK*</field>
<field name="pattern">PACK.</field>
</record>
<record id="barcode_rule_lot" model="barcode.rule">
@@ -25,7 +25,7 @@
<field name="sequence">80</field>
<field name="type">lot</field>
<field name="encoding">any</field>
<field name="pattern">10*</field>
<field name="pattern">10.</field>
</record>
<record id="barcode_rule_location" model="barcode.rule">
@@ -34,7 +34,7 @@
<field name="sequence">60</field>
<field name="type">location</field>
<field name="encoding">any</field>
<field name="pattern">414*</field>
<field name="pattern">414.</field>
</record>
</data>
</openerp>