From b9d3385fec886168cd9a34143a06749a1509b21b Mon Sep 17 00:00:00 2001 From: Saurabh Date: Sat, 12 May 2018 17:42:20 +0530 Subject: [PATCH] calculate TDS on Sales Invoice Amount --- .../in_standard_chart_of_accounts.json | 8 +-- .../purchase_invoice/purchase_invoice.py | 21 +++++- .../tax_withholding_category.json | 64 ++++++++++++++++++- .../tax_withholding_category.py | 5 +- erpnext/accounts/party.py | 61 +++++++++++++++++- erpnext/buying/doctype/supplier/supplier.json | 38 +---------- erpnext/regional/india/setup.py | 4 +- 7 files changed, 153 insertions(+), 48 deletions(-) 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 f2c767f7cd..2ec0b7f70c 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 3e375e5051..0b544b13a3 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -8,7 +8,7 @@ from frappe import _, throw 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 @@ class PurchaseInvoice(BuyingController): 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 @@ class PurchaseInvoice(BuyingController): self.pr_required() self.validate_supplier_invoice() - # validate cash purchase if (self.is_paid == 1): self.validate_cash() @@ -168,7 +168,6 @@ class PurchaseInvoice(BuyingController): 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 @@ class PurchaseInvoice(BuyingController): 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 f02a52043e..a590776e68 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json @@ -13,6 +13,68 @@ "editable_grid": 1, "engine": "InnoDB", "fields": [ + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "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, @@ -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 4940c4f3fe..61f4b60c8b 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 @@ import frappe 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 652272dbe1..6c778f99c8 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -448,7 +448,6 @@ def get_dashboard_info(party_type, party): 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 @@ def get_party_shipping_address(doctype, name): 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 508389f39d..eedbac1dff 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 f035249aa4..70960d714b 100644 --- a/erpnext/regional/india/setup.py +++ b/erpnext/regional/india/setup.py @@ -240,7 +240,7 @@ def set_tax_withholding_category(docs, company): 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