diff --git a/models/doctype/GSTR3B/GSTR3B.js b/models/doctype/GSTR3B/GSTR3B.js new file mode 100644 index 00000000..42233400 --- /dev/null +++ b/models/doctype/GSTR3B/GSTR3B.js @@ -0,0 +1,76 @@ +const frappe = require('frappejs'); + +module.exports = { + name: 'GSTR3B', + doctype: 'DocType', + documentClass: require('./GSTR3BDocument.js'), + print: { + printFormat: 'GSTR3B Print Format' + }, + keywordFields: ['name', 'month', 'year'], + fields: [ + { + fieldname: 'year', + label: 'Year', + fieldtype: 'Data', + required: 1 + }, + { + fieldname: 'month', + label: 'Month', + fieldtype: 'Select', + options: [ + '', + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December' + ], + required: 1 + }, + { + fieldname: 'jsonData', + label: 'JSON Data', + fieldtype: 'Code', + formula: doc => doc.getJson(), + required: 1, + disabled: 1, + rows: 15 + } + ], + layout: [ + { + columns: [{ fields: ['year', 'month', 'jsonData'] }] + } + ], + links: [ + { + label: 'Print PDF', + condition: form => !form.doc._notInserted, + action: async form => { + form.$router.push({ + path: `/print/GSTR3B/${form.doc.name}` + }); + } + }, + { + label: 'Delete', + condition: form => !form.doc._notInserted, + action: async form => { + const doc = await frappe.getDoc('GSTR3B', form.doc.name); + await doc.delete(); + form.$router.push({ + path: `/list/GSTR3B` + }); + } + } + ] +}; diff --git a/models/doctype/GSTR3B/GSTR3BDocument.js b/models/doctype/GSTR3B/GSTR3BDocument.js new file mode 100644 index 00000000..9314caec --- /dev/null +++ b/models/doctype/GSTR3B/GSTR3BDocument.js @@ -0,0 +1,147 @@ +const BaseDocument = require('frappejs/model/document'); +const frappe = require('frappejs'); +const { format } = require('./GSTR3BFormat'); + +module.exports = class GSTR3B extends BaseDocument { + async getData() { + const monthIndex = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December' + ].indexOf(this.month); + const month = monthIndex + 1 > 9 ? monthIndex + 1 : `0${monthIndex + 1}`; + const lastDate = new Date(this.year, monthIndex + 1, 0).getDate(); + const filters = { + date: [ + '>=', + `${this.year}-${month}-01`, + '<=', + `${this.year}-${month}-${lastDate}` + ] + }; + const invoices = frappe.db.getAll({ + doctype: 'Invoice', + filters, + fields: ['*'] + }); + const bills = frappe.db.getAll({ + doctype: 'Bill', + filters, + fields: ['*'] + }); + const [gstr1Data, gstr2Data] = await Promise.all([invoices, bills]); + let gstr3bData = [[], []]; + + for (let ledgerEntry of gstr1Data) { + ledgerEntry.doctype = 'Invoice'; + gstr3bData[0].push(await this.makeGSTRow(ledgerEntry)); + } + for (let ledgerEntry of gstr2Data) { + ledgerEntry.doctype = 'Bill'; + gstr3bData[1].push(await this.makeGSTRow(ledgerEntry)); + } + + return gstr3bData; + } + + async makeGSTRow(ledgerEntry) { + let row = {}; + ledgerEntry = await frappe.getDoc(ledgerEntry.doctype, ledgerEntry.name); + let party = await frappe.getDoc( + 'Party', + ledgerEntry.customer || ledgerEntry.supplier + ); + if (party.address) { + let addressDetails = await frappe.getDoc('Address', party.address); + row.place = addressDetails.state || ''; + } + row.gstin = party.gstin; + row.partyName = ledgerEntry.customer || ledgerEntry.supplier; + row.invNo = ledgerEntry.name; + row.invDate = ledgerEntry.date; + row.rate = 0; + row.inState = true; + row.reverseCharge = !party.gstin ? 'Y' : 'N'; + ledgerEntry.taxes.forEach(tax => { + row.rate += tax.rate; + const taxAmt = (tax.rate * ledgerEntry.netTotal) / 100; + if (tax.account === 'IGST') row.igstAmt = taxAmt; + if (tax.account === 'IGST') row.inState = false; + if (tax.account === 'CGST') row.cgstAmt = taxAmt; + if (tax.account === 'SGST') row.sgstAmt = taxAmt; + if (tax.account === 'Nil Rated') row.nilRated = true; + if (tax.account === 'Exempt') row.exempt = true; + if (tax.account === 'Non GST') row.nonGST = true; + }); + row.invAmt = ledgerEntry.grandTotal; + row.taxVal = ledgerEntry.netTotal; + return row; + } + + async createJson(data) { + let jsonData = JSON.parse(JSON.stringify(format)); + + for (let ledgerEntry of data[0]) { + if (ledgerEntry.rate > 0) { + jsonData['sup_details']['osup_det']['samt'] += ledgerEntry.sgstAmt || 0; + jsonData['sup_details']['osup_det']['camt'] += ledgerEntry.cgstAmt || 0; + jsonData['sup_details']['osup_det']['iamt'] += ledgerEntry.igstAmt || 0; + jsonData['sup_details']['osup_det']['txval'] += ledgerEntry.taxVal; + } + if (ledgerEntry.rate === 0) { + jsonData['sup_details']['osup_zero']['txval'] += ledgerEntry.taxVal; + } + if (ledgerEntry.nilRated || ledgerEntry.exempt) { + jsonData['sup_details']['osup_nil_exmp']['txval'] += ledgerEntry.taxVal; + } + if (ledgerEntry.nonGST) { + jsonData['sup_details']['osup_nongst']['txval'] += ledgerEntry.taxVal; + } + if (!ledgerEntry.inState && !ledgerEntry.gstin) { + jsonData['inter_sup']['unreg_details'].push({ + pos: ledgerEntry.place, + txval: ledgerEntry.taxVal, + iAmt: ledgerEntry.igstAmt || 0 + }); + } + } + + for (let ledgerEntry of data[1]) { + if (ledgerEntry.reverseCharge === 'Y') { + jsonData['sup_details']['isup_rev']['samt'] += ledgerEntry.sgstAmt || 0; + jsonData['sup_details']['isup_rev']['camt'] += ledgerEntry.cgstAmt || 0; + jsonData['sup_details']['isup_rev']['iamt'] += ledgerEntry.igstAmt || 0; + jsonData['sup_details']['isup_rev']['txval'] += ledgerEntry.taxVal; + } + if (ledgerEntry.nilRated || ledgerEntry.exempt) { + jsonData['inward_sup']['isup_details'][0][ + ledgerEntry.inState ? 'intra' : 'inter' + ] += ledgerEntry.taxVal; + } + if (ledgerEntry.nonGST) { + jsonData['inward_sup']['isup_details'][0][ + ledgerEntry.inState ? 'intra' : 'inter' + ] += ledgerEntry.taxVal; + } + } + + return jsonData; + } + + async getJson() { + if (this.year && this.month) { + const data = await this.getData(); + const json = await this.createJson(data); + return JSON.stringify(json, undefined, 2); + } + } +}; diff --git a/models/doctype/GSTR3B/GSTR3BFormat.js b/models/doctype/GSTR3B/GSTR3BFormat.js new file mode 100644 index 00000000..2d995177 --- /dev/null +++ b/models/doctype/GSTR3B/GSTR3BFormat.js @@ -0,0 +1,390 @@ +const format = { + gstin: '', + ret_period: '', + inward_sup: { + isup_details: [ + { + ty: 'GST', + intra: 0, + inter: 0 + }, + { + ty: 'NONGST', + inter: 0, + intra: 0 + } + ] + }, + sup_details: { + osup_zero: { + csamt: 0, + txval: 0, + iamt: 0 + }, + osup_nil_exmp: { + txval: 0 + }, + osup_det: { + samt: 0, + csamt: 0, + txval: 0, + camt: 0, + iamt: 0 + }, + isup_rev: { + samt: 0, + csamt: 0, + txval: 0, + camt: 0, + iamt: 0 + }, + osup_nongst: { + txval: 0 + } + }, + inter_sup: { + unreg_details: [], + comp_details: [], + uin_details: [] + }, + itc_elg: { + itc_avl: [ + { + csamt: 0, + samt: 0, + ty: 'IMPG', + camt: 0, + iamt: 0 + }, + { + csamt: 0, + samt: 0, + ty: 'IMPS', + camt: 0, + iamt: 0 + }, + { + samt: 0, + csamt: 0, + ty: 'ISRC', + camt: 0, + iamt: 0 + }, + { + ty: 'ISD', + iamt: 0, + camt: 0, + samt: 0, + csamt: 0 + }, + { + samt: 0, + csamt: 0, + ty: 'OTH', + camt: 0, + iamt: 0 + } + ], + itc_rev: [ + { + ty: 'RUL', + iamt: 0, + camt: 0, + samt: 0, + csamt: 0 + }, + { + ty: 'OTH', + iamt: 0, + camt: 0, + samt: 0, + csamt: 0 + } + ], + itc_net: { + samt: 0, + csamt: 0, + camt: 0, + iamt: 0 + }, + itc_inelg: [ + { + ty: 'RUL', + iamt: 0, + camt: 0, + samt: 0, + csamt: 0 + }, + { + ty: 'OTH', + iamt: 0, + camt: 0, + samt: 0, + csamt: 0 + } + ] + } +}; + +function generateHTML(data) { + let template = ` +
Nature Of Supplies | +Total Taxable value | +Integrated Tax | +Central Tax | +State/UT Tax | +Cess | +
---|---|---|---|---|---|
(a) Outward taxable supplies(other than zero rated, nil rated and exempted | +${data.sup_details.osup_det.txval} | +${data.sup_details.osup_det.iamt} | +${data.sup_details.osup_det.camt} | +${data.sup_details.osup_det.samt} | +${data.sup_details.osup_det.csamt} | +
(b) Outward taxable supplies(zero rated) | +${data.sup_details.osup_zero.txval} | +${data.sup_details.osup_zero.iamt} | ++ | + | ${data.sup_details.osup_zero.csamt} | +
(b) Other outward supplies(Nil rated,Exempted) | +${data.sup_details.osup_nil_exmp.txval} | ++ | + | + | + |
(d) Inward Supplies(liable to reverse charge | +${data.sup_details.isup_rev.txval} | +${data.sup_details.isup_rev.iamt} | +${data.sup_details.isup_rev.camt} | +${data.sup_details.isup_rev.samt} | +${data.sup_details.isup_rev.csamt} | +
(e) Non-GST outward supplies | +${data.sup_details.osup_nongst.txval} | ++ | + | + | + |
+ | Place Of Supply (State/UT) | +Total Taxable Value | +Amount of Integrated Tax | +
---|---|---|---|
Supplies made to Unregistered Persons | +`;
+ for (let row of data.inter_sup.unreg_details) {
+ if (row) template += row.pos + ' '; + } + template += ' | ';
+ for (let row of data.inter_sup.unreg_details) {
+ if (row) template += row.txval + ' '; + } + template += ' | ';
+ for (let row of data.inter_sup.unreg_details) {
+ if (row) template += row.iamt + ' '; + } + + template += + ' |
Supplies made to Composition Taxable Persons | ';
+ for (let row of data.inter_sup.comp_details) {
+ if (row) template += row.pos + ' '; + } + template += ' | ';
+ for (let row of data.inter_sup.comp_details) {
+ if (row) template += row.txval + ' '; + } + template += ' | ';
+ for (let row of data.inter_sup.comp_details) {
+ if (row) template += row.iamt + ' '; + } + + template += + ' |
Supplies made to UIN holders | ';
+ for (let row of data.inter_sup.uin_details) {
+ if (row) template += row.pos + ' '; + } + template += ' | ';
+ for (let row of data.inter_sup.uin_details) {
+ if (row) template += row.txval + ' '; + } + template += ' | ';
+ for (let row of data.inter_sup.uin_details) {
+ if (row) template += row.iamt + ' '; + } + + template += ` |
+
Details | +Integrated Tax | +Central Tax | +State/UT tax | +Cess | +
---|---|---|---|---|
(A) ITC Available (whether in full op part) | ++ | + | + | + |
  (1) Import of goods | +${data.itc_elg.itc_avl[0].iamt} | +${data.itc_elg.itc_avl[0].camt} | +${data.itc_elg.itc_avl[0].samt} | +${data.itc_elg.itc_avl[0].csamt} | +
  (2) Import of services | +${data.itc_elg.itc_avl[1].iamt} | +${data.itc_elg.itc_avl[1].camt} | +${data.itc_elg.itc_avl[1].samt} | +${data.itc_elg.itc_avl[1].csamt} | +
  (3) Inward supplies liable to reverse charge (other than 1 & 2 above) | +${data.itc_elg.itc_avl[2].iamt} | +${data.itc_elg.itc_avl[2].camt} | +${data.itc_elg.itc_avl[2].samt} | +${data.itc_elg.itc_avl[2].csamt} | +
  (4) Inward supplies from ISD | +${data.itc_elg.itc_avl[3].iamt} | +${data.itc_elg.itc_avl[3].camt} | +${data.itc_elg.itc_avl[3].samt} | +${data.itc_elg.itc_avl[3].csamt} | +
  (5) All other ITC | +${data.itc_elg.itc_avl[4].iamt} | +${data.itc_elg.itc_avl[4].camt} | +${data.itc_elg.itc_avl[4].samt} | +${data.itc_elg.itc_avl[4].csamt} | +
(B) ITC Reversed | ++ | + | + | + |
  (1) As per rules 42 & 43 of CGST Rules | +${data.itc_elg.itc_rev[0].iamt} | +${data.itc_elg.itc_rev[0].camt} | +${data.itc_elg.itc_rev[0].samt} | +${data.itc_elg.itc_rev[0].csamt} | +
  (2) Others | +${data.itc_elg.itc_rev[1].iamt} | +${data.itc_elg.itc_rev[1].camt} | +${data.itc_elg.itc_rev[1].samt} | +${data.itc_elg.itc_rev[1].csamt} | +
(C) Net ITC Available(A) - (B) | +${data.itc_elg.itc_net.iamt} | +${data.itc_elg.itc_net.camt} | +${data.itc_elg.itc_net.samt} | +${data.itc_elg.itc_net.csamt} | +
(D) Ineligible ITC | ++ | + | + | + |
  (1) As per section 17(5) | +${data.itc_elg.itc_inelg[0].iamt} | +${data.itc_elg.itc_inelg[0].camt} | +${data.itc_elg.itc_inelg[0].samt} | +${data.itc_elg.itc_inelg[0].csamt} | +
  (2) Others | +${data.itc_elg.itc_inelg[1].iamt} | +${data.itc_elg.itc_inelg[1].camt} | +${data.itc_elg.itc_inelg[1].samt} | +${data.itc_elg.itc_inelg[1].csamt} | +
Nature of Supplies | +Inter-State Supplies | +Intra-State Supplies | +
---|---|---|
From a supplier under composition scheme, Exempt and Nil rated | +${data.inward_sup.isup_details[0].inter} | +${data.inward_sup.isup_details[0].intra} | +
Non GST Inward Supplies | +${data.inward_sup.isup_details[1].inter} | +${data.inward_sup.isup_details[1].intra} | +
Nature Of Supplies | +Total Taxable value | +Integrated Tax | +Central Tax | +State/UT Tax | +Cess | +
---|---|---|---|---|---|
(a) Outward taxable supplies(other than zero rated, nil rated and exempted | +{{ jsonData.sup_details.osup_det.txval }} | +{{ jsonData.sup_details.osup_det.iamt }} | +{{ jsonData.sup_details.osup_det.camt }} | +{{ jsonData.sup_details.osup_det.samt }} | +{{ jsonData.sup_details.osup_det.csamt }} | +
(b) Outward taxable supplies(zero rated) | +{{ jsonData.sup_details.osup_zero.txval }} | +{{ jsonData.sup_details.osup_zero.iamt }} | ++ | + | {{ jsonData.sup_details.osup_zero.csamt }} | +
(b) Other outward supplies(Nil rated,Exempted) | +{{ jsonData.sup_details.osup_nil_exmp.txval }} | ++ | + | + | + |
(d) Inward Supplies(liable to reverse charge | +{{ jsonData.sup_details.isup_rev.txval }} | +{{ jsonData.sup_details.isup_rev.iamt }} | +{{ jsonData.sup_details.isup_rev.camt }} | +{{ jsonData.sup_details.isup_rev.samt }} | +{{ jsonData.sup_details.isup_rev.csamt }} | +
(e) Non-GST outward supplies | +{{ jsonData.sup_details.osup_nongst.txval }} | ++ | + | + | + |
+ | Place Of Supply (State/UT) | +Total Taxable Value | +Amount of Integrated Tax | +
---|---|---|---|
Supplies made to Unregistered Persons | +
+
+
+ {{ row.pos }} + |
+
+
+
+ {{ row.txval }} + |
+
+
+
+ {{ row.iamt }} + |
+
Suppliies made to Composition Taxable Persons | +
+
+
+ {{ row.pos }} + |
+
+
+
+ {{ row.txval }} + |
+
+
+
+ {{ row.iamt }} + |
+
Supplies made to UIN holders | +
+
+
+ {{ row.pos }} + |
+
+
+
+ {{ row.txval }} + |
+
+
+
+ {{ row.iamt }} + |
+
Details | +Integrated Tax | +Central Tax | +State/UT tax | +Cess | +
---|---|---|---|---|
+ (A) ITC Available (whether in full op part) + | ++ | + | + | + |
(1) Import of goods | +{{ jsonData.itc_elg.itc_avl[0].iamt }} | +{{ jsonData.itc_elg.itc_avl[0].camt }} | +{{ jsonData.itc_elg.itc_avl[0].samt }} | +{{ jsonData.itc_elg.itc_avl[0].csamt }} | +
(2) Import of services | +{{ jsonData.itc_elg.itc_avl[1].iamt }} | +{{ jsonData.itc_elg.itc_avl[1].camt }} | +{{ jsonData.itc_elg.itc_avl[1].samt }} | +{{ jsonData.itc_elg.itc_avl[1].csamt }} | +
(3) Inward supplies liable to reverse charge (other than 1 & 2 above) | +{{ jsonData.itc_elg.itc_avl[2].iamt }} | +{{ jsonData.itc_elg.itc_avl[2].camt }} | +{{ jsonData.itc_elg.itc_avl[2].samt }} | +{{ jsonData.itc_elg.itc_avl[2].csamt }} | +
(4) Inward supplies from ISD | +{{ jsonData.itc_elg.itc_avl[3].iamt }} | +{{ jsonData.itc_elg.itc_avl[3].camt }} | +{{ jsonData.itc_elg.itc_avl[3].samt }} | +{{ jsonData.itc_elg.itc_avl[3].csamt }} | +
(5) All other ITC | +{{ jsonData.itc_elg.itc_avl[4].iamt }} | +{{ jsonData.itc_elg.itc_avl[4].camt }} | +{{ jsonData.itc_elg.itc_avl[4].samt }} | +{{ jsonData.itc_elg.itc_avl[4].csamt }} | +
+ (B) ITC Reversed + | ++ | + | + | + |
(1) As per rules 42 & 43 of CGST Rules | +{{ jsonData.itc_elg.itc_rev[0].iamt }} | +{{ jsonData.itc_elg.itc_rev[0].camt }} | +{{ jsonData.itc_elg.itc_rev[0].samt }} | +{{ jsonData.itc_elg.itc_rev[0].csamt }} | +
(2) Others | +{{ jsonData.itc_elg.itc_rev[1].iamt }} | +{{ jsonData.itc_elg.itc_rev[1].camt }} | +{{ jsonData.itc_elg.itc_rev[1].samt }} | +{{ jsonData.itc_elg.itc_rev[1].csamt }} | +
+ (C) Net ITC Available(A) - (B) + | +{{ jsonData.itc_elg.itc_net.iamt }} | +{{ jsonData.itc_elg.itc_net.camt }} | +{{ jsonData.itc_elg.itc_net.samt }} | +{{ jsonData.itc_elg.itc_net.csamt }} | +
+ (D) Ineligible ITC + | ++ | + | + | + |
(1) As per section 17(5) | +{{ jsonData.itc_elg.itc_inelg[0].iamt }} | +{{ jsonData.itc_elg.itc_inelg[0].camt }} | +{{ jsonData.itc_elg.itc_inelg[0].samt }} | +{{ jsonData.itc_elg.itc_inelg[0].csamt }} | +
(2) Others | +{{ jsonData.itc_elg.itc_inelg[1].iamt }} | +{{ jsonData.itc_elg.itc_inelg[1].camt }} | +{{ jsonData.itc_elg.itc_inelg[1].samt }} | +{{ jsonData.itc_elg.itc_inelg[1].csamt }} | +
Nature of Supplies | +Inter-State Supplies | +Intra-State Supplies | +
---|---|---|
From a supplier under composition scheme, Exempt and Nil rated | +{{ jsonData.inward_sup.isup_details[0].inter }} | +{{ jsonData.inward_sup.isup_details[0].intra }} | +
Non GST Inward Supplies | +{{ jsonData.inward_sup.isup_details[1].inter }} | +{{ jsonData.inward_sup.isup_details[1].intra }} | +