[FIX] Barcode nomenclature generalized to Code128 in PoS
This commit is contained in:
committed by
Frédéric van der Essen
parent
809144f8a2
commit
97039fb591
@@ -24,7 +24,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.product_by_reference = {};
|
||||
|
||||
this.partner_sorted = [];
|
||||
this.partner_by_id = {};
|
||||
@@ -201,9 +201,9 @@ function openerp_pos_db(instance, module){
|
||||
if(product.ean13){
|
||||
this.product_by_ean13[product.ean13] = product;
|
||||
}
|
||||
if(product.default_code){
|
||||
/*if(product.default_code){
|
||||
this.product_by_reference[product.default_code] = product;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
},
|
||||
add_packagings: function(packagings){
|
||||
@@ -354,9 +354,9 @@ function openerp_pos_db(instance, module){
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
get_product_by_reference: function(ref){
|
||||
/*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 = [];
|
||||
|
||||
@@ -473,17 +473,16 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
}
|
||||
},
|
||||
|
||||
// when an ean is scanned and parsed, the callback corresponding
|
||||
// to its type is called with the parsed_ean as a parameter.
|
||||
// (parsed_ean is the result of parse_ean(ean))
|
||||
// when a barcode is scanned and parsed, the callback corresponding
|
||||
// to its type is called with the parsed_barcode as a parameter.
|
||||
// (parsed_barcode is the result of parse_barcode(barcode))
|
||||
//
|
||||
// callbacks is a Map of 'actions' : callback(parsed_ean)
|
||||
// callbacks is a Map of 'actions' : callback(parsed_barcode)
|
||||
// that sets the callback for each action. if a callback for the
|
||||
// specified action already exists, it is replaced.
|
||||
//
|
||||
// possible actions include :
|
||||
// 'product' | 'cashier' | 'client' | 'discount'
|
||||
|
||||
set_action_callback: function(action, callback){
|
||||
if(arguments.length == 2){
|
||||
this.action_callback[action] = callback;
|
||||
@@ -501,6 +500,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
this.action_callback[action] = undefined;
|
||||
}
|
||||
},
|
||||
|
||||
// returns the checksum of the ean, or -1 if the ean has not the correct length, ean must be a string
|
||||
ean_checksum: function(ean){
|
||||
var code = ean.split('');
|
||||
@@ -519,11 +519,7 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
total = oddsum * 3 + evensum;
|
||||
return Number((10 - total % 10) % 10);
|
||||
},
|
||||
// returns true if the ean is a valid EAN codebar number by checking the control digit.
|
||||
// ean must be a string
|
||||
check_ean: function(ean){
|
||||
return /^\d+$/.test(ean) && this.ean_checksum(ean) === Number(ean[ean.length-1]);
|
||||
},
|
||||
|
||||
// returns a valid zero padded ean13 from an ean prefix. the ean prefix must be a string.
|
||||
sanitize_ean:function(ean){
|
||||
ean = ean.substr(0,13);
|
||||
@@ -533,63 +529,80 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
}
|
||||
return ean.substr(0,12) + this.ean_checksum(ean);
|
||||
},
|
||||
|
||||
// attempts to interpret an ean (string encoding an ean)
|
||||
// it will check its validity then return an object containing various
|
||||
// information about the ean.
|
||||
|
||||
// attempts to interpret a barcode (string encoding a barcode Code-128)
|
||||
// it will return an object containing various information about the barcode.
|
||||
// most importantly :
|
||||
// - code : the ean
|
||||
// - type : the type of the ean:
|
||||
// 'price' | 'weight' | 'product' | 'cashier' | 'client' | 'discount' | 'error'
|
||||
// - code : the barcode
|
||||
// - type : the type of the barcode:
|
||||
// 'price' | 'weight' | 'product' | 'cashier' | 'client' | 'discount' | 'lot' |
|
||||
// 'package' | 'location' | 'error'
|
||||
//
|
||||
// - value : if the id encodes a numerical value, it will be put there
|
||||
// - base_code : the ean code with all the encoding parts set to zero; the one put on
|
||||
// - value : if the barcode encodes a numerical value, it will be put there
|
||||
// - base_code : the barcode with all the encoding parts set to zero; the one put on
|
||||
// the product in the backend
|
||||
|
||||
parse_ean: function(ean){
|
||||
parse_barcode: function(barcode){
|
||||
var self = this;
|
||||
var parse_result = {
|
||||
encoding: 'ean13',
|
||||
var parsed_result = {
|
||||
encoding: '',
|
||||
type:'error',
|
||||
code:ean,
|
||||
base_code: ean,
|
||||
code:barcode,
|
||||
base_code: barcode,
|
||||
value: 0,
|
||||
};
|
||||
|
||||
if (!this.pos.nomenclature) {
|
||||
return parse_result;
|
||||
return parsed_result;
|
||||
}
|
||||
|
||||
if (!this.check_ean(ean)){
|
||||
return parse_result;
|
||||
}
|
||||
// The barcode can contain any alphanumerical character, including ( and )
|
||||
/*if (!/^[A-Za-z0-9()]+$/.test(barcode)){
|
||||
return parsed_result;
|
||||
}*/
|
||||
|
||||
function is_number(char){
|
||||
var n = char.charCodeAt(0);
|
||||
return n >= 48 && n <= 57;
|
||||
}
|
||||
|
||||
function match_pattern(ean,pattern){
|
||||
for(var i = 0; i < pattern.length; i++){
|
||||
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];
|
||||
var e = ean[i];
|
||||
if( is_number(p) && p !== e ){
|
||||
if(p === "{" || p === "}"){
|
||||
numerical_content = !numerical_content;
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!numerical_content && p !== '*' && p !== barcode[j]){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function get_value(ean,pattern){
|
||||
function get_value(barcode,pattern){
|
||||
var value = 0;
|
||||
var decimals = 0;
|
||||
for(var i = 0; i < pattern.length; i++){
|
||||
var numerical_content = false;
|
||||
for(var i = 0, j = 0; i < pattern.length; i++, j++){
|
||||
var p = pattern[i];
|
||||
var v = parseInt(ean[i]);
|
||||
if( p === 'N'){
|
||||
if(!numerical_content && p !== "{"){
|
||||
continue;
|
||||
}
|
||||
else if(p === "{"){
|
||||
numerical_content = true;
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
else if(p === "}"){
|
||||
break;
|
||||
}
|
||||
|
||||
var v = parseInt(barcode[j]);
|
||||
if(p === 'N'){
|
||||
value *= 10;
|
||||
value += v;
|
||||
}else if( p === 'D'){ // FIXME precision ....
|
||||
}else if(p === 'D'){ // FIXME precision ....
|
||||
decimals += 1;
|
||||
value += v * Math.pow(10,-decimals);
|
||||
}
|
||||
@@ -597,65 +610,58 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
return value;
|
||||
}
|
||||
|
||||
function get_basecode(ean,pattern){
|
||||
function get_basecode(barcode,pattern,encoding){
|
||||
var base = '';
|
||||
for(var i = 0; i < pattern.length; i++){
|
||||
var numerical_content = false;
|
||||
for(var i = 0, j = 0; i < pattern.length; i++, j++){
|
||||
var p = pattern[i];
|
||||
var v = ean[i];
|
||||
if( p === 'x' || is_number(p)){
|
||||
base += v;
|
||||
}else{
|
||||
if(p === "{" || p === "}"){
|
||||
numerical_content = !numerical_content;
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(numerical_content){
|
||||
base += '0';
|
||||
}
|
||||
else{
|
||||
base += barcode[j];
|
||||
}
|
||||
}
|
||||
return self.sanitize_ean(base);
|
||||
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;
|
||||
}
|
||||
|
||||
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,rules[i].pattern);
|
||||
parse_result.base_code = get_basecode(ean,rules[i].pattern);
|
||||
return parse_result;
|
||||
if (match_pattern(barcode,rules[i].pattern)) {
|
||||
parsed_result.encoding = rules[i].encoding;
|
||||
parsed_result.type = rules[i].type;
|
||||
parsed_result.value = get_value(barcode,rules[i].pattern);
|
||||
parsed_result.base_code = get_basecode(barcode,rules[i].pattern,parsed_result.encoding);
|
||||
return parsed_result;
|
||||
}
|
||||
}
|
||||
|
||||
return parse_result;
|
||||
return parsed_result;
|
||||
},
|
||||
|
||||
scan: function(code){
|
||||
if(code.length < 3){
|
||||
return;
|
||||
}else if(code.length === 13 && this.check_ean(code)){
|
||||
var parse_result = this.parse_ean(code);
|
||||
}else if(code.length === 12 && this.check_ean('0'+code)){
|
||||
// many barcode scanners strip the leading zero of ean13 barcodes.
|
||||
// This is because ean-13 are UCP-A with an additional zero at the beginning,
|
||||
// so by stripping zeros you get retrocompatibility with UCP-A systems.
|
||||
var parse_result = this.parse_ean('0'+code);
|
||||
}else if(this.pos.db.get_product_by_reference(code)){
|
||||
var parse_result = {
|
||||
encoding: 'reference',
|
||||
type: 'product',
|
||||
code: code,
|
||||
};
|
||||
}else{
|
||||
var parse_result = {
|
||||
encoding: 'error',
|
||||
type: 'error',
|
||||
code: code,
|
||||
};
|
||||
}
|
||||
|
||||
if(parse_result.type in {'product':'', 'weight':'', 'price':'', 'discount':''}){ //ean is associated to a product
|
||||
var parsed_result = this.parse_barcode(code);
|
||||
|
||||
if(parsed_result.type in {'product':'', 'weight':'', 'price':''}){ //barcode is associated to a product
|
||||
if(this.action_callback['product']){
|
||||
this.action_callback['product'](parse_result);
|
||||
this.action_callback['product'](parsed_result);
|
||||
}
|
||||
}else{
|
||||
if(this.action_callback[parse_result.type]){
|
||||
this.action_callback[parse_result.type](parse_result);
|
||||
}
|
||||
else{
|
||||
if(this.action_callback[parsed_result.type]){
|
||||
this.action_callback[parsed_result.type](parsed_result);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -696,7 +702,9 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||
// Internal Ref 5449 vs EAN13 5449000...
|
||||
|
||||
timeout = setTimeout(function(){
|
||||
self.scan(code);
|
||||
if(code.length >= 3){
|
||||
self.scan(code);
|
||||
}
|
||||
code = "";
|
||||
onlynumbers = true;
|
||||
},100);
|
||||
|
||||
@@ -322,21 +322,21 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
},
|
||||
}, {
|
||||
model: 'barcode.rule',
|
||||
fields: ['name','sequence','type','pattern'],
|
||||
fields: ['name','sequence','type','encoding','pattern'],
|
||||
domain: function(self){ return [['barcode_nomenclature_id','=',self.nomenclature ? self.nomenclature.id : 0]]; },
|
||||
loaded: function(self,rules){
|
||||
if (self.nomenclature) {
|
||||
rules = rules.sort(function(a,b){ return a.sequence - b.sequence; });
|
||||
self.nomenclature.rules = rules;
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
/*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';
|
||||
pattern += '';
|
||||
}
|
||||
rules[i].pattern = pattern;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
},
|
||||
}, {
|
||||
@@ -719,11 +719,11 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||
scan_product: function(parsed_code){
|
||||
var self = this;
|
||||
var selectedOrder = this.get_order();
|
||||
if(parsed_code.encoding === 'ean13'){
|
||||
//if(parsed_code.encoding === 'barcode'){
|
||||
var product = this.db.get_product_by_ean13(parsed_code.base_code);
|
||||
}else if(parsed_code.encoding === 'reference'){
|
||||
/*}else if(parsed_code.encoding === 'reference'){
|
||||
var product = this.db.get_product_by_reference(parsed_code.code);
|
||||
}
|
||||
}*/
|
||||
|
||||
if(!product){
|
||||
return false;
|
||||
|
||||
@@ -233,7 +233,6 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||
this.pos_widget.set_leftpane_visible(this.show_leftpane);
|
||||
|
||||
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(code){ self.barcode_cashier_action(code); } : undefined ,
|
||||
'product': self.barcode_product_action ? function(code){ self.barcode_product_action(code); } : undefined ,
|
||||
|
||||
@@ -138,7 +138,8 @@ class barcode_rule(osv.osv):
|
||||
'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'),('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([('product','Unit Product'),('weight','Weighted Product'),('price','Priced Product'),('discount','Discounted Product'),('client','Client'),('cashier','Cashier')],'Type', required=True),
|
||||
'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([('product','Unit Product'),('weight','Weighted Product'),('price','Priced Product'),('discount','Discounted Product'),('client','Client'),('cashier','Cashier'),('location','Location'),('lot','Lot'),('package','Package')],'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'),
|
||||
}
|
||||
@@ -146,5 +147,5 @@ class barcode_rule(osv.osv):
|
||||
_defaults = {
|
||||
'type': 'product',
|
||||
'pattern': '*',
|
||||
#'encoding': 'any',
|
||||
'encoding': 'any',
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
<tree string='Tables'>
|
||||
<field name="name" />
|
||||
<field name="type" />
|
||||
<field name="encoding" />
|
||||
<field name="pattern" />
|
||||
<field name="sequence" />
|
||||
</tree>
|
||||
@@ -58,6 +59,7 @@
|
||||
<field name="name" />
|
||||
<field name="sequence" />
|
||||
<field name="type" />
|
||||
<field name="encoding"/>
|
||||
<field name="pattern" />
|
||||
</group>
|
||||
</form>
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
<record id="barcode_rule_product" model="barcode.rule">
|
||||
<field name="name">Product Barcodes</field>
|
||||
<field name="barcode_nomenclature_id" ref="default_barcode_nomenclature"/>
|
||||
<field name="sequence">60</field>
|
||||
<field name="sequence">90</field>
|
||||
<field name="type">product</field>
|
||||
<field name="encoding">ean13</field>
|
||||
<field name="pattern">*</field>
|
||||
</record>
|
||||
|
||||
@@ -18,23 +19,26 @@
|
||||
<field name="barcode_nomenclature_id" ref="default_barcode_nomenclature"/>
|
||||
<field name="sequence">50</field>
|
||||
<field name="type">cashier</field>
|
||||
<field name="encoding">any</field>
|
||||
<field name="pattern">041</field>
|
||||
</record>
|
||||
|
||||
<record id="barcode_rule_client" model="barcode.rule">
|
||||
<field name="name">Client Barcodes</field>
|
||||
<field name="name">Customer Barcodes</field>
|
||||
<field name="barcode_nomenclature_id" ref="default_barcode_nomenclature"/>
|
||||
<field name="sequence">40</field>
|
||||
<field name="type">client</field>
|
||||
<field name="encoding">any</field>
|
||||
<field name="pattern">042</field>
|
||||
</record>
|
||||
|
||||
<record id="barcode_rule_weight" model="barcode.rule">
|
||||
<field name="name">Weight Barcodes</field>
|
||||
<record id="barcode_rule_weight_three_dec" model="barcode.rule">
|
||||
<field name="name">Weight Barcodes 3 Decimals</field>
|
||||
<field name="barcode_nomenclature_id" ref="default_barcode_nomenclature"/>
|
||||
<field name="sequence">30</field>
|
||||
<field name="sequence">36</field>
|
||||
<field name="type">weight</field>
|
||||
<field name="pattern">21*****NNDDD*</field>
|
||||
<field name="encoding">ean13</field>
|
||||
<field name="pattern">21*****{NNDDD}*</field>
|
||||
</record>
|
||||
|
||||
<record id="barcode_rule_discount" model="barcode.rule">
|
||||
@@ -42,15 +46,44 @@
|
||||
<field name="barcode_nomenclature_id" ref="default_barcode_nomenclature"/>
|
||||
<field name="sequence">20</field>
|
||||
<field name="type">discount</field>
|
||||
<field name="pattern">22********NN*</field>
|
||||
<field name="encoding">any</field>
|
||||
<field name="pattern">22{NN}*</field>
|
||||
</record>
|
||||
|
||||
<record id="barcode_rule_price" model="barcode.rule">
|
||||
<field name="name">Price Barcodes</field>
|
||||
<record id="barcode_rule_price_two_dec" model="barcode.rule">
|
||||
<field name="name">Price Barcodes 2 Decimals</field>
|
||||
<field name="barcode_nomenclature_id" ref="default_barcode_nomenclature"/>
|
||||
<field name="sequence">10</field>
|
||||
<field name="sequence">14</field>
|
||||
<field name="type">price</field>
|
||||
<field name="pattern">23*****NNNDD*</field>
|
||||
<field name="encoding">ean13</field>
|
||||
<field name="pattern">23*****{NNNDD}*</field>
|
||||
</record>
|
||||
|
||||
<record id="barcode_rule_package" model="barcode.rule">
|
||||
<field name="name">Package barcodes</field>
|
||||
<field name="barcode_nomenclature_id" ref="default_barcode_nomenclature"/>
|
||||
<field name="sequence">70</field>
|
||||
<field name="type">package</field>
|
||||
<field name="encoding">any</field>
|
||||
<field name="pattern">PACK*</field>
|
||||
</record>
|
||||
|
||||
<record id="barcode_rule_lot" model="barcode.rule">
|
||||
<field name="name">Lot barcodes</field>
|
||||
<field name="barcode_nomenclature_id" ref="default_barcode_nomenclature"/>
|
||||
<field name="sequence">80</field>
|
||||
<field name="type">lot</field>
|
||||
<field name="encoding">any</field>
|
||||
<field name="pattern">10*</field>
|
||||
</record>
|
||||
|
||||
<record id="barcode_rule_location" model="barcode.rule">
|
||||
<field name="name">Location barcodes</field>
|
||||
<field name="barcode_nomenclature_id" ref="default_barcode_nomenclature"/>
|
||||
<field name="sequence">60</field>
|
||||
<field name="type">location</field>
|
||||
<field name="encoding">any</field>
|
||||
<field name="pattern">414*</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user