[IMP] point_of_sale: support for non ean13 barcodes using the Internal Reference field
bzr revid: fva@openerp.com-20130923145139-iu3ds9tcfzy1ffcf
This commit is contained in:
parent
13f6d59043
commit
e03f3aa288
|
@ -82,7 +82,7 @@ class PointOfSaleController(http.Controller):
|
||||||
"""
|
"""
|
||||||
print 'scan_item_success: ' + str(ean)
|
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):
|
def scan_item_error_unrecognized(self, ean):
|
||||||
"""
|
"""
|
||||||
A product has been scanned without success
|
A product has been scanned without success
|
||||||
|
|
|
@ -43,6 +43,7 @@ function openerp_pos_db(instance, module){
|
||||||
this.product_by_id = {};
|
this.product_by_id = {};
|
||||||
this.product_by_ean13 = {};
|
this.product_by_ean13 = {};
|
||||||
this.product_by_category_id = {};
|
this.product_by_category_id = {};
|
||||||
|
this.product_by_reference = {};
|
||||||
|
|
||||||
this.category_by_id = {};
|
this.category_by_id = {};
|
||||||
this.root_category_id = 0;
|
this.root_category_id = 0;
|
||||||
|
@ -197,6 +198,9 @@ function openerp_pos_db(instance, module){
|
||||||
if(product.ean13){
|
if(product.ean13){
|
||||||
this.product_by_ean13[product.ean13] = product;
|
this.product_by_ean13[product.ean13] = product;
|
||||||
}
|
}
|
||||||
|
if(product.default_code){
|
||||||
|
this.product_by_reference[product.default_code] = product;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
add_packagings: function(packagings){
|
add_packagings: function(packagings){
|
||||||
|
@ -241,6 +245,9 @@ function openerp_pos_db(instance, module){
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
|
get_product_by_reference: function(ref){
|
||||||
|
return this.product_by_reference[ref];
|
||||||
|
},
|
||||||
get_product_by_category: function(category_id){
|
get_product_by_category: function(category_id){
|
||||||
var product_ids = this.product_by_category_id[category_id];
|
var product_ids = this.product_by_category_id[category_id];
|
||||||
var list = [];
|
var list = [];
|
||||||
|
|
|
@ -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
|
// it will check its validity then return an object containing various
|
||||||
// information about the ean.
|
// information about the ean.
|
||||||
// most importantly :
|
// most importantly :
|
||||||
// - ean : the ean
|
// - code : the ean
|
||||||
// - type : the type of the ean:
|
// - type : the type of the ean:
|
||||||
// 'price' | 'weight' | 'unit' | 'cashier' | 'client' | 'discount' | 'error'
|
// '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.
|
// - 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
|
// not to be confused with the 'unit' type, which represent an unit of a
|
||||||
// unique product
|
// 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){
|
parse_ean: function(ean){
|
||||||
var parse_result = {
|
var parse_result = {
|
||||||
type:'unknown', //
|
encoding: 'ean13',
|
||||||
|
type:'unknown',
|
||||||
prefix:'',
|
prefix:'',
|
||||||
ean:ean,
|
code:ean,
|
||||||
base_ean: ean,
|
base_code: ean,
|
||||||
id:'',
|
id:'',
|
||||||
value: 0,
|
value: 0,
|
||||||
unit: 'none',
|
unit: 'none',
|
||||||
|
@ -487,13 +490,13 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||||
parse_result.type = 'error';
|
parse_result.type = 'error';
|
||||||
} else if( match_prefix(this.price_prefix_set,'price')){
|
} else if( match_prefix(this.price_prefix_set,'price')){
|
||||||
parse_result.id = ean.substring(0,7);
|
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.value = Number(ean.substring(7,12))/100.0;
|
||||||
parse_result.unit = 'euro';
|
parse_result.unit = 'euro';
|
||||||
} else if( match_prefix(this.weight_prefix_set,'weight')){
|
} else if( match_prefix(this.weight_prefix_set,'weight')){
|
||||||
parse_result.id = ean.substring(0,7);
|
parse_result.id = ean.substring(0,7);
|
||||||
parse_result.value = Number(ean.substring(7,12))/1000.0;
|
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';
|
parse_result.unit = 'Kg';
|
||||||
} else if( match_prefix(this.client_prefix_set,'client')){
|
} else if( match_prefix(this.client_prefix_set,'client')){
|
||||||
parse_result.id = ean.substring(0,7);
|
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);
|
parse_result.id = ean.substring(0,7);
|
||||||
} else if( match_prefix(this.discount_prefix_set,'discount')){
|
} else if( match_prefix(this.discount_prefix_set,'discount')){
|
||||||
parse_result.id = ean.substring(0,7);
|
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.value = Number(ean.substring(7,12))/100.0;
|
||||||
parse_result.unit = '%';
|
parse_result.unit = '%';
|
||||||
} else {
|
} else {
|
||||||
|
@ -512,9 +515,19 @@ function openerp_pos_devices(instance,module){ //module is instance.point_of_sal
|
||||||
}
|
}
|
||||||
return parse_result;
|
return parse_result;
|
||||||
},
|
},
|
||||||
|
|
||||||
on_ean: function(ean){
|
scan: function(type,code){
|
||||||
var parse_result = this.parse_ean(ean);
|
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
|
if (parse_result.type === 'error') { //most likely a checksum error, raise warning
|
||||||
console.warn('WARNING: barcode checksum error:',parse_result);
|
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']){
|
if(this.action_callback['product']){
|
||||||
this.action_callback['product'](parse_result);
|
this.action_callback['product'](parse_result);
|
||||||
}
|
}
|
||||||
//this.trigger("codebar",parse_result );
|
|
||||||
}else{
|
}else{
|
||||||
if(this.action_callback[parse_result.type]){
|
if(this.action_callback[parse_result.type]){
|
||||||
this.action_callback[parse_result.type](parse_result);
|
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
|
// starts catching keyboard events and tries to interpret codebar
|
||||||
// calling the callbacks when needed.
|
// calling the callbacks when needed.
|
||||||
connect: function(){
|
connect: function(){
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var codeNumbers = [];
|
var code = "";
|
||||||
var timeStamp = 0;
|
var timeStamp = 0;
|
||||||
var lastTimeStamp = 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){
|
this.handler = function(e){
|
||||||
//We only care about numbers
|
if(timeStamp + 50 < new Date().getTime()){
|
||||||
if (e.which >= 48 && e.which < 58){
|
code = "";
|
||||||
|
onlynumbers = true;
|
||||||
|
}
|
||||||
|
|
||||||
// The barcode reader sends keystrokes with a specific interval.
|
timeStamp = new Date().getTime();
|
||||||
// We look if the typed keys fit in the interval.
|
|
||||||
if (codeNumbers.length === 0) {
|
if( e.which < 48 || e.which >= 58 ){ // not a number
|
||||||
timeStamp = new Date().getTime();
|
onlynumbers = false;
|
||||||
} else {
|
}
|
||||||
if (lastTimeStamp + 30 < new Date().getTime()) {
|
|
||||||
// not a barcode reader
|
code += String.fromCharCode(e.which);
|
||||||
codeNumbers = [];
|
|
||||||
timeStamp = new Date().getTime();
|
if(code.length >= 2 && self.pos.db.get_product_by_reference(code)){
|
||||||
}
|
self.scan('reference',code);
|
||||||
}
|
code = "";
|
||||||
codeNumbers.push(e.which - 48);
|
onlynumbers = true;
|
||||||
lastTimeStamp = new Date().getTime();
|
}else if(code.length === 13 && onlynumbers){
|
||||||
if (codeNumbers.length === 13) {
|
self.scan('ean13',code);
|
||||||
//We have found what seems to be a valid codebar
|
code = "";
|
||||||
self.on_ean(codeNumbers.join(''));
|
onlynumbers = true;
|
||||||
codeNumbers = [];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// NaN
|
|
||||||
codeNumbers = [];
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$('body').on('keypress', this.handler);
|
$('body').on('keypress', this.handler);
|
||||||
|
|
|
@ -428,19 +428,23 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
|
||||||
return tried_all;
|
return tried_all;
|
||||||
},
|
},
|
||||||
|
|
||||||
scan_product: function(parsed_ean){
|
scan_product: function(parsed_code){
|
||||||
var self = this;
|
var self = this;
|
||||||
var product = this.db.get_product_by_ean13(parsed_ean.base_ean);
|
|
||||||
var selectedOrder = this.get('selectedOrder');
|
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){
|
if(!product){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(parsed_ean.type === 'price'){
|
if(parsed_code.type === 'price'){
|
||||||
selectedOrder.addProduct(new module.Product(product), {price:parsed_ean.value});
|
selectedOrder.addProduct(new module.Product(product), {price:parsed_code.value});
|
||||||
}else if(parsed_ean.type === 'weight'){
|
}else if(parsed_code.type === 'weight'){
|
||||||
selectedOrder.addProduct(new module.Product(product), {quantity:parsed_ean.value, merge:false});
|
selectedOrder.addProduct(new module.Product(product), {quantity:parsed_code.value, merge:false});
|
||||||
}else{
|
}else{
|
||||||
selectedOrder.addProduct(new module.Product(product));
|
selectedOrder.addProduct(new module.Product(product));
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,29 +160,29 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
// what happens when a product is scanned :
|
// 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
|
// 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.
|
// there's an error.
|
||||||
barcode_product_action: function(ean){
|
barcode_product_action: function(code){
|
||||||
var self = this;
|
var self = this;
|
||||||
if(self.pos.scan_product(ean)){
|
if(self.pos.scan_product(code)){
|
||||||
self.pos.proxy.scan_item_success(ean);
|
self.pos.proxy.scan_item_success(code);
|
||||||
if(self.barcode_product_screen){
|
if(self.barcode_product_screen){
|
||||||
self.pos_widget.screen_selector.set_current_screen(self.barcode_product_screen);
|
self.pos_widget.screen_selector.set_current_screen(self.barcode_product_screen);
|
||||||
}
|
}
|
||||||
}else{
|
}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'){
|
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);
|
self.pos_widget.screen_selector.show_popup(self.barcode_product_error_popup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// what happens when a cashier id barcode is scanned.
|
// what happens when a cashier id barcode is scanned.
|
||||||
// the default behavior is the following :
|
// 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
|
// - 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...
|
// - 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');
|
var users = this.pos.get('user_list');
|
||||||
for(var i = 0, len = users.length; i < len; i++){
|
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.set('cashier',users[i]);
|
||||||
this.pos_widget.username.refresh();
|
this.pos_widget.username.refresh();
|
||||||
this.pos.proxy.cashier_mode_activated();
|
this.pos.proxy.cashier_mode_activated();
|
||||||
|
@ -190,7 +190,7 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.pos.proxy.scan_item_error_unrecognized(ean);
|
this.pos.proxy.scan_item_error_unrecognized(code);
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -198,28 +198,28 @@ function openerp_pos_screens(instance, module){ //module is instance.point_of_sa
|
||||||
// the default behavior is the following :
|
// the default behavior is the following :
|
||||||
// - if there's a user with a matching ean, put it as the active 'client' and return true
|
// - if there's a user with a matching ean, put it as the active 'client' and return true
|
||||||
// - else : return false.
|
// - else : return false.
|
||||||
barcode_client_action: function(ean){
|
barcode_client_action: function(code){
|
||||||
var partners = this.pos.get('partner_list');
|
var partners = this.pos.get('partner_list');
|
||||||
for(var i = 0, len = partners.length; i < len; i++){
|
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.get('selectedOrder').set_client(partners[i]);
|
||||||
this.pos_widget.username.refresh();
|
this.pos_widget.username.refresh();
|
||||||
this.pos.proxy.scan_item_success(ean);
|
this.pos.proxy.scan_item_success(code);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.pos.proxy.scan_item_error_unrecognized(ean);
|
this.pos.proxy.scan_item_error_unrecognized(code);
|
||||||
return false;
|
return false;
|
||||||
//TODO start the transaction
|
//TODO start the transaction
|
||||||
},
|
},
|
||||||
|
|
||||||
// what happens when a discount barcode is scanned : the default behavior
|
// what happens when a discount barcode is scanned : the default behavior
|
||||||
// is to set the discount on the last order.
|
// is to set the discount on the last order.
|
||||||
barcode_discount_action: function(ean){
|
barcode_discount_action: function(code){
|
||||||
this.pos.proxy.scan_item_success(ean);
|
this.pos.proxy.scan_item_success(code);
|
||||||
var last_orderline = this.pos.get('selectedOrder').getLastOrderline();
|
var last_orderline = this.pos.get('selectedOrder').getLastOrderline();
|
||||||
if(last_orderline){
|
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_widget.username.set_user_mode(this.pos_widget.screen_selector.get_user_mode());
|
||||||
|
|
||||||
this.pos.barcode_reader.set_action_callback({
|
this.pos.barcode_reader.set_action_callback({
|
||||||
'cashier': self.barcode_cashier_action ? function(ean){ self.barcode_cashier_action(ean); } : undefined ,
|
'cashier': self.barcode_cashier_action ? function(code){ self.barcode_cashier_action(code); } : undefined ,
|
||||||
'product': self.barcode_product_action ? function(ean){ self.barcode_product_action(ean); } : undefined ,
|
'product': self.barcode_product_action ? function(code){ self.barcode_product_action(code); } : undefined ,
|
||||||
'client' : self.barcode_client_action ? function(ean){ self.barcode_client_action(ean); } : undefined ,
|
'client' : self.barcode_client_action ? function(code){ self.barcode_client_action(code); } : undefined ,
|
||||||
'discount': self.barcode_discount_action ? function(ean){ self.barcode_discount_action(ean); } : 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.save_callbacks();
|
||||||
this.pos.barcode_reader.reset_action_callbacks();
|
this.pos.barcode_reader.reset_action_callbacks();
|
||||||
this.pos.barcode_reader.set_action_callback({
|
this.pos.barcode_reader.set_action_callback({
|
||||||
'cashier': function(ean){
|
'cashier': function(code){
|
||||||
clearInterval(this.intervalID);
|
clearInterval(this.intervalID);
|
||||||
self.pos.proxy.cashier_mode_activated();
|
self.pos.proxy.cashier_mode_activated();
|
||||||
self.pos_widget.screen_selector.set_user_mode('cashier');
|
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_numpad: false,
|
||||||
show_leftpane: false,
|
show_leftpane: false,
|
||||||
barcode_product_action: function(ean){
|
barcode_product_action: function(code){
|
||||||
this.pos.proxy.transaction_start();
|
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.pos.proxy.transaction_start();
|
||||||
this._super(ean);
|
this._super(code);
|
||||||
$('.goodbye-message').addClass('oe_hidden');
|
$('.goodbye-message').addClass('oe_hidden');
|
||||||
this.pos_widget.screen_selector.show_popup('choose-receipt');
|
this.pos_widget.screen_selector.show_popup('choose-receipt');
|
||||||
},
|
},
|
||||||
|
|
|
@ -753,12 +753,15 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
|
||||||
this.$('.button.custom_ean').click(function(){
|
this.$('.button.custom_ean').click(function(){
|
||||||
var ean = self.pos.barcode_reader.sanitize_ean(self.$('input.ean').val() || '0');
|
var ean = self.pos.barcode_reader.sanitize_ean(self.$('input.ean').val() || '0');
|
||||||
self.$('input.ean').val(ean);
|
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){
|
_.each(this.eans, function(ean, name){
|
||||||
self.$('.button.'+name).click(function(){
|
self.$('.button.'+name).click(function(){
|
||||||
self.$('input.ean').val(ean);
|
self.$('input.ean').val(ean);
|
||||||
self.pos.barcode_reader.on_ean(ean);
|
self.pos.barcode_reader.scan('ean13',ean);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
_.each(this.events, function(name){
|
_.each(this.events, function(name){
|
||||||
|
|
|
@ -494,6 +494,7 @@
|
||||||
<li class="button lemon_price">1.54€ Lemon</li>
|
<li class="button lemon_price">1.54€ Lemon</li>
|
||||||
<li class="button unknown_product">Unknown Product</li>
|
<li class="button unknown_product">Unknown Product</li>
|
||||||
<li class="button invalid_ean">Invalid Ean</li>
|
<li class="button invalid_ean">Invalid Ean</li>
|
||||||
|
<li class="button reference">Reference</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p class="category">Hardware Status</p>
|
<p class="category">Hardware Status</p>
|
||||||
|
|
Loading…
Reference in New Issue