refactor: GL entries

This commit is contained in:
Ahmed Bouhuolia
2024-12-31 14:57:24 +02:00
parent 1b15261adb
commit a819d6c1ba
54 changed files with 2669 additions and 2298 deletions

View File

@@ -18,6 +18,8 @@ import { TemplateInjectableModule } from '../TemplateInjectable/TemplateInjectab
import { GetCreditNote } from './queries/GetCreditNote.service';
import { CreditNoteBrandingTemplate } from './queries/CreditNoteBrandingTemplate.service';
import { AutoIncrementOrdersModule } from '../AutoIncrementOrders/AutoIncrementOrders.module';
import CreditNoteGLEntries from './commands/CreditNoteGLEntries';
import CreditNoteGLEntriesSubscriber from './subscribers/CreditNoteGLEntriesSubscriber';
@Module({
imports: [
@@ -40,7 +42,9 @@ import { AutoIncrementOrdersModule } from '../AutoIncrementOrders/AutoIncrementO
CreditNoteAutoIncrementService,
GetCreditNoteState,
CreditNoteApplication,
CreditNoteBrandingTemplate
CreditNoteBrandingTemplate,
CreditNoteGLEntries,
CreditNoteGLEntriesSubscriber
],
exports: [
CreateCreditNoteService,

View File

@@ -1,297 +1,293 @@
// import { Inject, Service } from 'typedi';
// import { Knex } from 'knex';
// import * as R from 'ramda';
// import {
// AccountNormal,
// IItemEntry,
// ILedgerEntry,
// ICreditNote,
// ILedger,
// ICreditNoteGLCommonEntry,
// } from '@/interfaces';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// import Ledger from '@/services/Accounting/Ledger';
// import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
// import { SaleReceipt } from '@/models';
import { Inject, Service } from 'typedi';
import { Knex } from 'knex';
import * as R from 'ramda';
import {
AccountNormal,
IItemEntry,
ILedgerEntry,
ICreditNote,
ILedger,
ICreditNoteGLCommonEntry,
} from '@/interfaces';
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 {
// @Inject()
// private tenancy: HasTenancyService;
@Service()
export default class CreditNoteGLEntries {
@Inject()
private tenancy: HasTenancyService;
// @Inject()
// private ledgerStorage: LedgerStorageService;
@Inject()
private ledgerStorage: LedgerStorageService;
// /**
// * Retrieves the credit note GL.
// * @param {ICreditNote} creditNote
// * @param {number} receivableAccount
// * @returns {Ledger}
// */
// private getCreditNoteGLedger = (
// creditNote: ICreditNote,
// receivableAccount: number,
// discountAccount: number,
// adjustmentAccount: number
// ): Ledger => {
// const ledgerEntries = this.getCreditNoteGLEntries(
// creditNote,
// receivableAccount,
// discountAccount,
// adjustmentAccount
// );
// return new Ledger(ledgerEntries);
// };
/**
* Retrieves the credit note GL.
* @param {ICreditNote} creditNote
* @param {number} receivableAccount
* @returns {Ledger}
*/
private getCreditNoteGLedger = (
creditNote: ICreditNote,
receivableAccount: number,
discountAccount: number,
adjustmentAccount: number
): Ledger => {
const ledgerEntries = this.getCreditNoteGLEntries(
creditNote,
receivableAccount,
discountAccount,
adjustmentAccount
);
return new Ledger(ledgerEntries);
};
// /**
// * Saves credit note GL entries.
// * @param {number} tenantId -
// * @param {ICreditNote} creditNote - Credit note model.
// * @param {number} payableAccount - Payable account id.
// * @param {Knex.Transaction} trx
// */
// public saveCreditNoteGLEntries = async (
// tenantId: number,
// creditNote: ICreditNote,
// payableAccount: number,
// discountAccount: number,
// adjustmentAccount: number,
// trx?: Knex.Transaction
// ): Promise<void> => {
// const ledger = this.getCreditNoteGLedger(
// creditNote,
// payableAccount,
// discountAccount,
// adjustmentAccount
// );
/**
* Saves credit note GL entries.
* @param {number} tenantId -
* @param {ICreditNote} creditNote - Credit note model.
* @param {number} payableAccount - Payable account id.
* @param {Knex.Transaction} trx
*/
public saveCreditNoteGLEntries = async (
tenantId: number,
creditNote: ICreditNote,
payableAccount: number,
discountAccount: number,
adjustmentAccount: number,
trx?: Knex.Transaction
): Promise<void> => {
const ledger = this.getCreditNoteGLedger(
creditNote,
payableAccount,
discountAccount,
adjustmentAccount
);
// await this.ledgerStorage.commit(tenantId, ledger, trx);
// };
await this.ledgerStorage.commit(tenantId, ledger, trx);
};
// /**
// * Reverts the credit note associated GL entries.
// * @param {number} tenantId
// * @param {number} vendorCreditId
// * @param {Knex.Transaction} trx
// */
// public revertVendorCreditGLEntries = async (
// tenantId: number,
// creditNoteId: number,
// trx?: Knex.Transaction
// ): Promise<void> => {
// await this.ledgerStorage.deleteByReference(
// tenantId,
// creditNoteId,
// 'CreditNote',
// trx
// );
// };
/**
* Reverts the credit note associated GL entries.
* @param {number} tenantId
* @param {number} vendorCreditId
* @param {Knex.Transaction} trx
*/
public revertVendorCreditGLEntries = async (
creditNoteId: number,
trx?: Knex.Transaction
): Promise<void> => {
await this.ledgerStorage.deleteByReference(
creditNoteId,
'CreditNote',
trx
);
};
// /**
// * Writes vendor credit associated GL entries.
// * @param {number} tenantId - Tenant id.
// * @param {number} creditNoteId - Credit note id.
// * @param {Knex.Transaction} trx - Knex transactions.
// */
// public createVendorCreditGLEntries = async (
// tenantId: number,
// creditNoteId: number,
// trx?: Knex.Transaction
// ): Promise<void> => {
// const { CreditNote } = this.tenancy.models(tenantId);
// const { accountRepository } = this.tenancy.repositories(tenantId);
/**
* Writes vendor credit associated GL entries.
* @param {number} tenantId - Tenant id.
* @param {number} creditNoteId - Credit note id.
* @param {Knex.Transaction} trx - Knex transactions.
*/
public createVendorCreditGLEntries = async (
creditNoteId: number,
trx?: Knex.Transaction
): Promise<void> => {
const { CreditNote } = this.tenancy.models(tenantId);
const { accountRepository } = this.tenancy.repositories(tenantId);
// // Retrieve the credit note with associated entries and items.
// const creditNoteWithItems = await CreditNote.query(trx)
// .findById(creditNoteId)
// .withGraphFetched('entries.item');
// Retrieve the credit note with associated entries and items.
const creditNoteWithItems = await CreditNote.query(trx)
.findById(creditNoteId)
.withGraphFetched('entries.item');
// // Retreive the the `accounts receivable` account based on the given currency.
// 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
// );
// };
// Retreive the the `accounts receivable` account based on the given currency.
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
);
};
// /**
// * Edits vendor credit associated GL entries.
// * @param {number} tenantId
// * @param {number} creditNoteId
// * @param {Knex.Transaction} trx
// */
// public editVendorCreditGLEntries = async (
// tenantId: number,
// creditNoteId: number,
// trx?: Knex.Transaction
// ): Promise<void> => {
// // Reverts vendor credit GL entries.
// await this.revertVendorCreditGLEntries(tenantId, creditNoteId, trx);
/**
* Edits vendor credit associated GL entries.
* @param {number} tenantId
* @param {number} creditNoteId
* @param {Knex.Transaction} trx
*/
public editVendorCreditGLEntries = async (
creditNoteId: number,
trx?: Knex.Transaction
): Promise<void> => {
// Reverts vendor credit GL entries.
await this.revertVendorCreditGLEntries(creditNoteId, trx);
// // Creates vendor credit Gl entries.
// await this.createVendorCreditGLEntries(tenantId, creditNoteId, trx);
// };
// Creates vendor credit Gl entries.
await this.createVendorCreditGLEntries(creditNoteId, trx);
};
// /**
// * Retrieve the credit note common entry.
// * @param {ICreditNote} creditNote -
// * @returns {ICreditNoteGLCommonEntry}
// */
// private getCreditNoteCommonEntry = (
// creditNote: ICreditNote
// ): ICreditNoteGLCommonEntry => {
// return {
// date: creditNote.creditNoteDate,
// userId: creditNote.userId,
// currencyCode: creditNote.currencyCode,
// exchangeRate: creditNote.exchangeRate,
/**
* Retrieve the credit note common entry.
* @param {ICreditNote} creditNote -
* @returns {ICreditNoteGLCommonEntry}
*/
private getCreditNoteCommonEntry = (
creditNote: ICreditNote
): ICreditNoteGLCommonEntry => {
return {
date: creditNote.creditNoteDate,
userId: creditNote.userId,
currencyCode: creditNote.currencyCode,
exchangeRate: creditNote.exchangeRate,
// transactionType: 'CreditNote',
// transactionId: creditNote.id,
transactionType: 'CreditNote',
transactionId: creditNote.id,
// transactionNumber: creditNote.creditNoteNumber,
// referenceNumber: creditNote.referenceNo,
transactionNumber: creditNote.creditNoteNumber,
referenceNumber: creditNote.referenceNo,
// createdAt: creditNote.createdAt,
// indexGroup: 10,
createdAt: creditNote.createdAt,
indexGroup: 10,
// credit: 0,
// debit: 0,
credit: 0,
debit: 0,
// branchId: creditNote.branchId,
// };
// };
branchId: creditNote.branchId,
};
};
// /**
// * Retrieves the creidt note A/R entry.
// * @param {ICreditNote} creditNote -
// * @param {number} ARAccountId -
// * @returns {ILedgerEntry}
// */
// private getCreditNoteAREntry = (
// creditNote: ICreditNote,
// ARAccountId: number
// ): ILedgerEntry => {
// const commonEntry = this.getCreditNoteCommonEntry(creditNote);
/**
* Retrieves the creidt note A/R entry.
* @param {ICreditNote} creditNote -
* @param {number} ARAccountId -
* @returns {ILedgerEntry}
*/
private getCreditNoteAREntry = (
creditNote: ICreditNote,
ARAccountId: number
): ILedgerEntry => {
const commonEntry = this.getCreditNoteCommonEntry(creditNote);
// return {
// ...commonEntry,
// credit: creditNote.totalLocal,
// accountId: ARAccountId,
// contactId: creditNote.customerId,
// index: 1,
// accountNormal: AccountNormal.DEBIT,
// };
// };
return {
...commonEntry,
credit: creditNote.totalLocal,
accountId: ARAccountId,
contactId: creditNote.customerId,
index: 1,
accountNormal: AccountNormal.DEBIT,
};
};
// /**
// * Retrieve the credit note item entry.
// * @param {ICreditNote} creditNote
// * @param {IItemEntry} entry
// * @param {number} index
// * @returns {ILedgerEntry}
// */
// private getCreditNoteItemEntry = R.curry(
// (
// creditNote: ICreditNote,
// entry: IItemEntry,
// index: number
// ): ILedgerEntry => {
// const commonEntry = this.getCreditNoteCommonEntry(creditNote);
// const totalLocal = entry.totalExcludingTax * creditNote.exchangeRate;
/**
* Retrieve the credit note item entry.
* @param {ICreditNote} creditNote
* @param {IItemEntry} entry
* @param {number} index
* @returns {ILedgerEntry}
*/
private getCreditNoteItemEntry = R.curry(
(
creditNote: ICreditNote,
entry: IItemEntry,
index: number
): ILedgerEntry => {
const commonEntry = this.getCreditNoteCommonEntry(creditNote);
const totalLocal = entry.totalExcludingTax * creditNote.exchangeRate;
// return {
// ...commonEntry,
// debit: totalLocal,
// accountId: entry.sellAccountId || entry.item.sellAccountId,
// note: entry.description,
// index: index + 2,
// itemId: entry.itemId,
// itemQuantity: entry.quantity,
// accountNormal: AccountNormal.CREDIT,
// };
// }
// );
return {
...commonEntry,
debit: totalLocal,
accountId: entry.sellAccountId || entry.item.sellAccountId,
note: entry.description,
index: index + 2,
itemId: entry.itemId,
itemQuantity: entry.quantity,
accountNormal: AccountNormal.CREDIT,
};
}
);
// /**
// * 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);
/**
* 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,
// };
// };
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);
/**
* 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,
// };
// };
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.
// * @param {IAccount} receivableAccount - Receviable account.
// * @returns {ILedgerEntry[]} - Ledger entries.
// */
// public getCreditNoteGLEntries = (
// creditNote: ICreditNote,
// ARAccountId: number,
// discountAccountId: number,
// adjustmentAccountId: number
// ): ILedgerEntry[] => {
// const AREntry = this.getCreditNoteAREntry(creditNote, ARAccountId);
/**
* Retrieve the credit note GL entries.
* @param {ICreditNote} creditNote - Credit note.
* @param {IAccount} receivableAccount - Receviable account.
* @returns {ILedgerEntry[]} - Ledger entries.
*/
public getCreditNoteGLEntries = (
creditNote: ICreditNote,
ARAccountId: number,
discountAccountId: number,
adjustmentAccountId: number
): ILedgerEntry[] => {
const AREntry = this.getCreditNoteAREntry(creditNote, ARAccountId);
// const getItemEntry = this.getCreditNoteItemEntry(creditNote);
// const itemsEntries = creditNote.entries.map(getItemEntry);
const getItemEntry = this.getCreditNoteItemEntry(creditNote);
const itemsEntries = creditNote.entries.map(getItemEntry);
// const discountEntry = this.getDiscountEntry(creditNote, discountAccountId);
// const adjustmentEntry = this.getAdjustmentEntry(
// creditNote,
// adjustmentAccountId
// );
const discountEntry = this.getDiscountEntry(creditNote, discountAccountId);
const adjustmentEntry = this.getAdjustmentEntry(
creditNote,
adjustmentAccountId
);
// return [AREntry, discountEntry, adjustmentEntry, ...itemsEntries];
// };
// }
return [AREntry, discountEntry, adjustmentEntry, ...itemsEntries];
};
}

View File

@@ -1,113 +1,78 @@
// import { Service, Inject } from 'typedi';
// import events from '@/subscribers/events';
// import {
// ICreditNoteCreatedPayload,
// ICreditNoteDeletedPayload,
// ICreditNoteEditedPayload,
// ICreditNoteOpenedPayload,
// } from '@/interfaces';
// import CreditNoteGLEntries from '../commands/CreditNoteGLEntries';
import {
ICreditNoteCreatedPayload,
ICreditNoteDeletedPayload,
ICreditNoteEditedPayload,
ICreditNoteOpenedPayload,
} from '../types/CreditNotes.types';
import CreditNoteGLEntries from '../commands/CreditNoteGLEntries';
import { OnEvent } from '@nestjs/event-emitter';
import { Injectable } from '@nestjs/common';
import { events } from '@/common/events/events';
// @Service()
// export default class CreditNoteGLEntriesSubscriber {
// @Inject()
// private creditNoteGLEntries: CreditNoteGLEntries;
@Injectable()
export default class CreditNoteGLEntriesSubscriber {
constructor(private readonly creditNoteGLEntries: CreditNoteGLEntries) {}
// /**
// * Attaches events with handlers.
// * @param bus
// */
// public attach(bus) {
// bus.subscribe(
// events.creditNote.onCreated,
// this.writeGlEntriesOnceCreditNoteCreated
// );
// bus.subscribe(
// events.creditNote.onOpened,
// this.writeGLEntriesOnceCreditNoteOpened
// );
// bus.subscribe(
// events.creditNote.onEdited,
// this.editVendorCreditGLEntriesOnceEdited
// );
// bus.subscribe(
// events.creditNote.onDeleted,
// this.revertGLEntriesOnceCreditNoteDeleted
// );
// }
/**
* Writes the GL entries once the credit note transaction created or open.
* @param {ICreditNoteCreatedPayload|ICreditNoteOpenedPayload} payload -
*/
@OnEvent(events.creditNote.onCreated)
public async writeGlEntriesOnceCreditNoteCreated({
creditNote,
trx,
}: ICreditNoteCreatedPayload | ICreditNoteOpenedPayload) {
// Can't continue if the credit note is not published yet.
if (!creditNote.isPublished) return;
// /**
// * Writes the GL entries once the credit note transaction created or open.
// * @private
// * @param {ICreditNoteCreatedPayload|ICreditNoteOpenedPayload} payload -
// */
// private writeGlEntriesOnceCreditNoteCreated = async ({
// tenantId,
// creditNote,
// creditNoteId,
// trx,
// }: ICreditNoteCreatedPayload | ICreditNoteOpenedPayload) => {
// // Can't continue if the credit note is not published yet.
// if (!creditNote.isPublished) return;
await this.creditNoteGLEntries.createVendorCreditGLEntries(
creditNote.id,
trx,
);
}
// await this.creditNoteGLEntries.createVendorCreditGLEntries(
// tenantId,
// creditNoteId,
// trx
// );
// };
/**
* Writes the GL entries once the vendor credit transaction opened.
* @param {ICreditNoteOpenedPayload} payload
*/
@OnEvent(events.creditNote.onOpened)
public async writeGLEntriesOnceCreditNoteOpened({
creditNote,
trx,
}: ICreditNoteOpenedPayload) {
await this.creditNoteGLEntries.createVendorCreditGLEntries(
creditNote.id,
trx,
);
}
// /**
// * Writes the GL entries once the vendor credit transaction opened.
// * @param {ICreditNoteOpenedPayload} payload
// */
// private writeGLEntriesOnceCreditNoteOpened = async ({
// tenantId,
// creditNoteId,
// trx,
// }: ICreditNoteOpenedPayload) => {
// await this.creditNoteGLEntries.createVendorCreditGLEntries(
// tenantId,
// creditNoteId,
// trx
// );
// };
/**
* Reverts GL entries once credit note deleted.
*/
@OnEvent(events.creditNote.onDeleted)
public async revertGLEntriesOnceCreditNoteDeleted({
oldCreditNote,
creditNoteId,
trx,
}: ICreditNoteDeletedPayload) {
// Can't continue if the credit note is not published yet.
if (!oldCreditNote.isPublished) return;
// /**
// * Reverts GL entries once credit note deleted.
// */
// private revertGLEntriesOnceCreditNoteDeleted = async ({
// tenantId,
// oldCreditNote,
// creditNoteId,
// trx,
// }: ICreditNoteDeletedPayload) => {
// // Can't continue if the credit note is not published yet.
// if (!oldCreditNote.isPublished) return;
await this.creditNoteGLEntries.revertVendorCreditGLEntries(creditNoteId);
}
// await this.creditNoteGLEntries.revertVendorCreditGLEntries(
// tenantId,
// creditNoteId
// );
// };
/**
* Edits vendor credit associated GL entries once the transaction edited.
* @param {ICreditNoteEditedPayload} payload -
*/
@OnEvent(events.creditNote.onEdited)
public async editVendorCreditGLEntriesOnceEdited({
creditNote,
trx,
}: ICreditNoteEditedPayload) {
// Can't continue if the credit note is not published yet.
if (!creditNote.isPublished) return;
// /**
// * Edits vendor credit associated GL entries once the transaction edited.
// * @param {ICreditNoteEditedPayload} payload -
// */
// private editVendorCreditGLEntriesOnceEdited = async ({
// tenantId,
// creditNote,
// creditNoteId,
// trx,
// }: ICreditNoteEditedPayload) => {
// // Can't continue if the credit note is not published yet.
// if (!creditNote.isPublished) return;
// await this.creditNoteGLEntries.editVendorCreditGLEntries(
// tenantId,
// creditNoteId,
// trx
// );
// };
// }
await this.creditNoteGLEntries.editVendorCreditGLEntries(creditNote.id, trx);
}
}