mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-13 20:05:09 +00:00
fix(taxes): improve tax calculation accuracy and update test assertions
(cherry picked from commit a18196f584)
This commit is contained in:
@@ -285,6 +285,13 @@ class calculate_taxes_and_totals:
|
|||||||
self.doc._item_wise_tax_details = item_wise_tax_details
|
self.doc._item_wise_tax_details = item_wise_tax_details
|
||||||
self.doc.item_wise_tax_details = []
|
self.doc.item_wise_tax_details = []
|
||||||
|
|
||||||
|
for tax in self.doc.get("taxes"):
|
||||||
|
if not tax.get("dont_recompute_tax"):
|
||||||
|
tax._running_txn_tax_total = 0.0
|
||||||
|
tax._running_base_tax_total = 0.0
|
||||||
|
tax._running_txn_taxable_total = 0.0
|
||||||
|
tax._running_base_taxable_total = 0.0
|
||||||
|
|
||||||
def determine_exclusive_rate(self):
|
def determine_exclusive_rate(self):
|
||||||
if not any(cint(tax.included_in_print_rate) for tax in self.doc.get("taxes")):
|
if not any(cint(tax.included_in_print_rate) for tax in self.doc.get("taxes")):
|
||||||
return
|
return
|
||||||
@@ -521,8 +528,7 @@ class calculate_taxes_and_totals:
|
|||||||
actual_breakup = tax._total_tax_breakup
|
actual_breakup = tax._total_tax_breakup
|
||||||
diff = flt(expected_amount - actual_breakup, 5)
|
diff = flt(expected_amount - actual_breakup, 5)
|
||||||
|
|
||||||
# TODO: fix rounding difference issues
|
if abs(diff) <= 0.5:
|
||||||
if abs(diff) <= 1:
|
|
||||||
detail_row = self.doc._item_wise_tax_details[last_idx]
|
detail_row = self.doc._item_wise_tax_details[last_idx]
|
||||||
detail_row["amount"] = flt(detail_row["amount"] + diff, 5)
|
detail_row["amount"] = flt(detail_row["amount"] + diff, 5)
|
||||||
|
|
||||||
@@ -597,14 +603,25 @@ class calculate_taxes_and_totals:
|
|||||||
def set_item_wise_tax(self, item, tax, tax_rate, current_tax_amount, current_net_amount):
|
def set_item_wise_tax(self, item, tax, tax_rate, current_tax_amount, current_net_amount):
|
||||||
# store tax breakup for each item
|
# store tax breakup for each item
|
||||||
multiplier = -1 if tax.get("add_deduct_tax") == "Deduct" else 1
|
multiplier = -1 if tax.get("add_deduct_tax") == "Deduct" else 1
|
||||||
item_wise_tax_amount = flt(
|
|
||||||
current_tax_amount * self.doc.conversion_rate * multiplier, tax.precision("tax_amount")
|
# Error diffusion: derive each item's base amount as a delta of the running cumulative total
|
||||||
|
# so the sum always equals base_tax_amount_after_discount_amount.
|
||||||
|
tax._running_txn_tax_total += current_tax_amount * multiplier
|
||||||
|
new_base_tax_total = flt(
|
||||||
|
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
|
||||||
|
tax._running_base_tax_total = new_base_tax_total
|
||||||
|
|
||||||
if tax.charge_type != "On Item Quantity":
|
if tax.charge_type != "On Item Quantity":
|
||||||
item_wise_taxable_amount = flt(
|
tax._running_txn_taxable_total += current_net_amount * multiplier
|
||||||
current_net_amount * self.doc.conversion_rate * multiplier, tax.precision("tax_amount")
|
new_base_taxable_total = flt(
|
||||||
|
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
|
||||||
|
tax._running_base_taxable_total = new_base_taxable_total
|
||||||
else:
|
else:
|
||||||
item_wise_taxable_amount = 0.0
|
item_wise_taxable_amount = 0.0
|
||||||
|
|
||||||
|
|||||||
@@ -179,14 +179,11 @@ class TestTaxesAndTotals(ERPNextTestSuite):
|
|||||||
|
|
||||||
details_by_tax = {}
|
details_by_tax = {}
|
||||||
for detail in doc.item_wise_tax_details:
|
for detail in doc.item_wise_tax_details:
|
||||||
bucket = details_by_tax.setdefault(detail.tax_row, {"amount": 0.0, "taxable_amount": 0.0})
|
bucket = details_by_tax.setdefault(detail.tax_row, {"amount": 0.0})
|
||||||
bucket["amount"] += detail.amount
|
bucket["amount"] += detail.amount
|
||||||
|
|
||||||
for tax in doc.taxes:
|
for tax in doc.taxes:
|
||||||
detail_totals = details_by_tax[tax.name]
|
self.assertEqual(details_by_tax[tax.name]["amount"], tax.base_tax_amount_after_discount_amount)
|
||||||
self.assertAlmostEqual(
|
|
||||||
detail_totals["amount"], tax.base_tax_amount_after_discount_amount, places=2
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_item_wise_tax_detail_with_multi_currency_with_single_item(self):
|
def test_item_wise_tax_detail_with_multi_currency_with_single_item(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user