From 3aeb7d6b01ab01e947e4809e6e7425e22b61ac59 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Tue, 14 Apr 2026 12:31:10 +0530 Subject: [PATCH] fix(purchase_register): filter tax rows by parenttype in invoice tax map query --- .../purchase_register/purchase_register.py | 2 +- .../test_purchase_register.py | 47 +++++++++++++++++++ .../sales_register/test_sales_register.py | 38 +++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/purchase_register/purchase_register.py b/erpnext/accounts/report/purchase_register/purchase_register.py index 2ec8931b63d..4801bf15b56 100644 --- a/erpnext/accounts/report/purchase_register/purchase_register.py +++ b/erpnext/accounts/report/purchase_register/purchase_register.py @@ -499,7 +499,7 @@ def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts, inc else sum(base_tax_amount_after_discount_amount) * -1 end as tax_amount from `tabPurchase Taxes and Charges` where parent in (%s) and category in ('Total', 'Valuation and Total') - and base_tax_amount_after_discount_amount != 0 + and base_tax_amount_after_discount_amount != 0 and parenttype='Purchase Invoice' group by parent, account_head, add_deduct_tax """ % ", ".join(["%s"] * len(invoice_list)), diff --git a/erpnext/accounts/report/purchase_register/test_purchase_register.py b/erpnext/accounts/report/purchase_register/test_purchase_register.py index 400ee899fa1..e4ce5ffcfe3 100644 --- a/erpnext/accounts/report/purchase_register/test_purchase_register.py +++ b/erpnext/accounts/report/purchase_register/test_purchase_register.py @@ -5,6 +5,7 @@ import frappe from frappe.utils import add_months, today from erpnext.accounts.report.purchase_register.purchase_register import execute +from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt from erpnext.tests.utils import ERPNextTestSuite @@ -26,6 +27,52 @@ class TestPurchaseRegister(ERPNextTestSuite): self.assertEqual(first_row.total_tax, 100) self.assertEqual(first_row.grand_total, 1100) + def test_purchase_register_ignores_tax_rows_from_other_doctype(self): + frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company 6'") + frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 6'") + + filters = frappe._dict(company="_Test Company 6", from_date=add_months(today(), -1), to_date=today()) + + pi = make_purchase_invoice() + + # Real workflow setup: create a Purchase Receipt tax row in the same shared child table. + pr = make_purchase_receipt( + company="_Test Company 6", + supplier="_Test Supplier", + item="_Test Item", + warehouse="_Test Warehouse - _TC6", + cost_center="_Test Cost Center - _TC6", + do_not_save=1, + do_not_submit=1, + qty=1, + rate=1000, + ) + pr.append( + "taxes", + { + "account_head": "GST - _TC6", + "cost_center": "_Test Cost Center - _TC6", + "add_deduct_tax": "Add", + "category": "Valuation and Total", + "charge_type": "Actual", + "description": "PR Tax", + "tax_amount": 100.0, + "rate": 100, + }, + ) + pr.insert() + pr.submit() + + # Mimic custom naming collision across doctypes (same parent value in shared child table). + frappe.rename_doc("Purchase Receipt", pr.name, pi.name, force=True) + + report_results = execute(filters) + first_row = frappe._dict(report_results[1][0]) + + self.assertEqual(first_row.voucher_no, pi.name) + self.assertEqual(first_row.total_tax, 100) + self.assertEqual(first_row.grand_total, 1100) + def test_purchase_register_ledger_view(self): frappe.db.sql("delete from `tabPurchase Invoice` where company='_Test Company 6'") frappe.db.sql("delete from `tabGL Entry` where company='_Test Company 6'") diff --git a/erpnext/accounts/report/sales_register/test_sales_register.py b/erpnext/accounts/report/sales_register/test_sales_register.py index c6926d57dea..0875c7c143f 100644 --- a/erpnext/accounts/report/sales_register/test_sales_register.py +++ b/erpnext/accounts/report/sales_register/test_sales_register.py @@ -4,6 +4,7 @@ from frappe.utils import getdate, today from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice from erpnext.accounts.report.sales_register.sales_register import execute from erpnext.accounts.test.accounts_mixin import AccountsTestMixin +from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order from erpnext.tests.utils import ERPNextTestSuite @@ -72,6 +73,43 @@ class TestItemWiseSalesRegister(ERPNextTestSuite, AccountsTestMixin): report_output = {k: v for k, v in report[1][0].items() if k in expected_result} self.assertDictEqual(report_output, expected_result) + def test_sales_register_ignores_tax_rows_from_other_doctype(self): + si = self.create_sales_invoice(rate=98) + + # Real workflow setup: create a Sales Order with taxes in the shared child table. + so = make_sales_order( + item=self.item, + company=self.company, + customer=self.customer, + rate=77, + do_not_save=1, + do_not_submit=1, + ) + so.append( + "taxes", + { + "charge_type": "Actual", + "account_head": self.income_account, + "description": "SO Tax", + "tax_amount": 55.0, + }, + ) + so.insert() + so.submit() + + # Mimic custom naming collision across doctypes (same parent value in shared child table). + frappe.rename_doc("Sales Order", so.name, si.name, force=True) + + filters = frappe._dict({"from_date": today(), "to_date": today(), "company": self.company}) + report = execute(filters) + + self.assertEqual(len(report[1]), 1) + result = frappe._dict(report[1][0]) + self.assertEqual(result.voucher_no, si.name) + self.assertEqual(result.net_total, 98.0) + self.assertEqual(result.tax_total, 0) + self.assertEqual(result.grand_total, 98.0) + def test_journal_with_cost_center_filter(self): je1 = frappe.get_doc( {