Skip to content

Commit

Permalink
fix: Tax withholding post LDC limit consumed (#36611)
Browse files Browse the repository at this point in the history
* fix: Tax withholding post LDC limit consumed

* fix: LDC condition check

(cherry picked from commit 985ff97)

# Conflicts:
#	erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
  • Loading branch information
deepeshgarg007 authored and mergify[bot] committed Aug 14, 2023
1 parent 90b390c commit b2a2ccb
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -262,14 +262,20 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N
if tax_deducted:
net_total = inv.tax_withholding_net_total
if ldc:
tax_amount = get_tds_amount_from_ldc(ldc, parties, tax_details, posting_date, net_total)
limit_consumed = get_limit_consumed(ldc, parties)
if is_valid_certificate(ldc, posting_date, limit_consumed):
tax_amount = get_lower_deduction_amount(
net_total, limit_consumed, ldc.certificate_limit, ldc.rate, tax_details
)
else:
tax_amount = net_total * tax_details.rate / 100 if net_total > 0 else 0
else:
tax_amount = net_total * tax_details.rate / 100 if net_total > 0 else 0

# once tds is deducted, not need to add vouchers in the invoice
voucher_wise_amount = {}
else:
tax_amount = get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers)
tax_amount = get_tds_amount(ldc, parties, inv, tax_details, vouchers)

elif party_type == "Customer":
if tax_deducted:
Expand Down Expand Up @@ -416,7 +422,7 @@ def get_deducted_tax(taxable_vouchers, tax_details):
return sum(entries)


def get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers):
def get_tds_amount(ldc, parties, inv, tax_details, vouchers):
tds_amount = 0
invoice_filters = {"name": ("in", vouchers), "docstatus": 1, "apply_tds": 1}

Expand Down Expand Up @@ -496,15 +502,10 @@ def get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers):
net_total += inv.tax_withholding_net_total
supp_credit_amt = net_total - cumulative_threshold

if ldc and is_valid_certificate(
ldc.valid_from,
ldc.valid_upto,
inv.get("posting_date") or inv.get("transaction_date"),
tax_deducted,
inv.tax_withholding_net_total,
ldc.certificate_limit,
):
tds_amount = get_ltds_amount(supp_credit_amt, 0, ldc.certificate_limit, ldc.rate, tax_details)
if ldc and is_valid_certificate(ldc, inv.get("posting_date") or inv.get("transaction_date"), 0):
tds_amount = get_lower_deduction_amount(
supp_credit_amt, 0, ldc.certificate_limit, ldc.rate, tax_details
)
else:
tds_amount = supp_credit_amt * tax_details.rate / 100 if supp_credit_amt > 0 else 0

Expand Down Expand Up @@ -582,8 +583,7 @@ def get_invoice_total_without_tcs(inv, tax_details):
return inv.grand_total - tcs_tax_row_amount


def get_tds_amount_from_ldc(ldc, parties, tax_details, posting_date, net_total):
tds_amount = 0
def get_limit_consumed(ldc, parties):
limit_consumed = frappe.db.get_value(
"Purchase Invoice",
{
Expand All @@ -597,37 +597,29 @@ def get_tds_amount_from_ldc(ldc, parties, tax_details, posting_date, net_total):
"sum(tax_withholding_net_total)",
)

if is_valid_certificate(
ldc.valid_from, ldc.valid_upto, posting_date, limit_consumed, net_total, ldc.certificate_limit
):
tds_amount = get_ltds_amount(
net_total, limit_consumed, ldc.certificate_limit, ldc.rate, tax_details
)

return tds_amount
return limit_consumed


def get_ltds_amount(current_amount, deducted_amount, certificate_limit, rate, tax_details):
if certificate_limit - flt(deducted_amount) - flt(current_amount) >= 0:
def get_lower_deduction_amount(
current_amount, limit_consumed, certificate_limit, rate, tax_details
):
if certificate_limit - flt(limit_consumed) - flt(current_amount) >= 0:
return current_amount * rate / 100
else:
ltds_amount = certificate_limit - flt(deducted_amount)
ltds_amount = certificate_limit - flt(limit_consumed)
tds_amount = current_amount - ltds_amount

return ltds_amount * rate / 100 + tds_amount * tax_details.rate / 100


def is_valid_certificate(
valid_from, valid_upto, posting_date, deducted_amount, current_amount, certificate_limit
):
valid = False

available_amount = flt(certificate_limit) - flt(deducted_amount)

if (getdate(valid_from) <= getdate(posting_date) <= getdate(valid_upto)) and available_amount > 0:
valid = True
def is_valid_certificate(ldc, posting_date, limit_consumed):
available_amount = flt(ldc.certificate_limit) - flt(limit_consumed)
if (
getdate(ldc.valid_from) <= getdate(posting_date) <= getdate(ldc.valid_upto)
) and available_amount > 0:
return True

return valid
return False


def normal_round(number):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
import unittest

import frappe
<<<<<<< HEAD
from frappe.tests.utils import change_settings
=======
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
>>>>>>> 985ff9781b (fix: Tax withholding post LDC limit consumed (#36611))
from frappe.utils import today

from erpnext.accounts.utils import get_fiscal_year
Expand All @@ -18,6 +22,7 @@ def setUpClass(self):
# create relevant supplier, etc
create_records()
create_tax_withholding_category_records()
make_pan_no_field()

def tearDown(self):
cancel_invoices()
Expand Down Expand Up @@ -456,6 +461,40 @@ def test_tax_withholding_via_payment_entry_for_advances(self):
pe2.cancel()
pe3.cancel()

def test_lower_deduction_certificate_application(self):
frappe.db.set_value(
"Supplier",
"Test LDC Supplier",
{
"tax_withholding_category": "Test Service Category",
"pan": "ABCTY1234D",
},
)

create_lower_deduction_certificate(
supplier="Test LDC Supplier",
certificate_no="1AE0423AAJ",
tax_withholding_category="Test Service Category",
tax_rate=2,
limit=50000,
)

pi1 = create_purchase_invoice(supplier="Test LDC Supplier", rate=35000)
pi1.submit()
self.assertEqual(pi1.taxes[0].tax_amount, 700)

pi2 = create_purchase_invoice(supplier="Test LDC Supplier", rate=35000)
pi2.submit()
self.assertEqual(pi2.taxes[0].tax_amount, 2300)

pi3 = create_purchase_invoice(supplier="Test LDC Supplier", rate=35000)
pi3.submit()
self.assertEqual(pi3.taxes[0].tax_amount, 3500)

pi1.cancel()
pi2.cancel()
pi3.cancel()


def cancel_invoices():
purchase_invoices = frappe.get_all(
Expand Down Expand Up @@ -615,6 +654,7 @@ def create_records():
"Test TDS Supplier6",
"Test TDS Supplier7",
"Test TDS Supplier8",
"Test LDC Supplier",
]:
if frappe.db.exists("Supplier", name):
continue
Expand Down Expand Up @@ -811,3 +851,39 @@ def create_tax_withholding_category(
"accounts": [{"company": "_Test Company", "account": account}],
}
).insert()


def create_lower_deduction_certificate(
supplier, tax_withholding_category, tax_rate, certificate_no, limit
):
fiscal_year = get_fiscal_year(today(), company="_Test Company")
if not frappe.db.exists("Lower Deduction Certificate", certificate_no):
frappe.get_doc(
{
"doctype": "Lower Deduction Certificate",
"company": "_Test Company",
"supplier": supplier,
"certificate_no": certificate_no,
"tax_withholding_category": tax_withholding_category,
"fiscal_year": fiscal_year[0],
"valid_from": fiscal_year[1],
"valid_upto": fiscal_year[2],
"rate": tax_rate,
"certificate_limit": limit,
}
).insert()


def make_pan_no_field():
pan_field = {
"Supplier": [
{
"fieldname": "pan",
"label": "PAN",
"fieldtype": "Data",
"translatable": 0,
}
]
}

create_custom_fields(pan_field, update=1)

0 comments on commit b2a2ccb

Please sign in to comment.