calculate TDS on Sales Invoice Amount
diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/in_standard_chart_of_accounts.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/in_standard_chart_of_accounts.json
index f2c767f..2ec0b7f 100644
--- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/in_standard_chart_of_accounts.json
+++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/in_standard_chart_of_accounts.json
@@ -139,9 +139,6 @@
"Creditors": {
"account_type": "Payable"
},
- "TDS": {
- "account_type": "Payable"
- },
"Payroll Payable": {}
},
"Stock Liabilities": {
@@ -150,8 +147,9 @@
}
},
"Duties and Taxes": {
- "account_type": "Tax",
- "is_group": 1
+ "TDS": {
+ "account_type": "Tax"
+ }
},
"Loans (Liabilities)": {
"Secured Loans": {},
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 3e375e5..0b544b1 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -8,7 +8,7 @@
import frappe.defaults
from erpnext.controllers.buying_controller import BuyingController
-from erpnext.accounts.party import get_party_account, get_due_date
+from erpnext.accounts.party import get_party_account, get_due_date, get_patry_tax_withholding_details
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billed_amount_based_on_po
from erpnext.stock import get_warehouse_account_map
@@ -46,6 +46,7 @@
self.is_opening = 'No'
self.validate_posting_time()
+ self.set_tax_withholding()
super(PurchaseInvoice, self).validate()
if not self.is_return:
@@ -53,7 +54,6 @@
self.pr_required()
self.validate_supplier_invoice()
-
# validate cash purchase
if (self.is_paid == 1):
self.validate_cash()
@@ -168,7 +168,6 @@
super(PurchaseInvoice, self).validate_warehouse()
-
def validate_item_code(self):
for d in self.get('items'):
if not d.item_code:
@@ -731,6 +730,22 @@
def on_recurring(self, reference_doc, subscription_doc):
self.due_date = None
+ def set_tax_withholding(self):
+ """
+ 1. Get TDS Configurations against Supplier or Pull Default One.
+ 2. Form Purchase Order, identify partial payments
+ 3. If sum of all invoices grand total is greater than threshold and If TDS not deducted in previos Invoices
+ then deduct TDS for sum amount else deduct TDS for current Invoice
+ """
+ if not self.get("__islocal"):
+ return
+
+ tax_withholding_details = get_patry_tax_withholding_details(self)
+
+ if tax_withholding_details and\
+ flt(self.get("rounded_total") or self.grand_total) >= flt(tax_withholding_details['threshold']):
+ self.append('taxes', tax_withholding_details['taxes'])
+
@frappe.whitelist()
def make_debit_note(source_name, target_doc=None):
from erpnext.controllers.sales_and_purchase_return import make_return_doc
diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json
index f02a520..a590776 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json
@@ -19,6 +19,68 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
+ "fieldname": "is_default",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Is Default",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "fieldname": "enabled",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Enabled",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "translatable": 0,
+ "unique": 0
+ },
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
"fieldname": "percent_of_tax_withheld",
"fieldtype": "Float",
"hidden": 0,
@@ -271,7 +333,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-04-13 19:17:12.494050",
+ "modified": "2018-05-11 14:25:07.474461",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Tax Withholding Category",
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 4940c4f..61f4b60 100644
--- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
+++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.py
@@ -7,4 +7,7 @@
from frappe.model.document import Document
class TaxWithholdingCategory(Document):
- pass
+ def validate(self):
+ if not frappe.db.get_value("Tax Withholding Category",
+ {"is_default": 1, "name": ("!=", self.name)}, "name"):
+ self.is_default = 1
\ No newline at end of file
diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py
index 652272d..6c778f9 100644
--- a/erpnext/accounts/party.py
+++ b/erpnext/accounts/party.py
@@ -448,7 +448,6 @@
return info
-
def get_party_shipping_address(doctype, name):
"""
Returns an Address name (best guess) for the given doctype and name for which `address_type == 'Shipping'` is true.
@@ -476,3 +475,63 @@
return out[0][0]
else:
return ''
+
+def get_patry_tax_withholding_details(ref_doc):
+ supplier = frappe.get_doc("Supplier", ref_doc.supplier)
+ tax_withholding_details = {}
+
+ for tax in supplier.tax_withholding_config:
+ tax_mapper = get_tax_mapper()
+
+ set_tax_withholding_details(tax_mapper, ref_doc, tax_withholding_category=tax.tax_withholding_category)
+
+ if tax.valid_till and date_diff(tax.valid_till, ref_doc.posting_date) > 0:
+ tax_mapper.update({
+ "rate": tax.applicable_percentage
+ })
+
+ prepare_tax_withholding_details(tax_mapper, tax_withholding_details)
+
+ if not tax_withholding_details:
+ tax_mapper = get_tax_mapper()
+ set_tax_withholding_details(tax_mapper, ref_doc, use_default=1)
+ prepare_tax_withholding_details(tax_mapper, tax_withholding_details)
+
+ return tax_withholding_details
+
+def prepare_tax_withholding_details(tax_mapper, tax_withholding_details):
+ if tax_mapper.get('account_head'):
+ tax_withholding_details.update({
+ "threshold": tax_mapper['threshold'],
+ "taxes": tax_mapper
+ })
+ del tax_mapper['threshold']
+
+def set_tax_withholding_details(tax_mapper, ref_doc, tax_withholding_category=None, use_default=0):
+ if tax_withholding_category:
+ tax_withholding = frappe.get_doc("Tax Withholding Category", tax_withholding_category)
+ else:
+ tax_withholding = frappe.get_doc("Tax Withholding Category", {'is_default': 1, 'enabled': 1})
+
+ if tax_withholding.book_on_invoice and ref_doc.doctype=='Purchase Invoice' \
+ or tax_withholding.book_on_advance and ref_doc.doctype in ('Payment Entry', 'Journal Entry'):
+
+ for account_detail in tax_withholding.accounts:
+ if ref_doc.company == account_detail.company:
+ tax_mapper.update({
+ "account_head": account_detail.account,
+ "rate": tax_withholding.percent_of_tax_withheld,
+ "threshold": tax_withholding.threshold,
+ "description": tax_withholding.name
+ })
+
+def get_tax_mapper():
+ return {
+ "category": "Total",
+ "add_deduct_tax": "Deduct",
+ "charge_type": "On Net Total",
+ "rate": 0,
+ "description": '',
+ "account_head": '',
+ "threshold": 0.0
+ }
\ No newline at end of file
diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json
index 508389f..eedbac1 100644
--- a/erpnext/buying/doctype/supplier/supplier.json
+++ b/erpnext/buying/doctype/supplier/supplier.json
@@ -233,7 +233,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
- "reqd": 1,
+ "reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@@ -997,7 +997,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "fieldname": "tax_withholding_account",
+ "fieldname": "tax_withholding_config",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -1180,38 +1180,6 @@
"set_only_once": 0,
"translatable": 0,
"unique": 0
- },
- {
- "allow_bulk_edit": 0,
- "allow_on_submit": 0,
- "bold": 0,
- "collapsible": 0,
- "columns": 0,
- "fieldname": "tax_withholding_category",
- "fieldtype": "Link",
- "hidden": 0,
- "ignore_user_permissions": 0,
- "ignore_xss_filter": 0,
- "in_filter": 0,
- "in_global_search": 0,
- "in_list_view": 0,
- "in_standard_filter": 0,
- "label": "Tax Withholding Category",
- "length": 0,
- "no_copy": 0,
- "options": "Tax Withholding Category",
- "permlevel": 0,
- "precision": "",
- "print_hide": 0,
- "print_hide_if_no_value": 0,
- "read_only": 0,
- "remember_last_selected_value": 0,
- "report_hide": 0,
- "reqd": 0,
- "search_index": 0,
- "set_only_once": 0,
- "translatable": 0,
- "unique": 0
}
],
"has_web_view": 0,
@@ -1226,7 +1194,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2018-05-11 14:00:36.204532",
+ "modified": "2018-05-11 15:15:19.912308",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier",
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index f035249..70960d7 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -240,7 +240,7 @@
def set_tds_account(docs, company):
docs.extend([
{
- 'doctype': 'Account', 'account_name': 'TDS', 'account_type': 'Payable',
- 'parent_account': 'Accounts Payable', 'company': company
+ 'doctype': 'Account', 'account_name': 'TDS', 'account_type': 'Tax',
+ 'parent_account': 'Duties and Taxes', 'company': company
}
])
\ No newline at end of file