From c4c76cc1b2e65f510d57fa65a3ef966454ef6266 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Tue, 31 Mar 2026 17:23:01 +0530 Subject: [PATCH 1/2] fix: ensure accurate rounding for item-wise tax and taxable amounts (cherry picked from commit 9b37f2d95c343b878fb3872575bf231a96e93416) --- erpnext/controllers/taxes_and_totals.py | 8 ++- .../tests/test_item_wise_tax_details.py | 57 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index f0da61ad900..6f34e6bbb6e 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -611,7 +611,9 @@ class calculate_taxes_and_totals: flt(tax._running_txn_tax_total, tax.precision("tax_amount")) * self.doc.conversion_rate, tax.precision("base_tax_amount"), ) - item_wise_tax_amount = new_base_tax_total - tax._running_base_tax_total + item_wise_tax_amount = flt( + new_base_tax_total - tax._running_base_tax_total, tax.precision("base_tax_amount") + ) tax._running_base_tax_total = new_base_tax_total if tax.charge_type != "On Item Quantity": @@ -620,7 +622,9 @@ class calculate_taxes_and_totals: flt(tax._running_txn_taxable_total, tax.precision("net_amount")) * self.doc.conversion_rate, tax.precision("base_net_amount"), ) - item_wise_taxable_amount = new_base_taxable_total - tax._running_base_taxable_total + item_wise_taxable_amount = flt( + new_base_taxable_total - tax._running_base_taxable_total, tax.precision("base_net_amount") + ) tax._running_base_taxable_total = new_base_taxable_total else: item_wise_taxable_amount = 0.0 diff --git a/erpnext/controllers/tests/test_item_wise_tax_details.py b/erpnext/controllers/tests/test_item_wise_tax_details.py index 30f1e51d7f4..a921442472e 100644 --- a/erpnext/controllers/tests/test_item_wise_tax_details.py +++ b/erpnext/controllers/tests/test_item_wise_tax_details.py @@ -204,6 +204,63 @@ class TestTaxesAndTotals(ERPNextTestSuite): for tax in doc.taxes: self.assertEqual(details_by_tax[tax.name], tax.base_tax_amount_after_discount_amount) + @change_settings("Selling Settings", {"allow_multiple_items": 1}) + def test_rounding_in_item_wise_tax_details(self): + """ + This test verifies the amounts are properly rounded. + """ + doc = frappe.get_doc( + { + "doctype": "Sales Invoice", + "customer": "_Test Customer", + "company": "_Test Company", + "currency": "INR", + "conversion_rate": 1, + "items": [ + { + "item_code": "_Test Item", + "qty": 5, + "rate": 20, + "income_account": "Sales - _TC", + "expense_account": "Cost of Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", + }, + { + "item_code": "_Test Item", + "qty": 3, + "rate": 19, + "income_account": "Sales - _TC", + "expense_account": "Cost of Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", + }, + { + "item_code": "_Test Item", + "qty": 1, + "rate": 1000, + "income_account": "Sales - _TC", + "expense_account": "Cost of Goods Sold - _TC", + "cost_center": "_Test Cost Center - _TC", + }, + ], + "taxes": [ + { + "charge_type": "On Net Total", + "account_head": "_Test Account VAT - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "VAT", + "rate": 9, + }, + ], + } + ) + doc.save() + + # item 1: taxable=100, tax=9.0; item 2: taxable=57, tax=5.13; item 3: taxable=1000, tax=90.0 + # error diffusion: 14.13 - 9.0 = 5.130000000000001 without rounding + # 3rd item ensures the artifact is on a middle row (not corrected by last-row adjustment) + for detail in doc.item_wise_tax_details: + self.assertEqual(detail.amount, round(detail.amount, 2)) + def test_item_wise_tax_detail_with_multi_currency_with_single_item(self): """ When the tax amount (in transaction currency) has more decimals than From 9386c1328ad933186778677ec1c7e0a5a76de879 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Tue, 31 Mar 2026 17:46:46 +0530 Subject: [PATCH 2/2] test: improve test case (cherry picked from commit b73b161cbed791a8eb5e2f2939ed85a9c6534b50) --- erpnext/controllers/tests/test_item_wise_tax_details.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/tests/test_item_wise_tax_details.py b/erpnext/controllers/tests/test_item_wise_tax_details.py index a921442472e..7e19c1dc057 100644 --- a/erpnext/controllers/tests/test_item_wise_tax_details.py +++ b/erpnext/controllers/tests/test_item_wise_tax_details.py @@ -1,6 +1,7 @@ import json import frappe +from frappe.utils import flt from erpnext.tests.utils import ERPNextTestSuite, change_settings @@ -257,9 +258,8 @@ class TestTaxesAndTotals(ERPNextTestSuite): # item 1: taxable=100, tax=9.0; item 2: taxable=57, tax=5.13; item 3: taxable=1000, tax=90.0 # error diffusion: 14.13 - 9.0 = 5.130000000000001 without rounding - # 3rd item ensures the artifact is on a middle row (not corrected by last-row adjustment) for detail in doc.item_wise_tax_details: - self.assertEqual(detail.amount, round(detail.amount, 2)) + self.assertEqual(detail.amount, flt(detail.amount, detail.precision("amount"))) def test_item_wise_tax_detail_with_multi_currency_with_single_item(self): """