From 0eb61c9fac7f685de303288446cb32375c37b02d Mon Sep 17 00:00:00 2001 From: pandiyan Date: Sat, 8 Aug 2026 23:04:28 +0530 Subject: [PATCH] fix: roll up process loss to the work order for semi finished goods update_work_order_qty() returns early when track_semi_finished_goods is enabled, so set_process_loss_qty() never ran and Work Order.process_loss_qty stayed at zero even though the job cards and the work order operations had booked the loss. The work order also never reached the Completed status, since that needs produced_qty + process_loss_qty to cover the ordered qty. Calling set_process_loss_qty() from that early return is not enough: the final operation has no semi finished good bom, so its manufacture entry is not from a bom, remove_fg_completed_qty() zeroes fg_completed_qty and update_work_order_qty() is never reached at all. The manufacture entries cannot be summed either. Each one is reset to MAX(Work Order Operation.process_loss_qty), so every entry of a multi operation chain carries the running maximum instead of the loss of its own operation. Aggregate the operations instead, and refresh the work order from the job card, which is where the operation loss is written. --- erpnext/manufacturing/doctype/job_card/job_card.py | 3 +++ .../manufacturing/doctype/work_order/services/status.py | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index 89f5dbdcac7..1271f1b6117 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -1114,6 +1114,9 @@ class JobCard(Document): wo.calculate_operating_cost() wo.set_actual_dates() + if wo.track_semi_finished_goods: + wo.set_process_loss_qty() + if time_data: wo.status = "In Process" diff --git a/erpnext/manufacturing/doctype/work_order/services/status.py b/erpnext/manufacturing/doctype/work_order/services/status.py index eb074a4cc8b..74f204acd40 100644 --- a/erpnext/manufacturing/doctype/work_order/services/status.py +++ b/erpnext/manufacturing/doctype/work_order/services/status.py @@ -291,6 +291,12 @@ class StatusService: ) def set_process_loss_qty(self): + self.doc.db_set("process_loss_qty", self._process_loss_qty()) + + def _process_loss_qty(self): + if self.doc.track_semi_finished_goods: + return flt(sum(flt(row.process_loss_qty) for row in self.doc.operations)) + table = frappe.qb.DocType("Stock Entry") process_loss_qty = ( frappe.qb.from_(table) @@ -302,7 +308,7 @@ class StatusService: ) ).run()[0][0] - self.doc.db_set("process_loss_qty", flt(process_loss_qty)) + return flt(process_loss_qty) def update_production_plan_status(self): production_plan = frappe.get_doc("Production Plan", self.doc.production_plan)