Merge pull request #33063 from niralisatapara/tds_purchase_order
feat: item wise tds in purchase order
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 40c732b..23caac0 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
@@ -226,6 +226,42 @@
for d in reversed(invoices):
d.cancel()
+ orders = []
+
+ po = create_purchase_order(supplier="Test TDS Supplier4", rate=20000, do_not_save=True)
+ po.extend(
+ "items",
+ [
+ {
+ "doctype": "Purchase Order Item",
+ "item_code": frappe.db.get_value("Item", {"item_name": "TDS Item"}, "name"),
+ "qty": 1,
+ "rate": 20000,
+ "cost_center": "Main - _TC",
+ "expense_account": "Stock Received But Not Billed - _TC",
+ "apply_tds": 0,
+ },
+ {
+ "doctype": "Purchase Order Item",
+ "item_code": frappe.db.get_value("Item", {"item_name": "TDS Item"}, "name"),
+ "qty": 1,
+ "rate": 35000,
+ "cost_center": "Main - _TC",
+ "expense_account": "Stock Received But Not Billed - _TC",
+ "apply_tds": 1,
+ },
+ ],
+ )
+ po.save()
+ po.submit()
+ orders.append(po)
+
+ self.assertEqual(po.taxes[0].tax_amount, 5500)
+
+ # cancel orders to avoid clashing
+ for d in reversed(orders):
+ d.cancel()
+
def test_multi_category_single_supplier(self):
frappe.db.set_value(
"Supplier", "Test TDS Supplier5", "tax_withholding_category", "Test Service Category"
@@ -348,6 +384,39 @@
return pi
+def create_purchase_order(**args):
+ # return purchase order doc object
+ item = frappe.db.get_value("Item", {"item_name": "TDS Item"}, "name")
+
+ args = frappe._dict(args)
+ po = frappe.get_doc(
+ {
+ "doctype": "Purchase Order",
+ "transaction_date": today(),
+ "schedule_date": today(),
+ "apply_tds": 0 if args.do_not_apply_tds else 1,
+ "supplier": args.supplier,
+ "company": "_Test Company",
+ "taxes_and_charges": "",
+ "currency": "INR",
+ "taxes": [],
+ "items": [
+ {
+ "doctype": "Purchase Order Item",
+ "item_code": item,
+ "qty": args.qty or 1,
+ "rate": args.rate or 10000,
+ "cost_center": "Main - _TC",
+ "expense_account": "Stock Received But Not Billed - _TC",
+ }
+ ],
+ }
+ )
+
+ po.save()
+ return po
+
+
def create_sales_invoice(**args):
# return sales invoice doc object
item = frappe.db.get_value("Item", {"item_name": "TCS Item"}, "name")
diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json
index ded45b8..e2a70c2 100644
--- a/erpnext/buying/doctype/purchase_order/purchase_order.json
+++ b/erpnext/buying/doctype/purchase_order/purchase_order.json
@@ -54,6 +54,8 @@
"column_break_26",
"total",
"net_total",
+ "tax_withholding_net_total",
+ "base_tax_withholding_net_total",
"section_break_48",
"pricing_rules",
"raw_material_details",
@@ -1221,6 +1223,26 @@
"oldfieldtype": "Section Break"
},
{
+ "default": "0",
+ "fieldname": "tax_withholding_net_total",
+ "fieldtype": "Currency",
+ "hidden": 1,
+ "label": "Tax Withholding Net Total",
+ "no_copy": 1,
+ "options": "currency",
+ "read_only": 1
+ },
+ {
+ "fieldname": "base_tax_withholding_net_total",
+ "fieldtype": "Currency",
+ "hidden": 1,
+ "label": "Base Tax Withholding Net Total",
+ "no_copy": 1,
+ "options": "currency",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
"fieldname": "column_break_99",
"fieldtype": "Column Break"
},
diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
index b8203bd..d471783 100644
--- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
+++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
@@ -44,6 +44,7 @@
"discount_amount",
"base_rate_with_margin",
"sec_break2",
+ "apply_tds",
"rate",
"amount",
"item_tax_template",
@@ -889,6 +890,12 @@
{
"fieldname": "column_break_54",
"fieldtype": "Column Break"
+ },
+ {
+ "default": "1",
+ "fieldname": "apply_tds",
+ "fieldtype": "Check",
+ "label": "Apply TDS"
}
],
"idx": 1,
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 2624181..73d5d3e 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -317,4 +317,4 @@
erpnext.patches.v14_0.migrate_remarks_from_gl_to_payment_ledger
erpnext.patches.v13_0.update_schedule_type_in_loans
erpnext.patches.v14_0.create_accounting_dimensions_for_asset_capitalization
-erpnext.patches.v14_0.update_tds_fields
+erpnext.patches.v14_0.update_partial_tds_fields
diff --git a/erpnext/patches/v14_0/update_tds_fields.py b/erpnext/patches/v14_0/update_partial_tds_fields.py
similarity index 64%
rename from erpnext/patches/v14_0/update_tds_fields.py
rename to erpnext/patches/v14_0/update_partial_tds_fields.py
index a333c5d..5ccc2dc 100644
--- a/erpnext/patches/v14_0/update_tds_fields.py
+++ b/erpnext/patches/v14_0/update_partial_tds_fields.py
@@ -25,5 +25,21 @@
).where(
purchase_invoice.docstatus == 1
).run()
+
+ purchase_order = frappe.qb.DocType("Purchase Order")
+
+ frappe.qb.update(purchase_order).set(
+ purchase_order.tax_withholding_net_total, purchase_order.net_total
+ ).set(
+ purchase_order.base_tax_withholding_net_total, purchase_order.base_net_total
+ ).where(
+ purchase_order.company == company.name
+ ).where(
+ purchase_order.apply_tds == 1
+ ).where(
+ purchase_order.transaction_date >= fiscal_year_details.year_start_date
+ ).where(
+ purchase_order.docstatus == 1
+ ).run()
except FiscalYearError:
pass