diff --git a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py index f171b6e9cbe..68815bf1edf 100644 --- a/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py +++ b/erpnext/regional/report/hsn_wise_summary_of_outward_supplies/hsn_wise_summary_of_outward_supplies.py @@ -23,24 +23,31 @@ def _execute(filters=None): if not filters: filters = {} columns = get_columns() + output_gst_accounts = get_output_gst_accounts(filters.company) company_currency = erpnext.get_company_currency(filters.company) item_list = get_items(filters) if item_list: - itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency) + itemised_tax, tax_columns = get_tax_accounts( + item_list, columns, company_currency, output_gst_accounts + ) data = [] added_item = [] for d in item_list: if (d.parent, d.item_code) not in added_item: - row = [d.gst_hsn_code, d.description, d.stock_uom, d.stock_qty, d.tax_rate or 0] + row = [d.gst_hsn_code, d.description, d.stock_uom, d.stock_qty] total_tax = 0 + tax_rate = 0 for tax in tax_columns: item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {}) + if item_tax.get("is_gst_tax"): + tax_rate += flt(item_tax.get("tax_rate", 0)) total_tax += flt(item_tax.get("tax_amount", 0)) - row += [d.base_net_amount + total_tax] - row += [d.base_net_amount] + row += [tax_rate] + row += [d.taxable_value + total_tax] + row += [d.taxable_value] for tax in tax_columns: item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {}) row += [item_tax.get("tax_amount", 0)] @@ -51,6 +58,40 @@ def _execute(filters=None): return columns, data +def get_output_gst_accounts(company): + + accounts = frappe.qb.DocType("Account") + gst_accounts = frappe.qb.DocType("GST Account") + + accounts_query = ( + frappe.qb.from_(accounts) + .select(accounts.name) + .where((accounts.account_type == "Tax") & (accounts.root_type == "Liability")) + ) + + gst_accounts_query = ( + frappe.qb.from_(gst_accounts) + .select( + gst_accounts.cgst_account, + gst_accounts.sgst_account, + gst_accounts.igst_account, + gst_accounts.utgst_account, + gst_accounts.cess_account, + ) + .where((gst_accounts.is_reverse_charge_account == 0) & (gst_accounts.company == company)) + ) + + gst_accounts_list = [ + account for sublist in gst_accounts_query.run() for account in sublist if account + ] + + tax_accounts_list = [account[0] for account in accounts_query.run() if account] + + output_tax_list = [account for account in gst_accounts_list if account in tax_accounts_list] + + return output_tax_list + + def get_columns(): columns = [ { @@ -99,44 +140,24 @@ def get_items(filters): match_conditions = " and {0} ".format(match_conditions) items = frappe.db.sql( - """ + f""" SELECT `tabSales Invoice Item`.gst_hsn_code, `tabSales Invoice Item`.stock_uom, - sum( - `tabSales Invoice Item`.stock_qty - ) as stock_qty, - sum( - `tabSales Invoice Item`.base_net_amount - ) as base_net_amount, - sum( - `tabSales Invoice Item`.base_price_list_rate - ) as base_price_list_rate, - + sum(`tabSales Invoice Item`.stock_qty) AS stock_qty, + sum(`tabSales Invoice Item`.taxable_value) AS taxable_value, + sum(`tabSales Invoice Item`.base_price_list_rate) AS base_price_list_rate, `tabSales Invoice Item`.parent, `tabSales Invoice Item`.item_code, - `tabGST HSN Code`.description, - json_extract( - `tabSales Taxes and Charges`.item_wise_tax_detail, - concat( - '$."', `tabSales Invoice Item`.item_code, - '"[0]' - ) - ) * count( - distinct `tabSales Taxes and Charges`.name - ) as tax_rate + `tabGST HSN Code`.description FROM `tabSales Invoice` - INNER JOIN - `tabSales Invoice Item` ON `tabSales Invoice`.name = `tabSales Invoice Item`.parent - INNER JOIN - `tabGST HSN Code` ON `tabSales Invoice Item`.gst_hsn_code = `tabGST HSN Code`.name % s % s - LEFT JOIN - `tabSales Taxes and Charges` ON `tabSales Taxes and Charges`.parent = `tabSales Invoice`.name + INNER JOIN `tabSales Invoice Item` ON `tabSales Invoice`.name = `tabSales Invoice Item`.parent + INNER JOIN `tabGST HSN Code` ON `tabSales Invoice Item`.gst_hsn_code = `tabGST HSN Code`.name WHERE `tabSales Invoice`.docstatus = 1 - AND - `tabSales Invoice Item`.gst_hsn_code is not NULL + AND `tabSales Invoice Item`.gst_hsn_code IS NOT NULL + {conditions} GROUP BY `tabSales Invoice Item`.parent, `tabSales Invoice Item`.item_code, @@ -145,8 +166,9 @@ def get_items(filters): ORDER BY `tabSales Invoice Item`.gst_hsn_code, `tabSales Invoice Item`.uom - """ - % (conditions, match_conditions), + """.format( + conditions=conditions + ), filters, as_dict=1, ) @@ -158,6 +180,7 @@ def get_tax_accounts( item_list, columns, company_currency, + output_gst_accounts, doctype="Sales Invoice", tax_doctype="Sales Taxes and Charges", ): @@ -197,7 +220,7 @@ def get_tax_accounts( for parent, account_head, item_wise_tax_detail, tax_amount in tax_details: - if account_head not in tax_columns and tax_amount: + if account_head in output_gst_accounts and account_head not in tax_columns and tax_amount: # as description is text editor earlier and markup can break the column convention in reports tax_columns.append(account_head) @@ -210,29 +233,40 @@ def get_tax_accounts( continue itemised_tax.setdefault(item_code, frappe._dict()) if isinstance(tax_data, list): + tax_rate = 0 + is_gst_tax = 0 + if account_head in output_gst_accounts: + is_gst_tax = 1 + tax_rate = tax_data[0] tax_amount = tax_data[1] else: + tax_rate = 0 tax_amount = 0 for d in item_row_map.get(parent, {}).get(item_code, []): item_tax_amount = tax_amount if item_tax_amount: itemised_tax.setdefault((parent, item_code), {})[account_head] = frappe._dict( - {"tax_amount": flt(item_tax_amount, tax_amount_precision)} + { + "tax_rate": flt(tax_rate, 2), + "is_gst_tax": is_gst_tax, + "tax_amount": flt(item_tax_amount, tax_amount_precision), + } ) except ValueError: continue tax_columns.sort() for account_head in tax_columns: - columns.append( - { - "label": account_head, - "fieldname": frappe.scrub(account_head), - "fieldtype": "Float", - "width": 110, - } - ) + if account_head in output_gst_accounts: + columns.append( + { + "label": account_head, + "fieldname": frappe.scrub(account_head), + "fieldtype": "Float", + "width": 110, + } + ) return itemised_tax, tax_columns