diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index da695ef2817..81391cbd10c 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -24,6 +24,11 @@ from erpnext.tests.utils import ERPNextTestSuite class TestBOM(ERPNextTestSuite): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.load_test_records("BOM") + @timeout def test_get_items(self): from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict diff --git a/erpnext/manufacturing/doctype/bom/test_records.json b/erpnext/manufacturing/doctype/bom/test_records.json new file mode 100644 index 00000000000..e9cbdfe638a --- /dev/null +++ b/erpnext/manufacturing/doctype/bom/test_records.json @@ -0,0 +1,192 @@ +[ + { + "items": [ + { + "amount": 5000.0, + "doctype": "BOM Item", + "item_code": "_Test Serialized Item With Series", + "parentfield": "items", + "qty": 1.0, + "rate": 5000.0, + "uom": "_Test UOM", + "stock_uom": "_Test UOM", + "source_warehouse": "_Test Warehouse - _TC", + "include_item_in_manufacturing": 1 + }, + { + "amount": 2000.0, + "doctype": "BOM Item", + "item_code": "_Test Item 2", + "parentfield": "items", + "qty": 2.0, + "rate": 1000.0, + "uom": "_Test UOM", + "stock_uom": "_Test UOM", + "source_warehouse": "_Test Warehouse - _TC", + "include_item_in_manufacturing": 1 + } + ], + "docstatus": 1, + "doctype": "BOM", + "currency": "USD", + "is_active": 1, + "is_default": 1, + "item": "_Test Item Home Desktop Manufactured", + "company": "_Test Company", + "quantity": 1.0 + }, + { + "scrap_items":[ + { + "amount": 2000.0, + "doctype": "BOM Scrap Item", + "item_code": "_Test Item Home Desktop 100", + "parentfield": "scrap_items", + "stock_qty": 1.0, + "rate": 2000.0, + "stock_uom": "_Test UOM" + } + ], + "items": [ + { + "amount": 10000.0, + "doctype": "BOM Item", + "item_code": "_Test Item", + "parentfield": "items", + "qty": 1.0, + "rate": 5000.0, + "uom": "_Test UOM", + "stock_uom": "_Test UOM", + "source_warehouse": "_Test Warehouse - _TC", + "include_item_in_manufacturing": 1 + }, + { + "amount": 2000.0, + "doctype": "BOM Item", + "item_code": "_Test Item Home Desktop 100", + "parentfield": "items", + "qty": 2.0, + "rate": 1000.0, + "uom": "_Test UOM", + "stock_uom": "_Test UOM", + "source_warehouse": "_Test Warehouse - _TC", + "include_item_in_manufacturing": 1 + } + ], + "docstatus": 1, + "doctype": "BOM", + "is_active": 1, + "is_default": 1, + "currency": "USD", + "item": "_Test FG Item", + "quantity": 1.0 + }, + { + "operations": [ + { + "operation": "_Test Operation 1", + "description": "_Test", + "workstation": "_Test Workstation 1", + "hour_rate": 100, + "time_in_mins": 60, + "operating_cost": 100 + } + ], + "items": [ + { + "amount": 5000.0, + "doctype": "BOM Item", + "item_code": "_Test Item", + "parentfield": "items", + "qty": 1.0, + "rate": 5000.0, + "uom": "_Test UOM", + "stock_uom": "_Test UOM", + "source_warehouse": "_Test Warehouse - _TC", + "include_item_in_manufacturing": 1 + }, + { + "amount": 3000.0, + "bom_no": "BOM-_Test Item Home Desktop Manufactured-001", + "doctype": "BOM Item", + "item_code": "_Test Item Home Desktop Manufactured", + "parentfield": "items", + "qty": 3.0, + "rate": 1000.0, + "uom": "_Test UOM", + "stock_uom": "_Test UOM", + "source_warehouse": "_Test Warehouse - _TC", + "include_item_in_manufacturing": 1 + } + ], + "docstatus": 1, + "doctype": "BOM", + "is_active": 1, + "is_default": 1, + "currency": "USD", + "conversion_rate": 60, + "company": "_Test Company", + "item": "_Test FG Item 2", + "quantity": 1.0, + "with_operations": 1 + }, + { + "operations": [ + { + "operation": "_Test Operation 1", + "description": "_Test", + "workstation": "_Test Workstation 1", + "time_in_mins": 60, + "operating_cost": 140 + } + ], + "items": [ + { + "amount": 5000.0, + "doctype": "BOM Item", + "item_code": "_Test Item", + "parentfield": "items", + "qty": 2.0, + "rate": 3000.0, + "uom": "_Test UOM", + "stock_uom": "_Test UOM", + "source_warehouse": "_Test Warehouse - _TC", + "include_item_in_manufacturing": 1 + } + ], + "docstatus": 1, + "doctype": "BOM", + "is_active": 1, + "is_default": 1, + "currency": "USD", + "item": "_Test Variant Item", + "quantity": 1.0, + "with_operations": 1 + }, + { + "items": [ + { + "amount": 5000.0, + "doctype": "BOM Item", + "item_code": "_Test Item", + "parentfield": "items", + "qty": 2.0, + "rate": 3000.0, + "uom": "_Test UOM", + "stock_uom": "_Test UOM", + "source_warehouse": "_Test Warehouse - _TC", + "include_item_in_manufacturing": 1 + } + ], + "docstatus": 1, + "doctype": "BOM", + "is_active": 1, + "is_default": 1, + "currency": "USD", + "item": "_Test Variant Item", + "quantity": 1.0, + "with_operations": 0, + "fg_based_operating_cost": 1, + "operating_cost_per_bom_quantity": 140 + } +] diff --git a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py index 4d60506ca5e..82b9cff138e 100644 --- a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py +++ b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py @@ -17,6 +17,11 @@ from erpnext.tests.utils import ERPNextTestSuite class TestBOMUpdateLog(ERPNextTestSuite): "Test BOM Update Tool Operations via BOM Update Log." + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.load_test_records("BOM") + def setUp(self): bom_doc = frappe.copy_doc(self.globalTestRecords["BOM"][0]) bom_doc.items[1].item_code = "_Test Item" diff --git a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py index eec6db620da..e0750e58842 100644 --- a/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py +++ b/erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py @@ -16,6 +16,11 @@ from erpnext.tests.utils import ERPNextTestSuite class TestBOMUpdateTool(ERPNextTestSuite): "Test major functions run via BOM Update Tool." + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.load_test_records("BOM") + def tearDown(self): frappe.db.rollback() diff --git a/erpnext/manufacturing/doctype/job_card/test_job_card.py b/erpnext/manufacturing/doctype/job_card/test_job_card.py index 84bec0bcf3d..cdf6073ef7f 100644 --- a/erpnext/manufacturing/doctype/job_card/test_job_card.py +++ b/erpnext/manufacturing/doctype/job_card/test_job_card.py @@ -30,6 +30,9 @@ class TestJobCard(ERPNextTestSuite): @classmethod def setUpClass(cls): super().setUpClass() + # used in job card time log + cls.make_employees() + cls.load_test_records("BOM") def setUp(self): self.make_employees() # used in job card time log diff --git a/erpnext/tests/utils.py b/erpnext/tests/utils.py index 7102c313eb1..18a7be0510c 100644 --- a/erpnext/tests/utils.py +++ b/erpnext/tests/utils.py @@ -132,13 +132,13 @@ class ERPNextTestSuite(unittest.TestCase): @classmethod def setUpClass(cls): - cls.make_presets() - cls.make_persistent_master_data() - # initilize global test records attribute if not hasattr(cls, "globalTestRecords"): cls.globalTestRecords = {} + cls.make_presets() + cls.make_persistent_master_data() + @classmethod def load_test_records(cls, doctype): if doctype not in cls.globalTestRecords: @@ -239,6 +239,9 @@ class ERPNextTestSuite(unittest.TestCase): cls.make_loyalty_program() cls.make_shareholder() cls.make_sales_taxes_template() + cls.make_workstation() + cls.make_operation() + cls.make_bom() cls.update_selling_settings() cls.update_stock_settings() cls.update_system_settings() @@ -2786,6 +2789,56 @@ class ERPNextTestSuite(unittest.TestCase): ) ) + @classmethod + def make_operation(cls): + records = [ + {"doctype": "Operation", "name": "_Test Operation 1", "workstation": "_Test Workstation 1"} + ] + cls.operation = [] + for x in records: + if not frappe.db.exists("Operation", {"name": x.get("name")}): + cls.operation.append(frappe.get_doc(x).insert()) + else: + cls.operation.append(frappe.get_doc("Operation", {"name": x.get("name")})) + + @classmethod + def make_workstation(cls): + records = [ + { + "doctype": "Workstation", + "name": "_Test Workstation 1", + "workstation_name": "_Test Workstation 1", + "warehouse": "_Test warehouse - _TC", + "hour_rate_labour": 25, + "hour_rate_electricity": 25, + "hour_rate_consumable": 25, + "hour_rate_rent": 25, + "holiday_list": "_Test Holiday List", + "working_hours": [{"start_time": "10:00:00", "end_time": "20:00:00"}], + } + ] + cls.workstation = [] + for x in records: + if not frappe.db.exists("Workstation", {"workstation_name": x.get("workstation_name")}): + cls.workstation.append(frappe.get_doc(x).insert()) + else: + cls.workstation.append( + frappe.get_doc("Workstation", {"workstation_name": x.get("workstation_name")}) + ) + + @classmethod + def make_bom(cls): + # TODO: replace JSON source with hardcoded data in py + cls.load_test_records("BOM") + records = cls.globalTestRecords["BOM"] + cls.bom = [] + for x in records: + x["company"] = cls.companies[0].name + if not frappe.db.exists("BOM", {"item": x.get("item"), "company": x.get("company")}): + cls.bom.append(frappe.get_doc(x).insert()) + else: + cls.bom.append(frappe.get_doc("BOM", {"item": x.get("item"), "company": x.get("company")})) + @contextmanager def set_user(self, user: str): try: