feat: GSTR1 json format download (#16887)

* feat: download gstr-1 b2b in json in its appropriate json format

* fix: download file as raw type

* feat: added logic to convert export gst data to its json

* code commonify and logic for b2cl added

* fix: Codacy and typo fixes

* fix: B2B json creation fixes

* fix: Filter customer by category

* fix: Fetch fp from to date
This commit is contained in:
Deepesh Garg 2019-03-29 22:22:54 +05:30 committed by Karthikeyan S
parent 706cf7d3d2
commit 56e23e7d47
2 changed files with 193 additions and 12 deletions

View File

@ -4,7 +4,7 @@
frappe.query_reports["GSTR-1"] = {
"filters": [
{
"fieldname":"company",
"fieldname": "company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
@ -12,22 +12,22 @@ frappe.query_reports["GSTR-1"] = {
"default": frappe.defaults.get_user_default("Company")
},
{
"fieldname":"company_address",
"fieldname": "company_address",
"label": __("Address"),
"fieldtype": "Link",
"options": "Address",
"get_query": function() {
"get_query": function () {
var company = frappe.query_report.get_filter_value('company');
if (company) {
return {
"query": 'frappe.contacts.doctype.address.address.address_query',
"filters": { link_doctype: 'Company', link_name: company}
"filters": { link_doctype: 'Company', link_name: company }
};
}
}
},
{
"fieldname":"from_date",
"fieldname": "from_date",
"label": __("From Date"),
"fieldtype": "Date",
"reqd": 1,
@ -35,19 +35,34 @@ frappe.query_reports["GSTR-1"] = {
"width": "80"
},
{
"fieldname":"to_date",
"fieldname": "to_date",
"label": __("To Date"),
"fieldtype": "Date",
"reqd": 1,
"default": frappe.datetime.get_today()
},
{
"fieldname":"type_of_business",
"fieldname": "type_of_business",
"label": __("Type of Business"),
"fieldtype": "Select",
"reqd": 1,
"options": ["B2B", "B2C Large", "B2C Small","CDNR", "EXPORT"],
"options": ["B2B", "B2C Large", "B2C Small", "CDNR", "EXPORT"],
"default": "B2B"
}
]
],
onload: function (report) {
report.page.add_inner_button(__("Download as Json"), function () {
var filters = report.get_values();
const args = {
cmd: 'erpnext.regional.report.gstr_1.gstr_1.get_json',
data: report.data,
report_name: report.report_name,
filters: filters
};
open_url_post(frappe.request.url, args);
});
}
}

View File

@ -4,9 +4,10 @@
from __future__ import unicode_literals
import frappe, json
from frappe import _
from frappe.utils import flt, formatdate
from frappe.utils import flt, formatdate, now_datetime, getdate
from datetime import date
from six import iteritems
from erpnext.regional.doctype.gstr_3b_report.gstr_3b_report import get_period
def execute(filters=None):
return Gstr1Report(filters).run()
@ -38,7 +39,7 @@ class Gstr1Report(object):
shipping_bill_date,
reason_for_issuing_document
"""
self.customer_type = "Company" if self.filters.get("type_of_business") == "B2B" else "Individual"
# self.customer_type = "Company" if self.filters.get("type_of_business") == "B2B" else "Individual"
def run(self):
self.get_columns()
@ -113,9 +114,14 @@ class Gstr1Report(object):
if self.filters.get(opts[0]):
conditions += opts[1]
customers = frappe.get_all("Customer", filters={"customer_type": self.customer_type})
# customers = frappe.get_all("Customer", filters={"customer_type": self.customer_type})
if self.filters.get("type_of_business") == "B2B":
customers = frappe.get_all("Customer",
filters={
"gst_category": ["in", ["Registered Regular", "Deemed Export", "SEZ"]]
})
conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1
and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers]))
@ -124,6 +130,11 @@ class Gstr1Report(object):
if not b2c_limit:
frappe.throw(_("Please set B2C Limit in GST Settings."))
customers = frappe.get_all("Customer",
filters={
"gst_category": ["in", ["Unregistered"]]
})
if self.filters.get("type_of_business") == "B2C Large":
conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
and grand_total > {0} and is_return != 1 and customer in ({1})""".\
@ -494,3 +505,158 @@ class Gstr1Report(object):
}
]
self.columns = self.invoice_columns + self.tax_columns + self.other_columns
@frappe.whitelist()
def get_json():
data = frappe._dict(frappe.local.form_dict)
del data["cmd"]
if "csrf_token" in data:
del data["csrf_token"]
filters = json.loads(data["filters"])
report_data = json.loads(data["data"])
report_name = data["report_name"]
gstin = get_company_gstin_number(filters["company"])
fp = "%02d%s" % (getdate(filters["to_date"]).month, getdate(filters["to_date"]).year)
gst_json = {"gstin": "", "version": "GST2.2.9",
"hash": "hash", "gstin": gstin, "fp": fp}
res = {}
if filters["type_of_business"] == "B2B":
for item in report_data:
res.setdefault(item["customer_gstin"], {}).setdefault(item["invoice_number"],[]).append(item)
out = get_b2b_json(res, gstin)
gst_json["b2b"] = out
elif filters["type_of_business"] == "B2C Large":
for item in report_data:
res.setdefault(item["place_of_supply"], []).append(item)
out = get_b2cl_json(res, gstin)
gst_json["b2cl"] = out
elif filters["type_of_business"] == "EXPORT":
for item in report_data:
res.setdefault(item["export_type"], []).append(item)
out = get_export_json(res)
gst_json["exp"] = out
download_json_file(report_name, filters["type_of_business"], gst_json)
def get_b2b_json(res, gstin):
inv_type, out = {"Registered Regular": "R", "Deemed Export": "DE", "URD": "URD", "SEZ": "SEZ"}, []
for gst_in in res:
b2b_item, inv = {"ctin": gst_in, "inv": []}, []
if not gst_in: continue
for number, invoice in iteritems(res[gst_in]):
inv_item = get_basic_invoice_detail(invoice[0])
inv_item["pos"] = "%02d" % int(invoice[0]["place_of_supply"].split('-')[0])
inv_item["rchrg"] = invoice[0]["reverse_charge"]
inv_item["inv_typ"] = inv_type.get(invoice[0].get("gst_category", ""),"")
if inv_item["pos"]=="00": continue
inv_item["itms"] = []
for item in invoice:
inv_item["itms"].append(get_rate_and_tax_details(item, gstin))
inv.append(inv_item)
if not inv: continue
b2b_item["inv"] = inv
out.append(b2b_item)
return out
def get_b2cl_json(res, gstin):
out = []
for pos in res:
b2cl_item, inv = {"pos": "%02d" % int(pos.split('-')[0]), "inv": []}, []
for row in res[pos]:
inv_item = get_basic_invoice_detail(row)
if row.get("sale_from_bonded_wh"):
inv_item["inv_typ"] = "CBW"
inv_item["itms"] = [get_rate_and_tax_details(row, gstin)]
inv.append(inv_item)
b2cl_item["inv"] = inv
out.append(b2cl_item)
return out
def get_export_json(res):
out = []
for exp_type in res:
exp_item, inv = {"exp_typ": exp_type, "inv": []}, []
for row in res[exp_type]:
inv_item = get_basic_invoice_detail(row)
inv_item["itms"] = [{
"txval": flt(row["taxable_value"], 2),
"rt": row["rate"] or 0,
"iamt": 0,
"csamt": 0
}]
inv.append(inv_item)
exp_item["inv"] = inv
out.append(exp_item)
return out
def get_basic_invoice_detail(row):
return {
"inum": row["invoice_number"],
"idt": getdate(row["posting_date"]).strftime('%d-%m-%Y'),
"val": flt(row["invoice_value"], 2)
}
def get_rate_and_tax_details(row, gstin):
itm_det = {"txval": flt(row["taxable_value"], 2),
"rt": row["rate"],
"csamt": (flt(row.get("cess_amount"), 2) or 0)
}
# calculate rate
num = 1 if not row["rate"] else "%d%02d" % (row["rate"], 1)
rate = row.get("rate") or 0
# calculate tax amount added
tax = flt((row["taxable_value"]*rate)/100.0, 2)
frappe.errprint([tax, tax/2])
if row.get("customer_gstin") and gstin[0:2] == row["customer_gstin"][0:2]:
itm_det.update({"camt": flt(tax/2.0, 2), "samt": flt(tax/2.0, 2)})
else:
itm_det.update({"iamt": tax})
return {"num": int(num), "itm_det": itm_det}
def get_company_gstin_number(company):
filters = [
["is_your_company_address", "=", 1],
["Dynamic Link", "link_doctype", "=", "Company"],
["Dynamic Link", "link_name", "=", company],
["Dynamic Link", "parenttype", "=", "Address"],
]
gstin = frappe.get_all("Address", filters=filters, fields=["gstin"])
if gstin:
return gstin[0]["gstin"]
else:
frappe.throw(_("No GST No. found for the Company."))
def download_json_file(filename, report_type, data):
''' download json content in a file '''
frappe.response['filename'] = frappe.scrub("{0} {1}".format(filename, report_type)) + '.json'
frappe.response['filecontent'] = json.dumps(data)
frappe.response['content_type'] = 'application/json'
frappe.response['type'] = 'download'