[FIX] barcodes: handle ^ with | barcode rule patterns
Before this commit: If the barcode nomenclature uses the or `|` symbol. The part after it would be used as a "contains" instead of a "start with". e.g: `123|456` would be transformed in the JS code to `^123|456` instead of: `^123|^456` As such, you would have error "can't find product with barcode" if you set such a rule and a product barcode contains the second part. For e.g: the barcode `44445666` would match, but should not! After this commit: Force the second (and following if any) part to start with. Note: in practice it is pretty rare to have `|` in the pattern, but it is the case for a default rule in version 16, see: https://github.com/odoo/odoo/blob/5ac58ebf983c1c02019253c0430fde3502e13e7c/addons/pos_loyalty/data/default_barcode_patterns.xml#L10 In this case, if a regular product have `044` in its product barcode, the PoS will tell that there is no corresponding coupon instead of adding the product. But the issue itself still apply in version 14 in case of custom rules opw-3356951 closes odoo/odoo#130961 X-original-commit: 103566699d3492b682219efc3614f26d2ea972e5 Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com> Signed-off-by: Loan Sens (lse) <lse@odoo.com>
This commit is contained in:
@@ -158,9 +158,9 @@ export class BarcodeParser {
|
||||
match.base_code = base_code.join('');
|
||||
}
|
||||
|
||||
if (base_pattern[0] !== '^') {
|
||||
base_pattern = "^" + base_pattern;
|
||||
}
|
||||
base_pattern = base_pattern.split('|')
|
||||
.map(part => part.startsWith('^') ? part : '^' + part)
|
||||
.join('|');
|
||||
match.match = match.base_code.match(base_pattern);
|
||||
|
||||
return match;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { ProductScreen } from "@point_of_sale/../tests/tours/helpers/ProductScreenTourMethods";
|
||||
import { getSteps, startSteps } from "@point_of_sale/../tests/tours/helpers/utils";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("BarcodeScanningTour", {
|
||||
test: true,
|
||||
url: "/pos/ui",
|
||||
steps: () => {
|
||||
startSteps();
|
||||
|
||||
// The following step is to make sure that the Chrome widget initialization ends
|
||||
// If we try to use the barcode parser before its initiation, we will have
|
||||
// some inconsistent JS errors:
|
||||
// TypeError: Cannot read properties of undefined (reading 'parse_barcode')
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
|
||||
// Add a product with its barcode
|
||||
ProductScreen.do.scan_barcode("0123456789");
|
||||
ProductScreen.check.selectedOrderlineHas('Monitor Stand');
|
||||
ProductScreen.do.scan_barcode("0123456789");
|
||||
ProductScreen.check.selectedOrderlineHas('Monitor Stand', 2);
|
||||
|
||||
// Test "Prices product" EAN-13 `23.....{NNNDD}` barcode pattern
|
||||
ProductScreen.do.scan_ean13_barcode("2301000000006");
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', 1, "0.00");
|
||||
ProductScreen.do.scan_ean13_barcode("2301000123453");
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', 1, "123.45");
|
||||
|
||||
// Test "Weighted product" EAN-13 `21.....{NNDDD}` barcode pattern
|
||||
ProductScreen.do.scan_ean13_barcode("2100002000000");
|
||||
ProductScreen.check.selectedOrderlineHas('Wall Shelf Unit', 0, "0.00");
|
||||
ProductScreen.do.scan_ean13_barcode("2100002080000");
|
||||
ProductScreen.check.selectedOrderlineHas('Wall Shelf Unit', 8);
|
||||
|
||||
return getSteps();
|
||||
}
|
||||
});
|
||||
@@ -277,6 +277,29 @@ class Do {
|
||||
},
|
||||
];
|
||||
}
|
||||
scan_barcode(barcode) {
|
||||
return [
|
||||
{
|
||||
content: `PoS model scan barcode '${barcode}'`,
|
||||
trigger: '.pos', // The element here does not really matter as long as it is present
|
||||
run: () => { window.posmodel.env.services.barcode_reader.scan(barcode); },
|
||||
},
|
||||
];
|
||||
}
|
||||
scan_ean13_barcode(barcode) {
|
||||
return [
|
||||
{
|
||||
content: `PoS model scan EAN13 barcode '${barcode}'`,
|
||||
trigger: '.pos', // The element here does not really matter as long as it is present
|
||||
run: () => {
|
||||
const barcode_reader = window.posmodel.env.services.barcode_reader;
|
||||
barcode_reader.scan(
|
||||
barcode_reader.parser.sanitize_ean(barcode)
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
goBackToMainScreen() {
|
||||
return [
|
||||
{
|
||||
|
||||
@@ -113,6 +113,7 @@ class TestPointOfSaleHttpCommon(AccountTestInvoicingHttpCommon):
|
||||
'available_in_pos': True,
|
||||
'list_price': 1.98,
|
||||
'taxes_id': False,
|
||||
'barcode': '2100002000003',
|
||||
})
|
||||
cls.small_shelf = env['product.product'].create({
|
||||
'name': 'Small Shelf',
|
||||
@@ -125,12 +126,14 @@ class TestPointOfSaleHttpCommon(AccountTestInvoicingHttpCommon):
|
||||
'available_in_pos': True,
|
||||
'list_price': 1.98,
|
||||
'taxes_id': False,
|
||||
'barcode': '2301000000006',
|
||||
})
|
||||
cls.monitor_stand = env['product.product'].create({
|
||||
'name': 'Monitor Stand',
|
||||
'available_in_pos': True,
|
||||
'list_price': 3.19,
|
||||
'taxes_id': False,
|
||||
'barcode': '0123456789', # No pattern in barcode nomenclature
|
||||
})
|
||||
cls.desk_pad = env['product.product'].create({
|
||||
'name': 'Desk Pad',
|
||||
@@ -151,6 +154,7 @@ class TestPointOfSaleHttpCommon(AccountTestInvoicingHttpCommon):
|
||||
'available_in_pos': True,
|
||||
'list_price': 5.10,
|
||||
'taxes_id': False,
|
||||
'barcode': '2300001000008',
|
||||
})
|
||||
configurable_chair = env['product.product'].create({
|
||||
'name': 'Configurable Chair',
|
||||
@@ -856,6 +860,15 @@ 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, 'ReceiptScreenDiscountWithPricelistTour', login="pos_user")
|
||||
|
||||
def test_07_pos_barcodes_scan(self):
|
||||
barcode_rule = self.env.ref("point_of_sale.barcode_rule_client")
|
||||
barcode_rule.pattern = barcode_rule.pattern + "|234"
|
||||
# should in theory be changed in the JS code to `|^234`
|
||||
# If not, it will fail as it will mistakenly match with the product barcode "0123456789"
|
||||
|
||||
self.main_pos_config.with_user(self.pos_user).open_ui()
|
||||
self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'BarcodeScanningTour', login="pos_user")
|
||||
|
||||
def test_08_show_tax_excluded(self):
|
||||
# define a tax included tax record
|
||||
tax = self.env['account.tax'].create({
|
||||
|
||||
Reference in New Issue
Block a user