From de3df6bcefa69f26990a6f5ab2e09af0182f686a Mon Sep 17 00:00:00 2001 From: Umair Sayed Date: Fri, 12 Jun 2026 16:04:12 +0530 Subject: [PATCH] fix(manufacture): preserve user-entered rate for secondary items with zero cost allocation When a BOM secondary item has cost_allocation_per = 0 (the default), the previous code unconditionally computed `0 / transfer_qty = 0`, wiping any rate the user had entered for the item. Now the allocation formula only runs when cost_allocation_per > 0, allowing the valuation-rate fallback (or a manually entered rate) to apply instead. Additionally, secondary items with transfer_qty = 0 now short-circuit the entire rate pipeline: they get rate = 0 and amount = 0 immediately, avoiding a ZeroDivisionError and the spurious "enter basic rate" prompt. Co-Authored-By: Claude Sonnet 4.6 --- erpnext/stock/doctype/stock_entry/stock_entry.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 80552b7c25f..048fa211b6f 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -554,6 +554,13 @@ class StockEntry(StockController, SubcontractingInwardController): for d in self.get("items"): if d.s_warehouse or d.set_basic_rate_manually: continue + + # Zero-qty secondary items carry no inventory value; skip rate calculation + if d.secondary_item_type and flt(d.transfer_qty) == 0: + d.basic_rate = 0.0 + d.basic_amount = 0.0 + continue + self._set_incoming_item_rate(d, outgoing_items_cost, raise_error_if_no_rate, zero_valuation_items) if zero_valuation_items: @@ -575,7 +582,10 @@ class StockEntry(StockController, SubcontractingInwardController): cost_allocation_per = frappe.get_value( "BOM Secondary Item", d.bom_secondary_item, "cost_allocation_per" ) - d.basic_rate = (outgoing_items_cost * (cost_allocation_per / 100)) / d.transfer_qty + # Only recalculate when cost is actually allocated; otherwise preserve the + # user-entered rate (or fall through to get_valuation_rate below) + if cost_allocation_per and flt(d.transfer_qty): + d.basic_rate = (outgoing_items_cost * (cost_allocation_per / 100)) / d.transfer_qty if not d.basic_rate and not d.allow_zero_valuation_rate: d.basic_rate = get_valuation_rate(