From 43690fb32bc31fff73d274f93a6b43d452fc9ca0 Mon Sep 17 00:00:00 2001 From: S Sakthivel Murugan Date: Thu, 25 Jun 2026 11:11:40 +0530 Subject: [PATCH] fix: use company currency instead of global default in report (cherry picked from commit e6f9149ad70bb8a96993a8216954eee5f9eea367) # Conflicts: # erpnext/stock/report/landed_cost_report/landed_cost_report.py --- .../accounts/report/cash_flow/cash_flow.py | 1 + .../report/gross_profit/gross_profit.py | 2 + .../purchase_order_trends.py | 4 + erpnext/controllers/trends.py | 13 +- .../quotation_trends/quotation_trends.py | 6 +- .../sales_order_trends/sales_order_trends.py | 4 + .../delivery_note_trends.py | 4 + .../landed_cost_report/landed_cost_report.py | 154 ++++++++++++++++++ .../purchase_receipt_trends.py | 4 + 9 files changed, 187 insertions(+), 5 deletions(-) create mode 100644 erpnext/stock/report/landed_cost_report/landed_cost_report.py diff --git a/erpnext/accounts/report/cash_flow/cash_flow.py b/erpnext/accounts/report/cash_flow/cash_flow.py index c4b894a34b8..d476fd4b3ef 100644 --- a/erpnext/accounts/report/cash_flow/cash_flow.py +++ b/erpnext/accounts/report/cash_flow/cash_flow.py @@ -73,6 +73,7 @@ def execute(filters=None): "parent_section": None, "indent": 0.0, "section": cash_flow_section["section_header"], + "currency": company_currency, } ) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 8ecfe51d244..f557635aac1 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -227,6 +227,7 @@ def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_ ) if total_base_amount else 0, + "currency": filters.currency, } ) ) @@ -269,6 +270,7 @@ def get_data_when_not_grouped_by_invoice(gross_profit_data, filters, group_wise_ "buying_amount": total_buying_amount, "gross_profit": total_gross_profit, "gross_profit_percent": flt(gross_profit_percent, currency_precision), + "currency": filters.currency, } total_row = [total_row.get(col, None) for col in [*group_columns, "currency"]] diff --git a/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py b/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py index a7b4a7207c6..d59051407d2 100644 --- a/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py +++ b/erpnext/buying/report/purchase_order_trends/purchase_order_trends.py @@ -4,6 +4,7 @@ from frappe import _ +import erpnext from erpnext.controllers.trends import get_columns, get_data @@ -50,6 +51,7 @@ def get_chart_data(data, conditions, filters): for i in range(len(row)): datapoints[i] += row[i] + company_currency = erpnext.get_company_currency(filters.get("company")) return { "data": { "labels": labels, @@ -60,4 +62,6 @@ def get_chart_data(data, conditions, filters): "type": "line", "lineOptions": {"regionFill": 1}, "fieldtype": "Currency", + "options": "currency", + "currency": company_currency, } diff --git a/erpnext/controllers/trends.py b/erpnext/controllers/trends.py index 28ff84c83fd..fed7bec1351 100644 --- a/erpnext/controllers/trends.py +++ b/erpnext/controllers/trends.py @@ -6,6 +6,7 @@ import frappe from frappe import _ from frappe.utils import DateTimeLikeObject, getdate, today +import erpnext from erpnext.accounts.utils import get_fiscal_year @@ -206,7 +207,7 @@ def get_data(filters, conditions): data.append(des) - total_row = calculate_total_row(data1, conditions["columns"]) + total_row = calculate_total_row(data1, conditions["columns"], filters.get("company")) data.append(total_row) else: data = frappe.db.sql( @@ -231,20 +232,23 @@ def get_data(filters, conditions): as_list=1, ) - total_row = calculate_total_row(data, conditions["columns"]) + total_row = calculate_total_row(data, conditions["columns"], filters.get("company")) data.append(total_row) return data -def calculate_total_row(data, columns): +def calculate_total_row(data, columns, company=None): def wrap_in_quotes(label): return f"'{label}'" total_values = {} + currency_col_idx = None for i, col in enumerate(columns): if "Float" in col or "Currency/currency" in col: total_values[i] = 0 + if col.split(":")[0] == "Currency": + currency_col_idx = i for row in data: for i in total_values.keys(): @@ -254,6 +258,9 @@ def calculate_total_row(data, columns): for i in range(1, len(columns)): total_row.append(total_values.get(i, None)) + if currency_col_idx is not None: + total_row[currency_col_idx] = company and erpnext.get_company_currency(company) + return total_row diff --git a/erpnext/selling/report/quotation_trends/quotation_trends.py b/erpnext/selling/report/quotation_trends/quotation_trends.py index 92f9d17a9c7..57c6cc4e2e3 100644 --- a/erpnext/selling/report/quotation_trends/quotation_trends.py +++ b/erpnext/selling/report/quotation_trends/quotation_trends.py @@ -1,9 +1,9 @@ # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors # License: GNU General Public License v3. See license.txt - from frappe import _ +import erpnext from erpnext.controllers.trends import get_columns, get_data @@ -50,7 +50,7 @@ def get_chart_data(data, conditions, filters): for i in range(len(row)): datapoints[i] += row[i] - + company_currency = erpnext.get_company_currency(filters.get("company")) return { "data": { "labels": labels, @@ -59,4 +59,6 @@ def get_chart_data(data, conditions, filters): "type": "line", "lineOptions": {"regionFill": 1}, "fieldtype": "Currency", + "options": "currency", + "currency": company_currency, } diff --git a/erpnext/selling/report/sales_order_trends/sales_order_trends.py b/erpnext/selling/report/sales_order_trends/sales_order_trends.py index 0827110ae5d..e819ab949c3 100644 --- a/erpnext/selling/report/sales_order_trends/sales_order_trends.py +++ b/erpnext/selling/report/sales_order_trends/sales_order_trends.py @@ -4,6 +4,7 @@ from frappe import _ +import erpnext from erpnext.controllers.trends import get_columns, get_data @@ -50,6 +51,7 @@ def get_chart_data(data, conditions, filters): for i in range(len(row)): datapoints[i] += row[i] + company_currency = erpnext.get_company_currency(filters.get("company")) return { "data": { "labels": labels, @@ -58,4 +60,6 @@ def get_chart_data(data, conditions, filters): "type": "line", "lineOptions": {"regionFill": 1}, "fieldtype": "Currency", + "options": "currency", + "currency": company_currency, } diff --git a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py index a456bad72d7..8e98a6832e5 100644 --- a/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py +++ b/erpnext/stock/report/delivery_note_trends/delivery_note_trends.py @@ -4,6 +4,7 @@ from frappe import _ +import erpnext from erpnext.controllers.trends import get_columns, get_data @@ -45,6 +46,7 @@ def get_chart_data(data, filters): labels.append(row[0]) datapoints.append(row[-1]) + company_currency = erpnext.get_company_currency(filters.get("company")) return { "data": { "labels": labels, @@ -52,4 +54,6 @@ def get_chart_data(data, filters): }, "type": "bar", "fieldtype": "Currency", + "options": "currency", + "currency": company_currency, } diff --git a/erpnext/stock/report/landed_cost_report/landed_cost_report.py b/erpnext/stock/report/landed_cost_report/landed_cost_report.py new file mode 100644 index 00000000000..7b8503e8537 --- /dev/null +++ b/erpnext/stock/report/landed_cost_report/landed_cost_report.py @@ -0,0 +1,154 @@ +# Copyright (c) 2025, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +import frappe +from frappe import _ + + +def execute(filters: dict | None = None): + columns = get_columns() + data = get_data(filters) + + return columns, data + + +def get_columns() -> list[dict]: + return [ + { + "label": _("Landed Cost Id"), + "fieldname": "name", + "fieldtype": "Link", + "options": "Landed Cost Voucher", + }, + { + "label": _("Total Landed Cost"), + "fieldname": "landed_cost", + "fieldtype": "Currency", + "options": "currency", + }, + { + "label": _("Purchase Voucher Type"), + "fieldname": "voucher_type", + "fieldtype": "Data", + "width": 200, + }, + { + "label": _("Purchase Voucher No"), + "fieldname": "voucher_no", + "fieldtype": "Dynamic Link", + "options": "voucher_type", + "width": 220, + }, + { + "label": _("Vendor Invoice"), + "fieldname": "vendor_invoice", + "fieldtype": "Link", + "options": "Purchase Invoice", + "width": 200, + }, + ] + + +def get_data(filters) -> list[list]: + company_currency = frappe.get_cached_value("Company", filters.company, "default_currency") + + landed_cost_vouchers = get_landed_cost_vouchers(filters) or {} + landed_vouchers = list(landed_cost_vouchers.keys()) + vendor_invoices = {} + if landed_vouchers: + vendor_invoices = get_vendor_invoices(landed_vouchers) + + data = [] + + for name, vouchers in landed_cost_vouchers.items(): + res = { + "name": name, + } + + last_index = 0 + vendor_invoice_list = vendor_invoices.get(name, []) + for i, d in enumerate(vouchers): + if i == 0: + res.update( + { + "landed_cost": d.landed_cost, + "voucher_type": d.voucher_type, + "voucher_no": d.voucher_no, + "currency": company_currency, + } + ) + else: + res = { + "voucher_type": d.voucher_type, + "voucher_no": d.voucher_no, + } + + if len(vendor_invoice_list) > i: + res["vendor_invoice"] = vendor_invoice_list[i] + + data.append(res) + last_index = i + + if vendor_invoice_list and len(vendor_invoice_list) > len(vouchers): + for row in vendor_invoice_list[last_index + 1 :]: + data.append({"vendor_invoice": row}) + + return data + + +def get_landed_cost_vouchers(filters): + lcv = frappe.qb.DocType("Landed Cost Voucher") + lcv_voucher = frappe.qb.DocType("Landed Cost Purchase Receipt") + + query = ( + frappe.qb.from_(lcv) + .inner_join(lcv_voucher) + .on(lcv.name == lcv_voucher.parent) + .select( + lcv.name, + lcv.total_taxes_and_charges.as_("landed_cost"), + lcv_voucher.receipt_document_type.as_("voucher_type"), + lcv_voucher.receipt_document.as_("voucher_no"), + ) + .where((lcv.docstatus == 1) & (lcv.company == filters.company)) + ) + + if filters.from_date and filters.to_date: + query = query.where(lcv.posting_date.between(filters.from_date, filters.to_date)) + + if filters.raw_material_voucher_type: + query = query.where(lcv_voucher.receipt_document_type == filters.raw_material_voucher_type) + + if filters.raw_material_voucher_no: + query = query.where(lcv_voucher.receipt_document == filters.raw_material_voucher_no) + + data = query.run(as_dict=True) or [] + result = {} + for row in data: + result.setdefault((row.name), []).append(row) + + return result + + +def get_vendor_invoices(landed_vouchers): + doctype = frappe.qb.DocType("Landed Cost Vendor Invoice") + + query = ( + frappe.qb.from_(doctype) + .select( + doctype.parent, + doctype.vendor_invoice, + ) + .where((doctype.docstatus == 1) & (doctype.parent.isin(landed_vouchers))) + .orderby( + doctype.idx, + ) + ) + + data = query.run(as_dict=True) or [] + + result = {} + for row in data: + result.setdefault(row.parent, []).append(row.vendor_invoice) + + return result diff --git a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py index 9d313b477a3..1f7098ba806 100644 --- a/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py +++ b/erpnext/stock/report/purchase_receipt_trends/purchase_receipt_trends.py @@ -4,6 +4,7 @@ from frappe import _ +import erpnext from erpnext.controllers.trends import get_columns, get_data @@ -44,6 +45,7 @@ def get_chart_data(data, filters): labels.append(row[0]) datapoints.append(row[-1]) + company_currency = erpnext.get_company_currency(filters.get("company")) return { "data": { @@ -53,4 +55,6 @@ def get_chart_data(data, filters): "type": "bar", "colors": ["#5e64ff"], "fieldtype": "Currency", + "options": "currency", + "currency": company_currency, }