fix: Pick List barcode scanner and manual picking issues

- Fix barcode scanner serial_no_field configuration from 'not_supported' to 'serial_no'
- Add conditional serial assignment in create_pick_list to respect pick_manually flag
- Add client-side handler to clear auto-assigned data when switching to manual picking
- Add server-side validation to ensure data consistency
This commit is contained in:
Imesha Sudasingha
2025-08-07 04:51:54 +05:30
parent f4f1fdedee
commit 38c886db8b
3 changed files with 34 additions and 6 deletions

View File

@@ -1785,7 +1785,9 @@ def create_pick_list(source_name, target_doc=None):
doc.purpose = "Delivery"
doc.set_item_locations()
# Only auto-assign serial numbers if not picking manually
if not doc.pick_manually:
doc.set_item_locations()
return doc

View File

@@ -81,6 +81,26 @@ frappe.ui.form.on("Pick List", {
};
});
},
pick_manually: (frm) => {
// Clear auto-assigned serial numbers and related fields when switching to manual picking
if (frm.doc.pick_manually && frm.doc.locations) {
let has_changes = false;
frm.doc.locations.forEach((row) => {
if (row.serial_no || row.batch_no || row.serial_and_batch_bundle) {
row.serial_no = "";
row.batch_no = "";
row.serial_and_batch_bundle = "";
row.picked_qty = 0;
has_changes = true;
}
});
if (has_changes) {
frappe.show_alert(__("Cleared auto-assigned serial numbers and batch numbers for manual picking"), 3);
frm.refresh_field("locations");
}
}
},
set_item_locations: (frm, save) => {
if (!(frm.doc.locations && frm.doc.locations.length)) {
frappe.msgprint(__("Add items in the Item Locations table"));
@@ -273,7 +293,7 @@ frappe.ui.form.on("Pick List", {
max_qty_field: "qty",
dont_allow_new_row: true,
prompt_qty: frm.doc.prompt_qty,
serial_no_field: "not_supported", // doesn't make sense for picklist without a separate field.
serial_no_field: "serial_no",
};
const barcode_scanner = new erpnext.utils.BarcodeScanner(opts);
barcode_scanner.process_scan();

View File

@@ -572,10 +572,16 @@ class PickList(TransactionBase):
if not item.item_code:
frappe.throw(f"Row #{item.idx}: Item Code is Mandatory")
if not cint(
frappe.get_cached_value("Item", item.item_code, "is_stock_item")
) and not frappe.db.exists("Product Bundle", {"new_item_code": item.item_code, "disabled": 0}):
continue
# Check if item is stock item or product bundle
is_stock_item = cint(frappe.get_cached_value("Item", item.item_code, "is_stock_item"))
is_product_bundle = frappe.db.exists("Product Bundle", {"new_item_code": item.item_code, "disabled": 0})
# Include non-stock items for delivery purposes, but skip them for warehouse assignment
if not is_stock_item and not is_product_bundle:
# For non-stock items, set warehouse to None and continue processing
item.warehouse = None
item_code = item.item_code
reference = item.sales_order_item or item.material_request_item
key = (item_code, item.uom, item.warehouse, item.batch_no, reference)