diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py index 42c6c82b19f..ee52da291b1 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py @@ -4,6 +4,7 @@ import frappe from frappe import _ +from frappe.utils import getdate def execute(filters=None): @@ -33,6 +34,7 @@ def execute(filters=None): def validate_filters(filters): """Validate if dates are properly set""" + filters = frappe._dict(filters or {}) if filters.from_date > filters.to_date: frappe.throw(_("From Date must be before To Date")) @@ -68,7 +70,7 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_ if not tax_withholding_category: tax_withholding_category = party_map.get(party, {}).get("tax_withholding_category") - rate = tax_rate_map.get(tax_withholding_category) + rate = get_tax_withholding_rates(tax_rate_map.get(tax_withholding_category, []), posting_date) if net_total_map.get((voucher_type, name)): if voucher_type == "Journal Entry" and tax_amount and rate: # back calcalute total amount from rate and tax_amount @@ -435,12 +437,22 @@ def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None): def get_tax_rate_map(filters): rate_map = frappe.get_all( "Tax Withholding Rate", - filters={ - "from_date": ("<=", filters.get("from_date")), - "to_date": (">=", filters.get("to_date")), - }, - fields=["parent", "tax_withholding_rate"], - as_list=1, + filters={"from_date": ("<=", filters.to_date), "to_date": (">=", filters.from_date)}, + fields=["parent", "tax_withholding_rate", "from_date", "to_date"], ) - return frappe._dict(rate_map) + rate_list = frappe._dict() + + for rate in rate_map: + rate_list.setdefault(rate.parent, []).append(frappe._dict(rate)) + + return rate_list + + +def get_tax_withholding_rates(tax_withholding, posting_date): + # returns the row that matches with the fiscal year from posting date + for rate in tax_withholding: + if getdate(rate.from_date) <= getdate(posting_date) <= getdate(rate.to_date): + return rate.tax_withholding_rate + + return 0 diff --git a/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py b/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py index 7515616b0b8..6eff81e7f42 100644 --- a/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py +++ b/erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py @@ -3,7 +3,7 @@ import frappe from frappe.tests.utils import FrappeTestCase -from frappe.utils import today +from frappe.utils import add_to_date, today from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice @@ -60,6 +60,56 @@ class TestTaxWithholdingDetails(AccountsTestMixin, FrappeTestCase): ] self.check_expected_values(result, expected_values) + def test_date_filters_in_multiple_tax_withholding_rules(self): + create_tax_category("TDS - 3", rate=10, account="TDS - _TC", cumulative_threshold=1) + # insert new rate in same fiscal year + fiscal_year = get_fiscal_year(today(), company="_Test Company") + mid_year = add_to_date(fiscal_year[1], months=6) + tds_doc = frappe.get_doc("Tax Withholding Category", "TDS - 3") + tds_doc.rates[0].to_date = mid_year + tds_doc.append( + "rates", + { + "tax_withholding_rate": 20, + "from_date": add_to_date(mid_year, days=1), + "to_date": fiscal_year[2], + "single_threshold": 1, + "cumulative_threshold": 1, + }, + ) + + tds_doc.save() + + inv_1 = make_purchase_invoice(rate=1000, do_not_submit=True) + inv_1.apply_tds = 1 + inv_1.tax_withholding_category = "TDS - 3" + inv_1.submit() + + inv_2 = make_purchase_invoice( + rate=1000, do_not_submit=True, posting_date=add_to_date(mid_year, days=1), do_not_save=True + ) + inv_2.set_posting_time = 1 + + inv_1.apply_tds = 1 + inv_2.tax_withholding_category = "TDS - 3" + inv_2.save() + inv_2.submit() + + result = execute( + frappe._dict( + company="_Test Company", + party_type="Supplier", + from_date=fiscal_year[1], + to_date=fiscal_year[2], + ) + )[1] + + expected_values = [ + [inv_1.name, "TDS - 3", 10.0, 5000, 500, 4500], + [inv_2.name, "TDS - 3", 20.0, 5000, 1000, 4000], + ] + self.check_expected_values(result, expected_values) + def check_expected_values(self, result, expected_values): for i in range(len(result)): voucher = frappe._dict(result[i])