From 59c3eef7dbf6c93f5b037d7e317e283f28e98a39 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Wed, 19 Nov 2025 13:00:47 +0530 Subject: [PATCH] fix: stock entry manufacture - fix operating cost calculation --- erpnext/manufacturing/doctype/bom/bom.py | 1 + .../landed_cost_taxes_and_charges.json | 12 ++++++++-- .../landed_cost_taxes_and_charges.py | 1 + .../stock/doctype/stock_entry/stock_entry.py | 23 ++++++++++++++++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 754a64e11bb..753d5a6ec4d 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -1574,6 +1574,7 @@ def add_operations_cost(stock_entry, work_order=None, expense_account=None, job_ "expense_account": expense_account, "description": _("Operating Cost as per Work Order / BOM"), "amount": operating_cost_per_unit * flt(stock_entry.fg_completed_qty), + "has_operating_cost": 1, }, ) diff --git a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json index dac161a46ff..1bbafc08446 100644 --- a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json +++ b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json @@ -12,7 +12,8 @@ "col_break3", "amount", "base_amount", - "has_corrective_cost" + "has_corrective_cost", + "has_operating_cost" ], "fields": [ { @@ -70,13 +71,20 @@ "fieldtype": "Check", "label": "Has Corrective Cost", "read_only": 1 + }, + { + "default": "0", + "fieldname": "has_operating_cost", + "fieldtype": "Check", + "label": "Has Operating Cost", + "read_only": 1 } ], "grid_page_length": 50, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2025-06-09 10:22:20.286641", + "modified": "2025-07-16 15:27:59.175530", "modified_by": "Administrator", "module": "Stock", "name": "Landed Cost Taxes and Charges", diff --git a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py index a3f7f037d60..a4fb129a7ae 100644 --- a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py +++ b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.py @@ -21,6 +21,7 @@ class LandedCostTaxesandCharges(Document): exchange_rate: DF.Float expense_account: DF.Link | None has_corrective_cost: DF.Check + has_operating_cost: DF.Check parent: DF.Data parentfield: DF.Data parenttype: DF.Data diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index e67192a4299..540de088c42 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -3418,6 +3418,25 @@ def get_work_order_details(work_order, company): def get_operating_cost_per_unit(work_order=None, bom_no=None): + def get_consumed_operating_cost(wo_name, bom_no): + table = frappe.qb.DocType("Stock Entry") + child_table = frappe.qb.DocType("Landed Cost Taxes and Charges") + query = ( + frappe.qb.from_(child_table) + .join(table) + .on(child_table.parent == table.name) + .select(Sum(child_table.amount).as_("consumed_cost")) + .where( + (table.docstatus == 1) + & (table.work_order == wo_name) + & (table.purpose == "Manufacture") + & (table.bom_no == bom_no) + & (child_table.has_operating_cost == 1) + ) + ) + cost = query.run(pluck="consumed_cost") + return cost[0] if cost and cost[0] else 0 + operating_cost_per_unit = 0 if work_order: if ( @@ -3434,7 +3453,9 @@ def get_operating_cost_per_unit(work_order=None, bom_no=None): for d in work_order.get("operations"): if flt(d.completed_qty): - operating_cost_per_unit += flt(d.actual_operating_cost) / flt(d.completed_qty) + operating_cost_per_unit += flt( + d.actual_operating_cost - get_consumed_operating_cost(work_order.name, bom_no) + ) / flt(d.completed_qty - work_order.produced_qty) elif work_order.qty: operating_cost_per_unit += flt(d.planned_operating_cost) / flt(work_order.qty)