feat: add invoice totals in tax withholding report (#36567)

* fix: add invoice totals in tax withholding report

* fix: naming series col in tax withholding report

* fix: tds computation summary cols
This commit is contained in:
Gursheen Kaur Anand 2023-08-14 18:15:47 +05:30 committed by GitHub
parent 1ff80fcbee
commit 12a6f3b997
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 162 additions and 76 deletions

View File

@ -33,7 +33,14 @@ frappe.query_reports["Tax Withholding Details"] = {
frappe.throw(__("Please select Party Type first")); frappe.throw(__("Please select Party Type first"));
} }
return party_type; return party_type;
} },
"get_query": function() {
return {
"filters": {
"tax_withholding_category": ["!=",""],
}
}
},
}, },
{ {
"fieldname":"from_date", "fieldname":"from_date",

View File

@ -7,19 +7,26 @@ from frappe import _
def execute(filters=None): def execute(filters=None):
if filters.get("party_type") == "Customer":
party_naming_by = frappe.db.get_single_value("Selling Settings", "cust_master_name")
else:
party_naming_by = frappe.db.get_single_value("Buying Settings", "supp_master_name")
filters.update({"naming_series": party_naming_by})
validate_filters(filters) validate_filters(filters)
( (
tds_docs, tds_docs,
tds_accounts, tds_accounts,
tax_category_map, tax_category_map,
journal_entry_party_map, journal_entry_party_map,
invoice_net_total_map, net_total_map,
) = get_tds_docs(filters) ) = get_tds_docs(filters)
columns = get_columns(filters) columns = get_columns(filters)
res = get_result( res = get_result(
filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, invoice_net_total_map filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, net_total_map
) )
return columns, res return columns, res
@ -31,7 +38,7 @@ def validate_filters(filters):
def get_result( def get_result(
filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, invoice_net_total_map filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, net_total_map
): ):
party_map = get_party_pan_map(filters.get("party_type")) party_map = get_party_pan_map(filters.get("party_type"))
tax_rate_map = get_tax_rate_map(filters) tax_rate_map = get_tax_rate_map(filters)
@ -39,7 +46,7 @@ def get_result(
out = [] out = []
for name, details in gle_map.items(): for name, details in gle_map.items():
tax_amount, total_amount = 0, 0 tax_amount, total_amount, grand_total, base_total = 0, 0, 0, 0
tax_withholding_category = tax_category_map.get(name) tax_withholding_category = tax_category_map.get(name)
rate = tax_rate_map.get(tax_withholding_category) rate = tax_rate_map.get(tax_withholding_category)
@ -60,8 +67,8 @@ def get_result(
if entry.account in tds_accounts: if entry.account in tds_accounts:
tax_amount += entry.credit - entry.debit tax_amount += entry.credit - entry.debit
if invoice_net_total_map.get(name): if net_total_map.get(name):
total_amount = invoice_net_total_map.get(name) total_amount, grand_total, base_total = net_total_map.get(name)
else: else:
total_amount += entry.credit total_amount += entry.credit
@ -69,15 +76,13 @@ def get_result(
if party_map.get(party, {}).get("party_type") == "Supplier": if party_map.get(party, {}).get("party_type") == "Supplier":
party_name = "supplier_name" party_name = "supplier_name"
party_type = "supplier_type" party_type = "supplier_type"
table_name = "Supplier"
else: else:
party_name = "customer_name" party_name = "customer_name"
party_type = "customer_type" party_type = "customer_type"
table_name = "Customer"
row = { row = {
"pan" "pan"
if frappe.db.has_column(table_name, "pan") if frappe.db.has_column(filters.party_type, "pan")
else "tax_id": party_map.get(party, {}).get("pan"), else "tax_id": party_map.get(party, {}).get("pan"),
"party": party_map.get(party, {}).get("name"), "party": party_map.get(party, {}).get("name"),
} }
@ -91,6 +96,8 @@ def get_result(
"entity_type": party_map.get(party, {}).get(party_type), "entity_type": party_map.get(party, {}).get(party_type),
"rate": rate, "rate": rate,
"total_amount": total_amount, "total_amount": total_amount,
"grand_total": grand_total,
"base_total": base_total,
"tax_amount": tax_amount, "tax_amount": tax_amount,
"transaction_date": posting_date, "transaction_date": posting_date,
"transaction_type": voucher_type, "transaction_type": voucher_type,
@ -144,9 +151,9 @@ def get_gle_map(documents):
def get_columns(filters): def get_columns(filters):
pan = "pan" if frappe.db.has_column("Supplier", "pan") else "tax_id" pan = "pan" if frappe.db.has_column(filters.party_type, "pan") else "tax_id"
columns = [ columns = [
{"label": _(frappe.unscrub(pan)), "fieldname": pan, "fieldtype": "Data", "width": 90}, {"label": _(frappe.unscrub(pan)), "fieldname": pan, "fieldtype": "Data", "width": 60},
{ {
"label": _(filters.get("party_type")), "label": _(filters.get("party_type")),
"fieldname": "party", "fieldname": "party",
@ -158,25 +165,30 @@ def get_columns(filters):
if filters.naming_series == "Naming Series": if filters.naming_series == "Naming Series":
columns.append( columns.append(
{"label": _("Party Name"), "fieldname": "party_name", "fieldtype": "Data", "width": 180} {
"label": _(filters.party_type + " Name"),
"fieldname": "party_name",
"fieldtype": "Data",
"width": 180,
}
) )
columns.extend( columns.extend(
[ [
{
"label": _("Date of Transaction"),
"fieldname": "transaction_date",
"fieldtype": "Date",
"width": 100,
},
{ {
"label": _("Section Code"), "label": _("Section Code"),
"options": "Tax Withholding Category", "options": "Tax Withholding Category",
"fieldname": "section_code", "fieldname": "section_code",
"fieldtype": "Link", "fieldtype": "Link",
"width": 180,
},
{"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, "width": 90,
}, },
{"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 100},
{ {
"label": _("Total Amount"), "label": _("Total Amount"),
"fieldname": "total_amount", "fieldname": "total_amount",
@ -184,15 +196,27 @@ def get_columns(filters):
"width": 90, "width": 90,
}, },
{ {
"label": _("TDS Amount") if filters.get("party_type") == "Supplier" else _("TCS Amount"), "label": _("TDS Rate %") if filters.get("party_type") == "Supplier" else _("TCS Rate %"),
"fieldname": "rate",
"fieldtype": "Percent",
"width": 90,
},
{
"label": _("Tax Amount"),
"fieldname": "tax_amount", "fieldname": "tax_amount",
"fieldtype": "Float", "fieldtype": "Float",
"width": 90, "width": 90,
}, },
{ {
"label": _("Date of Transaction"), "label": _("Grand Total"),
"fieldname": "transaction_date", "fieldname": "grand_total",
"fieldtype": "Date", "fieldtype": "Float",
"width": 90,
},
{
"label": _("Base Total"),
"fieldname": "base_total",
"fieldtype": "Float",
"width": 90, "width": 90,
}, },
{"label": _("Transaction Type"), "fieldname": "transaction_type", "width": 100}, {"label": _("Transaction Type"), "fieldname": "transaction_type", "width": 100},
@ -216,7 +240,7 @@ def get_tds_docs(filters):
payment_entries = [] payment_entries = []
journal_entries = [] journal_entries = []
tax_category_map = frappe._dict() tax_category_map = frappe._dict()
invoice_net_total_map = frappe._dict() net_total_map = frappe._dict()
or_filters = frappe._dict() or_filters = frappe._dict()
journal_entry_party_map = frappe._dict() journal_entry_party_map = frappe._dict()
bank_accounts = frappe.get_all("Account", {"is_group": 0, "account_type": "Bank"}, pluck="name") bank_accounts = frappe.get_all("Account", {"is_group": 0, "account_type": "Bank"}, pluck="name")
@ -260,13 +284,13 @@ def get_tds_docs(filters):
tds_documents.append(d.voucher_no) tds_documents.append(d.voucher_no)
if purchase_invoices: if purchase_invoices:
get_doc_info(purchase_invoices, "Purchase Invoice", tax_category_map, invoice_net_total_map) get_doc_info(purchase_invoices, "Purchase Invoice", tax_category_map, net_total_map)
if sales_invoices: if sales_invoices:
get_doc_info(sales_invoices, "Sales Invoice", tax_category_map, invoice_net_total_map) get_doc_info(sales_invoices, "Sales Invoice", tax_category_map, net_total_map)
if payment_entries: if payment_entries:
get_doc_info(payment_entries, "Payment Entry", tax_category_map) get_doc_info(payment_entries, "Payment Entry", tax_category_map, net_total_map)
if journal_entries: if journal_entries:
journal_entry_party_map = get_journal_entry_party_map(journal_entries) journal_entry_party_map = get_journal_entry_party_map(journal_entries)
@ -277,7 +301,7 @@ def get_tds_docs(filters):
tds_accounts, tds_accounts,
tax_category_map, tax_category_map,
journal_entry_party_map, journal_entry_party_map,
invoice_net_total_map, net_total_map,
) )
@ -295,11 +319,25 @@ def get_journal_entry_party_map(journal_entries):
return journal_entry_party_map return journal_entry_party_map
def get_doc_info(vouchers, doctype, tax_category_map, invoice_net_total_map=None): def get_doc_info(vouchers, doctype, tax_category_map, net_total_map=None):
if doctype == "Purchase Invoice": if doctype == "Purchase Invoice":
fields = ["name", "tax_withholding_category", "base_tax_withholding_net_total"] fields = [
if doctype == "Sales Invoice": "name",
fields = ["name", "base_net_total"] "tax_withholding_category",
"base_tax_withholding_net_total",
"grand_total",
"base_total",
]
elif doctype == "Sales Invoice":
fields = ["name", "base_net_total", "grand_total", "base_total"]
elif doctype == "Payment Entry":
fields = [
"name",
"tax_withholding_category",
"paid_amount",
"paid_amount_after_tax",
"base_paid_amount",
]
else: else:
fields = ["name", "tax_withholding_category"] fields = ["name", "tax_withholding_category"]
@ -308,9 +346,15 @@ def get_doc_info(vouchers, doctype, tax_category_map, invoice_net_total_map=None
for entry in entries: for entry in entries:
tax_category_map.update({entry.name: entry.tax_withholding_category}) tax_category_map.update({entry.name: entry.tax_withholding_category})
if doctype == "Purchase Invoice": if doctype == "Purchase Invoice":
invoice_net_total_map.update({entry.name: entry.base_tax_withholding_net_total}) net_total_map.update(
if doctype == "Sales Invoice": {entry.name: [entry.base_tax_withholding_net_total, entry.grand_total, entry.base_total]}
invoice_net_total_map.update({entry.name: entry.base_net_total}) )
elif doctype == "Sales Invoice":
net_total_map.update({entry.name: [entry.base_net_total, entry.grand_total, entry.base_total]})
elif doctype == "Payment Entry":
net_total_map.update(
{entry.name: [entry.paid_amount, entry.paid_amount_after_tax, entry.base_paid_amount]}
)
def get_tax_rate_map(filters): def get_tax_rate_map(filters):

View File

@ -12,17 +12,35 @@ frappe.query_reports["TDS Computation Summary"] = {
"default": frappe.defaults.get_default('company') "default": frappe.defaults.get_default('company')
}, },
{ {
"fieldname":"supplier", "fieldname":"party_type",
"label": __("Supplier"), "label": __("Party Type"),
"fieldtype": "Link", "fieldtype": "Select",
"options": "Supplier", "options": ["Supplier", "Customer"],
"reqd": 1,
"default": "Supplier",
"on_change": function(){
frappe.query_report.set_filter_value("party", "");
}
},
{
"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;
},
"get_query": function() { "get_query": function() {
return { return {
"filters": { "filters": {
"tax_withholding_category": ["!=",""], "tax_withholding_category": ["!=",""],
} }
} }
} },
}, },
{ {
"fieldname":"from_date", "fieldname":"from_date",

View File

@ -9,9 +9,14 @@ from erpnext.accounts.utils import get_fiscal_year
def execute(filters=None): def execute(filters=None):
validate_filters(filters) if filters.get("party_type") == "Customer":
party_naming_by = frappe.db.get_single_value("Selling Settings", "cust_master_name")
else:
party_naming_by = frappe.db.get_single_value("Buying Settings", "supp_master_name")
filters.naming_series = frappe.db.get_single_value("Buying Settings", "supp_master_name") filters.update({"naming_series": party_naming_by})
validate_filters(filters)
columns = get_columns(filters) columns = get_columns(filters)
( (
@ -25,7 +30,7 @@ def execute(filters=None):
res = get_result( res = get_result(
filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, invoice_total_map filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, invoice_total_map
) )
final_result = group_by_supplier_and_category(res) final_result = group_by_party_and_category(res, filters)
return columns, final_result return columns, final_result
@ -43,60 +48,67 @@ def validate_filters(filters):
filters["fiscal_year"] = from_year filters["fiscal_year"] = from_year
def group_by_supplier_and_category(data): def group_by_party_and_category(data, filters):
supplier_category_wise_map = {} party_category_wise_map = {}
for row in data: for row in data:
supplier_category_wise_map.setdefault( party_category_wise_map.setdefault(
(row.get("supplier"), row.get("section_code")), (row.get("party"), row.get("section_code")),
{ {
"pan": row.get("pan"), "pan": row.get("pan"),
"supplier": row.get("supplier"), "tax_id": row.get("tax_id"),
"supplier_name": row.get("supplier_name"), "party": row.get("party"),
"party_name": row.get("party_name"),
"section_code": row.get("section_code"), "section_code": row.get("section_code"),
"entity_type": row.get("entity_type"), "entity_type": row.get("entity_type"),
"tds_rate": row.get("tds_rate"), "rate": row.get("rate"),
"total_amount_credited": 0.0, "total_amount": 0.0,
"tds_deducted": 0.0, "tax_amount": 0.0,
}, },
) )
supplier_category_wise_map.get((row.get("supplier"), row.get("section_code")))[ party_category_wise_map.get((row.get("party"), row.get("section_code")))[
"total_amount_credited" "total_amount"
] += row.get("total_amount_credited", 0.0) ] += row.get("total_amount", 0.0)
supplier_category_wise_map.get((row.get("supplier"), row.get("section_code")))[ party_category_wise_map.get((row.get("party"), row.get("section_code")))[
"tds_deducted" "tax_amount"
] += row.get("tds_deducted", 0.0) ] += row.get("tax_amount", 0.0)
final_result = get_final_result(supplier_category_wise_map) final_result = get_final_result(party_category_wise_map)
return final_result return final_result
def get_final_result(supplier_category_wise_map): def get_final_result(party_category_wise_map):
out = [] out = []
for key, value in supplier_category_wise_map.items(): for key, value in party_category_wise_map.items():
out.append(value) out.append(value)
return out return out
def get_columns(filters): def get_columns(filters):
pan = "pan" if frappe.db.has_column(filters.party_type, "pan") else "tax_id"
columns = [ columns = [
{"label": _("PAN"), "fieldname": "pan", "fieldtype": "Data", "width": 90}, {"label": _(frappe.unscrub(pan)), "fieldname": pan, "fieldtype": "Data", "width": 90},
{ {
"label": _("Supplier"), "label": _(filters.get("party_type")),
"options": "Supplier", "fieldname": "party",
"fieldname": "supplier", "fieldtype": "Dynamic Link",
"fieldtype": "Link", "options": "party_type",
"width": 180, "width": 180,
}, },
] ]
if filters.naming_series == "Naming Series": if filters.naming_series == "Naming Series":
columns.append( columns.append(
{"label": _("Supplier Name"), "fieldname": "supplier_name", "fieldtype": "Data", "width": 180} {
"label": _(filters.party_type + " Name"),
"fieldname": "party_name",
"fieldtype": "Data",
"width": 180,
}
) )
columns.extend( columns.extend(
@ -109,18 +121,23 @@ def get_columns(filters):
"width": 180, "width": 180,
}, },
{"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 180}, {"label": _("Entity Type"), "fieldname": "entity_type", "fieldtype": "Data", "width": 180},
{"label": _("TDS Rate %"), "fieldname": "tds_rate", "fieldtype": "Percent", "width": 90},
{ {
"label": _("Total Amount Credited"), "label": _("TDS Rate %") if filters.get("party_type") == "Supplier" else _("TCS Rate %"),
"fieldname": "total_amount_credited", "fieldname": "rate",
"fieldtype": "Float", "fieldtype": "Percent",
"width": 90, "width": 120,
}, },
{ {
"label": _("Amount of TDS Deducted"), "label": _("Total Amount"),
"fieldname": "tds_deducted", "fieldname": "total_amount",
"fieldtype": "Float", "fieldtype": "Float",
"width": 90, "width": 120,
},
{
"label": _("Tax Amount"),
"fieldname": "tax_amount",
"fieldtype": "Float",
"width": 120,
}, },
] ]
) )