diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 2176d75ee97..a2a07e6d11e 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -26,9 +26,8 @@ from erpnext.stock.get_item_details import get_conversion_factor class PickList(Document): def validate(self): self.validate_for_qty() - if self.pick_manually and self.get("locations"): - self.validate_stock_qty() - self.check_serial_no_status() + self.validate_stock_qty() + self.check_serial_no_status() def before_save(self): self.update_status() @@ -42,14 +41,24 @@ class PickList(Document): from erpnext.stock.doctype.batch.batch import get_batch_qty for row in self.get("locations"): - if row.batch_no and not row.qty: + if not row.picked_qty: + continue + + if row.batch_no and row.picked_qty: batch_qty = get_batch_qty(row.batch_no, row.warehouse, row.item_code) - if row.qty > batch_qty: + if row.picked_qty > batch_qty: frappe.throw( _( - "At Row #{0}: The picked quantity {1} for the item {2} is greater than available stock {3} for the batch {4} in the warehouse {5}." - ).format(row.idx, row.item_code, batch_qty, row.batch_no, bold(row.warehouse)), + "At Row #{0}: The picked quantity {1} for the item {2} is greater than available stock {3} for the batch {4} in the warehouse {5}. Please restock the item." + ).format( + row.idx, + row.picked_qty, + row.item_code, + batch_qty, + row.batch_no, + bold(row.warehouse), + ), title=_("Insufficient Stock"), ) @@ -61,11 +70,11 @@ class PickList(Document): "actual_qty", ) - if row.qty > flt(bin_qty): + if row.picked_qty > flt(bin_qty): frappe.throw( _( "At Row #{0}: The picked quantity {1} for the item {2} is greater than available stock {3} in the warehouse {4}." - ).format(row.idx, row.qty, bold(row.item_code), bin_qty, bold(row.warehouse)), + ).format(row.idx, row.picked_qty, bold(row.item_code), bin_qty, bold(row.warehouse)), title=_("Insufficient Stock"), ) @@ -253,7 +262,14 @@ class PickList(Document): locations_replica = self.get("locations") # reset - self.delete_key("locations") + reset_rows = [] + for row in self.get("locations"): + if not row.picked_qty: + reset_rows.append(row) + + for row in reset_rows: + self.remove(row) + updated_locations = frappe._dict() for item_doc in items: item_code = item_doc.item_code @@ -323,6 +339,9 @@ class PickList(Document): # aggregate qty for same item item_map = OrderedDict() for item in locations: + if item.picked_qty: + continue + if not item.item_code: frappe.throw(f"Row #{item.idx}: Item Code is Mandatory") if not cint( diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py index 162fcadde7a..f679d28c2b2 100644 --- a/erpnext/stock/doctype/pick_list/test_pick_list.py +++ b/erpnext/stock/doctype/pick_list/test_pick_list.py @@ -842,5 +842,47 @@ class TestPickList(FrappeTestCase): for row in pl.locations: row.qty = row.qty + 10 + row.picked_qty = row.qty self.assertRaises(frappe.ValidationError, pl.save) + + def test_pick_list_not_reset_batch(self): + warehouse = "_Test Warehouse - _TC" + item = make_item( + "Test Do Not Reset Picked Item", + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "BTH-PICKLT-.######", + }, + ).name + + se = make_stock_entry(item=item, to_warehouse=warehouse, qty=10) + se.reload() + batch1 = se.items[0].batch_no + se = make_stock_entry(item=item, to_warehouse=warehouse, qty=10) + se.reload() + batch2 = se.items[0].batch_no + + so = make_sales_order(item_code=item, qty=10, rate=100) + + pl = create_pick_list(so.name) + pl.save() + + for loc in pl.locations: + self.assertEqual(loc.batch_no, batch1) + loc.batch_no = batch2 + loc.picked_qty = 0.0 + + pl.save() + + for loc in pl.locations: + self.assertEqual(loc.batch_no, batch1) + loc.batch_no = batch2 + loc.picked_qty = 10.0 + + pl.save() + + for loc in pl.locations: + self.assertEqual(loc.batch_no, batch2)