From 90288720a99248dbc3f3fbdffa994d4e5d60e715 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Mon, 3 Aug 2026 13:28:20 +0530 Subject: [PATCH] test(stock): cover a secondary item added without a BOM A Manufacture entry with a raw material worth 1000, a finished good and a Scrap row typed in the UI must value the scrap at its own rate and take that value out of the finished good, leaving no difference. (cherry picked from commit 7f47361ebdfc743509a9b1d92690a4667d513091) # Conflicts: # erpnext/stock/doctype/stock_entry/test_stock_entry.py --- .../doctype/stock_entry/test_stock_entry.py | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index d91ec89d7dd..8dc46469154 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -2737,6 +2737,88 @@ class TestStockEntry(ERPNextTestSuite): self.assertEqual(fg_sle.incoming_rate, 0) self.assertEqual(fg_sle.stock_value_difference, 0) +<<<<<<< HEAD +======= + def test_secondary_item_type_does_not_waive_inspection_outside_manufacturing(self): + """A stray secondary item type must not let a QI-required item through a receipt.""" + item = make_item( + properties={ + "is_stock_item": 1, + "valuation_rate": 50, + "inspection_required_before_purchase": 1, + } + ).name + + def receipt(secondary_item_type): + se = frappe.new_doc("Stock Entry") + se.purpose = se.stock_entry_type = "Material Receipt" + se.company = "_Test Company" + se.inspection_required = 1 + se.append( + "items", + { + "item_code": item, + "t_warehouse": "_Test Warehouse - _TC", + "qty": 10, + "conversion_factor": 1, + "secondary_item_type": secondary_item_type, + }, + ) + return se + + self.assertRaises(QualityInspectionRequiredError, receipt("").submit) + self.assertRaises(QualityInspectionRequiredError, receipt("Scrap").submit) + + def test_manufacture_balances_secondary_item_added_without_a_bom(self): + """A secondary item with no BOM link is costed out of the finished good, as legacy scrap was.""" + rm_item = make_item(properties={"is_stock_item": 1}).name + fg_item = make_item(properties={"is_stock_item": 1}).name + scrap_item = make_item(properties={"is_stock_item": 1, "valuation_rate": 20}).name + warehouse = "_Test Warehouse - _TC" + + make_stock_entry(item_code=rm_item, target=warehouse, qty=10, basic_rate=100) + + se = frappe.new_doc("Stock Entry") + se.purpose = se.stock_entry_type = "Manufacture" + se.company = "_Test Company" + se.append( + "items", {"item_code": rm_item, "s_warehouse": warehouse, "qty": 10, "conversion_factor": 1} + ) + se.append( + "items", + { + "item_code": fg_item, + "t_warehouse": warehouse, + "qty": 10, + "is_finished_item": 1, + "conversion_factor": 1, + }, + ) + se.append( + "items", + { + "item_code": scrap_item, + "t_warehouse": warehouse, + "qty": 5, + "secondary_item_type": "Scrap", + "conversion_factor": 1, + }, + ) + se.save() + + scrap_row = se.items[2] + self.assertEqual(flt(scrap_row.basic_rate), 20.0) + self.assertEqual(flt(scrap_row.basic_amount), 100.0) + + fg_row = se.items[1] + self.assertEqual(flt(fg_row.basic_rate), 90.0) + self.assertEqual(flt(fg_row.basic_amount), 900.0) + + self.assertEqual(flt(se.total_incoming_value), 1000.0) + self.assertEqual(flt(se.total_outgoing_value), 1000.0) + self.assertEqual(flt(se.value_difference), 0.0) + +>>>>>>> 7f47361ebd (test(stock): cover a secondary item added without a BOM) def _make_wo_for_free_raw_material(self, rm_item, fg_item, bom_no): from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record from erpnext.manufacturing.doctype.work_order.work_order import (