fix: incorrect batch picked in the pick list

This commit is contained in:
Rohit Waghchaure
2025-03-05 14:29:22 +05:30
parent 90b5f0b7bf
commit ac25d3e1c4
2 changed files with 70 additions and 3 deletions

View File

@@ -2,6 +2,13 @@
// For license information, please see license.txt
frappe.ui.form.on("Pick List", {
after_save(frm) {
setTimeout(() => {
// Added to fix the issue of locations table not getting updated after save
frm.reload_doc();
}, 500);
},
setup: (frm) => {
frm.set_indicator_formatter("item_code", function (doc) {
return doc.stock_qty === 0 ? "red" : "green";

View File

@@ -25,10 +25,38 @@ from erpnext.stock.get_item_details import get_conversion_factor
class PickList(Document):
def validate(self):
self.validate_expired_batches()
self.validate_for_qty()
self.validate_stock_qty()
self.check_serial_no_status()
def validate_expired_batches(self):
batches = []
for row in self.get("locations"):
if row.get("batch_no") and row.get("picked_qty"):
batches.append(row.batch_no)
if batches:
batch = frappe.qb.DocType("Batch")
query = (
frappe.qb.from_(batch)
.select(batch.name)
.where(
(batch.name.isin(batches))
& (batch.expiry_date <= frappe.utils.nowdate())
& (batch.expiry_date.isnotnull())
)
)
expired_batches = query.run(as_dict=True)
if expired_batches:
msg = "<ul>" + "".join(f"<li>{batch.name}</li>" for batch in expired_batches) + "</ul>"
frappe.throw(
_("The following batches are expired, please restock them: <br> {0}").format(msg),
title=_("Expired Batches"),
)
def before_save(self):
self.update_status()
if not self.pick_manually:
@@ -271,6 +299,7 @@ class PickList(Document):
self.remove(row)
updated_locations = frappe._dict()
len_idx = len(self.get("locations")) or 0
for item_doc in items:
item_code = item_doc.item_code
@@ -313,6 +342,8 @@ class PickList(Document):
if location.picked_qty > location.stock_qty:
location.picked_qty = location.stock_qty
len_idx += 1
location.idx = len_idx
self.append("locations", location)
# If table is empty on update after submit, set stock_qty, picked_qty to 0 so that indicator is red
@@ -321,6 +352,9 @@ class PickList(Document):
for location in locations_replica:
location.stock_qty = 0
location.picked_qty = 0
len_idx += 1
location.idx = len_idx
self.append("locations", location)
frappe.msgprint(
_(
@@ -430,9 +464,11 @@ class PickList(Document):
pi_item.item_code,
pi_item.warehouse,
pi_item.batch_no,
Sum(Case().when(pi_item.picked_qty > 0, pi_item.picked_qty).else_(pi_item.stock_qty)).as_(
"picked_qty"
),
Sum(
Case()
.when((pi_item.picked_qty > 0) & (pi_item.docstatus == 1), pi_item.picked_qty)
.else_(pi_item.stock_qty)
).as_("picked_qty"),
Replace(GROUP_CONCAT(pi_item.serial_no), ",", "\n").as_("serial_no"),
)
.where(
@@ -465,8 +501,32 @@ class PickList(Document):
else:
picked_items[item_data.item_code][key] = data
self.update_picked_item_from_current_pick_list(picked_items)
return picked_items
def update_picked_item_from_current_pick_list(self, picked_items):
for row in self.get("locations"):
if flt(row.picked_qty) > 0:
key = (row.warehouse, row.batch_no) if row.batch_no else row.warehouse
serial_no = [x for x in row.serial_no.split("\n") if x] if row.serial_no else None
if row.item_code not in picked_items:
picked_items[row.item_code] = {}
if key not in picked_items[row.item_code]:
picked_items[row.item_code][key] = frappe._dict(
{
"picked_qty": 0,
"serial_no": [],
"batch_no": row.batch_no or "",
"warehouse": row.warehouse,
}
)
picked_items[row.item_code][key]["picked_qty"] += flt(row.stock_qty) or flt(row.picked_qty)
if serial_no:
picked_items[row.item_code][key]["serial_no"].extend(serial_no)
def _get_product_bundles(self) -> dict[str, str]:
# Dict[so_item_row: item_code]
product_bundles = {}