Merge pull request #31736 from maharshivpatel/fix-india-hsn-report
fix: (india) HSN wise report
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user