mirror of
https://github.com/frappe/books.git
synced 2024-12-23 03:19:01 +00:00
- GSTR1, GSTR2, GSTR3B Reports
- Message Dialog - Handle Error in Form Submit and Revert - Report Filter Custom Doc
This commit is contained in:
parent
472451203c
commit
ed164a492e
76
models/doctype/GSTR3B/GSTR3B.js
Normal file
76
models/doctype/GSTR3B/GSTR3B.js
Normal file
@ -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`
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
147
models/doctype/GSTR3B/GSTR3BDocument.js
Normal file
147
models/doctype/GSTR3B/GSTR3BDocument.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
390
models/doctype/GSTR3B/GSTR3BFormat.js
Normal file
390
models/doctype/GSTR3B/GSTR3BFormat.js
Normal file
@ -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 = `
|
||||
<div class="p-5 m-5" style="font-size: 14px !important">
|
||||
<div>
|
||||
<h3 class="text-center">GSTR3B-Form</h3>
|
||||
<h5>GSTIN:   ${data.gstin}</h5>
|
||||
<h5>Period:   ${data.ret_period}</h5>
|
||||
</div>
|
||||
|
||||
<h5>3.1  Details of Outward Supplies and inward supplies liable to reverse charge</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nature Of Supplies</th>
|
||||
<th>Total Taxable value</th>
|
||||
<th>Integrated Tax</th>
|
||||
<th>Central Tax</th>
|
||||
<th>State/UT Tax</th>
|
||||
<th>Cess</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>(a) Outward taxable supplies(other than zero rated, nil rated and exempted</td>
|
||||
<td class="right">${data.sup_details.osup_det.txval}</td>
|
||||
<td class="right">${data.sup_details.osup_det.iamt}</td>
|
||||
<td class="right">${data.sup_details.osup_det.camt}</td>
|
||||
<td class="right">${data.sup_details.osup_det.samt}</td>
|
||||
<td class="right">${data.sup_details.osup_det.csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(b) Outward taxable supplies(zero rated)</td>
|
||||
<td class="right">${data.sup_details.osup_zero.txval}</td>
|
||||
<td class="right">${data.sup_details.osup_zero.iamt}</td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
<td class="right">${data.sup_details.osup_zero.csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(b) Other outward supplies(Nil rated,Exempted)</td>
|
||||
<td class="right">${data.sup_details.osup_nil_exmp.txval}</td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
<tr>
|
||||
<td>(d) Inward Supplies(liable to reverse charge</td>
|
||||
<td class="right">${data.sup_details.isup_rev.txval}</td>
|
||||
<td class="right">${data.sup_details.isup_rev.iamt}</td>
|
||||
<td class="right">${data.sup_details.isup_rev.camt}</td>
|
||||
<td class="right">${data.sup_details.isup_rev.samt}</td>
|
||||
<td class="right">${data.sup_details.isup_rev.csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(e) Non-GST outward supplies</td>
|
||||
<td class="right">${data.sup_details.osup_nongst.txval}</td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
<td style="background-color:#d9d9d9;"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5>
|
||||
3.2  Of the supplies shown in 3.1 (a) above, details of inter-State supplies made to unregisterd
|
||||
persons, composition taxable persons and UIN holders
|
||||
</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Place Of Supply (State/UT)</th>
|
||||
<th>Total Taxable Value</th>
|
||||
<th>Amount of Integrated Tax</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Supplies made to Unregistered Persons</td>
|
||||
<td class="right">`;
|
||||
for (let row of data.inter_sup.unreg_details) {
|
||||
if (row) template += row.pos + '<br>';
|
||||
}
|
||||
template += '</td><td class="right">';
|
||||
for (let row of data.inter_sup.unreg_details) {
|
||||
if (row) template += row.txval + '<br>';
|
||||
}
|
||||
template += '</td><td class="right">';
|
||||
for (let row of data.inter_sup.unreg_details) {
|
||||
if (row) template += row.iamt + '<br>';
|
||||
}
|
||||
|
||||
template +=
|
||||
'</td></tr><tr><td>Supplies made to Composition Taxable Persons</td><td class="right">';
|
||||
for (let row of data.inter_sup.comp_details) {
|
||||
if (row) template += row.pos + '<br>';
|
||||
}
|
||||
template += '</td><td class="right">';
|
||||
for (let row of data.inter_sup.comp_details) {
|
||||
if (row) template += row.txval + '<br>';
|
||||
}
|
||||
template += '</td><td class="right">';
|
||||
for (let row of data.inter_sup.comp_details) {
|
||||
if (row) template += row.iamt + '<br>';
|
||||
}
|
||||
|
||||
template +=
|
||||
'</td></tr><tr><td>Supplies made to UIN holders</td><td class="right">';
|
||||
for (let row of data.inter_sup.uin_details) {
|
||||
if (row) template += row.pos + '<br>';
|
||||
}
|
||||
template += '</td><td class="right">';
|
||||
for (let row of data.inter_sup.uin_details) {
|
||||
if (row) template += row.txval + '<br>';
|
||||
}
|
||||
template += '</td><td class="right">';
|
||||
for (let row of data.inter_sup.uin_details) {
|
||||
if (row) template += row.iamt + '<br>';
|
||||
}
|
||||
|
||||
template += `</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5>4.   Eligible ITC</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<th>Integrated Tax</th>
|
||||
<th>Central Tax</th>
|
||||
<th>State/UT tax</th>
|
||||
<th>Cess</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>(A) ITC Available (whether in full op part)</b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (1) Import of goods </td>
|
||||
<td class="right">${data.itc_elg.itc_avl[0].iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[0].camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[0].samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[0].csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (2) Import of services</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[1].iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[1].camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[1].samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[1].csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (3) Inward supplies liable to reverse charge (other than 1 & 2 above)</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[2].iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[2].camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[2].samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[2].csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (4) Inward supplies from ISD</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[3].iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[3].camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[3].samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[3].csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (5) All other ITC</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[4].iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[4].camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[4].samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_avl[4].csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>(B) ITC Reversed</b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (1) As per rules 42 & 43 of CGST Rules</td>
|
||||
<td class="right">${data.itc_elg.itc_rev[0].iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_rev[0].camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_rev[0].samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_rev[0].csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (2) Others</td>
|
||||
<td class="right">${data.itc_elg.itc_rev[1].iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_rev[1].camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_rev[1].samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_rev[1].csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>(C) Net ITC Available(A) - (B)</b></td>
|
||||
<td class="right">${data.itc_elg.itc_net.iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_net.camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_net.samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_net.csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>(D) Ineligible ITC</b></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (1) As per section 17(5)</td>
|
||||
<td class="right">${data.itc_elg.itc_inelg[0].iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_inelg[0].camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_inelg[0].samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_inelg[0].csamt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>  (2) Others</td>
|
||||
<td class="right">${data.itc_elg.itc_inelg[1].iamt}</td>
|
||||
<td class="right">${data.itc_elg.itc_inelg[1].camt}</td>
|
||||
<td class="right">${data.itc_elg.itc_inelg[1].samt}</td>
|
||||
<td class="right">${data.itc_elg.itc_inelg[1].csamt}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5>5.    Values of exempt, nil rated and non-GST inward supplies</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nature of Supplies</th>
|
||||
<th>Inter-State Supplies</th>
|
||||
<th>Intra-State Supplies</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>From a supplier under composition scheme, Exempt and Nil rated</td>
|
||||
<td class="right">${data.inward_sup.isup_details[0].inter}</td>
|
||||
<td class="right">${data.inward_sup.isup_details[0].intra}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Non GST Inward Supplies</td>
|
||||
<td class="right">${data.inward_sup.isup_details[1].inter}</td>
|
||||
<td class="right">${data.inward_sup.isup_details[1].intra}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>`;
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
format
|
||||
};
|
7
models/doctype/GSTR3B/GSTR3BList.js
Normal file
7
models/doctype/GSTR3B/GSTR3BList.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { _ } from 'frappejs/utils';
|
||||
|
||||
export default {
|
||||
doctype: 'GSTR3B',
|
||||
title: _('GSTR 3B Report'),
|
||||
columns: ['year', 'month']
|
||||
};
|
304
models/doctype/GSTR3B/GSTR3BPrintView.vue
Normal file
304
models/doctype/GSTR3B/GSTR3BPrintView.vue
Normal file
@ -0,0 +1,304 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row no-gutters">
|
||||
<div class="col-8 mx-auto text-right mt-4">
|
||||
<f-button primary @click="$emit('makePDF', $refs.printComponent.innerHTML)">{{ _('PDF') }}</f-button>
|
||||
</div>
|
||||
</div>
|
||||
<div ref="printComponent" class="col-8 bg-white mt-4 mx-auto border shadow">
|
||||
<div class="print-format" style="padding: 3.5rem;">
|
||||
<div>
|
||||
<h3 class="text-center">GSTR3B-Form</h3>
|
||||
<h5>GSTIN: {{ jsonData.gstin }}</h5>
|
||||
<h5>Period: {{ jsonData.ret_period }}</h5>
|
||||
</div>
|
||||
|
||||
<h5>3.1 Details of Outward Supplies and inward supplies liable to reverse charge</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nature Of Supplies</th>
|
||||
<th>Total Taxable value</th>
|
||||
<th>Integrated Tax</th>
|
||||
<th>Central Tax</th>
|
||||
<th>State/UT Tax</th>
|
||||
<th>Cess</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>(a) Outward taxable supplies(other than zero rated, nil rated and exempted</td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_det.txval }}</td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_det.iamt }}</td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_det.camt }}</td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_det.samt }}</td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_det.csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(b) Outward taxable supplies(zero rated)</td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_zero.txval }}</td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_zero.iamt }}</td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_zero.csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(b) Other outward supplies(Nil rated,Exempted)</td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_nil_exmp.txval }}</td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(d) Inward Supplies(liable to reverse charge</td>
|
||||
<td class="right">{{ jsonData.sup_details.isup_rev.txval }}</td>
|
||||
<td class="right">{{ jsonData.sup_details.isup_rev.iamt }}</td>
|
||||
<td class="right">{{ jsonData.sup_details.isup_rev.camt }}</td>
|
||||
<td class="right">{{ jsonData.sup_details.isup_rev.samt }}</td>
|
||||
<td class="right">{{ jsonData.sup_details.isup_rev.csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>(e) Non-GST outward supplies</td>
|
||||
<td class="right">{{ jsonData.sup_details.osup_nongst.txval }}</td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
<td class="disabled"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5>3.2 Of the supplies shown in 3.1 (a) above, details of inter-State supplies made to unregisterd persons, composition taxable persons and UIN holders</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Place Of Supply (State/UT)</th>
|
||||
<th>Total Taxable Value</th>
|
||||
<th>Amount of Integrated Tax</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Supplies made to Unregistered Persons</td>
|
||||
<td class="right">
|
||||
<div v-for="(row, i) in jsonData.inter_sup.unreg_details" :key="i">
|
||||
<p>{{ row.pos }}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class="right">
|
||||
<div v-for="(row, i) in jsonData.inter_sup.unreg_details" :key="i">
|
||||
<p>{{ row.txval }}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class="right">
|
||||
<div v-for="(row, i) in jsonData.inter_sup.unreg_details" :key="i">
|
||||
<p>{{ row.iamt }}</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Suppliies made to Composition Taxable Persons</td>
|
||||
<td class="right">
|
||||
<div v-for="(row, i) in jsonData.inter_sup.comp_details" :key="i">
|
||||
<p>{{ row.pos }}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class="right">
|
||||
<div v-for="(row, i) in jsonData.inter_sup.comp_details" :key="i">
|
||||
<p>{{ row.txval }}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class="right">
|
||||
<div v-for="(row, i) in jsonData.inter_sup.comp_details" :key="i">
|
||||
<p>{{ row.iamt }}</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Supplies made to UIN holders</td>
|
||||
<td class="right">
|
||||
<div v-for="(row, i) in jsonData.inter_sup.uin_details" :key="i">
|
||||
<p>{{ row.pos }}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class="right">
|
||||
<div v-for="(row, i) in jsonData.inter_sup.uin_details" :key="i">
|
||||
<p>{{ row.txval }}</p>
|
||||
</div>
|
||||
</td>
|
||||
<td class="right">
|
||||
<div v-for="(row, i) in jsonData.inter_sup.uin_details" :key="i">
|
||||
<p>{{ row.iamt }}</p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5>4. Eligible ITC</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Details</th>
|
||||
<th>Integrated Tax</th>
|
||||
<th>Central Tax</th>
|
||||
<th>State/UT tax</th>
|
||||
<th>Cess</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<b>(A) ITC Available (whether in full op part)</b>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> (1) Import of goods</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[0].iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[0].camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[0].samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[0].csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> (2) Import of services</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[1].iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[1].camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[1].samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[1].csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> (3) Inward supplies liable to reverse charge (other than 1 & 2 above)</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[2].iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[2].camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[2].samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[2].csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> (4) Inward supplies from ISD</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[3].iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[3].camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[3].samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[3].csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> (5) All other ITC</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[4].iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[4].camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[4].samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_avl[4].csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>(B) ITC Reversed</b>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> (1) As per rules 42 & 43 of CGST Rules</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_rev[0].iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_rev[0].camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_rev[0].samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_rev[0].csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> (2) Others</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_rev[1].iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_rev[1].camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_rev[1].samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_rev[1].csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>(C) Net ITC Available(A) - (B)</b>
|
||||
</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_net.iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_net.camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_net.samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_net.csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<b>(D) Ineligible ITC</b>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> (1) As per section 17(5)</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_inelg[0].iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_inelg[0].camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_inelg[0].samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_inelg[0].csamt }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> (2) Others</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_inelg[1].iamt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_inelg[1].camt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_inelg[1].samt }}</td>
|
||||
<td class="right">{{ jsonData.itc_elg.itc_inelg[1].csamt }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h5>5. Values of exempt, nil rated and non-GST inward supplies</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nature of Supplies</th>
|
||||
<th>Inter-State Supplies</th>
|
||||
<th>Intra-State Supplies</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>From a supplier under composition scheme, Exempt and Nil rated</td>
|
||||
<td class="right">{{ jsonData.inward_sup.isup_details[0].inter }}</td>
|
||||
<td class="right">{{ jsonData.inward_sup.isup_details[0].intra }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Non GST Inward Supplies</td>
|
||||
<td class="right">{{ jsonData.inward_sup.isup_details[1].inter }}</td>
|
||||
<td class="right">{{ jsonData.inward_sup.isup_details[1].intra }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'GSTR3BPrintView',
|
||||
props: ['doc'],
|
||||
computed: {
|
||||
jsonData() {
|
||||
return JSON.parse(this.doc.jsonData);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.print-format {
|
||||
font-size: 8pt !important;
|
||||
}
|
||||
.disabled {
|
||||
background-color: #d9d9d9;
|
||||
}
|
||||
.right {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
19
models/doctype/GSTR3B/GSTR3BServer.js
Normal file
19
models/doctype/GSTR3B/GSTR3BServer.js
Normal file
@ -0,0 +1,19 @@
|
||||
const GSTR3B = require('./GSTR3BDocument');
|
||||
|
||||
module.exports = class GSTR3BServer extends GSTR3B {
|
||||
async validate() {
|
||||
if (this.month.length === 0 || this.year.length != 4) {
|
||||
frappe.call({
|
||||
method: 'show_dialog',
|
||||
args: {
|
||||
title: 'Invalid Entry',
|
||||
message: `Month or Year is not valid`
|
||||
}
|
||||
});
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
async beforeInsert() {
|
||||
this.name = `${this.doctype} Report ${this.month} ${this.year}`;
|
||||
}
|
||||
};
|
@ -1,60 +1,89 @@
|
||||
<template>
|
||||
<component :themeColor="color" :font="fontFamily" :is="invoiceTemplate" v-if="doc" :doc="doc"/>
|
||||
<div>
|
||||
<div class="row no-gutters">
|
||||
<div v-if="showInvoiceCustomizer" class="col-3 mt-4 mx-auto"></div>
|
||||
<div class="col-8 mx-auto text-right mt-4">
|
||||
<f-button primary @click="$emit('send', $refs.printComponent.innerHTML)">{{ _('Send') }}</f-button>
|
||||
<f-button secondary @click="toggleCustomizer">{{ _('Customize') }}</f-button>
|
||||
<f-button secondary @click="$emit('makePDF', $refs.printComponent.innerHTML)">{{ _('PDF') }}</f-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row no-gutters">
|
||||
<div v-if="showInvoiceCustomizer" class="col-3 mt-4 mx-auto">
|
||||
<invoice-customizer
|
||||
class="border"
|
||||
style="position: fixed"
|
||||
@closeInvoiceCustomizer="toggleCustomizer"
|
||||
@changeColor="changeColor($event)"
|
||||
@changeTemplate="changeTemplate($event)"
|
||||
@changeFont="changeFont($event)"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-8 bg-white mt-4 mx-auto border shadow" ref="printComponent">
|
||||
<component :themeColor="themeColor" :font="font" :is="template" v-if="doc" :doc="doc" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import InvoiceTemplate1 from '@/../models/doctype/Invoice/Templates/InvoiceTemplate1';
|
||||
import InvoiceTemplate2 from '@/../models/doctype/Invoice/Templates/InvoiceTemplate2';
|
||||
import InvoiceTemplate3 from '@/../models/doctype/Invoice/Templates/InvoiceTemplate3';
|
||||
import InvoiceCustomizer from '@/components/InvoiceCustomizer';
|
||||
|
||||
const invoiceTemplates = {
|
||||
'Basic I': InvoiceTemplate1,
|
||||
'Basic II': InvoiceTemplate2,
|
||||
'Modern': InvoiceTemplate3
|
||||
Modern: InvoiceTemplate3
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'InvoicePrint',
|
||||
props: ['doc', 'themeColor', 'template', 'font'],
|
||||
props: ['doc'],
|
||||
components: {
|
||||
InvoiceCustomizer
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
color: undefined,
|
||||
fontFamily: undefined,
|
||||
invoiceTemplate: undefined
|
||||
showInvoiceCustomizer: false,
|
||||
themeColor: undefined,
|
||||
template: undefined,
|
||||
font: undefined
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
themeColor: async function() {
|
||||
await this.loadInvoice();
|
||||
},
|
||||
font: async function() {
|
||||
await this.loadInvoice();
|
||||
},
|
||||
template: async function() {
|
||||
await this.loadInvoice();
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
await this.loadInvoice();
|
||||
},
|
||||
methods: {
|
||||
async loadInvoice() {
|
||||
this.color = this.themeColor !== undefined ? this.themeColor : await this.getColor();
|
||||
this.fontFamily = this.font !== undefined ? this.font : await this.getFont();
|
||||
let template = this.template !== undefined ? this.template : await this.getTemplate();
|
||||
let templateFile = invoiceTemplates[template];
|
||||
this.invoiceTemplate = templateFile;
|
||||
await this.getTemplate();
|
||||
await this.getColor();
|
||||
await this.getFont();
|
||||
},
|
||||
async getTemplate() {
|
||||
let invoiceSettings = await frappe.getDoc('InvoiceSettings');
|
||||
return invoiceSettings.template;
|
||||
this.template = invoiceTemplates[invoiceSettings.template];
|
||||
},
|
||||
async getColor() {
|
||||
let invoiceSettings = await frappe.getDoc('InvoiceSettings');
|
||||
return invoiceSettings.themeColor;
|
||||
this.themeColor = invoiceSettings.themeColor;
|
||||
},
|
||||
async getFont() {
|
||||
let invoiceSettings = await frappe.getDoc('InvoiceSettings');
|
||||
return invoiceSettings.font;
|
||||
this.font = invoiceSettings.font;
|
||||
},
|
||||
async toggleCustomizer() {
|
||||
await this.loadInvoice();
|
||||
this.showInvoiceCustomizer = !this.showInvoiceCustomizer;
|
||||
},
|
||||
async changeColor(color) {
|
||||
this.themeColor = color;
|
||||
},
|
||||
async changeTemplate(template) {
|
||||
this.template = invoiceTemplates[template];
|
||||
},
|
||||
async changeFont(font) {
|
||||
this.font = font;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -12,7 +12,8 @@ module.exports = class PaymentServer extends BaseDocument {
|
||||
return entries;
|
||||
}
|
||||
|
||||
async afterSubmit() {
|
||||
async beforeSubmit() {
|
||||
if (this.for.length > 0)
|
||||
for (let row of this.for) {
|
||||
if (['Invoice', 'Bill'].includes(row.referenceType)) {
|
||||
let { outstandingAmount, grandTotal } = await frappe.getDoc(
|
||||
@ -21,24 +22,43 @@ module.exports = class PaymentServer extends BaseDocument {
|
||||
);
|
||||
if (outstandingAmount === null) {
|
||||
outstandingAmount = grandTotal;
|
||||
console.log('Outstanding null');
|
||||
}
|
||||
if (this.amount > outstandingAmount) {
|
||||
console.log('Over Payment');
|
||||
frappe.call({
|
||||
method: 'show_dialog',
|
||||
args: {
|
||||
title: 'Invalid Payment Entry',
|
||||
message: `Payment amount is greater than Outstanding amount by \
|
||||
${this.amount - outstandingAmount}`
|
||||
}
|
||||
});
|
||||
throw new Error();
|
||||
} else {
|
||||
console.log('Payment Done');
|
||||
await frappe.db.setValue(
|
||||
row.referenceType,
|
||||
row.referenceName,
|
||||
'outstandingAmount',
|
||||
outstandingAmount - this.amount
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
frappe.call({
|
||||
method: 'show_dialog',
|
||||
args: {
|
||||
title: 'Invalid Payment Entry',
|
||||
message: `No reference for the payment.`
|
||||
}
|
||||
});
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
|
||||
async afterSubmit() {
|
||||
const entries = await this.getPosting();
|
||||
await entries.post();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async afterRevert() {
|
||||
const entries = await this.getPosting();
|
||||
|
@ -25,6 +25,8 @@ module.exports = {
|
||||
TaxDetail: require('./doctype/TaxDetail/TaxDetail.js'),
|
||||
TaxSummary: require('./doctype/TaxSummary/TaxSummary.js'),
|
||||
|
||||
GSTR3B: require('./doctype/GSTR3B/GSTR3B.js'),
|
||||
|
||||
Address: require('./doctype/Address/Address.js'),
|
||||
Contact: require('./doctype/Contact/Contact.js'),
|
||||
|
||||
@ -57,6 +59,6 @@ module.exports = {
|
||||
EventSettings: require('./doctype/EventSettings/EventSettings'),
|
||||
|
||||
Email: require('./doctype/Email/Email'),
|
||||
EmailAccount: require('./doctype/EmailAccount/EmailAccount'),
|
||||
EmailAccount: require('./doctype/EmailAccount/EmailAccount')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
68
reports/GoodsAndServiceTax/BaseGSTR.js
Normal file
68
reports/GoodsAndServiceTax/BaseGSTR.js
Normal file
@ -0,0 +1,68 @@
|
||||
const frappe = require('frappejs');
|
||||
|
||||
class BaseGSTR {
|
||||
async getCompleteReport(gstrType, filters) {
|
||||
if (['GSTR-1', 'GSTR-2'].includes(gstrType)) {
|
||||
let entries = await frappe.db.getAll({
|
||||
doctype: gstrType === 'GSTR-1' ? 'Invoice' : 'Bill',
|
||||
filters
|
||||
});
|
||||
|
||||
let tableData = [];
|
||||
for (let entry of entries) {
|
||||
entry.doctype = gstrType === 'GSTR-1' ? 'Invoice' : 'Bill';
|
||||
const row = await this.getRow(entry);
|
||||
tableData.push(row);
|
||||
}
|
||||
|
||||
if (Object.keys(filters).length != 0) {
|
||||
tableData = tableData.filter(row => {
|
||||
if (filters.account) return row.account === filters.account;
|
||||
if (filters.transferType)
|
||||
return row.transferType === filters.transferType;
|
||||
if (filters.place) return row.place === filters.place;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return tableData;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async getRow(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;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseGSTR;
|
@ -1,14 +1,5 @@
|
||||
const title = 'Goods and Service Tax';
|
||||
module.exports = {
|
||||
title: title,
|
||||
method: 'gst-taxes',
|
||||
filterFields: [
|
||||
{
|
||||
fieldtype: 'Select',
|
||||
label: 'Report Type',
|
||||
fieldname: 'reportType',
|
||||
options: ['', 'GSTR-1', 'GSTR-2', 'GSTR-3B']
|
||||
},
|
||||
{
|
||||
fieldtype: 'Select',
|
||||
label: 'Transfer Type',
|
||||
@ -35,6 +26,13 @@ module.exports = {
|
||||
fieldtype: 'Date',
|
||||
label: 'To Date',
|
||||
fieldname: 'toDate'
|
||||
},
|
||||
{
|
||||
fieldtype: 'Select',
|
||||
label: 'Report Type',
|
||||
fieldname: 'reportType',
|
||||
options: ['', 'GSTR-1', 'GSTR-2', 'GSTR-3B'],
|
||||
hidden: 1
|
||||
}
|
||||
],
|
||||
linkFields: [
|
26
reports/GoodsAndServiceTax/GSTR1.js
Normal file
26
reports/GoodsAndServiceTax/GSTR1.js
Normal file
@ -0,0 +1,26 @@
|
||||
const BaseGSTR = require('./BaseGSTR');
|
||||
|
||||
class GSTR1 extends BaseGSTR {
|
||||
async run(params) {
|
||||
let filters = {};
|
||||
if (params.toDate || params.fromDate) {
|
||||
filters.date = [];
|
||||
if (params.toDate) filters.date.push('<=', params.toDate);
|
||||
if (params.fromDate) filters.date.push('>=', params.fromDate);
|
||||
}
|
||||
|
||||
const data = await this.getCompleteReport('GSTR-1', filters);
|
||||
|
||||
const conditions = {
|
||||
B2B: row => row.gstin,
|
||||
'B2C-Large': row => !row.gstin && !row.inState && row.invAmt >= 250000,
|
||||
'B2C-Small': row =>
|
||||
!row.gstin && (row.inState || (row.inState && row.invAmt < 250000))
|
||||
};
|
||||
|
||||
if (!params.transferType) return data;
|
||||
return data.filter(row => conditions[params.transferType](row));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GSTR1;
|
9
reports/GoodsAndServiceTax/GSTR1View.js
Normal file
9
reports/GoodsAndServiceTax/GSTR1View.js
Normal file
@ -0,0 +1,9 @@
|
||||
const title = 'GSTR 1';
|
||||
const baseConfig = require('./BaseViewConfig');
|
||||
module.exports = {
|
||||
title: title,
|
||||
method: 'gstr-1',
|
||||
filterFields: baseConfig.filterFields,
|
||||
linkFields: baseConfig.linkFields,
|
||||
getColumns: baseConfig.getColumns
|
||||
};
|
26
reports/GoodsAndServiceTax/GSTR2.js
Normal file
26
reports/GoodsAndServiceTax/GSTR2.js
Normal file
@ -0,0 +1,26 @@
|
||||
const BaseGSTR = require('./BaseGSTR');
|
||||
|
||||
class GSTR2 extends BaseGSTR {
|
||||
async run(params) {
|
||||
let filters = {};
|
||||
if (params.toDate || params.fromDate) {
|
||||
filters.date = [];
|
||||
if (params.toDate) filters.date.push('<=', params.toDate);
|
||||
if (params.fromDate) filters.date.push('>=', params.fromDate);
|
||||
}
|
||||
|
||||
const data = await this.getCompleteReport('GSTR-2', filters);
|
||||
|
||||
const conditions = {
|
||||
B2B: row => row.gstin,
|
||||
'B2C-Large': row => !row.gstin && !row.inState && row.invAmt >= 250000,
|
||||
'B2C-Small': row =>
|
||||
!row.gstin && (row.inState || (row.inState && row.invAmt < 250000))
|
||||
};
|
||||
|
||||
if (!params.transferType) return data;
|
||||
return data.filter(row => conditions[params.transferType](row));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GSTR2;
|
9
reports/GoodsAndServiceTax/GSTR2View.js
Normal file
9
reports/GoodsAndServiceTax/GSTR2View.js
Normal file
@ -0,0 +1,9 @@
|
||||
const title = 'GSTR 2';
|
||||
const baseConfig = require('./BaseViewConfig');
|
||||
module.exports = {
|
||||
title: title,
|
||||
method: 'gstr-2',
|
||||
filterFields: baseConfig.filterFields,
|
||||
linkFields: baseConfig.linkFields,
|
||||
getColumns: baseConfig.getColumns
|
||||
};
|
@ -1,150 +0,0 @@
|
||||
const frappe = require('frappejs');
|
||||
|
||||
class GoodsAndServiceTax {
|
||||
async run(params) {
|
||||
let filters = {};
|
||||
if (params.toDate || params.fromDate) {
|
||||
filters.date = [];
|
||||
if (params.toDate) filters.date.push('<=', params.toDate);
|
||||
if (params.fromDate) filters.date.push('>=', params.fromDate);
|
||||
}
|
||||
|
||||
if (params.reportType === 'GSTR-3B') {
|
||||
this.getGSTR3bJson(filters);
|
||||
return [];
|
||||
}
|
||||
|
||||
const data = await this.getCompleteReport(params.reportType, filters);
|
||||
|
||||
const conditions = {
|
||||
B2B: row => row.gstin,
|
||||
'B2C-Large': row => !row.gstin && !row.inState && row.invAmt >= 250000,
|
||||
'B2C-Small': row =>
|
||||
!row.gstin && (row.inState || (row.inState && row.invAmt < 250000))
|
||||
};
|
||||
|
||||
if (!params.transferType) return data;
|
||||
return data.filter(row => conditions[params.transferType](row));
|
||||
}
|
||||
|
||||
async getCompleteReport(gstrType, filters) {
|
||||
if (['GSTR-1', 'GSTR-2'].includes(gstrType)) {
|
||||
let entries = await frappe.db.getAll({
|
||||
doctype: gstrType === 'GSTR-1' ? 'Invoice' : 'Bill',
|
||||
filter: filters
|
||||
});
|
||||
|
||||
let tableData = [];
|
||||
for (let entry of entries) {
|
||||
const row = await this.getRow({
|
||||
doctype: gstrType === 'GSTR-1' ? 'Invoice' : 'Bill',
|
||||
name: entry.name
|
||||
});
|
||||
tableData.push(row);
|
||||
}
|
||||
|
||||
if (Object.keys(filters).length != 0) {
|
||||
tableData = tableData.filter(row => {
|
||||
if (filters.account) return row.account === filters.account;
|
||||
if (filters.transferType)
|
||||
return row.transferType === filters.transferType;
|
||||
if (filters.place) return row.place === filters.place;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return tableData;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async getGSTR3bJson(filters) {
|
||||
const gstr1Data = this.getCompleteReport('GSTR-1', filters);
|
||||
const gsrt2Data = this.getCompleteReport('GSTR-2', filters);
|
||||
const gstr3bData = await Promise.all([gstr1Data, gsrt2Data]);
|
||||
|
||||
let gstr3bJson = require('./gstr3b.json');
|
||||
|
||||
for (let entry of gstr3bData[0]) {
|
||||
if (entry.rate > 0) {
|
||||
gstr3bJson['sup_details']['osup_det']['samt'] += entry.sgstAmt || 0;
|
||||
gstr3bJson['sup_details']['osup_det']['camt'] += entry.cgstAmt || 0;
|
||||
gstr3bJson['sup_details']['osup_det']['iamt'] += entry.igstAmt || 0;
|
||||
gstr3bJson['sup_details']['osup_det']['txval'] += entry.taxVal;
|
||||
}
|
||||
if (entry.rate === 0) {
|
||||
gstr3bJson['sup_details']['osup_zero']['txval'] += entry.taxVal;
|
||||
}
|
||||
if (entry.nilRated || entry.exempt) {
|
||||
gstr3bJson['sup_details']['osup_nil_exmp']['txval'] += entry.taxVal;
|
||||
}
|
||||
if (entry.nonGST) {
|
||||
gstr3bJson['sup_details']['osup_nongst']['txval'] += entry.taxVal;
|
||||
}
|
||||
if (!entry.inState && !entry.gstin) {
|
||||
gstr3bJson['inter_sup']['unreg_details'].push = {
|
||||
place: entry.place,
|
||||
taxVal: entry.taxVal,
|
||||
igstAmt: entry.igstAmt
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
for (let entry of gstr3bData[1]) {
|
||||
if (entry.reverseCharge === 'Y') {
|
||||
gstr3bJson['sup_details']['isup_rev']['samt'] += entry.sgstAmt || 0;
|
||||
gstr3bJson['sup_details']['isup_rev']['camt'] += entry.cgstAmt || 0;
|
||||
gstr3bJson['sup_details']['isup_rev']['iamt'] += entry.igstAmt || 0;
|
||||
gstr3bJson['sup_details']['isup_rev']['txval'] += entry.taxVal;
|
||||
}
|
||||
if (entry.nilRated || entry.exempt) {
|
||||
gstr3bJson['inward_sup']['isup_details'][0][
|
||||
entry.inState ? 'intra' : 'inter'
|
||||
] += entry.taxVal;
|
||||
}
|
||||
if (entry.nonGST) {
|
||||
gstr3bJson['inward_sup']['isup_details'][0][
|
||||
entry.inState ? 'intra' : 'inter'
|
||||
] += entry.taxVal;
|
||||
}
|
||||
}
|
||||
|
||||
return gstr3bJson;
|
||||
}
|
||||
|
||||
async getRow(entry) {
|
||||
let row = {};
|
||||
let entryDetails = await frappe.getDoc(entry.doctype, entry.name);
|
||||
let party = await frappe.getDoc(
|
||||
'Party',
|
||||
entryDetails.customer || entryDetails.supplier
|
||||
);
|
||||
if (party.address) {
|
||||
let addressDetails = await frappe.getDoc('Address', party.address);
|
||||
row.place = addressDetails.state || '';
|
||||
}
|
||||
row.gstin = party.gstin;
|
||||
row.partyName = entryDetails.customer || entryDetails.supplier;
|
||||
row.invNo = entryDetails.name;
|
||||
row.invDate = entryDetails.date;
|
||||
row.rate = 0;
|
||||
row.inState = true;
|
||||
row.reverseCharge = !party.gstin ? 'Y' : 'N';
|
||||
entryDetails.taxes.forEach(tax => {
|
||||
row.rate += tax.rate;
|
||||
const taxAmt = (tax.rate * entryDetails.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 = entryDetails.grandTotal;
|
||||
row.taxVal = entryDetails.netTotal;
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GoodsAndServiceTax;
|
@ -1,91 +0,0 @@
|
||||
const ReportPage = require('frappejs/client/desk/reportpage');
|
||||
const frappe = require('frappejs');
|
||||
|
||||
module.exports = class GoodsAndServiceTaxView extends ReportPage {
|
||||
constructor() {
|
||||
super({
|
||||
title: frappe._('Goods and Service Tax'),
|
||||
filterFields: [
|
||||
{
|
||||
fieldtype: 'Data',
|
||||
label: 'Transfer Type',
|
||||
options: ['In State', 'Out of State']
|
||||
},
|
||||
{
|
||||
fieldtype: 'Data',
|
||||
label: 'Place'
|
||||
},
|
||||
{
|
||||
fieldtype: 'Date',
|
||||
label: 'From Date'
|
||||
},
|
||||
{
|
||||
fieldtype: 'Date',
|
||||
label: 'To Date'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
this.method = 'gst-taxes';
|
||||
}
|
||||
|
||||
getColumns() {
|
||||
return [
|
||||
{
|
||||
label: 'GSTIN No.',
|
||||
fieldname: 'gstin',
|
||||
fieldtype: 'Data'
|
||||
},
|
||||
{
|
||||
fieldtype: 'Data',
|
||||
fieldname: 'cusName',
|
||||
label: 'Customer Name'
|
||||
},
|
||||
{
|
||||
label: 'Invoice No.',
|
||||
fieldname: 'invNo',
|
||||
fieldtype: 'Data'
|
||||
},
|
||||
{
|
||||
label: 'Invoice Value',
|
||||
fieldname: 'invAmt',
|
||||
fieldtype: 'Currency'
|
||||
},
|
||||
{
|
||||
label: 'Invoice Date',
|
||||
fieldname: 'invDate',
|
||||
fieldtype: 'Date'
|
||||
},
|
||||
{
|
||||
label: 'Place of supply',
|
||||
fieldname: 'place',
|
||||
fieldtype: 'Data'
|
||||
},
|
||||
{
|
||||
label: 'Rate',
|
||||
fieldname: 'rate',
|
||||
fieldtype: 'Data'
|
||||
},
|
||||
{
|
||||
label: 'Taxable Amount',
|
||||
fieldname: 'taxAmt',
|
||||
fieldtype: 'Currency'
|
||||
},
|
||||
{
|
||||
label: 'Intergrated Tax',
|
||||
fieldname: 'igstAmt',
|
||||
fieldtype: 'Currency'
|
||||
},
|
||||
{
|
||||
label: 'Central Tax',
|
||||
fieldname: 'cgstAmt',
|
||||
fieldtype: 'Currency'
|
||||
},
|
||||
{
|
||||
label: 'State Tax',
|
||||
fieldname: 'sgstAmt',
|
||||
fieldtype: 'Currency'
|
||||
}
|
||||
];
|
||||
}
|
||||
};
|
@ -1,127 +0,0 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -6,12 +6,14 @@ const TrialBalance = require('./TrialBalance/TrialBalance');
|
||||
const SalesRegister = require('./SalesRegister/SalesRegister');
|
||||
const PurchaseRegister = require('./PurchaseRegister/PurchaseRegister');
|
||||
const BankReconciliation = require('./BankReconciliation/BankReconciliation');
|
||||
const GoodsAndServiceTax = require('./GoodsAndServiceTax/GoodsAndServiceTax');
|
||||
const GSTR1 = require('./GoodsAndServiceTax/GSTR1');
|
||||
const GSTR2 = require('./GoodsAndServiceTax/GSTR2');
|
||||
const AccountsReceivablePayable = require('./AccountsReceivablePayable/AccountsReceivablePayable');
|
||||
|
||||
// called on server side
|
||||
function registerReportMethods() {
|
||||
const reports = [{
|
||||
const reports = [
|
||||
{
|
||||
method: 'general-ledger',
|
||||
class: GeneralLedger
|
||||
},
|
||||
@ -40,9 +42,13 @@ function registerReportMethods() {
|
||||
class: BankReconciliation
|
||||
},
|
||||
{
|
||||
method: 'gst-taxes',
|
||||
class: GoodsAndServiceTax
|
||||
method: 'gstr-1',
|
||||
class: GSTR1
|
||||
},
|
||||
{
|
||||
method: 'gstr-2',
|
||||
class: GSTR2
|
||||
}
|
||||
];
|
||||
|
||||
reports.forEach(report => {
|
||||
@ -67,4 +73,4 @@ function getReportData(ReportClass) {
|
||||
return args => new ReportClass().run(args);
|
||||
}
|
||||
|
||||
module.exports = registerReportMethods
|
||||
module.exports = registerReportMethods;
|
||||
|
@ -4,5 +4,6 @@ module.exports = {
|
||||
'profit-and-loss': require('./ProfitAndLoss/viewConfig'),
|
||||
'trial-balance': require('./TrialBalance/viewConfig'),
|
||||
'bank-reconciliation': require('./BankReconciliation/viewConfig'),
|
||||
'gst-taxes': require('./GoodsAndServiceTax/viewConfig'),
|
||||
}
|
||||
'gstr-1': require('./GoodsAndServiceTax/GSTR1View'),
|
||||
'gstr-2': require('./GoodsAndServiceTax/GSTR2View')
|
||||
};
|
||||
|
@ -8,6 +8,7 @@ module.exports = async function postStart() {
|
||||
frappe.models.Payment.documentClass = require('../models/doctype/Payment/PaymentServer.js');
|
||||
frappe.models.Bill.documentClass = require('../models/doctype/Bill/BillServer.js');
|
||||
frappe.models.JournalEntry.documentClass = require('../models/doctype/JournalEntry/JournalEntryServer.js');
|
||||
frappe.models.GSTR3B.documentClass = require('../models/doctype/GSTR3B/GSTR3BServer.js');
|
||||
|
||||
frappe.metaCache = {};
|
||||
|
||||
@ -25,4 +26,4 @@ module.exports = async function postStart() {
|
||||
await naming.createNumberSeries('PREC-', 'PurchaseReceiptSettings');
|
||||
|
||||
registerServerMethods();
|
||||
}
|
||||
};
|
||||
|
@ -20,14 +20,24 @@ module.exports = function registerServerMethods() {
|
||||
|
||||
frappe.registerMethod({
|
||||
method: 'print-pdf',
|
||||
handler({doctype, name, html}) {
|
||||
handler({ doctype, name, html }) {
|
||||
if (frappe.isElectron) {
|
||||
const path = require('path');
|
||||
const { getPDFForElectron } = require('frappejs/server/pdf');
|
||||
const { getSettings } = require('../electron/settings');
|
||||
const destination = path.resolve('.')
|
||||
const destination = path.resolve('.');
|
||||
getPDFForElectron(doctype, name, destination, html);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
frappe.registerMethod({
|
||||
method: 'show_dialog',
|
||||
handler({ title, message }) {
|
||||
frappe.showModal({
|
||||
modalProps: { title, noFooter: true },
|
||||
component: require('../src/components/MessageDialog').default,
|
||||
props: { message }
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -6,17 +6,13 @@
|
||||
<h4>Customizer</h4>
|
||||
</div>
|
||||
<div class="col-6 text-right">
|
||||
<f-button secondary @click="$emit('closeInvoiceCustomizer')">{{ _('Close') }}</f-button>
|
||||
<f-button secondary @click="saveAndClose">{{ _('Save & Close') }}</f-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 mt-4">
|
||||
<form-layout
|
||||
:doc="doc"
|
||||
:fields="fields"
|
||||
@updateDoc="saveDoc"
|
||||
/>
|
||||
<sketch-picker v-model="color"/>
|
||||
<form-layout :doc="doc" :fields="fields" @updateDoc="saveDoc" />
|
||||
<sketch-picker v-model="color" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -36,14 +32,16 @@ export default {
|
||||
return {
|
||||
doc: null,
|
||||
fields: [],
|
||||
color: null,
|
||||
}
|
||||
color: {}
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
this.doc = await frappe.getDoc('InvoiceSettings');
|
||||
this.color = this.doc.themeColor;
|
||||
this.color.hex = this.doc.themeColor;
|
||||
const meta = frappe.getMeta('InvoiceSettings');
|
||||
this.fields = meta.fields.filter((field) => field.fieldname !== "numberSeries");
|
||||
this.fields = meta.fields.filter(
|
||||
field => field.fieldname !== 'numberSeries'
|
||||
);
|
||||
},
|
||||
methods: {
|
||||
async saveDoc(updatedValue) {
|
||||
@ -53,16 +51,18 @@ export default {
|
||||
} else if (fieldname === 'font') {
|
||||
this.$emit('changeFont', value);
|
||||
}
|
||||
},
|
||||
async saveAndClose() {
|
||||
this.doc.themeColor = this.color.hex;
|
||||
await this.doc.update();
|
||||
this.$emit('closeInvoiceCustomizer');
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
color: async function() {
|
||||
if (this.doc) {
|
||||
if (this.doc.themeColor != this.color.hex) {
|
||||
this.doc.themeColor = this.color.hex;
|
||||
this.$emit('changeColor', this.color.hex);
|
||||
await this.doc.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
23
src/components/MessageDialog.vue
Normal file
23
src/components/MessageDialog.vue
Normal file
@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="p-3 d-flex align-items-center">
|
||||
<indicator :color="indicatorColor" class="mr-2 ml-1" />
|
||||
{{ message }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import indicators from 'frappejs/ui/constants/indicators';
|
||||
export default {
|
||||
name: 'MessageDialog',
|
||||
data() {
|
||||
return {
|
||||
indicatorColor: indicators.ORANGE
|
||||
};
|
||||
},
|
||||
props: {
|
||||
message: {
|
||||
type: String
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -5,7 +5,7 @@
|
||||
<a v-for="(item, index) in clickableBreadcrumbs" :key="index" :href="item.route">
|
||||
<h5 class="breadCrumbRoute">
|
||||
{{ item.title }}
|
||||
<feather-icon name="arrow-right" style="color: #212529 !important;"></feather-icon>
|
||||
<feather-icon name="chevron-right" style="color: #212529 !important;"></feather-icon>
|
||||
</h5>
|
||||
</a>
|
||||
<h5 class="breadCrumbRoute">{{ lastBreadcrumb.title }}</h5>
|
||||
|
@ -68,7 +68,7 @@ export default {
|
||||
methods: {
|
||||
isCurrentRoute(route) {
|
||||
if (this.activeGroup) return false;
|
||||
return this.$route.path === route;
|
||||
return this.$route.fullPath === route;
|
||||
},
|
||||
toggleGroup(groupTitle) {
|
||||
this.groupItems =
|
||||
|
@ -124,18 +124,28 @@ export default {
|
||||
this.$emit('save', this.doc);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return;
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
async submit() {
|
||||
this.doc.set('submitted', 1);
|
||||
try {
|
||||
await this.save();
|
||||
} catch (e) {
|
||||
this.doc.set('submitted', 0);
|
||||
this.doc.set('_dirty', false);
|
||||
}
|
||||
},
|
||||
|
||||
async revert() {
|
||||
this.doc.set('submitted', 0);
|
||||
try {
|
||||
await this.save();
|
||||
} catch (e) {
|
||||
this.doc.set('submitted', 1);
|
||||
this.doc._dirty = false;
|
||||
}
|
||||
},
|
||||
|
||||
print() {
|
||||
|
@ -7,6 +7,7 @@ import Payment from '../../../models/doctype/Payment/PaymentList';
|
||||
import Tax from '../../../models/doctype/Tax/TaxList';
|
||||
import JournalEntry from '../../../models/doctype/JournalEntry/JournalEntryList';
|
||||
import Account from '../../../models/doctype/Account/AccountList';
|
||||
import GSTR3B from '../../../models/doctype/GSTR3B/GSTR3BList';
|
||||
|
||||
export default {
|
||||
Invoice,
|
||||
@ -17,5 +18,6 @@ export default {
|
||||
Payment,
|
||||
Tax,
|
||||
JournalEntry,
|
||||
Account
|
||||
Account,
|
||||
GSTR3B
|
||||
};
|
||||
|
@ -1,61 +1,50 @@
|
||||
<template>
|
||||
<div class="bg-light">
|
||||
<page-header :title="doctype"/>
|
||||
<div class="row no-gutters">
|
||||
<div v-if="showInvoiceCustomizer" class="col-3 mt-4 mx-auto"></div>
|
||||
<div class="col-8 mx-auto text-right mt-4">
|
||||
<f-button primary @click="send">{{ _('Send') }}</f-button>
|
||||
<f-button secondary @click="toggleInvoiceCustomizer">{{ _('Customize') }}</f-button>
|
||||
<f-button secondary @click="makePDF">{{ _('PDF') }}</f-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row no-gutters">
|
||||
<div v-if="showInvoiceCustomizer" class="col-3 mt-4 mx-auto">
|
||||
<invoice-customizer
|
||||
class="border"
|
||||
style="position: fixed"
|
||||
@closeInvoiceCustomizer="toggleInvoiceCustomizer"
|
||||
@changeColor="changeColor($event)"
|
||||
@changeTemplate="changeTemplate($event)"
|
||||
@changeFont="changeFont($event)"
|
||||
/>
|
||||
</div>
|
||||
<div ref="printComponent" class="col-8 bg-white mt-4 mx-auto border shadow">
|
||||
<component
|
||||
:themeColor="themeColor"
|
||||
:template="template"
|
||||
:font="font"
|
||||
:is="printComponent"
|
||||
v-if="doc"
|
||||
:doc="doc"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<page-header :breadcrumbs="breadcrumbs" />
|
||||
<component :is="printComponent" v-if="doc" :doc="doc" @send="send" @makePDF="makePDF" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import PageHeader from '@/components/PageHeader';
|
||||
import InvoiceCustomizer from '@/components/InvoiceCustomizer';
|
||||
import InvoicePrint from '@/../models/doctype/Invoice/InvoicePrint';
|
||||
import GSTR3BPrintView from '@/../models/doctype/GSTR3B/GSTR3BPrintView';
|
||||
import EmailSend from '../Email/EmailSend';
|
||||
|
||||
const printComponents = {
|
||||
Invoice: InvoicePrint
|
||||
Invoice: InvoicePrint,
|
||||
GSTR3B: GSTR3BPrintView
|
||||
};
|
||||
export default {
|
||||
name: 'PrintView',
|
||||
props: ['doctype', 'name'],
|
||||
components: {
|
||||
PageHeader,
|
||||
InvoiceCustomizer
|
||||
PageHeader
|
||||
},
|
||||
computed: {
|
||||
breadcrumbs() {
|
||||
if (this.doc)
|
||||
return [
|
||||
{
|
||||
title: this.doctype,
|
||||
route: '#/list/' + this.doctype
|
||||
},
|
||||
{
|
||||
title: this.doc._notInserted
|
||||
? 'New ' + this.doctype
|
||||
: this.doc.name,
|
||||
route: `#/edit/${this.doctype}/${this.name}`
|
||||
},
|
||||
{
|
||||
title: 'Print',
|
||||
route: ``
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
doc: undefined,
|
||||
printComponent: undefined,
|
||||
themeColor: undefined,
|
||||
template: undefined,
|
||||
font: undefined,
|
||||
showInvoiceCustomizer: false
|
||||
};
|
||||
},
|
||||
@ -64,22 +53,22 @@ export default {
|
||||
this.printComponent = printComponents[this.doctype];
|
||||
},
|
||||
methods: {
|
||||
makePDF() {
|
||||
makePDF(html) {
|
||||
frappe.call({
|
||||
method: 'print-pdf',
|
||||
args: {
|
||||
doctype: this.doctype,
|
||||
name: this.name,
|
||||
html: this.$refs.printComponent.innerHTML
|
||||
html
|
||||
}
|
||||
});
|
||||
},
|
||||
async send() {
|
||||
async send(html) {
|
||||
let doc = await frappe.getNewDoc('Email');
|
||||
let emailFields = frappe.getMeta('Email').fields;
|
||||
var file_path = this.name;
|
||||
doc['fromEmailAddress'] = this.selectedId;
|
||||
this.makePDF();
|
||||
this.makePDF(html);
|
||||
doc['filePath'] = this.name + '.pdf';
|
||||
this.$modal.show({
|
||||
component: EmailSend,
|
||||
@ -88,25 +77,13 @@ export default {
|
||||
name: doc.name
|
||||
},
|
||||
modalProps: {
|
||||
title: 'Send Invoice',
|
||||
footerMessage: 'Invoice attached along..'
|
||||
title: `Send ${this.doctype}`,
|
||||
footerMessage: `${this.doctype} attached along..`
|
||||
}
|
||||
});
|
||||
doc.on('afterInsert', data => {
|
||||
this.$modal.hide();
|
||||
});
|
||||
},
|
||||
async toggleInvoiceCustomizer() {
|
||||
this.showInvoiceCustomizer = !this.showInvoiceCustomizer;
|
||||
},
|
||||
changeColor(color) {
|
||||
this.themeColor = color;
|
||||
},
|
||||
changeTemplate(template) {
|
||||
this.template = template;
|
||||
},
|
||||
changeFont(font) {
|
||||
this.font = font;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -2,15 +2,15 @@
|
||||
<div>
|
||||
<div class="px-3">
|
||||
<div class="row pb-4">
|
||||
<!-- <h4 class="col-6 d-flex">{{ reportConfig.title }}</h4> -->
|
||||
<page-header :class="linksExists ? 'col-6':'col-12'" :breadcrumbs="breadcrumbs" />
|
||||
<report-links class="col-6 d-flex pr-0 flex-row-reverse" v-if="linksExists" :links="links"></report-links>
|
||||
</div>
|
||||
<div class="row pb-4">
|
||||
<report-filters
|
||||
class="col-12 pr-0"
|
||||
v-if="filtersExists"
|
||||
:filters="reportConfig.filterFields"
|
||||
v-if="shouldRenderFields"
|
||||
:filterFields="reportConfig.filterFields"
|
||||
:filterDoc="filterDoc"
|
||||
:filterDefaults="filters"
|
||||
@change="getReportData"
|
||||
></report-filters>
|
||||
@ -33,7 +33,9 @@ export default {
|
||||
props: ['reportName', 'reportConfig', 'filters'],
|
||||
data() {
|
||||
return {
|
||||
currentFilters: this.filters
|
||||
currentFilters: this.filters,
|
||||
filterDoc: undefined,
|
||||
links: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -49,26 +51,16 @@ export default {
|
||||
}
|
||||
];
|
||||
},
|
||||
filtersExists() {
|
||||
return (this.reportConfig.filterFields || []).length;
|
||||
shouldRenderFields() {
|
||||
return (this.reportConfig.filterFields || []).length && this.filterDoc;
|
||||
},
|
||||
linksExists() {
|
||||
return (this.reportConfig.linkFields || []).length;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
reportName() {
|
||||
//FIX: Report's data forwards to next consecutively changed report
|
||||
this.getReportData(this.filters);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
links: []
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
this.setLinks();
|
||||
this.filterDoc = await frappe.newCustomDoc(this.reportConfig.filterFields);
|
||||
},
|
||||
methods: {
|
||||
async getReportData(filters) {
|
||||
@ -102,7 +94,7 @@ export default {
|
||||
}
|
||||
|
||||
if (this.datatable) {
|
||||
this.datatable.refresh(rows, columns);
|
||||
if (rows.length) this.datatable.refresh(rows, columns);
|
||||
} else {
|
||||
this.datatable = new DataTable(this.$refs.datatable, {
|
||||
columns: columns,
|
||||
|
@ -70,9 +70,6 @@ export default {
|
||||
label: _('Payment'),
|
||||
route: '/list/Payment'
|
||||
}
|
||||
// {
|
||||
// label: _('AccountingLedgerEntry'), route: '/list/AccountingLedgerEntry'
|
||||
// },
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -95,8 +92,16 @@ export default {
|
||||
route: '/report/bank-reconciliation'
|
||||
},
|
||||
{
|
||||
label: _('Goods and Service Tax'),
|
||||
route: '/report/gst-taxes'
|
||||
label: _('GSTR 1'),
|
||||
route: '/report/gstr-1?transferType=B2B'
|
||||
},
|
||||
{
|
||||
label: _('GSTR 2'),
|
||||
route: '/report/gstr-2?transferType=B2B'
|
||||
},
|
||||
{
|
||||
label: _('GSTR 3B'),
|
||||
route: '/list/GSTR3B'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -7,7 +7,7 @@
|
||||
}
|
||||
.slide-fade-enter,
|
||||
.slide-fade-leave-to {
|
||||
transform: translateX(-12px);
|
||||
transform: translateX(-5px);
|
||||
opacity: 0;
|
||||
}
|
||||
.slide-fade-move {
|
||||
|
Loading…
Reference in New Issue
Block a user