diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 8a35d2aced..4290ca3e4c 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -559,9 +559,11 @@ class ProductionPlan(Document): get_sub_assembly_items(row.bom_no, bom_data, row.planned_qty) self.set_sub_assembly_items_based_on_level(row, bom_data, manufacturing_type) - def set_sub_assembly_items_based_on_level(self, row, bom_data, manufacturing_type=None): - bom_data = sorted(bom_data, key = lambda i: i.bom_level, reverse=True) + self.sub_assembly_items.sort(key= lambda d: d.bom_level, reverse=True) + for idx, row in enumerate(self.sub_assembly_items, start=1): + row.idx = idx + def set_sub_assembly_items_based_on_level(self, row, bom_data, manufacturing_type=None): for data in bom_data: data.qty = data.stock_qty data.production_plan_item = row.name diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index 2febc1e23c..21a126b2a7 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -347,6 +347,45 @@ class TestProductionPlan(ERPNextTestCase): frappe.db.rollback() + def test_subassmebly_sorting(self): + """ Test subassembly sorting in case of multiple items with nested BOMs""" + from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom + + prefix = "_TestLevel_" + boms = { + "Assembly": { + "SubAssembly1": {"ChildPart1": {}, "ChildPart2": {},}, + "SubAssembly2": {"ChildPart3": {}}, + "SubAssembly3": {"SubSubAssy1": {"ChildPart4": {}}}, + "ChildPart5": {}, + "ChildPart6": {}, + "SubAssembly4": {"SubSubAssy2": {"ChildPart7": {}}}, + }, + "MegaDeepAssy": { + "SecretSubassy": {"SecretPart": {"VerySecret" : { "SuperSecret": {"Classified": {}}}},}, + # ^ assert that this is + # first item in subassy table + } + } + create_nested_bom(boms, prefix=prefix) + + items = [prefix + item_code for item_code in boms.keys()] + plan = create_production_plan(item_code=items[0], do_not_save=True) + plan.append("po_items", { + 'use_multi_level_bom': 1, + 'item_code': items[1], + 'bom_no': frappe.db.get_value('Item', items[1], 'default_bom'), + 'planned_qty': 1, + 'planned_start_date': now_datetime() + }) + plan.get_sub_assembly_items() + + bom_level_order = [d.bom_level for d in plan.sub_assembly_items] + self.assertEqual(bom_level_order, sorted(bom_level_order, reverse=True)) + # lowest most level of subassembly should be first + self.assertIn("SuperSecret", plan.sub_assembly_items[0].production_item) + + def create_production_plan(**args): args = frappe._dict(args)