55from unittest .mock import patch
66
77import frappe
8- from frappe .custom .doctype .custom_field .custom_field import create_custom_fields
9- from frappe .utils import add_days , add_months , today
8+ from frappe .utils import add_days , add_months , getdate , today
109
1110from erpnext .accounts .doctype .payment_entry .payment_entry import get_payment_entry
1211from erpnext .accounts .utils import get_fiscal_year
@@ -1922,7 +1921,6 @@ def test_payment_entry_with_ldc_and_partial_invoice_adjustment(self):
19221921
19231922 def set_previous_fy_and_tax_category (self ):
19241923 test_company = "_Test Company"
1925- category = "Cumulative Threshold TDS"
19261924
19271925 def add_company_to_fy (fy , company ):
19281926 if not [x .company for x in fy .companies if x .company == company ]:
@@ -1948,20 +1946,6 @@ def add_company_to_fy(fy, company):
19481946 )
19491947 self .prev_fy .save ()
19501948
1951- # setup tax withholding category for previous fiscal year
1952- cat = frappe .get_doc ("Tax Withholding Category" , category )
1953- cat .append (
1954- "rates" ,
1955- {
1956- "from_date" : self .prev_fy .year_start_date ,
1957- "to_date" : self .prev_fy .year_end_date ,
1958- "tax_withholding_rate" : 10 ,
1959- "single_threshold" : 0 ,
1960- "cumulative_threshold" : 30000 ,
1961- },
1962- )
1963- cat .save ()
1964-
19651949 def test_tds_across_fiscal_year (self ):
19661950 """
19671951 Advance TDS on previous fiscal year should be properly allocated on Invoices in upcoming fiscal year
@@ -1972,6 +1956,14 @@ def test_tds_across_fiscal_year(self):
19721956 supplier = "Test TDS Supplier"
19731957 # Cumulative threshold 30000 and tax rate 10%
19741958 category = "Cumulative Threshold TDS"
1959+ create_tax_withholding_category (
1960+ category_name = category ,
1961+ rate = 10 ,
1962+ from_date = self .prev_fy .year_start_date ,
1963+ to_date = self .prev_fy .year_end_date ,
1964+ account = "TDS - _TC" ,
1965+ cumulative_threshold = 30000 ,
1966+ )
19751967 frappe .db .set_value (
19761968 "Supplier" ,
19771969 supplier ,
@@ -2043,6 +2035,158 @@ def test_tds_across_fiscal_year(self):
20432035 self .assertEqual (pi2 .taxes , [])
20442036 self .assertEqual (payment .taxes [0 ].tax_amount , 6000 )
20452037
2038+ def test_threshold_resets_in_new_fiscal_year (self ):
2039+ """
2040+ Threshold entries from a previous FY must not carry over into the new FY.
2041+ """
2042+ self .set_previous_fy_and_tax_category ()
2043+ invoices = []
2044+ supplier = "Test TDS Supplier"
2045+ category = "Cumulative Threshold TDS"
2046+ create_tax_withholding_category (
2047+ category_name = category ,
2048+ rate = 10 ,
2049+ from_date = self .prev_fy .year_start_date ,
2050+ to_date = self .prev_fy .year_end_date ,
2051+ account = "TDS - _TC" ,
2052+ cumulative_threshold = 30000 ,
2053+ )
2054+ self .setup_party_with_category ("Supplier" , supplier , category )
2055+ prev_fy_date = add_days (self .prev_fy .year_end_date , - 10 )
2056+
2057+ # Previous FY: 3 invoices to cross the 30000 cumulative threshold
2058+ for _ in range (3 ):
2059+ pi = create_purchase_invoice (supplier = supplier , posting_date = prev_fy_date , set_posting_time = True )
2060+ pi .submit ()
2061+ invoices .append (pi )
2062+
2063+ # Third invoice crosses the threshold - 3000 TDS deducted across all three
2064+ self .validate_tax_deduction (invoices [- 1 ], 3000 )
2065+
2066+ # Current FY: 10000 invoice - must be Under Withheld, threshold resets
2067+ pi_curr = create_purchase_invoice (supplier = supplier )
2068+ pi_curr .submit ()
2069+ invoices .append (pi_curr )
2070+ self .validate_tax_deduction (pi_curr , 0 )
2071+
2072+ self .validate_tax_withholding_entries (
2073+ "Purchase Invoice" ,
2074+ pi_curr .name ,
2075+ [
2076+ self .get_tax_withholding_entry (
2077+ tax_withholding_category = category ,
2078+ party_type = "Supplier" ,
2079+ party = supplier ,
2080+ taxable_doctype = "Purchase Invoice" ,
2081+ taxable_name = pi_curr .name ,
2082+ tax_rate = 10.0 ,
2083+ taxable_amount = 10000.0 ,
2084+ withholding_amount = 0.0 ,
2085+ status = "Under Withheld" ,
2086+ withholding_doctype = None ,
2087+ withholding_name = None ,
2088+ under_withheld_reason = None ,
2089+ )
2090+ ],
2091+ )
2092+ self .cleanup_invoices (invoices )
2093+
2094+ def test_tax_on_excess_threshold_resets_in_new_fiscal_year (self ):
2095+ """
2096+ For tax-on-excess categories, unused threshold must reset each FY.
2097+ """
2098+ self .set_previous_fy_and_tax_category ()
2099+ invoices = []
2100+ supplier = "Test TDS Supplier3"
2101+ category = "New TDS Category"
2102+ create_tax_withholding_category (
2103+ category_name = category ,
2104+ rate = 10 ,
2105+ from_date = self .prev_fy .year_start_date ,
2106+ to_date = self .prev_fy .year_end_date ,
2107+ account = "TDS - _TC" ,
2108+ cumulative_threshold = 30000 ,
2109+ tax_on_excess_amount = 1 ,
2110+ round_off_tax_amount = 1 ,
2111+ )
2112+ self .setup_party_with_category ("Supplier" , supplier , category )
2113+ prev_fy_date = add_days (self .prev_fy .year_end_date , - 10 )
2114+
2115+ for _ in range (2 ):
2116+ pi = create_purchase_invoice (supplier = supplier , posting_date = prev_fy_date , set_posting_time = True )
2117+ pi .submit ()
2118+ invoices .append (pi )
2119+
2120+ pi3 = create_purchase_invoice (
2121+ supplier = supplier , rate = 20000 , posting_date = prev_fy_date , set_posting_time = True
2122+ )
2123+ pi3 .submit ()
2124+ invoices .append (pi3 )
2125+
2126+ self .validate_tax_deduction (pi3 , 1000 )
2127+ self .validate_tax_withholding_entries (
2128+ "Purchase Invoice" ,
2129+ pi3 .name ,
2130+ [
2131+ self .get_tax_withholding_entry (
2132+ tax_withholding_category = category ,
2133+ party_type = "Supplier" ,
2134+ party = supplier ,
2135+ taxable_doctype = "Purchase Invoice" ,
2136+ taxable_name = pi3 .name ,
2137+ tax_rate = 10.0 ,
2138+ taxable_amount = 10000.0 ,
2139+ withholding_amount = 0.0 ,
2140+ status = "Settled" ,
2141+ withholding_doctype = "Purchase Invoice" ,
2142+ withholding_name = pi3 .name ,
2143+ under_withheld_reason = "Threshold Exemption" ,
2144+ ),
2145+ self .get_tax_withholding_entry (
2146+ tax_withholding_category = category ,
2147+ party_type = "Supplier" ,
2148+ party = supplier ,
2149+ taxable_doctype = "Purchase Invoice" ,
2150+ taxable_name = pi3 .name ,
2151+ tax_rate = 10.0 ,
2152+ taxable_amount = 10000.0 ,
2153+ withholding_amount = 1000.0 ,
2154+ status = "Settled" ,
2155+ withholding_doctype = "Purchase Invoice" ,
2156+ withholding_name = pi3 .name ,
2157+ under_withheld_reason = None ,
2158+ ),
2159+ ],
2160+ )
2161+
2162+ # no excess, so no TDS
2163+ pi_curr = create_purchase_invoice (supplier = supplier , rate = 30000 )
2164+ pi_curr .submit ()
2165+ invoices .append (pi_curr )
2166+ self .validate_tax_deduction (pi_curr , 0 )
2167+
2168+ self .validate_tax_withholding_entries (
2169+ "Purchase Invoice" ,
2170+ pi_curr .name ,
2171+ [
2172+ self .get_tax_withholding_entry (
2173+ tax_withholding_category = category ,
2174+ party_type = "Supplier" ,
2175+ party = supplier ,
2176+ taxable_doctype = "Purchase Invoice" ,
2177+ taxable_name = pi_curr .name ,
2178+ tax_rate = 10.0 ,
2179+ taxable_amount = 30000.0 ,
2180+ withholding_amount = 0.0 ,
2181+ status = "Settled" ,
2182+ withholding_doctype = "Purchase Invoice" ,
2183+ withholding_name = pi_curr .name ,
2184+ under_withheld_reason = "Threshold Exemption" ,
2185+ ),
2186+ ],
2187+ )
2188+ self .cleanup_invoices (invoices )
2189+
20462190 @ERPNextTestSuite .change_settings ("Accounts Settings" , {"delete_linked_ledger_entries" : 1 })
20472191 def test_tds_payment_entry_cancellation (self ):
20482192 """
@@ -3997,7 +4141,7 @@ def create_tax_withholding_category(
39974141 tax_deduction_basis = "Net Total" ,
39984142):
39994143 if not frappe .db .exists ("Tax Withholding Category" , category_name ):
4000- frappe .get_doc (
4144+ doc = frappe .get_doc (
40014145 {
40024146 "doctype" : "Tax Withholding Category" ,
40034147 "name" : category_name ,
@@ -4018,6 +4162,22 @@ def create_tax_withholding_category(
40184162 "accounts" : [{"company" : "_Test Company" , "account" : account }],
40194163 }
40204164 ).insert ()
4165+ else :
4166+ doc = frappe .get_doc ("Tax Withholding Category" , category_name )
4167+ if not any (getdate (r .from_date ) == getdate (from_date ) for r in doc .rates ):
4168+ doc .append (
4169+ "rates" ,
4170+ {
4171+ "from_date" : from_date ,
4172+ "to_date" : to_date ,
4173+ "tax_withholding_rate" : rate ,
4174+ "single_threshold" : single_threshold ,
4175+ "cumulative_threshold" : cumulative_threshold ,
4176+ },
4177+ )
4178+ doc .save ()
4179+
4180+ return doc
40214181
40224182
40234183def create_lower_deduction_certificate (
0 commit comments