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()