diff --git a/models/baseModels/Invoice/Invoice.ts b/models/baseModels/Invoice/Invoice.ts index 6bc3925a..71a939c8 100644 --- a/models/baseModels/Invoice/Invoice.ts +++ b/models/baseModels/Invoice/Invoice.ts @@ -59,6 +59,10 @@ export abstract class Invoice extends Transactional { return this.fyo.singles.SystemSettings!.currency !== this.currency; } + get companyCurrency() { + return this.fyo.singles.SystemSettings?.currency ?? DEFAULT_CURRENCY; + } + constructor(schema: Schema, data: DocValueMap, fyo: Fyo) { super(schema, data, fyo); this._setGetCurrencies(); @@ -163,7 +167,6 @@ export abstract class Invoice extends Transactional { account: string; rate: number; amount: Money; - baseAmount: Money; [key: string]: DocValue; } > = {}; @@ -181,7 +184,6 @@ export abstract class Invoice extends Transactional { account, rate, amount: this.fyo.pesa(0), - baseAmount: this.fyo.pesa(0), }; let amount = item.amount!; @@ -196,9 +198,7 @@ export abstract class Invoice extends Transactional { return Object.keys(taxes) .map((account) => { - const tax = taxes[account]; - tax.baseAmount = tax.amount.mul(this.exchangeRate!); - return tax; + return taxes[account]; }) .filter((tax) => !tax.amount.isZero()); } @@ -311,6 +311,13 @@ export abstract class Invoice extends Transactional { }, exchangeRate: { formula: async () => { + if ( + this.currency === + (this.fyo.singles.SystemSettings?.currency ?? DEFAULT_CURRENCY) + ) { + return 1; + } + if (this.exchangeRate && this.exchangeRate !== 1) { return this.exchangeRate; } @@ -319,13 +326,11 @@ export abstract class Invoice extends Transactional { }, }, netTotal: { formula: async () => this.getSum('items', 'amount', false) }, - baseNetTotal: { - formula: async () => this.netTotal!.mul(this.exchangeRate!), - }, taxes: { formula: async () => await this.getTaxSummary() }, grandTotal: { formula: async () => await this.getGrandTotal() }, baseGrandTotal: { - formula: async () => (this.grandTotal as Money).mul(this.exchangeRate!), + formula: async () => + (this.grandTotal as Money).mul(this.exchangeRate! ?? 1), }, outstandingAmount: { formula: async () => { @@ -378,10 +383,13 @@ export abstract class Invoice extends Transactional { }), }; - getCurrencies: CurrenciesMap = {}; + getCurrencies: CurrenciesMap = { + baseGrandTotal: () => this.companyCurrency, + outstandingAmount: () => this.companyCurrency, + }; _getCurrency() { if (this.exchangeRate === 1) { - return this.fyo.singles.SystemSettings?.currency ?? DEFAULT_CURRENCY; + return this.companyCurrency; } return this.currency ?? DEFAULT_CURRENCY; @@ -392,7 +400,7 @@ export abstract class Invoice extends Transactional { ); for (const { fieldname } of currencyFields) { - this.getCurrencies[fieldname] = this._getCurrency.bind(this); + this.getCurrencies[fieldname] ??= this._getCurrency.bind(this); } } } diff --git a/models/baseModels/InvoiceItem/InvoiceItem.ts b/models/baseModels/InvoiceItem/InvoiceItem.ts index 82d2e2d5..8d6009e5 100644 --- a/models/baseModels/InvoiceItem/InvoiceItem.ts +++ b/models/baseModels/InvoiceItem/InvoiceItem.ts @@ -18,7 +18,6 @@ import { Invoice } from '../Invoice/Invoice'; export abstract class InvoiceItem extends Doc { account?: string; amount?: Money; - baseAmount?: Money; parentdoc?: Invoice; rate?: Money; quantity?: number; @@ -93,7 +92,7 @@ export abstract class InvoiceItem extends Doc { fieldname !== 'itemTaxedTotal' && fieldname !== 'itemDiscountedTotal' ) { - return rate ?? this.fyo.pesa(0); + return rate?.div(this.exchangeRate) ?? this.fyo.pesa(0); } const quantity = this.quantity ?? 0; @@ -122,17 +121,14 @@ export abstract class InvoiceItem extends Doc { return rateFromTotals ?? rate ?? this.fyo.pesa(0); }, dependsOn: [ + 'party', + 'exchangeRate', 'item', 'itemTaxedTotal', 'itemDiscountedTotal', 'setItemDiscountAmount', ], }, - baseRate: { - formula: () => - (this.rate as Money).mul(this.parentdoc!.exchangeRate as number), - dependsOn: ['item', 'rate'], - }, quantity: { formula: async () => { if (!this.item) { @@ -177,11 +173,6 @@ export abstract class InvoiceItem extends Doc { formula: () => (this.rate as Money).mul(this.quantity as number), dependsOn: ['item', 'rate', 'quantity'], }, - baseAmount: { - formula: () => - (this.amount as Money).mul(this.parentdoc!.exchangeRate as number), - dependsOn: ['item', 'amount', 'rate', 'quantity'], - }, hsnCode: { formula: async () => await this.fyo.getValue('Item', this.item as string, 'hsnCode'), @@ -373,7 +364,7 @@ export abstract class InvoiceItem extends Doc { ); for (const { fieldname } of currencyFields) { - this.getCurrencies[fieldname] = this._getCurrency.bind(this); + this.getCurrencies[fieldname] ??= this._getCurrency.bind(this); } } } diff --git a/models/baseModels/PurchaseInvoice/PurchaseInvoice.ts b/models/baseModels/PurchaseInvoice/PurchaseInvoice.ts index 47caf0a8..bb0002d4 100644 --- a/models/baseModels/PurchaseInvoice/PurchaseInvoice.ts +++ b/models/baseModels/PurchaseInvoice/PurchaseInvoice.ts @@ -10,16 +10,17 @@ export class PurchaseInvoice extends Invoice { items?: PurchaseInvoiceItem[]; async getPosting() { + const exchangeRate = this.exchangeRate ?? 1; const posting: LedgerPosting = new LedgerPosting(this, this.fyo); await posting.credit(this.account!, this.baseGrandTotal!); for (const item of this.items!) { - await posting.debit(item.account!, item.baseAmount!); + await posting.debit(item.account!, item.amount!.mul(exchangeRate)); } if (this.taxes) { for (const tax of this.taxes) { - await posting.debit(tax.account!, tax.baseAmount!); + await posting.debit(tax.account!, tax.amount!.mul(exchangeRate)); } } @@ -27,7 +28,7 @@ export class PurchaseInvoice extends Invoice { const discountAccount = this.fyo.singles.AccountingSettings ?.discountAccount as string | undefined; if (discountAccount && discountAmount.isPositive()) { - await posting.credit(discountAccount, discountAmount); + await posting.credit(discountAccount, discountAmount.mul(exchangeRate)); } await posting.makeRoundOffEntry(); diff --git a/models/baseModels/SalesInvoice/SalesInvoice.ts b/models/baseModels/SalesInvoice/SalesInvoice.ts index d50a6345..103cab44 100644 --- a/models/baseModels/SalesInvoice/SalesInvoice.ts +++ b/models/baseModels/SalesInvoice/SalesInvoice.ts @@ -10,16 +10,17 @@ export class SalesInvoice extends Invoice { items?: SalesInvoiceItem[]; async getPosting() { + const exchangeRate = this.exchangeRate ?? 1; const posting: LedgerPosting = new LedgerPosting(this, this.fyo); await posting.debit(this.account!, this.baseGrandTotal!); for (const item of this.items!) { - await posting.credit(item.account!, item.baseAmount!); + await posting.credit(item.account!, item.amount!.mul(exchangeRate)); } if (this.taxes) { for (const tax of this.taxes!) { - await posting.credit(tax.account!, tax.baseAmount!); + await posting.credit(tax.account!, tax.amount!.mul(exchangeRate)); } } @@ -27,7 +28,7 @@ export class SalesInvoice extends Invoice { const discountAccount = this.fyo.singles.AccountingSettings ?.discountAccount as string | undefined; if (discountAccount && discountAmount.isPositive()) { - await posting.debit(discountAccount, discountAmount); + await posting.debit(discountAccount, discountAmount.mul(exchangeRate)); } await posting.makeRoundOffEntry(); diff --git a/models/baseModels/TaxSummary/TaxSummary.ts b/models/baseModels/TaxSummary/TaxSummary.ts index 7ca232ba..7a4fbd06 100644 --- a/models/baseModels/TaxSummary/TaxSummary.ts +++ b/models/baseModels/TaxSummary/TaxSummary.ts @@ -1,21 +1,8 @@ import { Doc } from 'fyo/model/doc'; -import { FormulaMap } from 'fyo/model/types'; import { Money } from 'pesa'; export class TaxSummary extends Doc { account?: string; rate?: number; amount?: Money; - baseAmount?: Money; - - formulas: FormulaMap = { - baseAmount: { - formula: async () => { - const amount = this.amount as Money; - const exchangeRate = (this.parentdoc?.exchangeRate ?? 1) as number; - return amount.mul(exchangeRate); - }, - dependsOn: ['amount'], - }, - }; } diff --git a/reports/GoodsAndServiceTax/gstExporter.ts b/reports/GoodsAndServiceTax/gstExporter.ts index 42011683..01849fdd 100644 --- a/reports/GoodsAndServiceTax/gstExporter.ts +++ b/reports/GoodsAndServiceTax/gstExporter.ts @@ -218,6 +218,11 @@ async function generateB2bData(report: BaseGSTR): Promise { ? ModelNameEnum.SalesInvoiceItem : ModelNameEnum.PurchaseInvoiceItem; + const parentSchemaName = + report.gstrType === 'GSTR-1' + ? ModelNameEnum.SalesInvoice + : ModelNameEnum.PurchaseInvoice; + for (const row of report.gstrRows ?? []) { const invRecord: B2BInvRecord = { inum: row.invNo, @@ -229,20 +234,29 @@ async function generateB2bData(report: BaseGSTR): Promise { itms: [], }; + const exchangeRate = ( + await fyo.db.getAllRaw(parentSchemaName, { + fields: ['exchangeRate'], + filters: { name: invRecord.inum }, + }) + )[0].exchangeRate as number; + const items = await fyo.db.getAllRaw(schemaName, { - fields: ['baseAmount', 'tax', 'hsnCode'], - filters: { parent: invRecord.inum as string }, + fields: ['amount', 'tax', 'hsnCode'], + filters: { parent: invRecord.inum }, }); items.forEach((item) => { const hsnCode = item.hsnCode as number; const tax = item.tax as string; - const baseAmount = (item.baseAmount ?? 0) as string; + const baseAmount = fyo + .pesa((item.amount as string) ?? 0) + .mul(exchangeRate); const itemRecord: B2BItmRecord = { num: hsnCode, itm_det: { - txval: fyo.pesa(baseAmount).float, + txval: baseAmount.float, rt: GST[tax], csamt: 0, camt: fyo @@ -292,6 +306,11 @@ async function generateB2clData( ? ModelNameEnum.SalesInvoiceItem : ModelNameEnum.PurchaseInvoiceItem; + const parentSchemaName = + report.gstrType === 'GSTR-1' + ? ModelNameEnum.SalesInvoice + : ModelNameEnum.PurchaseInvoice; + for (const row of report.gstrRows ?? []) { const invRecord: B2CLInvRecord = { inum: row.invNo, @@ -300,20 +319,29 @@ async function generateB2clData( itms: [], }; + const exchangeRate = ( + await fyo.db.getAllRaw(parentSchemaName, { + fields: ['exchangeRate'], + filters: { name: invRecord.inum }, + }) + )[0].exchangeRate as number; + const items = await fyo.db.getAllRaw(schemaName, { - fields: ['hsnCode', 'tax', 'baseAmount'], + fields: ['amount', 'tax', 'hsnCode'], filters: { parent: invRecord.inum }, }); items.forEach((item) => { const hsnCode = item.hsnCode as number; const tax = item.tax as string; - const baseAmount = (item.baseAmount ?? 0) as string; + const baseAmount = fyo + .pesa((item.amount as string) ?? 0) + .mul(exchangeRate); const itemRecord: B2CLItmRecord = { num: hsnCode, itm_det: { - txval: fyo.pesa(baseAmount).float, + txval: baseAmount.float, rt: GST[tax] ?? 0, csamt: 0, iamt: fyo diff --git a/schemas/app/Invoice.json b/schemas/app/Invoice.json index d29a458e..98891ca3 100644 --- a/schemas/app/Invoice.json +++ b/schemas/app/Invoice.json @@ -54,12 +54,6 @@ "fieldtype": "Currency", "readOnly": true }, - { - "fieldname": "baseNetTotal", - "label": "Net Total (Company Currency)", - "fieldtype": "Currency", - "readOnly": true - }, { "fieldname": "taxes", "label": "Taxes", diff --git a/schemas/app/InvoiceItem.json b/schemas/app/InvoiceItem.json index 261d1695..e2130a4f 100644 --- a/schemas/app/InvoiceItem.json +++ b/schemas/app/InvoiceItem.json @@ -30,12 +30,6 @@ "fieldtype": "Currency", "required": true }, - { - "fieldname": "baseRate", - "label": "Rate (Company Currency)", - "fieldtype": "Currency", - "readOnly": true - }, { "fieldname": "account", "label": "Account", @@ -56,12 +50,6 @@ "fieldtype": "Currency", "readOnly": true }, - { - "fieldname": "baseAmount", - "label": "Amount (Company Currency)", - "fieldtype": "Currency", - "readOnly": true - }, { "fieldname": "setItemDiscountAmount", "label": "Set Discount Amount", diff --git a/schemas/app/TaxSummary.json b/schemas/app/TaxSummary.json index 71e23921..2f044605 100644 --- a/schemas/app/TaxSummary.json +++ b/schemas/app/TaxSummary.json @@ -21,12 +21,6 @@ "label": "Amount", "fieldtype": "Currency", "required": true - }, - { - "fieldname": "baseAmount", - "label": "Amount (Company Currency)", - "fieldtype": "Currency", - "readOnly": true } ] } \ No newline at end of file diff --git a/src/pages/InvoiceForm.vue b/src/pages/InvoiceForm.vue index 2d722fee..732ab3f3 100644 --- a/src/pages/InvoiceForm.vue +++ b/src/pages/InvoiceForm.vue @@ -77,8 +77,8 @@ :border="true" :df="getField('party')" :value="doc.party" - @change="(value) => doc.set('party', value)" - @new-doc="(party) => doc.set('party', party.name)" + @change="(value) => doc.set('party', value, true)" + @new-doc="(party) => doc.set('party', party.name, true)" :read-only="doc?.submitted" /> {{ formattedValue('grandTotal') }} + +
+
{{ t`Base Grand Total` }}
+
{{ formattedValue('baseGrandTotal') }}
+
+