From dd37f6cbd631a1e2e74bc6f81f6dadc9a794fcad Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 19 Jul 2023 11:51:45 +0530 Subject: [PATCH 1/6] fix: show tax withholding category details for customers --- .../tds_payable_monthly.js | 21 +++- .../tds_payable_monthly.py | 101 ++++++++++++------ 2 files changed, 84 insertions(+), 38 deletions(-) diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js index ff2aa30601..d7f396d298 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js @@ -12,10 +12,23 @@ frappe.query_reports["TDS Payable Monthly"] = { "default": frappe.defaults.get_default('company') }, { - "fieldname":"supplier", - "label": __("Supplier"), - "fieldtype": "Link", - "options": "Supplier", + "fieldname":"party_type", + "label": __("Party Type"), + "fieldtype": "Select", + "options": ["Supplier", "Customer"] + }, + { + "fieldname":"party", + "label": __("Party"), + "fieldtype": "Dynamic Link", + "get_options": function() { + var party_type = frappe.query_report.get_filter_value('party_type'); + var party = frappe.query_report.get_filter_value('party'); + if(party && !party_type) { + frappe.throw(__("Please select Party Type first")); + } + return party_type; + } }, { "fieldname":"from_date", diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index 98838907be..7304448f83 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -33,77 +33,95 @@ def validate_filters(filters): def get_result( filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, invoice_net_total_map ): - supplier_map = get_supplier_pan_map() + party_map = get_party_pan_map() tax_rate_map = get_tax_rate_map(filters) gle_map = get_gle_map(tds_docs) out = [] for name, details in gle_map.items(): - tds_deducted, total_amount_credited = 0, 0 + tax_deducted, total_amount_credited = 0, 0 tax_withholding_category = tax_category_map.get(name) rate = tax_rate_map.get(tax_withholding_category) for entry in details: - supplier = entry.party or entry.against + party = entry.party or entry.against posting_date = entry.posting_date voucher_type = entry.voucher_type if voucher_type == "Journal Entry": - suppliers = journal_entry_party_map.get(name) - if suppliers: - supplier = suppliers[0] + party_list = journal_entry_party_map.get(name) + if party_list: + party = party_list[0] if not tax_withholding_category: - tax_withholding_category = supplier_map.get(supplier, {}).get("tax_withholding_category") + tax_withholding_category = party_map.get(party, {}).get("tax_withholding_category") rate = tax_rate_map.get(tax_withholding_category) if entry.account in tds_accounts: - tds_deducted += entry.credit - entry.debit + tax_deducted += entry.credit - entry.debit if invoice_net_total_map.get(name): total_amount_credited = invoice_net_total_map.get(name) else: total_amount_credited += entry.credit - if tds_deducted: + if tax_deducted: + if party_map.get(party, {}).get("party_type") == "Supplier": + party_name = "supplier_name" + party_type = "supplier_type" + table_name = "Supplier" + else: + party_name = "customer_name" + party_type = "customer_type" + table_name = "Customer" + row = { "pan" - if frappe.db.has_column("Supplier", "pan") - else "tax_id": supplier_map.get(supplier, {}).get("pan"), - "supplier": supplier_map.get(supplier, {}).get("name"), + if frappe.db.has_column(table_name, "pan") + else "tax_id": party_map.get(party, {}).get("pan"), + "party": party_map.get(party, {}).get("name"), } if filters.naming_series == "Naming Series": - row.update({"supplier_name": supplier_map.get(supplier, {}).get("supplier_name")}) + row.update({"party_name": party_map.get(party, {}).get(party_name)}) row.update( { "section_code": tax_withholding_category, - "entity_type": supplier_map.get(supplier, {}).get("supplier_type"), - "tds_rate": rate, + "entity_type": party_map.get(party, {}).get(party_type), + "rate": rate, "total_amount_credited": total_amount_credited, - "tds_deducted": tds_deducted, + "tax_deducted": tax_deducted, "transaction_date": posting_date, "transaction_type": voucher_type, "ref_no": name, + "party_type": party_map.get(party, {}).get("party_type"), } ) - out.append(row) return out -def get_supplier_pan_map(): - supplier_map = frappe._dict() - suppliers = frappe.db.get_all( - "Supplier", fields=["name", "pan", "supplier_type", "supplier_name", "tax_withholding_category"] - ) +def get_party_pan_map(): + party_map = frappe._dict() + fields = ["name", "supplier_type", "supplier_name", "tax_withholding_category"] + if frappe.db.has_column("Supplier", "pan"): + fields.append("pan") + suppliers = frappe.db.get_all("Supplier", fields=fields) + fields = ["name", "customer_type", "customer_name", "tax_withholding_category"] + if frappe.db.has_column("Customer", "pan"): + fields.append("pan") + customers = frappe.db.get_all("Customer", fields=fields) for d in suppliers: - supplier_map[d.name] = d + d.party_type = "Supplier" + party_map[d.name] = d + for d in customers: + d.party_type = "Customer" + party_map[d.name] = d - return supplier_map + return party_map def get_gle_map(documents): @@ -131,17 +149,22 @@ def get_columns(filters): columns = [ {"label": _(frappe.unscrub(pan)), "fieldname": pan, "fieldtype": "Data", "width": 90}, { - "label": _("Supplier"), - "options": "Supplier", - "fieldname": "supplier", - "fieldtype": "Link", + "label": _("Party Type"), + "fieldname": "party_type", + "width": 180, + }, + { + "label": _("Party"), + "fieldname": "party", + "fieldtype": "Dynamic Link", + "options": "party_type", "width": 180, }, ] if filters.naming_series == "Naming Series": columns.append( - {"label": _("Supplier Name"), "fieldname": "supplier_name", "fieldtype": "Data", "width": 180} + {"label": _("Party Name"), "fieldname": "party_name", "fieldtype": "Data", "width": 180} ) columns.extend( @@ -154,7 +177,7 @@ def get_columns(filters): "width": 180, }, {"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 180}, - {"label": _("TDS Rate %"), "fieldname": "tds_rate", "fieldtype": "Percent", "width": 90}, + {"label": _("Rate %"), "fieldname": "rate", "fieldtype": "Percent", "width": 90}, { "label": _("Total Amount Credited"), "fieldname": "total_amount_credited", @@ -162,8 +185,8 @@ def get_columns(filters): "width": 90, }, { - "label": _("Amount of TDS Deducted"), - "fieldname": "tds_deducted", + "label": _("Amount of Tax Deducted"), + "fieldname": "tax_deducted", "fieldtype": "Float", "width": 90, }, @@ -190,6 +213,7 @@ def get_columns(filters): def get_tds_docs(filters): tds_documents = [] purchase_invoices = [] + sales_invoices = [] payment_entries = [] journal_entries = [] tax_category_map = frappe._dict() @@ -209,10 +233,10 @@ def get_tds_docs(filters): "against": ("not in", bank_accounts), } - if filters.get("supplier"): + if filters.get("party"): del query_filters["account"] del query_filters["against"] - or_filters = {"against": filters.get("supplier"), "party": filters.get("supplier")} + or_filters = {"against": filters.get("party"), "party": filters.get("party")} tds_docs = frappe.get_all( "GL Entry", @@ -224,6 +248,8 @@ def get_tds_docs(filters): for d in tds_docs: if d.voucher_type == "Purchase Invoice": purchase_invoices.append(d.voucher_no) + if d.voucher_type == "Sales Invoice": + sales_invoices.append(d.voucher_no) elif d.voucher_type == "Payment Entry": payment_entries.append(d.voucher_no) elif d.voucher_type == "Journal Entry": @@ -234,6 +260,9 @@ def get_tds_docs(filters): if purchase_invoices: get_doc_info(purchase_invoices, "Purchase Invoice", tax_category_map, invoice_net_total_map) + if sales_invoices: + get_doc_info(sales_invoices, "Sales Invoice", tax_category_map, invoice_net_total_map) + if payment_entries: get_doc_info(payment_entries, "Payment Entry", tax_category_map) @@ -267,6 +296,8 @@ def get_journal_entry_party_map(journal_entries): def get_doc_info(vouchers, doctype, tax_category_map, invoice_net_total_map=None): if doctype == "Purchase Invoice": fields = ["name", "tax_withholding_category", "base_tax_withholding_net_total"] + if doctype == "Sales Invoice": + fields = ["name", "base_net_total"] else: fields = ["name", "tax_withholding_category"] @@ -276,6 +307,8 @@ def get_doc_info(vouchers, doctype, tax_category_map, invoice_net_total_map=None tax_category_map.update({entry.name: entry.tax_withholding_category}) if doctype == "Purchase Invoice": invoice_net_total_map.update({entry.name: entry.base_tax_withholding_net_total}) + if doctype == "Sales Invoice": + invoice_net_total_map.update({entry.name: entry.base_net_total}) def get_tax_rate_map(filters): From ec80dc6f09f0daf2495db5ed1c84fe3a332b31fa Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Fri, 21 Jul 2023 15:55:31 +0530 Subject: [PATCH 2/6] fix: make column names more general --- .../tds_payable_monthly.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index 7304448f83..b1a112ad55 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -39,7 +39,7 @@ def get_result( out = [] for name, details in gle_map.items(): - tax_deducted, total_amount_credited = 0, 0 + tax_amount, total_amount = 0, 0 tax_withholding_category = tax_category_map.get(name) rate = tax_rate_map.get(tax_withholding_category) @@ -58,14 +58,14 @@ def get_result( rate = tax_rate_map.get(tax_withholding_category) if entry.account in tds_accounts: - tax_deducted += entry.credit - entry.debit + tax_amount += entry.credit - entry.debit if invoice_net_total_map.get(name): - total_amount_credited = invoice_net_total_map.get(name) + total_amount = invoice_net_total_map.get(name) else: - total_amount_credited += entry.credit + total_amount += entry.credit - if tax_deducted: + if tax_amount: if party_map.get(party, {}).get("party_type") == "Supplier": party_name = "supplier_name" party_type = "supplier_type" @@ -90,8 +90,8 @@ def get_result( "section_code": tax_withholding_category, "entity_type": party_map.get(party, {}).get(party_type), "rate": rate, - "total_amount_credited": total_amount_credited, - "tax_deducted": tax_deducted, + "total_amount": total_amount, + "tax_amount": tax_amount, "transaction_date": posting_date, "transaction_type": voucher_type, "ref_no": name, @@ -179,14 +179,14 @@ def get_columns(filters): {"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 180}, {"label": _("Rate %"), "fieldname": "rate", "fieldtype": "Percent", "width": 90}, { - "label": _("Total Amount Credited"), - "fieldname": "total_amount_credited", + "label": _("Total Amount"), + "fieldname": "total_amount", "fieldtype": "Float", "width": 90, }, { - "label": _("Amount of Tax Deducted"), - "fieldname": "tax_deducted", + "label": _("Tax Amount"), + "fieldname": "tax_amount", "fieldtype": "Float", "width": 90, }, From 38b501e0041328cb77f59b971a4faf56955b27e3 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 24 Jul 2023 12:13:47 +0530 Subject: [PATCH 3/6] fix: make party type filter mandatory --- .../tds_payable_monthly.js | 6 +++- .../tds_payable_monthly.py | 33 ++++++++++--------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js index d7f396d298..11b80aab07 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js @@ -15,7 +15,11 @@ frappe.query_reports["TDS Payable Monthly"] = { "fieldname":"party_type", "label": __("Party Type"), "fieldtype": "Select", - "options": ["Supplier", "Customer"] + "options": ["Supplier", "Customer"], + "reqd": 1, + "on_change": function(){ + frappe.query_report.set_filter_value("party", ""); + } }, { "fieldname":"party", diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index b1a112ad55..ce1297b49d 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -33,7 +33,7 @@ def validate_filters(filters): def get_result( filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, invoice_net_total_map ): - party_map = get_party_pan_map() + party_map = get_party_pan_map(filters.get("party_type")) tax_rate_map = get_tax_rate_map(filters) gle_map = get_gle_map(tds_docs) @@ -103,23 +103,23 @@ def get_result( return out -def get_party_pan_map(): +def get_party_pan_map(party_type): party_map = frappe._dict() - fields = ["name", "supplier_type", "supplier_name", "tax_withholding_category"] - if frappe.db.has_column("Supplier", "pan"): - fields.append("pan") - suppliers = frappe.db.get_all("Supplier", fields=fields) - fields = ["name", "customer_type", "customer_name", "tax_withholding_category"] - if frappe.db.has_column("Customer", "pan"): + fields = ["name", "tax_withholding_category"] + if party_type == "Supplier": + fields += ["supplier_type", "supplier_name"] + else: + fields += ["customer_type", "customer_name"] + + if frappe.db.has_column(party_type, "pan"): fields.append("pan") - customers = frappe.db.get_all("Customer", fields=fields) - for d in suppliers: - d.party_type = "Supplier" - party_map[d.name] = d - for d in customers: - d.party_type = "Customer" - party_map[d.name] = d + + party_details = frappe.db.get_all(party_type, fields=fields) + + for party in party_details: + party.party_type = party_type + party_map[party.name] = party return party_map @@ -233,6 +233,9 @@ def get_tds_docs(filters): "against": ("not in", bank_accounts), } + party = frappe.get_all(filters.get("party_type"), pluck="name") + query_filters.update({"against": ("in", party)}) + if filters.get("party"): del query_filters["account"] del query_filters["against"] From 2f6d0bdceef2aefe3d46c0c5c7997750d4fc3bc8 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 24 Jul 2023 12:20:58 +0530 Subject: [PATCH 4/6] fix: col names for party types --- .../tds_payable_monthly.py | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py index ce1297b49d..ddd049a115 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py +++ b/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py @@ -95,7 +95,6 @@ def get_result( "transaction_date": posting_date, "transaction_type": voucher_type, "ref_no": name, - "party_type": party_map.get(party, {}).get("party_type"), } ) out.append(row) @@ -149,12 +148,7 @@ def get_columns(filters): columns = [ {"label": _(frappe.unscrub(pan)), "fieldname": pan, "fieldtype": "Data", "width": 90}, { - "label": _("Party Type"), - "fieldname": "party_type", - "width": 180, - }, - { - "label": _("Party"), + "label": _(filters.get("party_type")), "fieldname": "party", "fieldtype": "Dynamic Link", "options": "party_type", @@ -176,8 +170,13 @@ def get_columns(filters): "fieldtype": "Link", "width": 180, }, - {"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 180}, - {"label": _("Rate %"), "fieldname": "rate", "fieldtype": "Percent", "width": 90}, + {"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 120}, + { + "label": _("TDS Rate %") if filters.get("party_type") == "Supplier" else _("TCS Rate %"), + "fieldname": "rate", + "fieldtype": "Percent", + "width": 90, + }, { "label": _("Total Amount"), "fieldname": "total_amount", @@ -185,7 +184,7 @@ def get_columns(filters): "width": 90, }, { - "label": _("Tax Amount"), + "label": _("TDS Amount") if filters.get("party_type") == "Supplier" else _("TCS Amount"), "fieldname": "tax_amount", "fieldtype": "Float", "width": 90, @@ -196,13 +195,13 @@ def get_columns(filters): "fieldtype": "Date", "width": 90, }, - {"label": _("Transaction Type"), "fieldname": "transaction_type", "width": 90}, + {"label": _("Transaction Type"), "fieldname": "transaction_type", "width": 100}, { "label": _("Reference No."), "fieldname": "ref_no", "fieldtype": "Dynamic Link", "options": "transaction_type", - "width": 90, + "width": 180, }, ] ) From 5224f13db26ddb4983430a59fc7b1053d7523c5d Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 24 Jul 2023 14:52:29 +0530 Subject: [PATCH 5/6] fix: add patch for renaming tds payable report --- .../__init__.py | 0 .../tax_withholding_details.js} | 2 +- .../tax_withholding_details.json} | 4 ++-- .../tax_withholding_details.py} | 0 erpnext/patches.txt | 1 + 5 files changed, 4 insertions(+), 3 deletions(-) rename erpnext/accounts/report/{tds_payable_monthly => tax_withholding_details}/__init__.py (100%) rename erpnext/accounts/report/{tds_payable_monthly/tds_payable_monthly.js => tax_withholding_details/tax_withholding_details.js} (96%) rename erpnext/accounts/report/{tds_payable_monthly/tds_payable_monthly.json => tax_withholding_details/tax_withholding_details.json} (88%) rename erpnext/accounts/report/{tds_payable_monthly/tds_payable_monthly.py => tax_withholding_details/tax_withholding_details.py} (100%) diff --git a/erpnext/accounts/report/tds_payable_monthly/__init__.py b/erpnext/accounts/report/tax_withholding_details/__init__.py similarity index 100% rename from erpnext/accounts/report/tds_payable_monthly/__init__.py rename to erpnext/accounts/report/tax_withholding_details/__init__.py diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.js similarity index 96% rename from erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js rename to erpnext/accounts/report/tax_withholding_details/tax_withholding_details.js index 11b80aab07..c29a801059 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.js +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.js @@ -2,7 +2,7 @@ // For license information, please see license.txt /* eslint-disable */ -frappe.query_reports["TDS Payable Monthly"] = { +frappe.query_reports["Tax Withholding Details"] = { "filters": [ { "fieldname":"company", diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.json b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.json similarity index 88% rename from erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.json rename to erpnext/accounts/report/tax_withholding_details/tax_withholding_details.json index 4d555bd8ba..fb204b319d 100644 --- a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.json +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.json @@ -12,11 +12,11 @@ "modified": "2021-09-20 12:05:50.387572", "modified_by": "Administrator", "module": "Accounts", - "name": "TDS Payable Monthly", + "name": "Tax Withholding Details", "owner": "Administrator", "prepared_report": 0, "ref_doctype": "Purchase Invoice", - "report_name": "TDS Payable Monthly", + "report_name": "Tax Withholding Details", "report_type": "Script Report", "roles": [ { diff --git a/erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py similarity index 100% rename from erpnext/accounts/report/tds_payable_monthly/tds_payable_monthly.py rename to erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 73e0a95da9..17add82d45 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -262,6 +262,7 @@ erpnext.patches.v14_0.update_reference_due_date_in_journal_entry erpnext.patches.v15_0.saudi_depreciation_warning erpnext.patches.v15_0.delete_saudi_doctypes erpnext.patches.v14_0.show_loan_management_deprecation_warning +execute:frappe.rename_doc("Report", "TDS Payable Monthly", "Tax Withholding Details", force=True) [post_model_sync] execute:frappe.delete_doc_if_exists('Workspace', 'ERPNext Integrations Settings') From 8c410c617c45292e1783ee9f90359d1c245d5e16 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 25 Jul 2023 14:47:46 +0530 Subject: [PATCH 6/6] chore: Add default value --- .../report/tax_withholding_details/tax_withholding_details.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.js b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.js index e330d2f7fe..b66a555522 100644 --- a/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.js +++ b/erpnext/accounts/report/tax_withholding_details/tax_withholding_details.js @@ -17,6 +17,7 @@ frappe.query_reports["Tax Withholding Details"] = { "fieldtype": "Select", "options": ["Supplier", "Customer"], "reqd": 1, + "default": "Supplier", "on_change": function(){ frappe.query_report.set_filter_value("party", ""); }