From 20682997661ff64b8beafa187aae6278e7d1b126 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Fri, 23 Jan 2026 20:30:07 +0530 Subject: [PATCH] fix: prevent precision errors in discount distribution with inclusive tax --- erpnext/controllers/taxes_and_totals.py | 5 +++ .../tests/test_distributed_discount.py | 38 +++++++++++++++++++ .../public/js/controllers/taxes_and_totals.js | 6 +++ 3 files changed, 49 insertions(+) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 773bd25ec4a..41f532a98e7 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -671,6 +671,11 @@ class calculate_taxes_and_totals: else: self.grand_total_diff = 0 + # Apply rounding adjustment to grand_total_for_distributing_discount + # to prevent precision errors during discount distribution + if hasattr(self, "grand_total_for_distributing_discount") and not self.discount_amount_applied: + self.grand_total_for_distributing_discount += self.grand_total_diff + def calculate_totals(self): grand_total_diff = self.grand_total_diff diff --git a/erpnext/controllers/tests/test_distributed_discount.py b/erpnext/controllers/tests/test_distributed_discount.py index ae2381152ec..05db1496da8 100644 --- a/erpnext/controllers/tests/test_distributed_discount.py +++ b/erpnext/controllers/tests/test_distributed_discount.py @@ -59,3 +59,41 @@ class TestTaxesAndTotals(AccountsTestMixin, IntegrationTestCase): self.assertEqual(so.total, 1500) self.assertAlmostEqual(so.net_total, 1272.73, places=2) self.assertEqual(so.grand_total, 1400) + + def test_100_percent_discount_with_inclusive_tax(self): + """Test that 100% discount with inclusive taxes results in zero net_total""" + so = make_sales_order(do_not_save=1) + so.apply_discount_on = "Grand Total" + so.items[0].qty = 2 + so.items[0].rate = 1300 + so.append( + "taxes", + { + "charge_type": "On Net Total", + "account_head": "_Test Account VAT - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Account VAT", + "included_in_print_rate": True, + "rate": 9, + }, + ) + so.append( + "taxes", + { + "charge_type": "On Net Total", + "account_head": "_Test Account Service Tax - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Account Service Tax", + "included_in_print_rate": True, + "rate": 9, + }, + ) + so.save() + + # Apply 100% discount + so.discount_amount = 2600 + calculate_taxes_and_totals(so) + + # net_total should be exactly 0, not 0.01 + self.assertEqual(so.net_total, 0) + self.assertEqual(so.grand_total, 0) diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 87ec985ad18..e7b5b6dddab 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -623,6 +623,12 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { } else { me.grand_total_diff = 0; } + + // Apply rounding adjustment to grand_total_for_distributing_discount + // to prevent precision errors during discount distribution + if (me.grand_total_for_distributing_discount && !me.discount_amount_applied) { + me.grand_total_for_distributing_discount += me.grand_total_diff; + } } } }