diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 5ff531e797d5e47e9107ffea1c38035bc7666916..a4d132e89336530d0f85cedcd05fad5b8edb96fd 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -1321,12 +1321,18 @@ def get_children(parent=None, is_root=False, **filters): def add_additional_cost(stock_entry, work_order): # Add non stock items cost in the additional cost stock_entry.additional_costs = [] - default_expense_account = frappe.get_cached_value( - "Company", work_order.company, "default_expense_account" + company_account = frappe.db.get_value( + "Company", + work_order.company, + ["default_expense_account", "default_operating_cost_account"], + as_dict=1, ) - add_non_stock_items_cost(stock_entry, work_order, default_expense_account) - add_operations_cost(stock_entry, work_order, default_expense_account) + expecnse_account = ( + company_account.default_operating_cost_account or company_account.default_expense_account + ) + add_non_stock_items_cost(stock_entry, work_order, expecnse_account) + add_operations_cost(stock_entry, work_order, expecnse_account) def add_non_stock_items_cost(stock_entry, work_order, expense_account): diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index e451898797c75ba325416c156f18ac8b120ceff6..8f33104bfc76a6c68fdc9ece3dc05141d5fcdd22 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -1749,6 +1749,81 @@ class TestWorkOrder(FrappeTestCase): job_card2.time_logs = [] job_card2.save() + def test_operating_cost_account(self): + operating_cost_account = "Test Operating Cost Account - _TC" + company = "_Test Company" + if not frappe.db.exists("Account", operating_cost_account): + frappe.get_doc( + { + "doctype": "Account", + "account_name": "Test Operating Cost Account", + "account_type": "Expense Account", + "company": company, + "parent_account": "Expenses - _TC", + "root_type": "Expense", + } + ).insert() + + frappe.db.set_value("Company", company, "default_operating_cost_account", operating_cost_account) + + for item in ["TEST RM OP COST Item 1", "TEST FG OP COST Item"]: + if not frappe.db.exists("Item", item): + make_item(item_code=item, properties={"is_stock_item": 1}) + + fg_item = "TEST FG OP COST Item" + bom_doc = make_bom( + item=fg_item, + raw_materials=["TEST RM OP COST Item 1"], + rate=150, + with_operations=1, + do_not_save=True, + ) + + workstation = "Test Workstation For Capacity Planning 1" + if not frappe.db.exists("Workstation", workstation): + make_workstation(workstation=workstation, production_capacity=1) + + operation = "Test Operation For Capacity Planning 1" + if not frappe.db.exists("Operation", operation): + make_operation(operation=operation, workstation=workstation) + + bom_doc.append( + "operations", + {"operation": operation, "time_in_mins": 60, "hour_rate": 100, "workstation": workstation}, + ) + + bom_doc.save() + bom_doc.submit() + + wo = make_wo_order_test_record( + production_item=fg_item, + bom_no=bom_doc.name, + qty=1, + skip_transfer=1, + ) + + job_cards = frappe.get_all("Job Card", filters={"work_order": wo.name}) + for job_card in job_cards: + job_card_doc = frappe.get_doc("Job Card", job_card.name) + job_card_doc.time_logs = [] + job_card_doc.append( + "time_logs", + { + "from_time": now(), + "to_time": add_to_date(now(), minutes=60), + "time_in_mins": 60, + "completed_qty": 1, + }, + ) + + job_card_doc.submit() + + se_doc = frappe.get_doc(make_stock_entry(wo.name, "Manufacture", 1)) + se_doc.save() + + for row in se_doc.additional_costs: + self.assertEqual(row.expense_account, operating_cost_account) + def test_op_cost_and_scrap_based_on_sub_assemblies(self): # Make Sub Assembly BOM 1 diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 45d8b496321c21acdba64650e18003373c1ca844..a042b8ce01319775170be475c3792d7b68e410a7 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -28,6 +28,12 @@ frappe.ui.form.on("Company", { }; }); + frm.set_query("default_operating_cost_account", function (doc) { + return { + filters: { company: doc.name, root_type: "Expense" }, + }; + }); + frm.set_query("default_selling_terms", function () { return { filters: { selling: 1 } }; }); diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 289d303d25113c24ca194810b7bcb32d38f20999..897eeeb44614fb7704f7771d77fbe0a61595053a 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -108,6 +108,8 @@ "stock_received_but_not_billed", "default_provisional_account", "default_in_transit_warehouse", + "manufacturing_section", + "default_operating_cost_account", "dashboard_tab" ], "fields": [ @@ -764,13 +766,24 @@ { "fieldname": "stock_tab", "fieldtype": "Tab Break", - "label": "Stock" + "label": "Stock and Manufacturing" }, { "fieldname": "dashboard_tab", "fieldtype": "Tab Break", "label": "Dashboard", "show_dashboard": 1 + }, + { + "fieldname": "manufacturing_section", + "fieldtype": "Section Break", + "label": "Manufacturing" + }, + { + "fieldname": "default_operating_cost_account", + "fieldtype": "Link", + "label": "Default Operating Cost Account", + "options": "Account" } ], "icon": "fa fa-building", @@ -778,7 +791,7 @@ "image_field": "company_logo", "is_tree": 1, "links": [], - "modified": "2024-05-27 17:32:49.057386", + "modified": "2024-06-21 17:46:25.567565", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 0725fd15072b5a0a7580dba1fb8fb69b927cb1db..845e97df102fb165127849723f358db3f22e68bb 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -60,6 +60,7 @@ class Company(NestedSet): default_income_account: DF.Link | None default_inventory_account: DF.Link | None default_letter_head: DF.Link | None + default_operating_cost_account: DF.Link | None default_payable_account: DF.Link | None default_provisional_account: DF.Link | None default_receivable_account: DF.Link | None