[FIX] point_of_sale: accept GS1 barcodes in PoS
This update enables PoS to handle GS1 barcodes, which was previously not possible even though the GS1 nomenclature could be selected. GS1 barcodes can now be used to extract product identifiers, lot numbers, and serial numbers from the code. opw-3204299 closes odoo/odoo#125906 X-original-commit: cd2061c02b6c7001558178ade025a1fc4917bf9e Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com> Signed-off-by: Pedram Bi Ria (pebr) <pebr@odoo.com>
This commit is contained in:
@@ -61,7 +61,10 @@ patch(BarcodeParser.prototype, "barcodes_gs1_nomenclature.BarcodeParser", {
|
||||
const result = {
|
||||
rule: Object.assign({}, rule),
|
||||
ai: match[1],
|
||||
string_value: match[2]
|
||||
string_value: match[2],
|
||||
code: match[2],
|
||||
base_code: match[2],
|
||||
type: rule.type
|
||||
};
|
||||
if (rule.gs1_content_type === 'measure'){
|
||||
let decimalPosition = 0; // Decimal position begin at the end, 0 means no decimal
|
||||
|
||||
@@ -51,12 +51,10 @@ export class BarcodeReader {
|
||||
|
||||
const cbMaps = this.exclusiveCbMap ? [this.exclusiveCbMap] : [...this.cbMaps];
|
||||
|
||||
let parsedResult = this.parser.parse_barcode(code);
|
||||
if (!Array.isArray(parsedResult)) {
|
||||
parsedResult = [parsedResult];
|
||||
}
|
||||
|
||||
for (const parseBarcode of parsedResult) {
|
||||
let parseBarcode = this.parser.parse_barcode(code);
|
||||
if (Array.isArray(parseBarcode)) {
|
||||
cbMaps.map((cb) => cb.gs1?.(parseBarcode));
|
||||
} else {
|
||||
const cbs = cbMaps.map((cbMap) => cbMap[parseBarcode.type]).filter(Boolean);
|
||||
if (cbs.length === 0) {
|
||||
this.popup.add(ErrorBarcodePopup, { code: this.codeRepr(parseBarcode) });
|
||||
|
||||
@@ -49,6 +49,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
price: this._barcodeProductAction,
|
||||
client: this._barcodePartnerAction,
|
||||
discount: this._barcodeDiscountAction,
|
||||
gs1: this._barcodeGS1Action,
|
||||
});
|
||||
|
||||
// Call `resset` when the `onMounted` callback in `numberBuffer.use` is done.
|
||||
@@ -132,7 +133,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
}
|
||||
}
|
||||
}
|
||||
async _barcodeProductAction(code) {
|
||||
async _getProductByBarcode(code) {
|
||||
let product = this.pos.db.get_product_by_barcode(code.base_code);
|
||||
if (!product) {
|
||||
// find the barcode in the backend
|
||||
@@ -148,6 +149,13 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
return this.popup.add(ErrorBarcodePopup, { code: code.base_code });
|
||||
}
|
||||
}
|
||||
return product;
|
||||
}
|
||||
async _barcodeProductAction(code) {
|
||||
const product = await this._getProductByBarcode(code);
|
||||
if (!product) {
|
||||
return;
|
||||
}
|
||||
const options = await product.getAddProductOptions(code);
|
||||
// Do not proceed on adding the product when no options is returned.
|
||||
// This is consistent with clickProduct.
|
||||
@@ -193,6 +201,22 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
if (last_orderline) {
|
||||
last_orderline.set_discount(code.value);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add a product to the current order using the product identifier and lot number from parsed results.
|
||||
* This function retrieves the product identifier and lot number from the `parsed_results` parameter.
|
||||
* It then uses these values to retrieve the product and add it to the current order.
|
||||
*/
|
||||
async _barcodeGS1Action(parsed_results) {
|
||||
const productBarcode = parsed_results.find(element => element.type === 'product');
|
||||
const lotBarcode = parsed_results.find(element => element.type === 'lot');
|
||||
const product = await this._getProductByBarcode(productBarcode);
|
||||
if (!product) {
|
||||
return;
|
||||
}
|
||||
const options = await product.getAddProductOptions(lotBarcode);
|
||||
await this.currentOrder.add_product(product, options);
|
||||
this.numberBuffer.reset();
|
||||
}
|
||||
async displayAllControlPopup() {
|
||||
await this.popup.add(ControlButtonPopup, {
|
||||
|
||||
@@ -112,7 +112,7 @@ export class Product extends PosModel {
|
||||
get isScaleAvailable() {
|
||||
return true;
|
||||
}
|
||||
async getAddProductOptions(base_code) {
|
||||
async getAddProductOptions(code) {
|
||||
let price_extra = 0.0;
|
||||
let draftPackLotLines, weight, description, packLotLinesToEdit;
|
||||
let quantity = 1;
|
||||
@@ -158,26 +158,39 @@ export class Product extends PosModel {
|
||||
packLotLinesToEdit = [];
|
||||
}
|
||||
}
|
||||
const { confirmed, payload } = await this.pos.env.services.popup.add(EditListPopup, {
|
||||
title: this.pos.env._t("Lot/Serial Number(s) Required"),
|
||||
name: this.display_name,
|
||||
isSingleItem: isAllowOnlyOneLot,
|
||||
array: packLotLinesToEdit,
|
||||
});
|
||||
if (confirmed) {
|
||||
// Segregate the old and new packlot lines
|
||||
// if the lot information exists in the barcode, we don't need to ask it from the user.
|
||||
if (code && code.type === 'lot') {
|
||||
// consider the old and new packlot lines
|
||||
const modifiedPackLotLines = Object.fromEntries(
|
||||
payload.newArray.filter((item) => item.id).map((item) => [item.id, item.text])
|
||||
packLotLinesToEdit.filter(item => item.id).map(item => [item.id, item.text])
|
||||
);
|
||||
const newPackLotLines = payload.newArray
|
||||
.filter((item) => !item.id)
|
||||
.map((item) => ({ lot_name: item.text }));
|
||||
|
||||
const newPackLotLines = [
|
||||
{ lot_name: code.code },
|
||||
];
|
||||
draftPackLotLines = { modifiedPackLotLines, newPackLotLines };
|
||||
} else {
|
||||
// We don't proceed on adding product.
|
||||
return;
|
||||
const { confirmed, payload } = await this.pos.env.services.popup.add(EditListPopup, {
|
||||
title: this.pos.env._t("Lot/Serial Number(s) Required"),
|
||||
name: this.display_name,
|
||||
isSingleItem: isAllowOnlyOneLot,
|
||||
array: packLotLinesToEdit,
|
||||
});
|
||||
if (confirmed) {
|
||||
// Segregate the old and new packlot lines
|
||||
const modifiedPackLotLines = Object.fromEntries(
|
||||
payload.newArray.filter((item) => item.id).map((item) => [item.id, item.text])
|
||||
);
|
||||
const newPackLotLines = payload.newArray
|
||||
.filter((item) => !item.id)
|
||||
.map((item) => ({ lot_name: item.text }));
|
||||
|
||||
draftPackLotLines = { modifiedPackLotLines, newPackLotLines };
|
||||
} else {
|
||||
// We don't proceed on adding product.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Take the weight if necessary.
|
||||
@@ -202,8 +215,8 @@ export class Product extends PosModel {
|
||||
}
|
||||
}
|
||||
|
||||
if (base_code && this.pos.db.product_packaging_by_barcode[base_code.code]) {
|
||||
weight = this.pos.db.product_packaging_by_barcode[base_code.code].qty;
|
||||
if (code && this.pos.db.product_packaging_by_barcode[code.code]) {
|
||||
weight = this.pos.db.product_packaging_by_barcode[code.code].qty;
|
||||
}
|
||||
|
||||
return { draftPackLotLines, quantity, weight, description, price_extra };
|
||||
|
||||
Reference in New Issue
Block a user