From e4098be07d65029b25135e3eb8ffb3e622ae464e Mon Sep 17 00:00:00 2001 From: CarmenMiranda Date: Tue, 3 May 2022 19:46:53 +0000 Subject: [PATCH 1/3] [FIX] barcodes: Parsing Barcodes (Multiple Rules Apply) Now when the Barcode match with multiple barcode patterns in the rules of the Barcode Nomenclatures all the possible matching will be returned instead of only returning the first option. This will solve the issue that exists when more than one rule has the same barcode pattern [1] and allow doing those searches and not only searching for one option when the result can be in the second option. For example, before this change having the "Customer Barcodes" and "Product Barcodes" with the same pattern `.*` as rules in the Barcode Nomenclatures if we scan in the POS the barcode "0020200002" the first that applies will be the customer for the sequence in the POS if we search for a product with the barcode "0020200002" the first rule will be "Customer" for the sequence and if there is no customer with that barcode it will return an error saying "The Point of Sale could not find any product, client, employee or action associated with the scanned barcode." which is not true because there is a product with that barcode. Now it will return both rules instead of only the first one, also we add in the results the rule that is matching in order to keep the return almost the same as in the module `barcodes_gs1_nomenclature` in the method `parse_gs1_rule_pattern` (that is inside of their parser) returns the rule and the `stock_barcode` module in Odoo Enterprise use it. [1] [Issue 90353: Unknown Barcode in POS when Product exists](https://github.com/odoo/odoo/issues/90353) --- .../barcodes/static/src/js/barcode_parser.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/addons/barcodes/static/src/js/barcode_parser.js b/addons/barcodes/static/src/js/barcode_parser.js index 37408ef816ed6..d3a47a18b1b74 100644 --- a/addons/barcodes/static/src/js/barcode_parser.js +++ b/addons/barcodes/static/src/js/barcode_parser.js @@ -196,6 +196,7 @@ var BarcodeParser = Class.extend({ * - base_code: the barcode with all the encoding parts set to zero; the one put on the product in the backend */ parse_barcode: function(barcode){ + var results = []; var parsed_result = { encoding: '', type:'error', @@ -230,27 +231,29 @@ var BarcodeParser = Class.extend({ var match = this.match_pattern(cur_barcode, rules[i].pattern, rule.encoding); if (match.match) { + var parsed_result_tmp = {...parsed_result}; if(rules[i].type === 'alias') { barcode = rules[i].alias; parsed_result.code = barcode; parsed_result.type = 'alias'; } else { - parsed_result.encoding = rules[i].encoding; - parsed_result.type = rules[i].type; - parsed_result.value = match.value; - parsed_result.code = cur_barcode; + parsed_result_tmp.encoding = rules[i].encoding; + parsed_result_tmp.type = rules[i].type; + parsed_result_tmp.value = match.value; + parsed_result_tmp.code = cur_barcode; if (rules[i].encoding === "ean13"){ - parsed_result.base_code = this.sanitize_ean(match.base_code); + parsed_result_tmp.base_code = this.sanitize_ean(match.base_code); } else{ - parsed_result.base_code = match.base_code; + parsed_result_tmp.base_code = match.base_code; } - return parsed_result; + parsed_result_tmp.rule = rules[i]; + results.push(parsed_result_tmp); } } } - return parsed_result; + return results || parsed_result; }, //-------------------------------------------------------------------------- From 2eb74a20efcd5489d14551b50af9dd5850dee974 Mon Sep 17 00:00:00 2001 From: CarmenMiranda Date: Tue, 3 May 2022 19:36:29 +0000 Subject: [PATCH 2/3] [FIX] point_of_sale: Barcode Error As we can now have multiple rules (Barcode Nomenclatures) that apply in the parse of the barcode we have multiple parsed results that we can search in the scanning process we had to avoid showing the error of the function `_barcodeErrorAction` when we have more parsed results to search into so now we only want to show it when is the last result and none of the callbacks returned a successful response. --- .../js/Screens/ProductScreen/ProductScreen.js | 8 ++++++ .../static/src/js/barcode_reader.js | 25 ++++++++++++++----- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductScreen.js b/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductScreen.js index c8c088e42f003..99db9d74aa328 100644 --- a/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductScreen.js +++ b/addons/point_of_sale/static/src/js/Screens/ProductScreen/ProductScreen.js @@ -307,6 +307,7 @@ odoo.define('point_of_sale.ProductScreen', function(require) { }); } await this.currentOrder.add_product(product, options); + return true; } _barcodeClientAction(code) { const partner = this.env.pos.db.get_partner_by_barcode(code.code); @@ -324,6 +325,7 @@ odoo.define('point_of_sale.ProductScreen', function(require) { var last_orderline = this.currentOrder.get_last_orderline(); if (last_orderline) { last_orderline.set_discount(code.value); + return true; } } /** @@ -333,6 +335,9 @@ odoo.define('point_of_sale.ProductScreen', function(require) { */ async _barcodeGS1Action(parsed_results) { const productBarcode = parsed_results.find(element => element.type === 'product'); + if (!productBarcode) { + return this._barcodeErrorAction(parsed_results); + } const lotBarcode = parsed_results.find(element => element.type === 'lot'); const product = await this._getProductByBarcode(productBarcode); if (!product) { @@ -346,6 +351,9 @@ odoo.define('point_of_sale.ProductScreen', function(require) { // Why? Because once we start declaring barcode actions in different // screens, these methods will also be declared over and over. _barcodeErrorAction(code) { + if (this.env.pos.show_barcode_error_modal === false) { + return ; + } this.showPopup('ErrorBarcodePopup', { code: this._codeRepr(code) }); } _codeRepr(code) { diff --git a/addons/point_of_sale/static/src/js/barcode_reader.js b/addons/point_of_sale/static/src/js/barcode_reader.js index e28f376b35f19..17f9bcc042fc5 100644 --- a/addons/point_of_sale/static/src/js/barcode_reader.js +++ b/addons/point_of_sale/static/src/js/barcode_reader.js @@ -19,6 +19,7 @@ var BarcodeReader = core.Class.extend({ init: function (attributes) { this.mutex = new Mutex(); this.pos = attributes.pos; + this.pos.show_barcode_error_modal = true; this.action_callbacks = {}; this.exclusive_callbacks = {}; this.proxy = attributes.proxy; @@ -110,13 +111,25 @@ var BarcodeReader = core.Class.extend({ const callbacks = Object.keys(this.exclusive_callbacks).length ? this.exclusive_callbacks : this.action_callbacks; - let parsed_result = this.barcode_parser.parse_barcode(code); - if (Array.isArray(parsed_result)) { - [...callbacks.gs1].map(cb => cb(parsed_result)); - } else { - if (callbacks[parsed_result.type]) { + // TODO: Fix this since gs1 nomenclatures could return more than one results + // https://github.com/odoo-dev/odoo/blob/a764f029514a45a77f4fb977ee1306a510aeefa2/addons/barcodes_gs1_nomenclature/static/src/js/barcode_parser.js#L105 + // This conflicts with the actual patch that try to find all the rules applying to the barcode + // in order to ensure the proper fiding of it. + let parsed_results = this.barcode_parser.parse_barcode(code); + if (! Array.isArray(parsed_results)) { + parsed_results = [parsed_results]; + } + parsed_results_loop: for (const [index, parsed_result] of parsed_results.entries()) { + let is_last_index = index + 1 === parsed_results.length; + this.pos.show_barcode_error_modal = is_last_index; + if (callbacks.gs1) { + [...callbacks.gs1].map(cb => cb([parsed_result])); + } else if (callbacks[parsed_result.type]) { for (const cb of callbacks[parsed_result.type]) { - await cb(parsed_result); + let result_callback = await cb(parsed_result); + if (result_callback) { + break parsed_results_loop; + } } } else if (callbacks.error) { [...callbacks.error].map(cb => cb(parsed_result)); From 387394c78b0974a7a7d0c956ddc99cab40381c00 Mon Sep 17 00:00:00 2001 From: Hugo Adan Date: Thu, 13 Jun 2024 01:58:55 +0000 Subject: [PATCH 3/3] [FIX] point_of_sale: make compatible gs1 nomenclatures with Scanning Barcodes (Multiple Rules Apply) Fix this since gs1 nomenclatures could return more than one result https://github.com/odoo-dev/odoo/blob/a764f029514a45a77f4fb977ee1306a510aeefa2/addons/barcodes_gs1_nomenclature/static/src/js/barcode_parser.js#L105 This conflicts with the actual patch that try to find all the rules applying to the barcode in order to ensure the proper fiding of it. Now we filter out parsed results by the type of the nomenclature they belong --- .../static/src/js/barcode_reader.js | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/addons/point_of_sale/static/src/js/barcode_reader.js b/addons/point_of_sale/static/src/js/barcode_reader.js index 17f9bcc042fc5..1681191b070f5 100644 --- a/addons/point_of_sale/static/src/js/barcode_reader.js +++ b/addons/point_of_sale/static/src/js/barcode_reader.js @@ -111,30 +111,29 @@ var BarcodeReader = core.Class.extend({ const callbacks = Object.keys(this.exclusive_callbacks).length ? this.exclusive_callbacks : this.action_callbacks; - // TODO: Fix this since gs1 nomenclatures could return more than one results - // https://github.com/odoo-dev/odoo/blob/a764f029514a45a77f4fb977ee1306a510aeefa2/addons/barcodes_gs1_nomenclature/static/src/js/barcode_parser.js#L105 - // This conflicts with the actual patch that try to find all the rules applying to the barcode - // in order to ensure the proper fiding of it. let parsed_results = this.barcode_parser.parse_barcode(code); if (! Array.isArray(parsed_results)) { parsed_results = [parsed_results]; } - parsed_results_loop: for (const [index, parsed_result] of parsed_results.entries()) { - let is_last_index = index + 1 === parsed_results.length; - this.pos.show_barcode_error_modal = is_last_index; - if (callbacks.gs1) { - [...callbacks.gs1].map(cb => cb([parsed_result])); - } else if (callbacks[parsed_result.type]) { - for (const cb of callbacks[parsed_result.type]) { - let result_callback = await cb(parsed_result); - if (result_callback) { - break parsed_results_loop; + let gs1_parsed_results = parsed_results.filter((result) => !!result.rule.gs1_content_type) + if (gs1_parsed_results.length){ + [...callbacks.gs1].map(cb => cb(gs1_parsed_results)); + }else { + parsed_results_loop: for (const [index, parsed_result] of parsed_results.filter((result) => !result.rule.gs1_content_type).entries()) { + let is_last_index = index + 1 === parsed_results.length; + this.pos.show_barcode_error_modal = is_last_index; + if (callbacks[parsed_result.type]) { + for (const cb of callbacks[parsed_result.type]) { + let result_callback = await cb(parsed_result); + if (result_callback) { + break parsed_results_loop; + } } + } else if (callbacks.error) { + [...callbacks.error].map(cb => cb(parsed_result)); + } else { + console.warn('Ignored Barcode Scan:', parsed_result); } - } else if (callbacks.error) { - [...callbacks.error].map(cb => cb(parsed_result)); - } else { - console.warn('Ignored Barcode Scan:', parsed_result); } } },