feat: UOM specific barcodes (#30988)
This commit is contained in:
parent
37433aad48
commit
3974fbbb6e
@ -423,7 +423,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
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 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
||||
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,
|
||||
|
@ -9,6 +9,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
|
||||
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 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
|
||||
// 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 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
|
||||
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 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
|
||||
}
|
||||
|
||||
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 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
|
||||
|
||||
// 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 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
|
||||
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 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner {
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -558,7 +558,7 @@ def scan_barcode(search_value: str) -> Dict[str, Optional[str]]:
|
||||
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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user