Merge pull request #31736 from maharshivpatel/fix-india-hsn-report

fix: (india) HSN wise report
This commit is contained in:
Deepesh Garg
2022-08-09 18:58:25 +05:30
committed by GitHub

View File

@@ -23,24 +23,31 @@ def _execute(filters=None):
if not filters: if not filters:
filters = {} filters = {}
columns = get_columns() columns = get_columns()
output_gst_accounts = get_output_gst_accounts(filters.company)
company_currency = erpnext.get_company_currency(filters.company) company_currency = erpnext.get_company_currency(filters.company)
item_list = get_items(filters) item_list = get_items(filters)
if item_list: 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 = [] data = []
added_item = [] added_item = []
for d in item_list: for d in item_list:
if (d.parent, d.item_code) not in added_item: 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 total_tax = 0
tax_rate = 0
for tax in tax_columns: for tax in tax_columns:
item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {}) 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)) total_tax += flt(item_tax.get("tax_amount", 0))
row += [d.base_net_amount + total_tax] row += [tax_rate]
row += [d.base_net_amount] row += [d.taxable_value + total_tax]
row += [d.taxable_value]
for tax in tax_columns: for tax in tax_columns:
item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {}) item_tax = itemised_tax.get((d.parent, d.item_code), {}).get(tax, {})
row += [item_tax.get("tax_amount", 0)] row += [item_tax.get("tax_amount", 0)]
@@ -51,6 +58,40 @@ def _execute(filters=None):
return columns, data 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(): def get_columns():
columns = [ columns = [
{ {
@@ -99,44 +140,24 @@ def get_items(filters):
match_conditions = " and {0} ".format(match_conditions) match_conditions = " and {0} ".format(match_conditions)
items = frappe.db.sql( items = frappe.db.sql(
""" f"""
SELECT SELECT
`tabSales Invoice Item`.gst_hsn_code, `tabSales Invoice Item`.gst_hsn_code,
`tabSales Invoice Item`.stock_uom, `tabSales Invoice Item`.stock_uom,
sum( sum(`tabSales Invoice Item`.stock_qty) AS stock_qty,
`tabSales Invoice Item`.stock_qty sum(`tabSales Invoice Item`.taxable_value) AS taxable_value,
) as stock_qty, sum(`tabSales Invoice Item`.base_price_list_rate) AS base_price_list_rate,
sum(
`tabSales Invoice Item`.base_net_amount
) as base_net_amount,
sum(
`tabSales Invoice Item`.base_price_list_rate
) as base_price_list_rate,
`tabSales Invoice Item`.parent, `tabSales Invoice Item`.parent,
`tabSales Invoice Item`.item_code, `tabSales Invoice Item`.item_code,
`tabGST HSN Code`.description, `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
FROM FROM
`tabSales Invoice` `tabSales Invoice`
INNER JOIN INNER JOIN `tabSales Invoice Item` ON `tabSales Invoice`.name = `tabSales Invoice Item`.parent
`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
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
WHERE WHERE
`tabSales Invoice`.docstatus = 1 `tabSales Invoice`.docstatus = 1
AND AND `tabSales Invoice Item`.gst_hsn_code IS NOT NULL
`tabSales Invoice Item`.gst_hsn_code is not NULL {conditions}
GROUP BY GROUP BY
`tabSales Invoice Item`.parent, `tabSales Invoice Item`.parent,
`tabSales Invoice Item`.item_code, `tabSales Invoice Item`.item_code,
@@ -145,8 +166,9 @@ def get_items(filters):
ORDER BY ORDER BY
`tabSales Invoice Item`.gst_hsn_code, `tabSales Invoice Item`.gst_hsn_code,
`tabSales Invoice Item`.uom `tabSales Invoice Item`.uom
""" """.format(
% (conditions, match_conditions), conditions=conditions
),
filters, filters,
as_dict=1, as_dict=1,
) )
@@ -158,6 +180,7 @@ def get_tax_accounts(
item_list, item_list,
columns, columns,
company_currency, company_currency,
output_gst_accounts,
doctype="Sales Invoice", doctype="Sales Invoice",
tax_doctype="Sales Taxes and Charges", 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: 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 # as description is text editor earlier and markup can break the column convention in reports
tax_columns.append(account_head) tax_columns.append(account_head)
@@ -210,29 +233,40 @@ def get_tax_accounts(
continue continue
itemised_tax.setdefault(item_code, frappe._dict()) itemised_tax.setdefault(item_code, frappe._dict())
if isinstance(tax_data, list): 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] tax_amount = tax_data[1]
else: else:
tax_rate = 0
tax_amount = 0 tax_amount = 0
for d in item_row_map.get(parent, {}).get(item_code, []): for d in item_row_map.get(parent, {}).get(item_code, []):
item_tax_amount = tax_amount item_tax_amount = tax_amount
if item_tax_amount: if item_tax_amount:
itemised_tax.setdefault((parent, item_code), {})[account_head] = frappe._dict( 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: except ValueError:
continue continue
tax_columns.sort() tax_columns.sort()
for account_head in tax_columns: for account_head in tax_columns:
columns.append( if account_head in output_gst_accounts:
{ columns.append(
"label": account_head, {
"fieldname": frappe.scrub(account_head), "label": account_head,
"fieldtype": "Float", "fieldname": frappe.scrub(account_head),
"width": 110, "fieldtype": "Float",
} "width": 110,
) }
)
return itemised_tax, tax_columns return itemised_tax, tax_columns