2
0
mirror of https://github.com/frappe/books.git synced 2024-12-31 22:11:48 +00:00

feat: add gst1 b2cs and b2cl

This commit is contained in:
Ankit Singhaniya 2021-12-23 22:05:34 +05:30
parent 070b49d90f
commit 80606b2cca
5 changed files with 171 additions and 15 deletions

View File

@ -5,6 +5,45 @@ import { DateTime } from 'luxon';
import { saveExportData } from '../reports/commonExporter';
import { getSavePath } from '../src/utils';
export const stateCodeMap = {
'JAMMU AND KASHMIR': '1',
'HIMACHAL PRADESH': '2',
'PUNJAB': '3',
'CHANDIGARH': '4',
'UTTARAKHAND': '5',
'HARYANA': '6',
'DELHI': '7',
'RAJASTHAN': '8',
'UTTAR PRADESH': '9',
'BIHAR': '10',
'SIKKIM': '11',
'ARUNACHAL PRADESH': '12',
'NAGALAND': '13',
'MANIPUR': '14',
'MIZORAM': '15',
'TRIPURA': '16',
'MEGHALAYA': '17',
'ASSAM': '18',
'WEST BENGAL': '19',
'JHARKHAND': '20',
'ODISHA': '21',
'CHATTISGARH': '22',
'MADHYA PRADESH': '23',
'GUJARAT': '24',
'DADRA AND NAGAR HAVELI AND DAMAN AND DIU': '26',
'MAHARASHTRA': '27',
'KARNATAKA': '29',
'GOA': '30',
'LAKSHADWEEP': '31',
'KERALA': '32',
'TAMIL NADU': '33',
'PUDUCHERRY': '34',
'ANDAMAN AND NICOBAR ISLANDS': '35',
'TELANGANA': '36',
'ANDHRA PRADESH': '37',
'LADAKH': '38',
};
const GST = {
'GST-0': 0,
'GST-0.25': 0.25,
@ -75,9 +114,9 @@ export async function generateGstr1Json(getReportData) {
if (transferType === 'B2B') {
gstData.b2b = await generateB2bData(rows);
} else if (transferType === 'B2CL') {
} else if (transferType === 'B2C-Large') {
gstData.b2cl = await generateB2clData(rows);
} else if (transferType === 'B2CS') {
} else if (transferType === 'B2C-Small') {
gstData.b2cs = await generateB2csData(rows);
}
@ -112,7 +151,7 @@ async function generateB2bData(invoices) {
items.forEach((item) => {
const itemRecord = {
num: item.hsnCode || 0,
num: item.hsnCode,
itm_det: {
txval: item.baseAmount,
rt: GST[item.tax],
@ -140,9 +179,79 @@ async function generateB2bData(invoices) {
}
async function generateB2clData(invoices) {
return [];
const b2cl = [];
invoices.forEach(async (invoice) => {
const stateInvoiceRecord = {
pos: stateCodeMap[invoice.place.toUpperCase()],
inv: []
};
const invRecord = {
inum: invoice.invNo,
idt: DateTime.fromFormat(invoice.invDate, 'yyyy-MM-dd').toFormat(
'dd-MM-yyyy'
),
val: invoice.invAmt,
itms: [],
}
let items = await frappe.db
.knex('SalesInvoiceItem')
.where('parent', invRecord.inum);
items.forEach((item) => {
const itemRecord = {
num: item.hsnCode,
itm_det: {
txval: item.baseAmount,
rt: GST[item.tax],
csamt: 0,
iamt: ((invoice.rate || 0) * item.baseAmount) / 100,
},
};
invRecord.itms.push(itemRecord);
});
const stateRecord = b2cl.find((b) => b.pos === stateCodeMap[invoice.place]);
if (stateRecord) {
stateRecord.inv.push(invRecord);
} else {
stateInvoiceRecord.inv.push(invRecord);
b2cl.push(stateInvoiceRecord);
}
})
return b2cl;
}
async function generateB2csData(invoices) {
return [];
const b2cs = [];
invoices.forEach(async (invoice) => {
const pos = invoice.place.toUpperCase();
const invRecord = {
"sply_ty": invoice.inState ? "INTRA" : "INTER",
"pos": stateCodeMap[pos],
// "OE" - Abbreviation for errors and omissions excepted.
// https://specialties.bayt.com/en/specialties/q/53093/what-is-meant-by-e-amp-oe-on-bill-or-invoice-or-any-document/#:~:text=E%26OE%20on,not%20purposely%20written
"typ": "OE",
"txval": invoice.taxVal,
"rt": invoice.rate,
"iamt": !invoice.inState ? (invoice.taxVal * invoice.rate / 100) : 0,
"camt": invoice.inState ? invoice.cgstAmt : 0,
"samt": invoice.inState ? invoice.sgstAmt : 0,
"csamt": 0
}
b2cs.push(invRecord);
});
return b2cs;
}

View File

@ -1,12 +1,12 @@
export default {
name: 'Address',
doctype: 'DocType',
regional: 1,
isSingle: 0,
keywordFields: [
'addressLine1',
'addressLine2',
'city',
'state',
'country',
'postalCode'
],
@ -31,12 +31,6 @@ export default {
fieldtype: 'Data',
required: 1
},
{
fieldname: 'state',
label: 'State',
placeholder: 'State',
fieldtype: 'Data'
},
{
fieldname: 'country',
label: 'Country',
@ -90,7 +84,6 @@ export default {
'addressLine1',
'addressLine2',
'city',
'state',
'country',
'postalCode'
],

View File

@ -0,0 +1,52 @@
import { cloneDeep, capitalize } from 'lodash';
import AddressOriginal from './Address';
import { stateCodeMap } from '../../../accounting/gst';
export default function getAugmentedAddress({ country }) {
const Address = cloneDeep(AddressOriginal);
if (!country) {
return Address;
}
const cityFieldIndex = Address.fields.findIndex(
(i) => i.fieldname === 'city'
);
if (country === 'India') {
Address.fields = [
...Address.fields.slice(0, cityFieldIndex + 1),
{
fieldname: 'state',
label: 'State',
fieldtype: 'Select',
placeholder: 'State',
options: Object.keys(stateCodeMap).map((key) => capitalize(key)),
},
...Address.fields.slice(cityFieldIndex + 1, Address.fields.length),
];
// Setting country as India for customers as default for SMBs in India
Address.fields.forEach((field) => {
if (field.fieldname === 'country') {
field.default = 'India';
}
});
} else {
Address.fields = [
...Address.fields.slice(0, cityFieldIndex + 1),
{
fieldname: 'state',
label: 'State',
placeholder: 'State',
fieldtype: 'Data',
},
...Address.fields.slice(cityFieldIndex + 1, Address.fields.length),
];
}
Address.quickEditFields = [
...Address.quickEditFields.slice(0, cityFieldIndex + 1),
'state',
...Address.quickEditFields.slice(cityFieldIndex + 1, Address.fields.length),
];
return Address;
}

View File

@ -1,4 +1,5 @@
import frappe from 'frappejs';
import { stateCodeMap } from '../../accounting/gst'
class BaseGSTR {
async getCompleteReport(gstrType, filters) {
@ -33,6 +34,7 @@ class BaseGSTR {
async getRow(ledgerEntry) {
let row = {};
ledgerEntry = await frappe.getDoc(ledgerEntry.doctype, ledgerEntry.name);
const { gstin } = frappe.AccountingSettings;
let party = await frappe.getDoc(
'Party',
ledgerEntry.customer || ledgerEntry.supplier
@ -46,7 +48,7 @@ class BaseGSTR {
row.invNo = ledgerEntry.name;
row.invDate = ledgerEntry.date;
row.rate = 0;
row.inState = true;
row.inState = gstin.substring(0, 2) === stateCodeMap[row.place];
row.reverseCharge = !party.gstin ? 'Y' : 'N';
ledgerEntry.taxes?.forEach(tax => {
row.rate += tax.rate;

View File

@ -17,7 +17,7 @@ class GSTR1 extends BaseGSTR {
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)),
'B2C-Small': row => !row.gstin && (row.inState || row.invAmt < 250000),
'Nil Rated, Exempted and Non GST supplies': row => (row.rate === 0), // this takes care of both nil rated, exempted goods
};