refactor: migrate to nestjs

This commit is contained in:
Ahmed Bouhuolia
2025-01-01 13:39:31 +02:00
parent 505c4b28a5
commit 8bacf3a001
7 changed files with 241 additions and 250 deletions

View File

@@ -35,6 +35,8 @@ import { InvoiceGLEntriesSubscriber } from './subscribers/InvoiceGLEntriesSubscr
import { SaleInvoiceGLEntries } from './ledger/InvoiceGLEntries';
import { LedgerModule } from '../Ledger/Ledger.module';
import { AccountsModule } from '../Accounts/Accounts.module';
import SaleInvoiceWriteoffSubscriber from './subscribers/SaleInvoiceWriteoffSubscriber';
import { SaleInvoiceWriteoffGLStorage } from './commands/writeoff/SaleInvoiceWriteoffGLStorage';
@Module({
imports: [
@@ -76,6 +78,8 @@ import { AccountsModule } from '../Accounts/Accounts.module';
GetInvoicePaymentsService,
SaleInvoiceGLEntries,
InvoiceGLEntriesSubscriber,
SaleInvoiceWriteoffGLStorage,
SaleInvoiceWriteoffSubscriber
],
})
export class SaleInvoicesModule {}

View File

@@ -1,104 +0,0 @@
// import { Service } from 'typedi';
// import { ISaleInvoice, AccountNormal, ILedgerEntry, ILedger } from '@/interfaces';
// import Ledger from '@/services/Accounting/Ledger';
// @Service()
// export class SaleInvoiceWriteoffGLEntries {
// /**
// * Retrieves the invoice write-off common GL entry.
// * @param {ISaleInvoice} saleInvoice
// */
// private getInvoiceWriteoffGLCommonEntry = (saleInvoice: ISaleInvoice) => {
// return {
// date: saleInvoice.invoiceDate,
// currencyCode: saleInvoice.currencyCode,
// exchangeRate: saleInvoice.exchangeRate,
// transactionId: saleInvoice.id,
// transactionType: 'InvoiceWriteOff',
// transactionNumber: saleInvoice.invoiceNo,
// referenceNo: saleInvoice.referenceNo,
// branchId: saleInvoice.branchId,
// };
// };
// /**
// * Retrieves the invoice write-off receiveable GL entry.
// * @param {number} ARAccountId
// * @param {ISaleInvoice} saleInvoice
// * @returns {ILedgerEntry}
// */
// private getInvoiceWriteoffGLReceivableEntry = (
// ARAccountId: number,
// saleInvoice: ISaleInvoice
// ): ILedgerEntry => {
// const commontEntry = this.getInvoiceWriteoffGLCommonEntry(saleInvoice);
// return {
// ...commontEntry,
// credit: saleInvoice.localWrittenoffAmount,
// accountId: ARAccountId,
// contactId: saleInvoice.customerId,
// debit: 0,
// index: 1,
// indexGroup: 300,
// accountNormal: saleInvoice.writtenoffExpenseAccount.accountNormal,
// };
// };
// /**
// * Retrieves the invoice write-off expense GL entry.
// * @param {ISaleInvoice} saleInvoice
// * @returns {ILedgerEntry}
// */
// private getInvoiceWriteoffGLExpenseEntry = (
// saleInvoice: ISaleInvoice
// ): ILedgerEntry => {
// const commontEntry = this.getInvoiceWriteoffGLCommonEntry(saleInvoice);
// return {
// ...commontEntry,
// debit: saleInvoice.localWrittenoffAmount,
// accountId: saleInvoice.writtenoffExpenseAccountId,
// credit: 0,
// index: 2,
// indexGroup: 300,
// accountNormal: AccountNormal.DEBIT,
// };
// };
// /**
// * Retrieves the invoice write-off GL entries.
// * @param {number} ARAccountId
// * @param {ISaleInvoice} saleInvoice
// * @returns {ILedgerEntry[]}
// */
// public getInvoiceWriteoffGLEntries = (
// ARAccountId: number,
// saleInvoice: ISaleInvoice
// ): ILedgerEntry[] => {
// const creditEntry = this.getInvoiceWriteoffGLExpenseEntry(saleInvoice);
// const debitEntry = this.getInvoiceWriteoffGLReceivableEntry(
// ARAccountId,
// saleInvoice
// );
// return [debitEntry, creditEntry];
// };
// /**
// * Retrieves the invoice write-off ledger.
// * @param {number} ARAccountId
// * @param {ISaleInvoice} saleInvoice
// * @returns {Ledger}
// */
// public getInvoiceWriteoffLedger = (
// ARAccountId: number,
// saleInvoice: ISaleInvoice
// ): ILedger => {
// const entries = this.getInvoiceWriteoffGLEntries(ARAccountId, saleInvoice);
// return new Ledger(entries);
// };
// }

View File

@@ -1,88 +0,0 @@
// import { Knex } from 'knex';
// import LedgerStorageService from '@/services/Accounting/LedgerStorageService';
// import HasTenancyService from '@/services/Tenancy/TenancyService';
// import { Service, Inject } from 'typedi';
// import { SaleInvoiceWriteoffGLEntries } from './SaleInvoiceWriteoffGLEntries';
// @Service()
// export class SaleInvoiceWriteoffGLStorage {
// @Inject()
// private invoiceWriteoffLedger: SaleInvoiceWriteoffGLEntries;
// @Inject()
// private ledgerStorage: LedgerStorageService;
// @Inject()
// private tenancy: HasTenancyService;
// /**
// * Writes the invoice write-off GL entries.
// * @param {number} tenantId
// * @param {number} saleInvoiceId
// * @param {Knex.Transaction} trx
// * @returns {Promise<void>}
// */
// public writeInvoiceWriteoffEntries = async (
// tenantId: number,
// saleInvoiceId: number,
// trx?: Knex.Transaction
// ) => {
// const { SaleInvoice } = this.tenancy.models(tenantId);
// const { accountRepository } = this.tenancy.repositories(tenantId);
// // Retrieves the sale invoice.
// const saleInvoice = await SaleInvoice.query(trx)
// .findById(saleInvoiceId)
// .withGraphFetched('writtenoffExpenseAccount');
// // Find or create the A/R account.
// const ARAccount = await accountRepository.findOrCreateAccountReceivable(
// saleInvoice.currencyCode,
// {},
// trx
// );
// // Retrieves the invoice write-off ledger.
// const ledger = this.invoiceWriteoffLedger.getInvoiceWriteoffLedger(
// ARAccount.id,
// saleInvoice
// );
// return this.ledgerStorage.commit(tenantId, ledger, trx);
// };
// /**
// * Rewrites the invoice write-off GL entries.
// * @param {number} tenantId
// * @param {number} saleInvoiceId
// * @param {Knex.Transactio} actiontrx
// * @returns {Promise<void>}
// */
// public rewriteInvoiceWriteoffEntries = async (
// tenantId: number,
// saleInvoiceId: number,
// trx?: Knex.Transaction
// ) => {
// await this.revertInvoiceWriteoffEntries(tenantId, saleInvoiceId, trx);
// await this.writeInvoiceWriteoffEntries(tenantId, saleInvoiceId, trx);
// };
// /**
// * Reverts the invoice write-off GL entries.
// * @param {number} tenantId
// * @param {number} saleInvoiceId
// * @param {Knex.Transaction} trx
// * @returns {Promise<void>}
// */
// public revertInvoiceWriteoffEntries = async (
// tenantId: number,
// saleInvoiceId: number,
// trx?: Knex.Transaction
// ) => {
// await this.ledgerStorage.deleteByReference(
// tenantId,
// saleInvoiceId,
// 'InvoiceWriteOff',
// trx
// );
// };
// }

View File

@@ -0,0 +1,111 @@
import { SaleInvoice } from '../../models/SaleInvoice';
import { ILedger } from '@/modules/Ledger/types/Ledger.types';
import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
import { AccountNormal } from '@/interfaces/Account';
import { Ledger } from '@/modules/Ledger/Ledger';
export class SaleInvoiceWriteoffGL {
private saleInvoiceModel: SaleInvoice;
private ARAccountId: number;
/**
* Sets the sale invoice model.
* @param {SaleInvoice} saleInvoiceModel -
*/
constructor(saleInvoiceModel: SaleInvoice) {
this.saleInvoiceModel = saleInvoiceModel;
}
/**
* Sets the A/R account ID.
* @param {number} ARAccountId -
*/
setARAccountId(ARAccountId: number) {
this.ARAccountId = ARAccountId;
return this;
}
/**
* Retrieves the invoice write-off common GL entry.
* @param {ISaleInvoice} saleInvoice
*/
private get invoiceWriteoffGLCommonEntry() {
return {
date: this.saleInvoiceModel.invoiceDate,
currencyCode: this.saleInvoiceModel.currencyCode,
exchangeRate: this.saleInvoiceModel.exchangeRate,
transactionId: this.saleInvoiceModel.id,
transactionType: 'InvoiceWriteOff',
transactionNumber: this.saleInvoiceModel.invoiceNo,
referenceNo: this.saleInvoiceModel.referenceNo,
branchId: this.saleInvoiceModel.branchId,
};
}
/**
* Retrieves the invoice write-off receiveable GL entry.
* @param {number} ARAccountId
* @param {ISaleInvoice} saleInvoice
* @returns {ILedgerEntry}
*/
private get invoiceWriteoffGLReceivableEntry(): ILedgerEntry {
const commontEntry = this.invoiceWriteoffGLCommonEntry;
return {
...commontEntry,
credit: this.saleInvoiceModel.localWrittenoffAmount,
accountId: this.ARAccountId,
contactId: this.saleInvoiceModel.customerId,
debit: 0,
index: 1,
indexGroup: 300,
accountNormal:
this.saleInvoiceModel.writtenoffExpenseAccount.accountNormal,
};
}
/**
* Retrieves the invoice write-off expense GL entry.
* @param {ISaleInvoice} saleInvoice
* @returns {ILedgerEntry}
*/
private get invoiceWriteoffGLExpenseEntry(): ILedgerEntry {
const commontEntry = this.invoiceWriteoffGLCommonEntry;
return {
...commontEntry,
debit: this.saleInvoiceModel.writtenoffAmount,
accountId: this.saleInvoiceModel.writtenoffExpenseAccountId,
credit: 0,
index: 2,
indexGroup: 300,
accountNormal: AccountNormal.DEBIT,
};
}
/**
* Retrieves the invoice write-off GL entries.
* @returns {ILedgerEntry[]}
*/
public getInvoiceWriteoffGLEntries(): ILedgerEntry[] {
const creditEntry = this.invoiceWriteoffGLExpenseEntry;
const debitEntry = this.invoiceWriteoffGLReceivableEntry;
return [debitEntry, creditEntry];
}
/**
* Retrieves the invoice write-off ledger.
* @param {number} ARAccountId
* @param {ISaleInvoice} saleInvoice
* @returns {Ledger}
*/
public getInvoiceWriteoffLedger(): ILedger {
const entries = this.getInvoiceWriteoffGLEntries();
return new Ledger(entries);
}
}

View File

@@ -0,0 +1,87 @@
import { Inject, Injectable } from '@nestjs/common';
import { Knex } from 'knex';
import { Account } from '@/modules/Accounts/models/Account.model';
import { AccountRepository } from '@/modules/Accounts/repositories/Account.repository';
import { LedgerStorageService } from '@/modules/Ledger/LedgerStorage.service';
import { SaleInvoice } from '../../models/SaleInvoice';
import { SaleInvoiceWriteoffGL } from './SaleInvoiceWriteoffGL';
@Injectable()
export class SaleInvoiceWriteoffGLStorage {
/**
* @param {LedgerStorageService} ledgerStorage - Ledger storage service.
* @param {AccountRepository} accountRepository - Account repository.
* @param {Account} accountModel - Account model.
* @param {SaleInvoice} saleInvoiceModel - Sale invoice model.
*/
constructor(
private readonly ledgerStorage: LedgerStorageService,
private readonly accountRepository: AccountRepository,
@Inject(Account.name) private readonly accountModel: typeof Account,
@Inject(SaleInvoice.name)
private readonly saleInvoiceModel: typeof SaleInvoice,
) {}
/**
* Writes the invoice write-off GL entries.
* @param {number} saleInvoiceId - Sale invoice id.
* @param {Knex.Transaction} trx - Knex transaction.
* @returns {Promise<void>}
*/
public async writeInvoiceWriteoffEntries(
saleInvoiceId: number,
trx?: Knex.Transaction,
) {
// Retrieves the sale invoice.
const saleInvoice = await this.saleInvoiceModel
.query(trx)
.findById(saleInvoiceId)
.withGraphFetched('writtenoffExpenseAccount');
// Find or create the A/R account.
const ARAccount =
await this.accountRepository.findOrCreateAccountReceivable(
saleInvoice.currencyCode,
{},
trx,
);
const ledger = new SaleInvoiceWriteoffGL(saleInvoice)
.setARAccountId(ARAccount.id)
.getInvoiceWriteoffLedger();
return this.ledgerStorage.commit(ledger, trx);
}
/**
* Rewrites the invoice write-off GL entries.
* @param {number} saleInvoiceId - Sale invoice id.
* @param {Knex.Transaction} trx - Knex transaction.
* @returns {Promise<void>}
*/
public async rewriteInvoiceWriteoffEntries(
saleInvoiceId: number,
trx?: Knex.Transaction,
) {
await this.revertInvoiceWriteoffEntries(saleInvoiceId, trx);
await this.writeInvoiceWriteoffEntries(saleInvoiceId, trx);
}
/**
* Reverts the invoice write-off GL entries.
* @param {number} saleInvoiceId - Sale invoice id.
* @param {Knex.Transaction} trx - Knex transaction.
* @returns {Promise<void>}
*/
public revertInvoiceWriteoffEntries = async (
saleInvoiceId: number,
trx?: Knex.Transaction,
) => {
await this.ledgerStorage.deleteByReference(
saleInvoiceId,
'InvoiceWriteOff',
trx,
);
};
}

View File

@@ -15,6 +15,7 @@ import { TaxRateTransaction } from '@/modules/TaxRates/models/TaxRateTransaction
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
import { Document } from '@/modules/ChromiumlyTenancy/models/Document';
import { DiscountType } from '@/common/types/Discount';
import { Account } from '@/modules/Accounts/models/Account.model';
export class SaleInvoice extends BaseModel {
public taxAmountWithheld: number;
@@ -51,9 +52,10 @@ export class SaleInvoice extends BaseModel {
public branchId: number;
public warehouseId: number;
public taxes: TaxRateTransaction[];
public entries: ItemEntry[];
public attachments: Document[];
public taxes!: TaxRateTransaction[];
public entries!: ItemEntry[];
public attachments!: Document[];
public writtenoffExpenseAccount!: Account;
/**
* Table name

View File

@@ -1,58 +1,37 @@
// import { Inject, Service } from 'typedi';
// import events from '@/subscribers/events';
// import {
// ISaleInvoiceWriteoffCreatePayload,
// ISaleInvoiceWrittenOffCanceledPayload,
// } from '@/interfaces';
// import { SaleInvoiceWriteoffGLStorage } from './SaleInvoiceWriteoffGLStorage';
import { Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import {
ISaleInvoiceWriteoffCreatePayload,
ISaleInvoiceWrittenOffCanceledPayload,
} from '../SaleInvoice.types';
import { SaleInvoiceWriteoffGLStorage } from '../commands/writeoff/SaleInvoiceWriteoffGLStorage';
import { events } from '@/common/events/events';
// @Service()
// export default class SaleInvoiceWriteoffSubscriber {
// @Inject()
// writeGLStorage: SaleInvoiceWriteoffGLStorage;
@Injectable()
export default class SaleInvoiceWriteoffSubscriber {
constructor(private readonly writeGLStorage: SaleInvoiceWriteoffGLStorage) {}
// /**
// * Attaches events.
// */
// public attach(bus) {
// bus.subscribe(
// events.saleInvoice.onWrittenoff,
// this.writeJournalEntriesOnceWriteoffCreate
// );
// bus.subscribe(
// events.saleInvoice.onWrittenoffCanceled,
// this.revertJournalEntriesOnce
// );
// }
// /**
// * Write the written-off sale invoice journal entries.
// * @param {ISaleInvoiceWriteoffCreatePayload}
// */
// private writeJournalEntriesOnceWriteoffCreate = async ({
// tenantId,
// saleInvoice,
// trx,
// }: ISaleInvoiceWriteoffCreatePayload) => {
// await this.writeGLStorage.writeInvoiceWriteoffEntries(
// tenantId,
// saleInvoice.id,
// trx
// );
// };
/**
* Write the written-off sale invoice journal entries.
* @param {ISaleInvoiceWriteoffCreatePayload}
*/
@OnEvent(events.saleInvoice.onWrittenoff)
public async writeJournalEntriesOnceWriteoffCreate({
saleInvoice,
trx,
}: ISaleInvoiceWriteoffCreatePayload) {
await this.writeGLStorage.writeInvoiceWriteoffEntries(saleInvoice.id, trx);
}
// /**
// * Reverts the written-of sale invoice jounral entries.
// * @param {ISaleInvoiceWrittenOffCanceledPayload}
// */
// private revertJournalEntriesOnce = async ({
// tenantId,
// saleInvoice,
// trx,
// }: ISaleInvoiceWrittenOffCanceledPayload) => {
// await this.writeGLStorage.revertInvoiceWriteoffEntries(
// tenantId,
// saleInvoice.id,
// trx
// );
// };
// }
/**
* Reverts the written-of sale invoice jounral entries.
* @param {ISaleInvoiceWrittenOffCanceledPayload}
*/
@OnEvent(events.saleInvoice.onWrittenoffCanceled)
public async revertJournalEntriesOnce({
saleInvoice,
trx,
}: ISaleInvoiceWrittenOffCanceledPayload) {
await this.writeGLStorage.revertInvoiceWriteoffEntries(saleInvoice.id, trx);
}
}