Item Wise TDS Calculation
For calculating Item wise TDS in Purchase Invoice.
This commit is contained in:
parent
ccf2952b76
commit
e758a753f8
File diff suppressed because it is too large
Load Diff
@ -1574,6 +1574,35 @@ class TestPurchaseInvoice(unittest.TestCase, StockTestMixin):
|
||||
|
||||
self.assertTrue(return_pi.docstatus == 1)
|
||||
|
||||
def test_without_tds(self):
|
||||
make_purchase_invoice_tds()
|
||||
|
||||
def test_total_tds(self):
|
||||
supplier = create_supplier(
|
||||
supplier_name="_Test TDS Advance Supplier",
|
||||
tax_withholding_category="TDS - 194 - Dividends - Individual",
|
||||
)
|
||||
pi = make_purchase_invoice_tds(supplier= "_Test TDS Advance Supplier",total_tds = 1)
|
||||
|
||||
sum_tds = 0
|
||||
for item in pi.items:
|
||||
sum_tds += item.net_amount
|
||||
|
||||
self.assertEqual(pi.tax_withholding_net_total, sum_tds)
|
||||
for tax in pi.taxes:
|
||||
self.assertEqual(tax.tax_amount, pi.tax_withholding_net_total * 0.10)
|
||||
|
||||
def test_partial_tds(self):
|
||||
pi = make_purchase_invoice_tds(supplier= "_Test TDS Advance Supplier",partial_tds = 1)
|
||||
|
||||
sum_tds = 0
|
||||
for item in pi.items:
|
||||
if item.apply_tds:
|
||||
sum_tds += item.net_amount
|
||||
|
||||
self.assertEqual(pi.tax_withholding_net_total, sum_tds)
|
||||
for tax in pi.taxes:
|
||||
self.assertEqual(tax.tax_amount, pi.tax_withholding_net_total * 0.10)
|
||||
|
||||
def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
|
||||
gl_entries = frappe.db.sql(
|
||||
@ -1682,6 +1711,86 @@ def make_purchase_invoice(**args):
|
||||
pi.submit()
|
||||
return pi
|
||||
|
||||
def make_purchase_invoice_tds(**args):
|
||||
pi = frappe.new_doc("Purchase Invoice")
|
||||
args = frappe._dict(args)
|
||||
pi.posting_date = args.posting_date or today()
|
||||
if args.posting_time:
|
||||
pi.posting_time = args.posting_time
|
||||
if args.update_stock:
|
||||
pi.update_stock = 1
|
||||
if args.is_paid:
|
||||
pi.is_paid = 1
|
||||
|
||||
if args.cash_bank_account:
|
||||
pi.cash_bank_account = args.cash_bank_account
|
||||
|
||||
pi.company = args.company or "_Test Company"
|
||||
pi.supplier = args.supplier or "_Test Supplier"
|
||||
pi.currency = args.currency or "INR"
|
||||
pi.conversion_rate = args.conversion_rate or 1
|
||||
pi.is_return = args.is_return
|
||||
pi.return_against = args.return_against
|
||||
pi.is_subcontracted = args.is_subcontracted or 0
|
||||
pi.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC"
|
||||
pi.cost_center = args.parent_cost_center
|
||||
|
||||
if args.total_tds or args.partial_tds:
|
||||
pi.apply_tds = 1
|
||||
|
||||
pi.extend(
|
||||
"items",
|
||||
[
|
||||
{
|
||||
"item_code": args.item or args.item_code or "_Test Item",
|
||||
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||
"qty": args.qty or 5,
|
||||
"received_qty": args.received_qty or 0,
|
||||
"rejected_qty": args.rejected_qty or 0,
|
||||
"rate": args.rate or 5000,
|
||||
"price_list_rate": args.price_list_rate or 5000,
|
||||
"expense_account": args.expense_account or "_Test Account Cost for Goods Sold - _TC",
|
||||
"discount_account": args.discount_account or None,
|
||||
"discount_amount": args.discount_amount or 0,
|
||||
"conversion_factor": 1.0,
|
||||
"serial_no": args.serial_no,
|
||||
"stock_uom": args.uom or "_Test UOM",
|
||||
"cost_center": args.cost_center or "_Test Cost Center - _TC",
|
||||
"project": args.project,
|
||||
"rejected_warehouse": args.rejected_warehouse or "",
|
||||
"rejected_serial_no": args.rejected_serial_no or "",
|
||||
"asset_location": args.location or "",
|
||||
"allow_zero_valuation_rate": args.get("allow_zero_valuation_rate") or 0,
|
||||
"apply_tds": 1 if (args.total_tds or args.partial_tds) else 0
|
||||
},
|
||||
{
|
||||
"item_code": args.item or args.item_code or "_Test Item",
|
||||
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||
"qty": args.qty or 5,
|
||||
"received_qty": args.received_qty or 0,
|
||||
"rejected_qty": args.rejected_qty or 0,
|
||||
"rate": args.rate or 5000,
|
||||
"price_list_rate": args.price_list_rate or 5000,
|
||||
"expense_account": args.expense_account or "_Test Account Cost for Goods Sold - _TC",
|
||||
"discount_account": args.discount_account or None,
|
||||
"discount_amount": args.discount_amount or 0,
|
||||
"conversion_factor": 1.0,
|
||||
"serial_no": args.serial_no,
|
||||
"stock_uom": args.uom or "_Test UOM",
|
||||
"cost_center": args.cost_center or "_Test Cost Center - _TC",
|
||||
"project": args.project,
|
||||
"rejected_warehouse": args.rejected_warehouse or "",
|
||||
"rejected_serial_no": args.rejected_serial_no or "",
|
||||
"asset_location": args.location or "",
|
||||
"allow_zero_valuation_rate": args.get("allow_zero_valuation_rate") or 0,
|
||||
"apply_tds": 1 if (args.total_tds) else 0
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
pi.save()
|
||||
pi.submit()
|
||||
return pi
|
||||
|
||||
def make_purchase_invoice_against_cost_center(**args):
|
||||
pi = frappe.new_doc("Purchase Invoice")
|
||||
@ -1734,4 +1843,4 @@ def make_purchase_invoice_against_cost_center(**args):
|
||||
return pi
|
||||
|
||||
|
||||
test_records = frappe.get_test_records("Purchase Invoice")
|
||||
test_records = frappe.get_test_records("Purchase Invoice")
|
@ -40,6 +40,7 @@
|
||||
"discount_amount",
|
||||
"base_rate_with_margin",
|
||||
"sec_break2",
|
||||
"apply_tds",
|
||||
"rate",
|
||||
"amount",
|
||||
"item_tax_template",
|
||||
@ -865,6 +866,12 @@
|
||||
"label": "Product Bundle",
|
||||
"options": "Product Bundle",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "apply_tds",
|
||||
"fieldtype": "Check",
|
||||
"label": "Apply TDS"
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
|
@ -61,6 +61,9 @@ def get_party_details(inv):
|
||||
|
||||
|
||||
def get_party_tax_withholding_details(inv, tax_withholding_category=None):
|
||||
if inv.doctype == "Payment Entry":
|
||||
inv.tax_withholding_net_total = inv.net_total
|
||||
|
||||
pan_no = ""
|
||||
parties = []
|
||||
party_type, party = get_party_details(inv)
|
||||
@ -242,7 +245,7 @@ def get_tax_amount(party_type, parties, inv, tax_details, posting_date, pan_no=N
|
||||
if party_type == "Supplier":
|
||||
ldc = get_lower_deduction_certificate(tax_details, pan_no)
|
||||
if tax_deducted:
|
||||
net_total = inv.net_total
|
||||
net_total = inv.tax_withholding_net_total
|
||||
if ldc:
|
||||
tax_amount = get_tds_amount_from_ldc(
|
||||
ldc, parties, pan_no, tax_details, posting_date, net_total
|
||||
@ -389,7 +392,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers):
|
||||
tds_amount = 0
|
||||
invoice_filters = {"name": ("in", vouchers), "docstatus": 1, "apply_tds": 1}
|
||||
|
||||
field = "sum(net_total)"
|
||||
field = "sum(tax_withholding_net_total)"
|
||||
|
||||
if cint(tax_details.consider_party_ledger_amount):
|
||||
invoice_filters.pop("apply_tds", None)
|
||||
@ -412,12 +415,12 @@ def get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers):
|
||||
)
|
||||
|
||||
supp_credit_amt += supp_jv_credit_amt
|
||||
supp_credit_amt += inv.net_total
|
||||
supp_credit_amt += inv.tax_withholding_net_total
|
||||
|
||||
threshold = tax_details.get("threshold", 0)
|
||||
cumulative_threshold = tax_details.get("cumulative_threshold", 0)
|
||||
|
||||
if (threshold and inv.net_total >= threshold) or (
|
||||
if (threshold and inv.tax_withholding_net_total >= threshold) or (
|
||||
cumulative_threshold and supp_credit_amt >= cumulative_threshold
|
||||
):
|
||||
if (cumulative_threshold and supp_credit_amt >= cumulative_threshold) and cint(
|
||||
@ -425,8 +428,8 @@ def get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers):
|
||||
):
|
||||
# Get net total again as TDS is calculated on net total
|
||||
# Grand is used to just check for threshold breach
|
||||
net_total = frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(net_total)") or 0.0
|
||||
net_total += inv.net_total
|
||||
net_total = frappe.db.get_value("Purchase Invoice", invoice_filters, "sum(tax_withholding_net_total)") or 0.0
|
||||
net_total += inv.tax_withholding_net_total
|
||||
supp_credit_amt = net_total - cumulative_threshold
|
||||
|
||||
if ldc and is_valid_certificate(
|
||||
@ -434,7 +437,7 @@ def get_tds_amount(ldc, parties, inv, tax_details, tax_deducted, vouchers):
|
||||
ldc.valid_upto,
|
||||
inv.get("posting_date") or inv.get("transaction_date"),
|
||||
tax_deducted,
|
||||
inv.net_total,
|
||||
inv.tax_withholding_net_total,
|
||||
ldc.certificate_limit,
|
||||
):
|
||||
tds_amount = get_ltds_amount(supp_credit_amt, 0, ldc.certificate_limit, ldc.rate, tax_details)
|
||||
@ -517,7 +520,7 @@ def get_tds_amount_from_ldc(ldc, parties, pan_no, tax_details, posting_date, net
|
||||
limit_consumed = frappe.db.get_value(
|
||||
"Purchase Invoice",
|
||||
{"supplier": ("in", parties), "apply_tds": 1, "docstatus": 1},
|
||||
"sum(net_total)",
|
||||
"sum(tax_withholding_net_total)",
|
||||
)
|
||||
|
||||
if is_valid_certificate(
|
||||
|
@ -58,12 +58,23 @@ class calculate_taxes_and_totals(object):
|
||||
self.initialize_taxes()
|
||||
self.determine_exclusive_rate()
|
||||
self.calculate_net_total()
|
||||
self.calculate_tax_withholding_net_total()
|
||||
self.calculate_taxes()
|
||||
self.manipulate_grand_total_for_inclusive_tax()
|
||||
self.calculate_totals()
|
||||
self._cleanup()
|
||||
self.calculate_total_net_weight()
|
||||
|
||||
def calculate_tax_withholding_net_total(self):
|
||||
if hasattr(self.doc, "tax_withholding_net_total"):
|
||||
|
||||
sum_net_amount = 0
|
||||
for item in self.doc.get("items"):
|
||||
if hasattr(item, "apply_tds") and item.apply_tds:
|
||||
sum_net_amount += item.net_amount
|
||||
|
||||
self.doc.tax_withholding_net_total = sum_net_amount
|
||||
|
||||
def validate_item_tax_template(self):
|
||||
for item in self.doc.get("items"):
|
||||
if item.item_code and item.get("item_tax_template"):
|
||||
|
Loading…
Reference in New Issue
Block a user