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:
parent
070b49d90f
commit
80606b2cca
@ -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;
|
||||
}
|
||||
|
@ -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'
|
||||
],
|
||||
|
52
models/doctype/Address/RegionalChanges.js
Normal file
52
models/doctype/Address/RegionalChanges.js
Normal 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;
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user