diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 065707e7e6d..6029a073961 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -341,13 +341,6 @@ class BOM(WebsiteGenerator): ).format(item.idx, get_link_to_form("Item", item.item_code)) ) - if not item.qty: - frappe.throw( - _("Row #{0}: Quantity should be greater than 0 for {1} Item {2}").format( - item.idx, item.type, get_link_to_form("Item", item.item_code) - ) - ) - if item.process_loss_per >= 100: frappe.throw( _("Row #{0}: Process Loss Percentage should be less than 100% for {1} Item {2}").format( diff --git a/erpnext/manufacturing/doctype/bom_secondary_item/bom_secondary_item.json b/erpnext/manufacturing/doctype/bom_secondary_item/bom_secondary_item.json index 39fa55123f4..ad2f69af5d9 100644 --- a/erpnext/manufacturing/doctype/bom_secondary_item/bom_secondary_item.json +++ b/erpnext/manufacturing/doctype/bom_secondary_item/bom_secondary_item.json @@ -138,8 +138,7 @@ "fieldtype": "Float", "in_list_view": 1, "label": "Qty", - "non_negative": 1, - "reqd": 1 + "non_negative": 1 }, { "default": "0", @@ -218,7 +217,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2026-03-11 12:12:29.208031", + "modified": "2026-06-16 16:49:19.000000", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Secondary Item", diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index ae536b8dc42..55463364a3c 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1380,6 +1380,12 @@ class StockEntry(StockController, SubcontractingInwardController): if d.s_warehouse or d.set_basic_rate_manually: continue + # Zero-qty secondary items carry no inventory value; skip rate calculation + if d.type and flt(d.transfer_qty) == 0: + d.basic_rate = 0.0 + d.basic_amount = 0.0 + continue + if d.allow_zero_valuation_rate and d.basic_rate and self.purpose != "Receive from Customer": d.basic_rate = 0.0 items.append(d.item_code) @@ -1397,7 +1403,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: if self.is_new():