test(selling): cover disabled Product Bundle behaviour

Resolution skips disabled bundles, transactions referencing a disabled
version are blocked, rows without an explicit version stop packing, and
the Item Where Used report surfaces the disabled flag on bundle rows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Mihir Kandoi
2026-06-10 10:57:40 +05:30
parent cf37478870
commit c97c2d1e02
2 changed files with 55 additions and 0 deletions

View File

@@ -103,6 +103,38 @@ class TestProductBundle(ERPNextTestSuite):
bundle.items[0].qty = 99
self.assertRaises(frappe.exceptions.UpdateAfterSubmitError, bundle.save)
def test_disabled_bundle_is_not_resolved(self):
bundle = make_product_bundle(self.parent, ["_Test PB Child A"])
bundle.disabled = 1
bundle.save()
self.assertIsNone(get_active_product_bundle(self.parent))
# disabling parks the version without ceding the active slot, so re-enabling
# restores resolution without re-activation
self.assertEqual(frappe.db.get_value("Product Bundle", bundle.name, "is_active"), 1)
bundle.disabled = 0
bundle.save()
self.assertEqual(get_active_product_bundle(self.parent), bundle.name)
def test_item_where_used_report_shows_disabled_flag(self):
from erpnext.stock.report.item_where_used.item_where_used import execute
bundle = make_product_bundle(self.parent, ["_Test PB Child A"])
bundle.disabled = 1
bundle.save()
_, component_rows = execute({"item": "_Test PB Child A", "section": "Where Used"})
rows = [r for r in component_rows if r.document_name == bundle.name]
self.assertTrue(rows)
self.assertEqual(rows[0].disabled, 1)
self.assertEqual(rows[0].is_active, 1)
_, parent_rows = execute({"item": self.parent, "section": "References"})
rows = [r for r in parent_rows if r.document_name == bundle.name]
self.assertTrue(rows)
self.assertEqual(rows[0].disabled, 1)
def test_child_cannot_be_active_bundle(self):
make_product_bundle(self.parent, ["_Test PB Child A"])
outer = make_item("_Test PB Outer", {"is_stock_item": 0, "is_sales_item": 1}).name

View File

@@ -165,6 +165,29 @@ class TestPackedItem(ERPNextTestSuite):
self.assertEqual(so.items[0].product_bundle, v1)
self.assertEqual(sorted(pi.item_code for pi in so.packed_items), sorted(self.bundle_items))
def test_disabled_bundle_blocks_transaction(self):
"A row that explicitly references a disabled version cannot be saved."
from erpnext.selling.doctype.product_bundle.product_bundle import get_active_product_bundle
version = get_active_product_bundle(self.bundle)
so = make_sales_order(item_code=self.bundle, qty=1, warehouse=self.warehouse, do_not_submit=True)
self.assertEqual(so.items[0].product_bundle, version)
frappe.db.set_value("Product Bundle", version, "disabled", 1)
self.assertRaises(frappe.ValidationError, so.save)
def test_disabled_bundle_is_not_packed(self):
"Without an explicit version, a disabled bundle is not treated as a bundle at all."
from erpnext.selling.doctype.product_bundle.product_bundle import get_active_product_bundle
version = get_active_product_bundle(self.bundle2)
frappe.db.set_value("Product Bundle", version, "disabled", 1)
so = make_sales_order(item_code=self.bundle2, qty=1, warehouse=self.warehouse, do_not_submit=True)
self.assertEqual(so.items[0].is_product_bundle, 0)
self.assertFalse(so.items[0].product_bundle)
self.assertFalse(so.get("packed_items"))
@ERPNextTestSuite.change_settings("Selling Settings", {"allow_multiple_items": 1})
def test_recurring_bundle_item(self):
"Test impact on packed items if same bundle item is added and removed."