From bce80def3ac07103deb43a774ddd0f48b5bf62dd Mon Sep 17 00:00:00 2001 From: "Pedram (PEBR)" Date: Tue, 22 Aug 2023 13:30:03 +0000 Subject: [PATCH] [FIX] point_of_sale: improved GS1 Barcode Recognition for PoS Before this commit, when a regular barcode, like '3700000000370', which could be interpreted using GS1 rules, was scanned in PoS, it was incorrectly identified as a GS1 barcode even though it didn't contain a product reference. This commit addresses this issue by implementing a validation check during barcode scanning. The system now verifies whether a scanned barcode conforms to GS1 rules and contains a product reference. This ensures accurate barcode recognition. opw-3468158 closes odoo/odoo#134069 X-original-commit: a62a9ef5f3a0067ed5eb772f850f6ef0fefb6821 Signed-off-by: Joseph Caburnay (jcb) Signed-off-by: Pedram Bi Ria (pebr) --- .../src/app/barcode/barcode_reader_service.js | 3 ++ .../tests/tours/BarcodeScanning.tour.js | 32 +++++++++++++++++ addons/point_of_sale/tests/test_frontend.py | 34 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/addons/point_of_sale/static/src/app/barcode/barcode_reader_service.js b/addons/point_of_sale/static/src/app/barcode/barcode_reader_service.js index 61f6b8d5d8e..ea9822872f3 100644 --- a/addons/point_of_sale/static/src/app/barcode/barcode_reader_service.js +++ b/addons/point_of_sale/static/src/app/barcode/barcode_reader_service.js @@ -56,6 +56,9 @@ export class BarcodeReader { let parseBarcode; try { parseBarcode = this.parser.parse_barcode(code); + if (Array.isArray(parseBarcode) && !parseBarcode.some(element => element.type === 'product')) { + throw new GS1BarcodeError('The GS1 barcode must contain a product.'); + } } catch (error) { if (this.fallbackParser && error instanceof GS1BarcodeError) { parseBarcode = this.fallbackParser.parse_barcode(code); diff --git a/addons/point_of_sale/static/tests/tours/BarcodeScanning.tour.js b/addons/point_of_sale/static/tests/tours/BarcodeScanning.tour.js index 9a28db2baa9..bbfa4bd0c6c 100644 --- a/addons/point_of_sale/static/tests/tours/BarcodeScanning.tour.js +++ b/addons/point_of_sale/static/tests/tours/BarcodeScanning.tour.js @@ -65,3 +65,35 @@ registry return getSteps(); } }); + +registry + .category("web_tour.tours") + .add("GS1BarcodeScanningTour", { + test: true, + url: "/pos/ui", + steps: () => { + startSteps(); + + ProductScreen.do.confirmOpeningPopup(); + + // Add the Product 1 with GS1 barcode + ProductScreen.do.scan_barcode("0108431673020125100000001"); + ProductScreen.check.selectedOrderlineHas('Product 1'); + ProductScreen.do.scan_barcode("0108431673020125100000001"); + ProductScreen.check.selectedOrderlineHas('Product 1', 2); + + // Add the Product 2 with normal barcode + ProductScreen.do.scan_barcode("08431673020126"); + ProductScreen.check.selectedOrderlineHas('Product 2'); + ProductScreen.do.scan_barcode("08431673020126"); + ProductScreen.check.selectedOrderlineHas('Product 2', 2); + + // Add the Product 3 with normal barcode + ProductScreen.do.scan_barcode("3760171283370"); + ProductScreen.check.selectedOrderlineHas('Product 3'); + ProductScreen.do.scan_barcode("3760171283370"); + ProductScreen.check.selectedOrderlineHas('Product 3', 2); + + return getSteps(); + } + }); diff --git a/addons/point_of_sale/tests/test_frontend.py b/addons/point_of_sale/tests/test_frontend.py index 112d18563f5..bc23496c3e0 100644 --- a/addons/point_of_sale/tests/test_frontend.py +++ b/addons/point_of_sale/tests/test_frontend.py @@ -941,6 +941,40 @@ class TestUi(TestPointOfSaleHttpCommon): self.main_pos_config.with_user(self.pos_user).open_ui() self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'BarcodeScanningProductPackagingTour', login="pos_user") + def test_GS1_pos_barcodes_scan(self): + barcodes_gs1_nomenclature = self.env.ref("barcodes_gs1_nomenclature.default_gs1_nomenclature") + self.main_pos_config.company_id.write({ + 'nomenclature_id': barcodes_gs1_nomenclature.id + }) + + self.env['product.product'].create({ + 'name': 'Product 1', + 'available_in_pos': True, + 'list_price': 10, + 'taxes_id': False, + 'barcode': '08431673020125', + }) + + self.env['product.product'].create({ + 'name': 'Product 2', + 'available_in_pos': True, + 'list_price': 10, + 'taxes_id': False, + 'barcode': '08431673020126', + }) + + # 3760171283370 can be parsed with GS1 rules but it's not GS1 + self.env['product.product'].create({ + 'name': 'Product 3', + 'available_in_pos': True, + 'list_price': 10, + 'taxes_id': False, + 'barcode': '3760171283370', + }) + + self.main_pos_config.open_ui() + self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'GS1BarcodeScanningTour', login="accountman") + # This class just runs the same tests as above but with mobile emulation class MobileTestUi(TestUi): browser_size = '375x667'