diff --git a/india_compliance/gst_india/overrides/test_transaction.py b/india_compliance/gst_india/overrides/test_transaction.py index 200a7de832..c591e02235 100644 --- a/india_compliance/gst_india/overrides/test_transaction.py +++ b/india_compliance/gst_india/overrides/test_transaction.py @@ -55,6 +55,13 @@ create_sales_invoice, create_transaction, ) +from india_compliance.income_tax_india.overrides.company import ( + TDS_ACCOUNT_NAME, + create_tds_account, +) +from india_compliance.income_tax_india.overrides.test_tax_withholding_category import ( + create_tax_withholding_category, +) @parameterized_class( @@ -1844,6 +1851,36 @@ def test_is_multicurrency_doc(self): self.assertFalse(_is_multicurrency_doc({})) self.assertFalse(_is_multicurrency_doc('{"conversion_rate": 1}')) + def test_taxable_value_excludes_tcs_without_gst_rows(self): + """ + Zero-rated Sales Invoice with no GST rows and TCS via Tax Withholding Category. + TCS row is identified by `is_tax_withholding_account` and must not be + apportioned into the item's taxable value. + """ + company = "_Test Indian Registered Company" + category = "_Test TCS Category" + + create_tds_account(company) + create_tax_withholding_category(category, f"{TDS_ACCOUNT_NAME} - _TIRC") + + doc = create_transaction( + doctype="Sales Invoice", + item_code="_Test Nil Rated Item", + apply_tds=1, + do_not_save=True, + ) + doc.items[0].tax_withholding_category = category + doc.save() + + self.assertFalse([row for row in doc.taxes if row.gst_tax_type]) + + tcs_rows = [row for row in doc.taxes if row.is_tax_withholding_account] + self.assertTrue(tcs_rows) + self.assertTrue(tcs_rows[0].base_tax_amount_after_discount_amount) + + item = doc.items[0] + self.assertEqual(item.taxable_value, item.base_net_amount) + def test_copy_e_waybill_fields_from_dn_to_si(self): "Make sure e-Waybill fields are copied from Delivery Note to Sales Invoice" dn = create_transaction(doctype="Delivery Note", vehicle_no="GJ01AA1111") diff --git a/india_compliance/gst_india/overrides/transaction.py b/india_compliance/gst_india/overrides/transaction.py index 09859d6eff..e0019e87d9 100644 --- a/india_compliance/gst_india/overrides/transaction.py +++ b/india_compliance/gst_india/overrides/transaction.py @@ -52,10 +52,14 @@ validate_gst_category, validate_gstin, ) +<<<<<<< HEAD from india_compliance.gst_india.utils.gstr_1 import SUPECOM from india_compliance.income_tax_india.overrides.tax_withholding_category import ( get_tax_withholding_accounts, ) +======= +from india_compliance.gst_returns.fields.gstr1 import SubCategory +>>>>>>> 326fe3d (fix: use tds row check instead of account) DOCTYPES_WITH_GST_DETAIL = { "Supplier Quotation", @@ -168,10 +172,9 @@ def validate_item_wise_tax_detail(doc): def get_tds_amount(doc): - tds_accounts = get_tax_withholding_accounts(doc.company) tds_amount = 0 for row in doc.taxes: - if row.account_head not in tds_accounts: + if not row.get("is_tax_withholding_account"): continue multiplier = -1 if row.get("add_deduct_tax") == "Deduct" else 1 diff --git a/india_compliance/gst_india/report/gst_account_wise_summary/gst_account_wise_summary.py b/india_compliance/gst_india/report/gst_account_wise_summary/gst_account_wise_summary.py index 5a9b0b369d..437c4e81e8 100644 --- a/india_compliance/gst_india/report/gst_account_wise_summary/gst_account_wise_summary.py +++ b/india_compliance/gst_india/report/gst_account_wise_summary/gst_account_wise_summary.py @@ -9,9 +9,6 @@ from frappe.query_builder.functions import IfNull, Sum from india_compliance.gst_india.constants import GST_TAX_TYPES, TAX_TYPES -from india_compliance.income_tax_india.overrides.tax_withholding_category import ( - get_tax_withholding_accounts, -) def execute(filters: dict | None = None): @@ -30,7 +27,6 @@ def execute(filters: dict | None = None): class AccountWiseSummary: def __init__(self, filters): self.filters = filters - self.tds_accounts = get_tax_withholding_accounts(filters.company) @staticmethod def get_columns(): @@ -118,7 +114,7 @@ def allocate_additional_charges(self, invoice, additional_tax, total_proportion, is_after_gst = True continue - elif tax.account_head in self.tds_accounts or not tax.base_tax_amount_after_discount_amount: + elif tax.is_tax_withholding_account or not tax.base_tax_amount_after_discount_amount: continue if not is_after_gst: @@ -240,6 +236,7 @@ def get_taxes_for_docs(self): taxes_doc.parent, taxes_doc.account_head, taxes_doc.charge_type, + taxes_doc.is_tax_withholding_account, ) .orderby(taxes_doc.idx) ) diff --git a/india_compliance/hooks.py b/india_compliance/hooks.py index 799a0b3a96..0e499a524f 100644 --- a/india_compliance/hooks.py +++ b/india_compliance/hooks.py @@ -296,9 +296,6 @@ "after_insert": ("india_compliance.gst_india.overrides.party.create_primary_address"), }, "Tax Category": {"validate": "india_compliance.gst_india.overrides.tax_category.validate"}, - "Tax Withholding Category": { - "on_change": "india_compliance.income_tax_india.overrides.tax_withholding_category.on_change", - }, "Unreconcile Payment": { "before_submit": "india_compliance.gst_india.overrides.unreconcile_payment.before_submit", }, diff --git a/india_compliance/income_tax_india/overrides/tax_withholding_category.py b/india_compliance/income_tax_india/overrides/tax_withholding_category.py index e500d75874..2e00c5ce09 100644 --- a/india_compliance/income_tax_india/overrides/tax_withholding_category.py +++ b/india_compliance/income_tax_india/overrides/tax_withholding_category.py @@ -1,17 +1,6 @@ import frappe -def on_change(doc, method=None): - frappe.cache.delete_value("tax_withholding_accounts") - - -def get_tax_withholding_accounts(company): - def _get_tax_withholding_accounts(): - return set(frappe.get_all("Tax Withholding Account", pluck="account", filters={"company": company})) - - return frappe.cache.hget("tax_withholding_accounts", company, generator=_get_tax_withholding_accounts) - - def get_tax_id_for_party(party_type, party): # PAN field is only available for Customer and Supplier. if party_type in ("Customer", "Supplier"):