diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index b63df53bd32..e9a15a7e40d 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -70,6 +70,15 @@ from erpnext.controllers.subcontracting_inward_controller import SubcontractingI form_grid_templates = {"items": "templates/form_grid/stock_entry_grid.html"} +def is_costed_out_of_finished_item(row) -> bool: + """Whether the row takes its value out of the finished good instead of adding to it. + + A secondary item that is not linked to a BOM has no cost allocation of its own, so it is + valued the way the legacy scrap item was: its cost is deducted from the finished good. + """ + return bool(row.is_legacy_scrap_item or (row.secondary_item_type and not row.bom_secondary_item)) + + class StockEntry(StockController, SubcontractingInwardController): # begin: auto-generated types # This code is auto-generated. Do not modify anything in this block. @@ -564,7 +573,8 @@ class StockEntry(StockController, SubcontractingInwardController): ) zero_valuation_items = [] - for d in self.get("items"): + finished_items_last = sorted(self.get("items"), key=lambda row: cint(row.is_finished_item)) + for d in finished_items_last: if d.s_warehouse or d.set_basic_rate_manually: continue @@ -736,7 +746,9 @@ class StockEntry(StockController, SubcontractingInwardController): self, finished_item_qty, outgoing_items_cost=0, has_consumption_basis=False ) -> float: settings = frappe.get_single("Manufacturing Settings") - scrap_items_cost = sum([flt(d.basic_amount) for d in self.get("items") if d.is_legacy_scrap_item]) + scrap_items_cost = sum( + [flt(d.basic_amount) for d in self.get("items") if is_costed_out_of_finished_item(d)] + ) if settings.material_consumption: outgoing_items_cost = self._get_rm_cost_for_manufacture(