feat: add local discount and adjustment calculations to financial models and transformers

- Introduced `discountAmountLocal` and `adjustmentLocal` properties across Bill, CreditNote, SaleInvoice, SaleReceipt, and VendorCredit models to calculate amounts in local currency.
- Updated transformers for CreditNote, PurchaseInvoice, and VendorCredit to include formatted representations of local discount and adjustment amounts.
- Enhanced GL entry services to handle discount and adjustment entries for SaleReceipt and CreditNote, ensuring accurate ledger entries.
- Improved overall consistency in handling financial calculations across various models and services.
This commit is contained in:
Ahmed Bouhuolia
2024-12-08 18:11:03 +02:00
parent 0a5115fc20
commit 994c441bb8
11 changed files with 351 additions and 30 deletions

View File

@@ -12,6 +12,7 @@ import {
import HasTenancyService from '@/services/Tenancy/TenancyService';
import Ledger from '@/services/Accounting/Ledger';
import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
import { SaleReceipt } from '@/models';
@Service()
export default class CreditNoteGLEntries {
@@ -29,11 +30,15 @@ export default class CreditNoteGLEntries {
*/
private getCreditNoteGLedger = (
creditNote: ICreditNote,
receivableAccount: number
receivableAccount: number,
discountAccount: number,
adjustmentAccount: number
): Ledger => {
const ledgerEntries = this.getCreditNoteGLEntries(
creditNote,
receivableAccount
receivableAccount,
discountAccount,
adjustmentAccount
);
return new Ledger(ledgerEntries);
};
@@ -49,9 +54,16 @@ export default class CreditNoteGLEntries {
tenantId: number,
creditNote: ICreditNote,
payableAccount: number,
discountAccount: number,
adjustmentAccount: number,
trx?: Knex.Transaction
): Promise<void> => {
const ledger = this.getCreditNoteGLedger(creditNote, payableAccount);
const ledger = this.getCreditNoteGLedger(
creditNote,
payableAccount,
discountAccount,
adjustmentAccount
);
await this.ledgerStorage.commit(tenantId, ledger, trx);
};
@@ -98,11 +110,18 @@ export default class CreditNoteGLEntries {
const ARAccount = await accountRepository.findOrCreateAccountReceivable(
creditNoteWithItems.currencyCode
);
const discountAccount = await accountRepository.findOrCreateDiscountAccount(
{}
);
const adjustmentAccount =
await accountRepository.findOrCreateOtherChargesAccount({});
// Saves the credit note GL entries.
await this.saveCreditNoteGLEntries(
tenantId,
creditNoteWithItems,
ARAccount.id,
discountAccount.id,
adjustmentAccount.id,
trx
);
};
@@ -169,7 +188,7 @@ export default class CreditNoteGLEntries {
return {
...commonEntry,
credit: creditNote.localAmount,
credit: creditNote.totalLocal,
accountId: ARAccountId,
contactId: creditNote.customerId,
index: 1,
@@ -206,6 +225,50 @@ export default class CreditNoteGLEntries {
}
);
/**
* Retrieves the credit note discount entry.
* @param {ICreditNote} creditNote
* @param {number} discountAccountId
* @returns {ILedgerEntry}
*/
private getDiscountEntry = (
creditNote: ICreditNote,
discountAccountId: number
): ILedgerEntry => {
const commonEntry = this.getCreditNoteCommonEntry(creditNote);
return {
...commonEntry,
credit: creditNote.discountAmountLocal,
accountId: discountAccountId,
index: 1,
accountNormal: AccountNormal.CREDIT,
};
};
/**
* Retrieves the credit note adjustment entry.
* @param {ICreditNote} creditNote
* @param {number} adjustmentAccountId
* @returns {ILedgerEntry}
*/
private getAdjustmentEntry = (
creditNote: ICreditNote,
adjustmentAccountId: number
): ILedgerEntry => {
const commonEntry = this.getCreditNoteCommonEntry(creditNote);
const adjustmentAmount = Math.abs(creditNote.adjustmentLocal);
return {
...commonEntry,
credit: creditNote.adjustmentLocal < 0 ? adjustmentAmount : 0,
debit: creditNote.adjustmentLocal > 0 ? adjustmentAmount : 0,
accountId: adjustmentAccountId,
accountNormal: AccountNormal.CREDIT,
index: 1,
};
};
/**
* Retrieve the credit note GL entries.
* @param {ICreditNote} creditNote - Credit note.
@@ -214,13 +277,21 @@ export default class CreditNoteGLEntries {
*/
public getCreditNoteGLEntries = (
creditNote: ICreditNote,
ARAccountId: number
ARAccountId: number,
discountAccountId: number,
adjustmentAccountId: number
): ILedgerEntry[] => {
const AREntry = this.getCreditNoteAREntry(creditNote, ARAccountId);
const getItemEntry = this.getCreditNoteItemEntry(creditNote);
const itemsEntries = creditNote.entries.map(getItemEntry);
return [AREntry, ...itemsEntries];
const discountEntry = this.getDiscountEntry(creditNote, discountAccountId);
const adjustmentEntry = this.getAdjustmentEntry(
creditNote,
adjustmentAccountId
);
return [AREntry, discountEntry, adjustmentEntry, ...itemsEntries];
};
}

View File

@@ -18,11 +18,18 @@ export class CreditNoteTransformer extends Transformer {
'formattedAmount',
'formattedCreditsUsed',
'formattedSubtotal',
'discountAmountFormatted',
'discountAmountLocalFormatted',
'discountPercentageFormatted',
'adjustmentFormatted',
'adjustmentLocalFormatted',
'totalFormatted',
'totalLocalFormatted',
'entries',
'attachments',
];
@@ -39,7 +46,7 @@ export class CreditNoteTransformer extends Transformer {
/**
* Retrieve formatted created at date.
* @param credit
* @param credit
* @returns {string}
*/
protected formattedCreatedAt = (credit): string => {
@@ -90,7 +97,7 @@ export class CreditNoteTransformer extends Transformer {
/**
* Retrieves formatted discount amount.
* @param credit
* @param credit
* @returns {string}
*/
protected discountAmountFormatted = (credit): string => {
@@ -100,20 +107,30 @@ export class CreditNoteTransformer extends Transformer {
});
};
/**
* Retrieves the formatted discount amount in local currency.
* @param {ICreditNote} credit
* @returns {string}
*/
protected discountAmountLocalFormatted = (credit): string => {
return formatNumber(credit.discountAmountLocal, {
currencyCode: credit.currencyCode,
excerptZero: true,
});
};
/**
* Retrieves formatted discount percentage.
* @param credit
* @param credit
* @returns {string}
*/
protected discountPercentageFormatted = (credit): string => {
return credit.discountPercentage
? `${credit.discountPercentage}%`
: '';
return credit.discountPercentage ? `${credit.discountPercentage}%` : '';
};
/**
* Retrieves formatted adjustment amount.
* @param credit
* @param credit
* @returns {string}
*/
protected adjustmentFormatted = (credit): string => {
@@ -123,9 +140,21 @@ export class CreditNoteTransformer extends Transformer {
});
};
/**
* Retrieves the formatted adjustment amount in local currency.
* @param {ICreditNote} credit
* @returns {string}
*/
protected adjustmentLocalFormatted = (credit): string => {
return formatNumber(credit.adjustmentLocal, {
currencyCode: this.context.organization.baseCurrency,
excerptZero: true,
});
};
/**
* Retrieves the formatted total.
* @param credit
* @param credit
* @returns {string}
*/
protected totalFormatted = (credit): string => {
@@ -136,7 +165,7 @@ export class CreditNoteTransformer extends Transformer {
/**
* Retrieves the formatted total in local currency.
* @param credit
* @param credit
* @returns {string}
*/
protected totalLocalFormatted = (credit): string => {