mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-11 13:41:47 +00:00
fix: scale generated raw materials to the manufacture entry's production share
Every generated entry copied each Job Card Item's full required_qty in the skip-transfer and BOM-backflush paths, so two entries for one job card consumed the requirement twice. Scale the rows to the share of production this entry accounts for and cap them at the requirement still unconsumed, dropping rows that have nothing left. An entry whose materials are exhausted then fails the existing at-least-one-raw-material check instead of minting finished goods from nothing.
This commit is contained in:
@@ -126,6 +126,7 @@ class ManufactureEntry:
|
||||
if backflush_based_on != "BOM":
|
||||
available_serial_batches = self.get_transferred_serial_batches()
|
||||
|
||||
production_share = self.get_production_share()
|
||||
for item_code, _dict in item_dict.items():
|
||||
_dict.s_warehouse = self.source_wh.get(item_code) or self.wip_warehouse
|
||||
_dict.t_warehouse = ""
|
||||
@@ -140,11 +141,29 @@ class ManufactureEntry:
|
||||
|
||||
_dict.qty = calculated_qty
|
||||
self.update_available_serial_batches(_dict, available_serial_batches)
|
||||
elif self.skip_material_transfer:
|
||||
set_previous_operation_serial_batch(self.stock_entry, _dict)
|
||||
else:
|
||||
remaining_qty = max(flt(_dict.qty) - flt(_dict.consumed_qty), 0)
|
||||
_dict.qty = min(flt(_dict.qty) * production_share, remaining_qty)
|
||||
if not _dict.qty:
|
||||
continue
|
||||
|
||||
if self.skip_material_transfer:
|
||||
set_previous_operation_serial_batch(self.stock_entry, _dict)
|
||||
|
||||
self.stock_entry.append("items", _dict)
|
||||
|
||||
def get_production_share(self):
|
||||
"""Fraction of the job card's production this entry accounts for; raw materials are
|
||||
generated proportionally so several partial entries never consume more than required."""
|
||||
for_quantity, pending_qty = frappe.db.get_value(
|
||||
"Job Card", self.job_card, ["for_quantity", "pending_qty"]
|
||||
)
|
||||
qty_to_produce = flt(for_quantity) - flt(pending_qty)
|
||||
if not qty_to_produce:
|
||||
return 1
|
||||
|
||||
return min(flt(self.for_quantity) / qty_to_produce, 1)
|
||||
|
||||
def parse_available_serial_batches(self, item_dict, available_serial_batches):
|
||||
key = (item_dict.item_code, item_dict.from_warehouse)
|
||||
if key not in available_serial_batches:
|
||||
|
||||
Reference in New Issue
Block a user