mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-21 14:09:19 +00:00
fix: Cleanup and fixes in GSTR3B report
This commit is contained in:
@@ -172,7 +172,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>(A) {{__("ITC Available (whether in full op part)")}}</b></td>
|
<td><b>(A) {{__("ITC Available (whether in full or part)")}}</b></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
|
|||||||
@@ -13,11 +13,9 @@ from erpnext.regional.india import state_numbers
|
|||||||
|
|
||||||
class GSTR3BReport(Document):
|
class GSTR3BReport(Document):
|
||||||
def before_save(self):
|
def before_save(self):
|
||||||
|
|
||||||
self.get_data()
|
self.get_data()
|
||||||
|
|
||||||
def get_data(self):
|
def get_data(self):
|
||||||
|
|
||||||
self.report_dict = {
|
self.report_dict = {
|
||||||
"gstin": "",
|
"gstin": "",
|
||||||
"ret_period": "",
|
"ret_period": "",
|
||||||
@@ -179,8 +177,7 @@ class GSTR3BReport(Document):
|
|||||||
self.report_dict["inward_sup"]["isup_details"][1]["intra"] = flt(inward_nil_exempt.get("non_gst").get("intra"), 2)
|
self.report_dict["inward_sup"]["isup_details"][1]["intra"] = flt(inward_nil_exempt.get("non_gst").get("intra"), 2)
|
||||||
|
|
||||||
def set_itc_details(self, itc_details):
|
def set_itc_details(self, itc_details):
|
||||||
|
itc_eligible_type_map = {
|
||||||
itc_type_map = {
|
|
||||||
'IMPG': 'Import Of Capital Goods',
|
'IMPG': 'Import Of Capital Goods',
|
||||||
'IMPS': 'Import Of Service',
|
'IMPS': 'Import Of Service',
|
||||||
'ISRC': 'ITC on Reverse Charge',
|
'ISRC': 'ITC on Reverse Charge',
|
||||||
@@ -188,53 +185,35 @@ class GSTR3BReport(Document):
|
|||||||
'OTH': 'All Other ITC'
|
'OTH': 'All Other ITC'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
itc_ineligible_map = {
|
||||||
|
'RUL': 'Ineligible As Per Section 17(5)',
|
||||||
|
'OTH': 'Ineligible Others'
|
||||||
|
}
|
||||||
|
|
||||||
net_itc = self.report_dict["itc_elg"]["itc_net"]
|
net_itc = self.report_dict["itc_elg"]["itc_net"]
|
||||||
|
|
||||||
for d in self.report_dict["itc_elg"]["itc_avl"]:
|
for d in self.report_dict["itc_elg"]["itc_avl"]:
|
||||||
|
itc_type = itc_eligible_type_map.get(d["ty"])
|
||||||
itc_type = itc_type_map.get(d["ty"])
|
|
||||||
|
|
||||||
if d["ty"] == 'ISRC':
|
|
||||||
reverse_charge = ["Y"]
|
|
||||||
itc_type = 'All Other ITC'
|
|
||||||
gst_category = ['Unregistered', 'Overseas']
|
|
||||||
else:
|
|
||||||
gst_category = ['Overseas', 'Registered Regular']
|
|
||||||
reverse_charge = ["N", "Y"]
|
|
||||||
|
|
||||||
for account_head in self.account_heads:
|
|
||||||
for category in gst_category:
|
|
||||||
for charge_type in reverse_charge:
|
|
||||||
for key in [['iamt', 'igst_account'], ['camt', 'cgst_account'], ['samt', 'sgst_account'], ['csamt', 'cess_account']]:
|
|
||||||
d[key[0]] += flt(itc_details.get((category, itc_type, charge_type, account_head.get(key[1])), {}).get("amount"), 2)
|
|
||||||
|
|
||||||
for key in ['iamt', 'camt', 'samt', 'csamt']:
|
for key in ['iamt', 'camt', 'samt', 'csamt']:
|
||||||
|
d[key] = flt(itc_details.get(itc_type, {}).get(key))
|
||||||
net_itc[key] += flt(d[key], 2)
|
net_itc[key] += flt(d[key], 2)
|
||||||
|
|
||||||
for account_head in self.account_heads:
|
for d in self.report_dict["itc_elg"]["itc_inelg"]:
|
||||||
itc_inelg = self.report_dict["itc_elg"]["itc_inelg"][1]
|
itc_type = itc_ineligible_map.get(d["ty"])
|
||||||
for key in [['iamt', 'igst_account'], ['camt', 'cgst_account'], ['samt', 'sgst_account'], ['csamt', 'cess_account']]:
|
for key in ['iamt', 'camt', 'samt', 'csamt']:
|
||||||
itc_inelg[key[0]] = flt(itc_details.get(("Ineligible", "N", account_head.get(key[1])), {}).get("amount"), 2)
|
d[key] = flt(itc_details.get(itc_type, {}).get(key))
|
||||||
|
|
||||||
def prepare_data(self, doctype, tax_details, supply_type, supply_category, gst_category_list, reverse_charge="N"):
|
def prepare_data(self, doctype, tax_details, supply_type, supply_category, gst_category_list, reverse_charge="N"):
|
||||||
|
|
||||||
account_map = {
|
|
||||||
'sgst_account': 'samt',
|
|
||||||
'cess_account': 'csamt',
|
|
||||||
'cgst_account': 'camt',
|
|
||||||
'igst_account': 'iamt'
|
|
||||||
}
|
|
||||||
|
|
||||||
txval = 0
|
txval = 0
|
||||||
total_taxable_value = self.get_total_taxable_value(doctype, reverse_charge)
|
total_taxable_value = self.get_total_taxable_value(doctype, reverse_charge)
|
||||||
|
|
||||||
for gst_category in gst_category_list:
|
for gst_category in gst_category_list:
|
||||||
txval += total_taxable_value.get(gst_category,0)
|
txval += total_taxable_value.get(gst_category,0)
|
||||||
for account_head in self.account_heads:
|
for key in ['camt', 'samt', 'iamt', 'csamt']:
|
||||||
for account_type, account_name in iteritems(account_head):
|
for account_head in self.account_heads.get(key):
|
||||||
if account_map.get(account_type) in self.report_dict.get(supply_type).get(supply_category):
|
if key in self.report_dict.get(supply_type).get(supply_category):
|
||||||
self.report_dict[supply_type][supply_category][account_map.get(account_type)] += \
|
self.report_dict[supply_type][supply_category][key] += \
|
||||||
flt(tax_details.get((account_name, gst_category), {}).get("amount"), 2)
|
flt(tax_details.get((account_head, gst_category), {}).get("amount"), 2)
|
||||||
|
|
||||||
self.report_dict[supply_type][supply_category]["txval"] += flt(txval, 2)
|
self.report_dict[supply_type][supply_category]["txval"] += flt(txval, 2)
|
||||||
|
|
||||||
@@ -263,23 +242,20 @@ class GSTR3BReport(Document):
|
|||||||
group by ja.account, j.reversal_type""", (self.month_no, self.year, self.company,
|
group by ja.account, j.reversal_type""", (self.month_no, self.year, self.company,
|
||||||
self.gst_details.get("gstin")), as_dict=1)
|
self.gst_details.get("gstin")), as_dict=1)
|
||||||
|
|
||||||
|
net_itc = self.report_dict["itc_elg"]["itc_net"]
|
||||||
|
|
||||||
for entry in reversal_entries:
|
for entry in reversal_entries:
|
||||||
if entry.reversal_type == 'As per rules 42 & 43 of CGST Rules':
|
if entry.reversal_type == 'As per rules 42 & 43 of CGST Rules':
|
||||||
index = 0
|
index = 0
|
||||||
else:
|
else:
|
||||||
index = 1
|
index = 1
|
||||||
|
|
||||||
if entry.account in [a.cgst_account for a in self.account_heads]:
|
for key in ['camt', 'samt', 'iamt', 'csamt']:
|
||||||
self.report_dict["itc_elg"]["itc_rev"][index]["camt"] += flt(entry.amount)
|
if entry.account in self.account_heads.get(key):
|
||||||
if entry.account in [a.sgst_account for a in self.account_heads]:
|
self.report_dict["itc_elg"]["itc_rev"][index][key] += flt(entry.amount)
|
||||||
self.report_dict["itc_elg"]["itc_rev"][index]["samt"] += flt(entry.amount)
|
net_itc[key] -= flt(entry.amount)
|
||||||
if entry.account in [a.igst_account for a in self.account_heads]:
|
|
||||||
self.report_dict["itc_elg"]["itc_rev"][index]["iamt"] += flt(entry.amount)
|
|
||||||
if entry.account in [a.cess_account for a in self.account_heads]:
|
|
||||||
self.report_dict["itc_elg"]["itc_rev"][index]["csamt"] += flt(entry.amount)
|
|
||||||
|
|
||||||
def get_total_taxable_value(self, doctype, reverse_charge):
|
def get_total_taxable_value(self, doctype, reverse_charge):
|
||||||
|
|
||||||
return frappe._dict(frappe.db.sql("""
|
return frappe._dict(frappe.db.sql("""
|
||||||
select gst_category, sum(net_total) as total
|
select gst_category, sum(net_total) as total
|
||||||
from `tab{doctype}`
|
from `tab{doctype}`
|
||||||
@@ -291,28 +267,30 @@ class GSTR3BReport(Document):
|
|||||||
.format(doctype = doctype), (self.month_no, self.year, reverse_charge, self.company, self.gst_details.get("gstin"))))
|
.format(doctype = doctype), (self.month_no, self.year, reverse_charge, self.company, self.gst_details.get("gstin"))))
|
||||||
|
|
||||||
def get_itc_details(self):
|
def get_itc_details(self):
|
||||||
itc_amount = frappe.db.sql("""
|
itc_amounts = frappe.db.sql("""
|
||||||
select s.gst_category, sum(t.base_tax_amount_after_discount_amount) as tax_amount,
|
SELECT eligibility_for_itc, sum(itc_integrated_tax) as itc_integrated_tax,
|
||||||
t.account_head, s.eligibility_for_itc, s.reverse_charge
|
sum(itc_central_tax) as itc_central_tax,
|
||||||
from `tabPurchase Invoice` s , `tabPurchase Taxes and Charges` t
|
sum(itc_state_tax) as itc_state_tax,
|
||||||
where s.docstatus = 1 and t.parent = s.name
|
sum(itc_cess_amount) as itc_cess_amount
|
||||||
and month(s.posting_date) = %s and year(s.posting_date) = %s and s.company = %s
|
FROM `tabPurchase Invoice`
|
||||||
and s.company_gstin = %s
|
where docstatus = 1
|
||||||
group by t.account_head, s.gst_category, s.eligibility_for_itc
|
and month(posting_date) = %s and year(posting_date) = %s and company = %s
|
||||||
""",
|
and company_gstin = %s
|
||||||
(self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
|
group by eligibility_for_itc
|
||||||
|
""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1, debug=1)
|
||||||
|
|
||||||
itc_details = {}
|
itc_details = {}
|
||||||
|
for d in itc_amounts:
|
||||||
for d in itc_amount:
|
itc_details.setdefault(d.eligibility_for_itc, {
|
||||||
itc_details.setdefault((d.gst_category, d.eligibility_for_itc, d.reverse_charge, d.account_head),{
|
'iamt': d.itc_integrated_tax,
|
||||||
"amount": d.tax_amount
|
'camt': d.itc_central_tax,
|
||||||
|
'samt': d.itc_state_tax,
|
||||||
|
'csamt': d.itc_cess_amount
|
||||||
})
|
})
|
||||||
|
|
||||||
return itc_details
|
return itc_details
|
||||||
|
|
||||||
def get_nil_rated_supply_value(self):
|
def get_nil_rated_supply_value(self):
|
||||||
|
|
||||||
return frappe.db.sql("""
|
return frappe.db.sql("""
|
||||||
select sum(i.base_amount) as total from
|
select sum(i.base_amount) as total from
|
||||||
`tabSales Invoice Item` i, `tabSales Invoice` s
|
`tabSales Invoice Item` i, `tabSales Invoice` s
|
||||||
@@ -342,17 +320,9 @@ class GSTR3BReport(Document):
|
|||||||
'csamt': 0.0
|
'csamt': 0.0
|
||||||
})
|
})
|
||||||
|
|
||||||
if d.account_head in [a.cgst_account for a in self.account_heads]:
|
for key in ['camt', 'samt', 'iamt', 'csamt']:
|
||||||
inter_state_supply_tax_mapping[d.name]['camt'] += d.tax_amount
|
if d.account_head in self.account_heads.get(key):
|
||||||
|
inter_state_supply_tax_mapping[d.name][key] += d.tax_amount
|
||||||
if d.account_head in [a.sgst_account for a in self.account_heads]:
|
|
||||||
inter_state_supply_tax_mapping[d.name]['samt'] += d.tax_amount
|
|
||||||
|
|
||||||
if d.account_head in [a.igst_account for a in self.account_heads]:
|
|
||||||
inter_state_supply_tax_mapping[d.name]['iamt'] += d.tax_amount
|
|
||||||
|
|
||||||
if d.account_head in [a.cess_account for a in self.account_heads]:
|
|
||||||
inter_state_supply_tax_mapping[d.name]['csamt'] += d.tax_amount
|
|
||||||
|
|
||||||
for key, value in iteritems(inter_state_supply_tax_mapping):
|
for key, value in iteritems(inter_state_supply_tax_mapping):
|
||||||
if value.get('place_of_supply'):
|
if value.get('place_of_supply'):
|
||||||
@@ -408,7 +378,6 @@ class GSTR3BReport(Document):
|
|||||||
return inward_nil_exempt_details
|
return inward_nil_exempt_details
|
||||||
|
|
||||||
def get_tax_amounts(self, doctype, reverse_charge="N"):
|
def get_tax_amounts(self, doctype, reverse_charge="N"):
|
||||||
|
|
||||||
if doctype == "Sales Invoice":
|
if doctype == "Sales Invoice":
|
||||||
tax_template = 'Sales Taxes and Charges'
|
tax_template = 'Sales Taxes and Charges'
|
||||||
elif doctype == "Purchase Invoice":
|
elif doctype == "Purchase Invoice":
|
||||||
@@ -429,7 +398,7 @@ class GSTR3BReport(Document):
|
|||||||
|
|
||||||
for d in tax_amounts:
|
for d in tax_amounts:
|
||||||
tax_details.setdefault(
|
tax_details.setdefault(
|
||||||
(d.account_head,d.gst_category),{
|
(d.account_head, d.gst_category),{
|
||||||
"amount": d.get("tax_amount"),
|
"amount": d.get("tax_amount"),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -437,7 +406,6 @@ class GSTR3BReport(Document):
|
|||||||
return tax_details
|
return tax_details
|
||||||
|
|
||||||
def get_company_gst_details(self):
|
def get_company_gst_details(self):
|
||||||
|
|
||||||
gst_details = frappe.get_all("Address",
|
gst_details = frappe.get_all("Address",
|
||||||
fields=["gstin", "gst_state", "gst_state_number"],
|
fields=["gstin", "gst_state", "gst_state_number"],
|
||||||
filters={
|
filters={
|
||||||
@@ -450,20 +418,28 @@ class GSTR3BReport(Document):
|
|||||||
frappe.throw(_("Please enter GSTIN and state for the Company Address {0}").format(self.company_address))
|
frappe.throw(_("Please enter GSTIN and state for the Company Address {0}").format(self.company_address))
|
||||||
|
|
||||||
def get_account_heads(self):
|
def get_account_heads(self):
|
||||||
|
account_map = {
|
||||||
|
'sgst_account': 'samt',
|
||||||
|
'cess_account': 'csamt',
|
||||||
|
'cgst_account': 'camt',
|
||||||
|
'igst_account': 'iamt'
|
||||||
|
}
|
||||||
|
|
||||||
account_heads = frappe.get_all("GST Account",
|
account_heads = {}
|
||||||
fields=["cgst_account", "sgst_account", "igst_account", "cess_account"],
|
gst_settings_accounts = frappe.get_all("GST Account",
|
||||||
filters={
|
filters={'company': self.company, 'is_reverse_charge_account': 0},
|
||||||
"company":self.company
|
fields=["cgst_account", "sgst_account", "igst_account", "cess_account"])
|
||||||
})
|
|
||||||
|
|
||||||
if account_heads:
|
if not gst_settings_accounts:
|
||||||
return account_heads
|
frappe.throw(_("Please set GST Accounts in GST Settings"))
|
||||||
else:
|
|
||||||
frappe.throw(_("Please set account heads in GST Settings for Compnay {0}").format(self.company))
|
for d in gst_settings_accounts:
|
||||||
|
for acc, val in d.items():
|
||||||
|
account_heads.setdefault(account_map.get(acc), []).append(val)
|
||||||
|
|
||||||
|
return account_heads
|
||||||
|
|
||||||
def get_missing_field_invoices(self):
|
def get_missing_field_invoices(self):
|
||||||
|
|
||||||
missing_field_invoices = []
|
missing_field_invoices = []
|
||||||
|
|
||||||
for doctype in ["Sales Invoice", "Purchase Invoice"]:
|
for doctype in ["Sales Invoice", "Purchase Invoice"]:
|
||||||
@@ -488,13 +464,11 @@ class GSTR3BReport(Document):
|
|||||||
return ",".join(missing_field_invoices)
|
return ",".join(missing_field_invoices)
|
||||||
|
|
||||||
def get_state_code(state):
|
def get_state_code(state):
|
||||||
|
|
||||||
state_code = state_numbers.get(state)
|
state_code = state_numbers.get(state)
|
||||||
|
|
||||||
return state_code
|
return state_code
|
||||||
|
|
||||||
def get_period(month, year=None):
|
def get_period(month, year=None):
|
||||||
|
|
||||||
month_no = {
|
month_no = {
|
||||||
"January": 1,
|
"January": 1,
|
||||||
"February": 2,
|
"February": 2,
|
||||||
@@ -518,13 +492,11 @@ def get_period(month, year=None):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def view_report(name):
|
def view_report(name):
|
||||||
|
|
||||||
json_data = frappe.get_value("GSTR 3B Report", name, 'json_output')
|
json_data = frappe.get_value("GSTR 3B Report", name, 'json_output')
|
||||||
return json.loads(json_data)
|
return json.loads(json_data)
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_json(name):
|
def make_json(name):
|
||||||
|
|
||||||
json_data = frappe.get_value("GSTR 3B Report", name, 'json_output')
|
json_data = frappe.get_value("GSTR 3B Report", name, 'json_output')
|
||||||
file_name = "GST3B.json"
|
file_name = "GST3B.json"
|
||||||
frappe.local.response.filename = file_name
|
frappe.local.response.filename = file_name
|
||||||
|
|||||||
@@ -190,7 +190,8 @@ def make_custom_fields(update=True):
|
|||||||
purchase_invoice_itc_fields = [
|
purchase_invoice_itc_fields = [
|
||||||
dict(fieldname='eligibility_for_itc', label='Eligibility For ITC',
|
dict(fieldname='eligibility_for_itc', label='Eligibility For ITC',
|
||||||
fieldtype='Select', insert_after='reason_for_issuing_document', print_hide=1,
|
fieldtype='Select', insert_after='reason_for_issuing_document', print_hide=1,
|
||||||
options='Input Service Distributor\nImport Of Service\nImport Of Capital Goods\nITC on Reverse Charge\nIneligible\nAll Other ITC', default="All Other ITC"),
|
options='Input Service Distributor\nImport Of Service\nImport Of Capital Goods\nITC on Reverse Charge\nIneligible As Per Section 17(5)\nIneligible Others\nAll Other ITC',
|
||||||
|
default="All Other ITC"),
|
||||||
dict(fieldname='itc_integrated_tax', label='Availed ITC Integrated Tax',
|
dict(fieldname='itc_integrated_tax', label='Availed ITC Integrated Tax',
|
||||||
fieldtype='Data', insert_after='eligibility_for_itc', print_hide=1),
|
fieldtype='Data', insert_after='eligibility_for_itc', print_hide=1),
|
||||||
dict(fieldname='itc_central_tax', label='Availed ITC Central Tax',
|
dict(fieldname='itc_central_tax', label='Availed ITC Central Tax',
|
||||||
|
|||||||
Reference in New Issue
Block a user