feat: UOM specific barcodes (#30988)
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index edc4b06..de93c82 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -423,7 +423,7 @@
item.barcode = null;
- if(item.item_code || item.barcode || item.serial_no) {
+ if(item.item_code || item.serial_no) {
if(!this.validate_company_and_party()) {
this.frm.fields_dict["items"].grid.grid_rows[item.idx - 1].remove();
} else {
@@ -463,6 +463,7 @@
stock_qty: item.stock_qty,
conversion_factor: item.conversion_factor,
weight_per_unit: item.weight_per_unit,
+ uom: item.uom,
weight_uom: item.weight_uom,
manufacturer: item.manufacturer,
stock_uom: item.stock_uom,
diff --git a/erpnext/public/js/utils/barcode_scanner.js b/erpnext/public/js/utils/barcode_scanner.js
index 943db07..a6bff2c 100644
--- a/erpnext/public/js/utils/barcode_scanner.js
+++ b/erpnext/public/js/utils/barcode_scanner.js
@@ -9,6 +9,7 @@
this.barcode_field = opts.barcode_field || "barcode";
this.serial_no_field = opts.serial_no_field || "serial_no";
this.batch_no_field = opts.batch_no_field || "batch_no";
+ this.uom_field = opts.uom_field || "uom";
this.qty_field = opts.qty_field || "qty";
// field name on row which defines max quantity to be scanned e.g. picklist
this.max_qty_field = opts.max_qty_field;
@@ -26,6 +27,7 @@
// bar_code: "123456", // present if barcode was scanned
// batch_no: "LOT12", // present if batch was scanned
// serial_no: "987XYZ", // present if serial no was scanned
+ // uom: "Kg", // present if barcode UOM is different from default
// }
this.scan_api = opts.scan_api || "erpnext.stock.utils.scan_barcode";
}
@@ -67,9 +69,9 @@
return new Promise(resolve => {
let cur_grid = this.frm.fields_dict[this.items_table_name].grid;
- const {item_code, barcode, batch_no, serial_no} = data;
+ const {item_code, barcode, batch_no, serial_no, uom} = data;
- let row = this.get_row_to_modify_on_scan(item_code, batch_no);
+ let row = this.get_row_to_modify_on_scan(item_code, batch_no, uom);
if (!row) {
if (this.dont_allow_new_row) {
@@ -90,10 +92,11 @@
}
frappe.run_serially([
- () => this.set_selector_trigger_flag(row, data),
+ () => this.set_selector_trigger_flag(data),
() => this.set_item(row, item_code).then(qty => {
this.show_scan_message(row.idx, row.item_code, qty);
}),
+ () => this.set_barcode_uom(row, uom),
() => this.set_serial_no(row, serial_no),
() => this.set_batch_no(row, batch_no),
() => this.set_barcode(row, barcode),
@@ -106,7 +109,7 @@
// batch and serial selector is reduandant when all info can be added by scan
// this flag on item row is used by transaction.js to avoid triggering selector
- set_selector_trigger_flag(row, data) {
+ set_selector_trigger_flag(data) {
const {batch_no, serial_no, has_batch_no, has_serial_no} = data;
const require_selecting_batch = has_batch_no && !batch_no;
@@ -154,6 +157,12 @@
}
}
+ async set_barcode_uom(row, uom) {
+ if (uom && frappe.meta.has_field(row.doctype, this.uom_field)) {
+ await frappe.model.set_value(row.doctype, row.name, this.uom_field, uom);
+ }
+ }
+
async set_batch_no(row, batch_no) {
if (batch_no && frappe.meta.has_field(row.doctype, this.batch_no_field)) {
await frappe.model.set_value(row.doctype, row.name, this.batch_no_field, batch_no);
@@ -184,7 +193,7 @@
return is_duplicate;
}
- get_row_to_modify_on_scan(item_code, batch_no) {
+ get_row_to_modify_on_scan(item_code, batch_no, uom) {
let cur_grid = this.frm.fields_dict[this.items_table_name].grid;
// Check if batch is scanned and table has batch no field
@@ -193,10 +202,12 @@
const matching_row = (row) => {
const item_match = row.item_code == item_code;
- const batch_match = row.batch_no == batch_no;
+ const batch_match = row[this.batch_no_field] == batch_no;
+ const uom_match = !uom || row[this.uom_field] == uom;
const qty_in_limit = flt(row[this.qty_field]) < flt(row[this.max_qty_field]);
return item_match
+ && uom_match
&& (!is_batch_no_scan || batch_match)
&& (!check_max_qty || qty_in_limit)
}
diff --git a/erpnext/stock/doctype/item_barcode/item_barcode.json b/erpnext/stock/doctype/item_barcode/item_barcode.json
index eef70c9..56832f3 100644
--- a/erpnext/stock/doctype/item_barcode/item_barcode.json
+++ b/erpnext/stock/doctype/item_barcode/item_barcode.json
@@ -6,7 +6,8 @@
"engine": "InnoDB",
"field_order": [
"barcode",
- "barcode_type"
+ "barcode_type",
+ "uom"
],
"fields": [
{
@@ -24,11 +25,18 @@
"in_list_view": 1,
"label": "Barcode Type",
"options": "\nEAN\nUPC-A"
+ },
+ {
+ "fieldname": "uom",
+ "fieldtype": "Link",
+ "in_list_view": 1,
+ "label": "UOM",
+ "options": "UOM"
}
],
"istable": 1,
"links": [],
- "modified": "2022-04-01 05:54:27.314030",
+ "modified": "2022-06-01 06:24:33.969534",
"modified_by": "Administrator",
"module": "Stock",
"name": "Item Barcode",
diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py
index 2120304..6d8fdaa 100644
--- a/erpnext/stock/utils.py
+++ b/erpnext/stock/utils.py
@@ -558,7 +558,7 @@
barcode_data = frappe.db.get_value(
"Item Barcode",
{"barcode": search_value},
- ["barcode", "parent as item_code"],
+ ["barcode", "parent as item_code", "uom"],
as_dict=True,
)
if barcode_data: