Merge pull request #56800 from aerele/fix/wo-status-partial-pick

fix(manufacturing): update work order status on partial pick-list transfer
This commit is contained in:
Mihir Kandoi
2026-07-02 21:44:46 +05:30
committed by GitHub
2 changed files with 55 additions and 1 deletions

View File

@@ -132,7 +132,9 @@ class StatusService:
status = (
"In Process"
if flt(self.doc.material_transferred_for_manufacturing) > 0 or self.doc.skip_transfer
if flt(self.doc.material_transferred_for_manufacturing) > 0
or self.doc.skip_transfer
or self._has_transferred_material()
else "Not Started"
)
precision = frappe.get_precision("Work Order", "produced_qty")
@@ -141,6 +143,26 @@ class StatusService:
status = "Completed"
return status
def _has_transferred_material(self):
"""True if any raw material was transferred against this work order via a pick list
(these leave material_transferred_for_manufacturing at 0 via the min-fraction rule)."""
ste = frappe.qb.DocType("Stock Entry")
ste_child = frappe.qb.DocType("Stock Entry Detail")
qty = (
frappe.qb.from_(ste)
.inner_join(ste_child)
.on(ste_child.parent == ste.name)
.select(Sum(ste_child.transfer_qty))
.where(
(ste.work_order == self.doc.name)
& (ste.docstatus == 1)
& (ste.purpose == "Material Transfer for Manufacture")
& (ste.is_return == 0)
& (ste.pick_list.isnotnull())
)
).run()[0][0]
return flt(qty) > 0
def _is_partial_skip_transfer(self):
return bool(
self.doc.skip_transfer

View File

@@ -1528,6 +1528,38 @@ class TestWorkOrder(ERPNextTestSuite):
work_order.reload()
self.assertEqual(work_order.material_transferred_for_manufacturing, 2.0)
def test_status_in_process_when_only_one_required_item_transferred(self):
"""Stock Entry created from a Pick List that picked only one of the required items:
min-fraction keeps material_transferred_for_manufacturing at 0, but the work order must
still move to In Process because material is already in WIP."""
from erpnext.manufacturing.doctype.work_order.mapper import create_pick_list
from erpnext.stock.doctype.pick_list.mapper import create_stock_entry
work_order = make_wo_order_test_record(
planned_start_date=now(), qty=2, source_warehouse="Stores - _TC"
)
test_stock_entry.make_stock_entry(
item_code="_Test Item", target="Stores - _TC", qty=10, basic_rate=5000.0
)
test_stock_entry.make_stock_entry(
item_code="_Test Item Home Desktop 100", target="Stores - _TC", qty=10, basic_rate=1000.0
)
pick_list = create_pick_list(work_order.name, for_qty=work_order.qty)
# pick only _Test Item; the other required item is left out of this pick list
pick_list.pick_manually = 1
pick_list.locations = [loc for loc in pick_list.locations if loc.item_code == "_Test Item"]
pick_list.save()
pick_list.submit()
stock_entry = frappe.get_doc(create_stock_entry(pick_list.as_dict()))
self.assertEqual(stock_entry.fg_completed_qty, 0.0)
stock_entry.submit()
work_order.reload()
self.assertEqual(work_order.material_transferred_for_manufacturing, 0.0)
self.assertEqual(work_order.status, "In Process")
def test_backflushed_batch_raw_materials_based_on_transferred(self):
frappe.db.set_single_value(
"Manufacturing Settings",