fix: TDS deduction in payment entry (#33747)
* fix: TDS deduction in payment entry
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
index 1bce43f..2c829b2 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -410,12 +410,26 @@
tds_amount = 0
invoice_filters = {"name": ("in", vouchers), "docstatus": 1, "apply_tds": 1}
+ ## for TDS to be deducted on advances
+ payment_entry_filters = {
+ "party_type": "Supplier",
+ "party": ("in", parties),
+ "docstatus": 1,
+ "apply_tax_withholding_amount": 1,
+ "unallocated_amount": (">", 0),
+ "posting_date": ["between", (tax_details.from_date, tax_details.to_date)],
+ "tax_withholding_category": tax_details.get("tax_withholding_category"),
+ }
+
field = "sum(tax_withholding_net_total)"
if cint(tax_details.consider_party_ledger_amount):
invoice_filters.pop("apply_tds", None)
field = "sum(grand_total)"
+ payment_entry_filters.pop("apply_tax_withholding_amount", None)
+ payment_entry_filters.pop("tax_withholding_category", None)
+
supp_credit_amt = frappe.db.get_value("Purchase Invoice", invoice_filters, field) or 0.0
supp_jv_credit_amt = (
@@ -427,14 +441,28 @@
"party": ("in", parties),
"reference_type": ("!=", "Purchase Invoice"),
},
- "sum(credit_in_account_currency)",
+ "sum(credit_in_account_currency - debit_in_account_currency)",
)
or 0.0
)
+ # Get Amount via payment entry
+ payment_entry_amounts = frappe.db.get_all(
+ "Payment Entry",
+ filters=payment_entry_filters,
+ fields=["sum(unallocated_amount) as amount", "payment_type"],
+ group_by="payment_type",
+ )
+
supp_credit_amt += supp_jv_credit_amt
supp_credit_amt += inv.tax_withholding_net_total
+ for type in payment_entry_amounts:
+ if type.payment_type == "Pay":
+ supp_credit_amt += type.amount
+ else:
+ supp_credit_amt -= type.amount
+
threshold = tax_details.get("threshold", 0)
cumulative_threshold = tax_details.get("cumulative_threshold", 0)
diff --git a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
index 23caac0..1e86cf5 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
@@ -16,7 +16,7 @@
def setUpClass(self):
# create relevant supplier, etc
create_records()
- create_tax_with_holding_category()
+ create_tax_withholding_category_records()
def tearDown(self):
cancel_invoices()
@@ -38,7 +38,7 @@
pi = create_purchase_invoice(supplier="Test TDS Supplier")
pi.submit()
- # assert equal tax deduction on total invoice amount uptil now
+ # assert equal tax deduction on total invoice amount until now
self.assertEqual(pi.taxes_and_charges_deducted, 3000)
self.assertEqual(pi.grand_total, 7000)
invoices.append(pi)
@@ -47,7 +47,7 @@
pi = create_purchase_invoice(supplier="Test TDS Supplier", rate=5000)
pi.submit()
- # assert equal tax deduction on total invoice amount uptil now
+ # assert equal tax deduction on total invoice amount until now
self.assertEqual(pi.taxes_and_charges_deducted, 500)
invoices.append(pi)
@@ -130,7 +130,7 @@
invoices.append(si)
# create another invoice whose total when added to previously created invoice,
- # surpasses cumulative threshhold
+ # surpasses cumulative threshold
si = create_sales_invoice(customer="Test TCS Customer", rate=12000)
si.submit()
@@ -329,6 +329,38 @@
for d in reversed(invoices):
d.cancel()
+ def test_tax_withholding_via_payment_entry_for_advances(self):
+ frappe.db.set_value(
+ "Supplier", "Test TDS Supplier7", "tax_withholding_category", "Advance TDS Category"
+ )
+
+ # create payment entry
+ pe1 = create_payment_entry(
+ payment_type="Pay", party_type="Supplier", party="Test TDS Supplier7", paid_amount=4000
+ )
+ pe1.submit()
+
+ self.assertFalse(pe1.get("taxes"))
+
+ pe2 = create_payment_entry(
+ payment_type="Pay", party_type="Supplier", party="Test TDS Supplier7", paid_amount=4000
+ )
+ pe2.submit()
+
+ self.assertFalse(pe2.get("taxes"))
+
+ pe3 = create_payment_entry(
+ payment_type="Pay", party_type="Supplier", party="Test TDS Supplier7", paid_amount=4000
+ )
+ pe3.apply_tax_withholding_amount = 1
+ pe3.save()
+ pe3.submit()
+
+ self.assertEquals(pe3.get("taxes")[0].tax_amount, 1200)
+ pe1.cancel()
+ pe2.cancel()
+ pe3.cancel()
+
def cancel_invoices():
purchase_invoices = frappe.get_all(
@@ -450,6 +482,32 @@
return si
+def create_payment_entry(**args):
+ # return payment entry doc object
+ args = frappe._dict(args)
+ pe = frappe.get_doc(
+ {
+ "doctype": "Payment Entry",
+ "posting_date": today(),
+ "payment_type": args.payment_type,
+ "party_type": args.party_type,
+ "party": args.party,
+ "company": "_Test Company",
+ "paid_from": "Cash - _TC",
+ "paid_to": "Creditors - _TC",
+ "paid_amount": args.paid_amount or 10000,
+ "received_amount": args.paid_amount or 10000,
+ "reference_no": args.reference_no or "12345",
+ "reference_date": today(),
+ "paid_from_account_currency": "INR",
+ "paid_to_account_currency": "INR",
+ }
+ )
+
+ pe.save()
+ return pe
+
+
def create_records():
# create a new suppliers
for name in [
@@ -460,6 +518,7 @@
"Test TDS Supplier4",
"Test TDS Supplier5",
"Test TDS Supplier6",
+ "Test TDS Supplier7",
]:
if frappe.db.exists("Supplier", name):
continue
@@ -530,142 +589,129 @@
).insert()
-def create_tax_with_holding_category():
+def create_tax_withholding_category_records():
fiscal_year = get_fiscal_year(today(), company="_Test Company")
+ from_date = fiscal_year[1]
+ to_date = fiscal_year[2]
+
# Cumulative threshold
- if not frappe.db.exists("Tax Withholding Category", "Cumulative Threshold TDS"):
- frappe.get_doc(
- {
- "doctype": "Tax Withholding Category",
- "name": "Cumulative Threshold TDS",
- "category_name": "10% TDS",
- "rates": [
- {
- "from_date": fiscal_year[1],
- "to_date": fiscal_year[2],
- "tax_withholding_rate": 10,
- "single_threshold": 0,
- "cumulative_threshold": 30000.00,
- }
- ],
- "accounts": [{"company": "_Test Company", "account": "TDS - _TC"}],
- }
- ).insert()
+ create_tax_withholding_category(
+ category_name="Cumulative Threshold TDS",
+ rate=10,
+ from_date=from_date,
+ to_date=to_date,
+ account="TDS - _TC",
+ single_threshold=0,
+ cumulative_threshold=30000.00,
+ )
- if not frappe.db.exists("Tax Withholding Category", "Cumulative Threshold TCS"):
- frappe.get_doc(
- {
- "doctype": "Tax Withholding Category",
- "name": "Cumulative Threshold TCS",
- "category_name": "10% TCS",
- "rates": [
- {
- "from_date": fiscal_year[1],
- "to_date": fiscal_year[2],
- "tax_withholding_rate": 10,
- "single_threshold": 0,
- "cumulative_threshold": 30000.00,
- }
- ],
- "accounts": [{"company": "_Test Company", "account": "TCS - _TC"}],
- }
- ).insert()
+ # Category for TCS
+ create_tax_withholding_category(
+ category_name="Cumulative Threshold TCS",
+ rate=10,
+ from_date=from_date,
+ to_date=to_date,
+ account="TCS - _TC",
+ single_threshold=0,
+ cumulative_threshold=30000.00,
+ )
- # Single thresold
- if not frappe.db.exists("Tax Withholding Category", "Single Threshold TDS"):
- frappe.get_doc(
- {
- "doctype": "Tax Withholding Category",
- "name": "Single Threshold TDS",
- "category_name": "10% TDS",
- "rates": [
- {
- "from_date": fiscal_year[1],
- "to_date": fiscal_year[2],
- "tax_withholding_rate": 10,
- "single_threshold": 20000.00,
- "cumulative_threshold": 0,
- }
- ],
- "accounts": [{"company": "_Test Company", "account": "TDS - _TC"}],
- }
- ).insert()
+ # Single threshold
+ create_tax_withholding_category(
+ category_name="Single Threshold TDS",
+ rate=10,
+ from_date=from_date,
+ to_date=to_date,
+ account="TDS - _TC",
+ single_threshold=20000,
+ cumulative_threshold=0,
+ )
- if not frappe.db.exists("Tax Withholding Category", "New TDS Category"):
- frappe.get_doc(
- {
- "doctype": "Tax Withholding Category",
- "name": "New TDS Category",
- "category_name": "New TDS Category",
- "round_off_tax_amount": 1,
- "consider_party_ledger_amount": 1,
- "tax_on_excess_amount": 1,
- "rates": [
- {
- "from_date": fiscal_year[1],
- "to_date": fiscal_year[2],
- "tax_withholding_rate": 10,
- "single_threshold": 0,
- "cumulative_threshold": 30000,
- }
- ],
- "accounts": [{"company": "_Test Company", "account": "TDS - _TC"}],
- }
- ).insert()
+ create_tax_withholding_category(
+ category_name="New TDS Category",
+ rate=10,
+ from_date=from_date,
+ to_date=to_date,
+ account="TDS - _TC",
+ single_threshold=0,
+ cumulative_threshold=30000,
+ round_off_tax_amount=1,
+ consider_party_ledger_amount=1,
+ tax_on_excess_amount=1,
+ )
- if not frappe.db.exists("Tax Withholding Category", "Test Service Category"):
- frappe.get_doc(
- {
- "doctype": "Tax Withholding Category",
- "name": "Test Service Category",
- "category_name": "Test Service Category",
- "rates": [
- {
- "from_date": fiscal_year[1],
- "to_date": fiscal_year[2],
- "tax_withholding_rate": 10,
- "single_threshold": 2000,
- "cumulative_threshold": 2000,
- }
- ],
- "accounts": [{"company": "_Test Company", "account": "TDS - _TC"}],
- }
- ).insert()
+ create_tax_withholding_category(
+ category_name="Test Service Category",
+ rate=10,
+ from_date=from_date,
+ to_date=to_date,
+ account="TDS - _TC",
+ single_threshold=2000,
+ cumulative_threshold=2000,
+ )
- if not frappe.db.exists("Tax Withholding Category", "Test Goods Category"):
- frappe.get_doc(
- {
- "doctype": "Tax Withholding Category",
- "name": "Test Goods Category",
- "category_name": "Test Goods Category",
- "rates": [
- {
- "from_date": fiscal_year[1],
- "to_date": fiscal_year[2],
- "tax_withholding_rate": 10,
- "single_threshold": 2000,
- "cumulative_threshold": 2000,
- }
- ],
- "accounts": [{"company": "_Test Company", "account": "TDS - _TC"}],
- }
- ).insert()
+ create_tax_withholding_category(
+ category_name="Test Goods Category",
+ rate=10,
+ from_date=from_date,
+ to_date=to_date,
+ account="TDS - _TC",
+ single_threshold=2000,
+ cumulative_threshold=2000,
+ )
- if not frappe.db.exists("Tax Withholding Category", "Test Multi Invoice Category"):
+ create_tax_withholding_category(
+ category_name="Test Multi Invoice Category",
+ rate=10,
+ from_date=from_date,
+ to_date=to_date,
+ account="TDS - _TC",
+ single_threshold=5000,
+ cumulative_threshold=10000,
+ )
+
+ create_tax_withholding_category(
+ category_name="Advance TDS Category",
+ rate=10,
+ from_date=from_date,
+ to_date=to_date,
+ account="TDS - _TC",
+ single_threshold=5000,
+ cumulative_threshold=10000,
+ consider_party_ledger_amount=1,
+ )
+
+
+def create_tax_withholding_category(
+ category_name,
+ rate,
+ from_date,
+ to_date,
+ account,
+ single_threshold=0,
+ cumulative_threshold=0,
+ round_off_tax_amount=0,
+ consider_party_ledger_amount=0,
+ tax_on_excess_amount=0,
+):
+ if not frappe.db.exists("Tax Withholding Category", category_name):
frappe.get_doc(
{
"doctype": "Tax Withholding Category",
- "name": "Test Multi Invoice Category",
- "category_name": "Test Multi Invoice Category",
+ "name": category_name,
+ "category_name": category_name,
+ "round_off_tax_amount": round_off_tax_amount,
+ "consider_party_ledger_amount": consider_party_ledger_amount,
+ "tax_on_excess_amount": tax_on_excess_amount,
"rates": [
{
- "from_date": fiscal_year[1],
- "to_date": fiscal_year[2],
- "tax_withholding_rate": 10,
- "single_threshold": 5000,
- "cumulative_threshold": 10000,
+ "from_date": from_date,
+ "to_date": to_date,
+ "tax_withholding_rate": rate,
+ "single_threshold": single_threshold,
+ "cumulative_threshold": cumulative_threshold,
}
],
- "accounts": [{"company": "_Test Company", "account": "TDS - _TC"}],
+ "accounts": [{"company": "_Test Company", "account": account}],
}
).insert()