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:
|
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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user