From 3ad34ba56f2652a25747fd8470911aa231644f18 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Tue, 31 Dec 2024 23:51:24 +0200 Subject: [PATCH] refactor: migrate ledger subscribers to nestjs --- .../modules/CreditNotes/CreditNotes.module.ts | 12 +- .../CreditNotes/commands/CreditNoteGL.ts | 186 ++++++++++ .../commands/CreditNoteGLEntries.ts | 283 ++-------------- .../modules/CreditNotes/models/CreditNote.ts | 1 + .../CreditNoteGLEntriesSubscriber.ts | 4 +- .../subscribers/ExpenseGLEntries.service.ts | 5 +- .../ExpenseGLEntries.subscriber.ts | 2 +- .../src/modules/Ledger/types/Ledger.types.ts | 2 +- .../PaymentsReceived.module.ts | 17 +- .../commands/CreatePaymentReceived.serivce.ts | 2 +- .../commands/PaymentReceivedGL.ts | 17 +- .../queries/GetPaymentReceivedPdf.service.ts | 2 +- .../PaymentReceivedAutoIncrementSubscriber.ts | 19 ++ .../PaymentReceivedGLEntriesSubscriber.ts | 61 ++++ ...aymentReceivedSmsNotificationSubscriber.ts | 40 +++ .../PaymentReceivedSmsSubscriber.ts | 0 .../PaymentReceivedSyncInvoices.ts | 71 ++++ .../VendorCredit/VendorCredits.module.ts | 6 +- .../VendorCredit/commands/VendorCreditGL.ts | 163 +++++++++ .../commands/VendorCreditGLEntries.ts | 320 +++++------------- .../VendorCreditGLEntriesSubscriber.ts | 177 ++++------ 21 files changed, 779 insertions(+), 611 deletions(-) create mode 100644 packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedAutoIncrementSubscriber.ts create mode 100644 packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSmsNotificationSubscriber.ts rename packages/server-nest/src/modules/PaymentReceived/{commands => subscribers}/PaymentReceivedSmsSubscriber.ts (100%) create mode 100644 packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSyncInvoices.ts create mode 100644 packages/server-nest/src/modules/VendorCredit/commands/VendorCreditGL.ts diff --git a/packages/server-nest/src/modules/CreditNotes/CreditNotes.module.ts b/packages/server-nest/src/modules/CreditNotes/CreditNotes.module.ts index 8f50385c4..caf5bdbb0 100644 --- a/packages/server-nest/src/modules/CreditNotes/CreditNotes.module.ts +++ b/packages/server-nest/src/modules/CreditNotes/CreditNotes.module.ts @@ -18,8 +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'; +import { CreditNoteGLEntries } from './commands/CreditNoteGLEntries'; +import { CreditNoteGLEntriesSubscriber } from './subscribers/CreditNoteGLEntriesSubscriber'; @Module({ imports: [ @@ -29,7 +29,7 @@ import CreditNoteGLEntriesSubscriber from './subscribers/CreditNoteGLEntriesSubs PdfTemplatesModule, ChromiumlyTenancyModule, TemplateInjectableModule, - AutoIncrementOrdersModule + AutoIncrementOrdersModule, ], providers: [ CreateCreditNoteService, @@ -44,12 +44,12 @@ import CreditNoteGLEntriesSubscriber from './subscribers/CreditNoteGLEntriesSubs CreditNoteApplication, CreditNoteBrandingTemplate, CreditNoteGLEntries, - CreditNoteGLEntriesSubscriber + CreditNoteGLEntriesSubscriber, ], exports: [ CreateCreditNoteService, GetCreditNote, - CommandCreditNoteDTOTransform, + CommandCreditNoteDTOTransform, EditCreditNoteService, OpenCreditNoteService, DeleteCreditNoteService, @@ -57,7 +57,7 @@ import CreditNoteGLEntriesSubscriber from './subscribers/CreditNoteGLEntriesSubs CreditNoteAutoIncrementService, GetCreditNoteState, CreditNoteApplication, - CreditNoteBrandingTemplate + CreditNoteBrandingTemplate, ], controllers: [CreditNotesController], }) diff --git a/packages/server-nest/src/modules/CreditNotes/commands/CreditNoteGL.ts b/packages/server-nest/src/modules/CreditNotes/commands/CreditNoteGL.ts index e69de29bb..b143f0c91 100644 --- a/packages/server-nest/src/modules/CreditNotes/commands/CreditNoteGL.ts +++ b/packages/server-nest/src/modules/CreditNotes/commands/CreditNoteGL.ts @@ -0,0 +1,186 @@ +import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types'; +import { CreditNote } from '../models/CreditNote'; +import { AccountNormal } from '@/interfaces/Account'; +import { Ledger } from '@/modules/Ledger/Ledger'; +import { ItemEntry } from '@/modules/Items/models/ItemEntry'; + +export class CreditNoteGL { + creditNoteModel: CreditNote; + ARAccountId: number; + discountAccountId: number; + adjustmentAccountId: number; + + /** + * @param {CreditNote} creditNoteModel - Credit note model. + */ + constructor(creditNoteModel: CreditNote) { + this.creditNoteModel = creditNoteModel; + } + + /** + * Sets the A/R account id. + * @param {number} ARAccountId - A/R account id. + */ + public setARAccountId(ARAccountId: number) { + this.ARAccountId = ARAccountId; + return this; + } + + /** + * Sets the discount account id. + * @param {number} discountAccountId - Discount account id. + */ + public setDiscountAccountId(discountAccountId: number) { + this.discountAccountId = discountAccountId; + return this; + } + + /** + * Sets the adjustment account id. + * @param {number} adjustmentAccountId - Adjustment account id. + */ + public setAdjustmentAccountId(adjustmentAccountId: number) { + this.adjustmentAccountId = adjustmentAccountId; + return this; + } + + /** + * Retrieve the credit note common entry. + * @returns {ICreditNoteGLCommonEntry} + */ + private get creditNoteCommonEntry() { + return { + date: this.creditNoteModel.creditNoteDate, + userId: this.creditNoteModel.userId, + currencyCode: this.creditNoteModel.currencyCode, + exchangeRate: this.creditNoteModel.exchangeRate, + + transactionType: 'CreditNote', + transactionId: this.creditNoteModel.id, + + transactionNumber: this.creditNoteModel.creditNoteNumber, + referenceNumber: this.creditNoteModel.referenceNo, + + createdAt: this.creditNoteModel.createdAt, + indexGroup: 10, + + credit: 0, + debit: 0, + + branchId: this.creditNoteModel.branchId, + }; + } + + /** + * Retrieves the creidt note A/R entry. + * @param {ICreditNote} creditNote - + * @param {number} ARAccountId - + * @returns {ILedgerEntry} + */ + private get creditNoteAREntry() { + const commonEntry = this.creditNoteCommonEntry; + + return { + ...commonEntry, + credit: this.creditNoteModel.totalLocal, + accountId: this.ARAccountId, + contactId: this.creditNoteModel.customerId, + index: 1, + accountNormal: AccountNormal.DEBIT, + }; + } + + /** + * Retrieve the credit note item entry. + * @param {ItemEntry} entry + * @param {number} index + * @returns {ILedgerEntry} + */ + private getCreditNoteItemEntry( + entry: ItemEntry, + index: number, + ): ILedgerEntry { + const commonEntry = this.creditNoteCommonEntry; + const totalLocal = + entry.totalExcludingTax * this.creditNoteModel.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, + }; + } + + /** + * Retrieves the credit note discount entry. + * @param {ICreditNote} creditNote + * @param {number} discountAccountId + * @returns {ILedgerEntry} + */ + private get discountEntry(): ILedgerEntry { + const commonEntry = this.creditNoteCommonEntry; + + return { + ...commonEntry, + credit: this.creditNoteModel.discountAmountLocal, + accountId: this.discountAccountId, + accountNormal: AccountNormal.CREDIT, + index: 1, + }; + } + + /** + * Retrieves the credit note adjustment entry. + * @param {ICreditNote} creditNote + * @param {number} adjustmentAccountId + * @returns {ILedgerEntry} + */ + private get adjustmentEntry(): ILedgerEntry { + const commonEntry = this.creditNoteCommonEntry; + const adjustmentAmount = Math.abs(this.creditNoteModel.adjustmentLocal); + + return { + ...commonEntry, + credit: this.creditNoteModel.adjustmentLocal < 0 ? adjustmentAmount : 0, + debit: this.creditNoteModel.adjustmentLocal > 0 ? adjustmentAmount : 0, + accountId: this.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(): ILedgerEntry[] { + const AREntry = this.creditNoteAREntry; + + const getItemEntry = this.getCreditNoteItemEntry; + const itemsEntries = this.creditNoteModel.entries.map(getItemEntry); + + const discountEntry = this.discountEntry; + const adjustmentEntry = this.adjustmentEntry; + + return [AREntry, discountEntry, adjustmentEntry, ...itemsEntries]; + } + + /** + * Retrieves the credit note GL. + * @param {ICreditNote} creditNote + * @param {number} receivableAccount + * @returns {Ledger} + */ + public getCreditNoteLedger(): Ledger { + const ledgerEntries = this.getCreditNoteGLEntries(); + + return new Ledger(ledgerEntries); + } +} diff --git a/packages/server-nest/src/modules/CreditNotes/commands/CreditNoteGLEntries.ts b/packages/server-nest/src/modules/CreditNotes/commands/CreditNoteGLEntries.ts index 95586ee2e..e2eb4d459 100644 --- a/packages/server-nest/src/modules/CreditNotes/commands/CreditNoteGLEntries.ts +++ b/packages/server-nest/src/modules/CreditNotes/commands/CreditNoteGLEntries.ts @@ -1,137 +1,75 @@ -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 { CreditNoteGL } from './CreditNoteGL'; +import { Inject, Injectable } from '@nestjs/common'; +import { LedgerStorageService } from '@/modules/Ledger/LedgerStorage.service'; +import { CreditNote } from '../models/CreditNote'; +import { AccountRepository } from '@/modules/Accounts/repositories/Account.repository'; -@Service() -export default class CreditNoteGLEntries { - @Inject() - private tenancy: HasTenancyService; +@Injectable() +export class CreditNoteGLEntries { + constructor( + private readonly ledgerStorage: LedgerStorageService, + private readonly accountRepository: AccountRepository, - @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); - }; - - /** - * 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 => { - const ledger = this.getCreditNoteGLedger( - creditNote, - payableAccount, - discountAccount, - adjustmentAccount - ); - - await this.ledgerStorage.commit(tenantId, ledger, trx); - }; + @Inject(CreditNote.name) + private readonly creditNoteModel: typeof CreditNote, + ) {} /** * Reverts the credit note associated GL entries. - * @param {number} tenantId - * @param {number} vendorCreditId + * @param {number} creditNoteId - Credit note id. * @param {Knex.Transaction} trx */ public revertVendorCreditGLEntries = async ( creditNoteId: number, - trx?: Knex.Transaction + trx?: Knex.Transaction, ): Promise => { - await this.ledgerStorage.deleteByReference( - creditNoteId, - 'CreditNote', - trx - ); + 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 ( creditNoteId: number, - trx?: Knex.Transaction + trx?: Knex.Transaction, ): Promise => { - 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'); // Retreive the the `accounts receivable` account based on the given currency. - const ARAccount = await accountRepository.findOrCreateAccountReceivable( - creditNoteWithItems.currencyCode - ); - const discountAccount = await accountRepository.findOrCreateDiscountAccount( - {} - ); + const ARAccount = + await this.accountRepository.findOrCreateAccountReceivable( + creditNoteWithItems.currencyCode, + ); + const discountAccount = + await this.accountRepository.findOrCreateDiscountAccount({}); + const adjustmentAccount = - await accountRepository.findOrCreateOtherChargesAccount({}); + await this.accountRepository.findOrCreateOtherChargesAccount({}); + + const creditNoteLedger = new CreditNoteGL(creditNoteWithItems) + .setARAccountId(ARAccount.id) + .setDiscountAccountId(discountAccount.id) + .setAdjustmentAccountId(adjustmentAccount.id) + .getCreditNoteLedger(); + // Saves the credit note GL entries. - await this.saveCreditNoteGLEntries( - tenantId, - creditNoteWithItems, - ARAccount.id, - discountAccount.id, - adjustmentAccount.id, - trx - ); + await this.ledgerStorage.commit(creditNoteLedger, trx); }; /** * Edits vendor credit associated GL entries. - * @param {number} tenantId - * @param {number} creditNoteId + * @param {number} creditNoteId - Credit note id. * @param {Knex.Transaction} trx */ public editVendorCreditGLEntries = async ( creditNoteId: number, - trx?: Knex.Transaction + trx?: Knex.Transaction, ): Promise => { // Reverts vendor credit GL entries. await this.revertVendorCreditGLEntries(creditNoteId, trx); @@ -139,155 +77,4 @@ export default class CreditNoteGLEntries { // 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, - - transactionType: 'CreditNote', - transactionId: creditNote.id, - - transactionNumber: creditNote.creditNoteNumber, - referenceNumber: creditNote.referenceNo, - - createdAt: creditNote.createdAt, - indexGroup: 10, - - credit: 0, - debit: 0, - - 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); - - 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; - - 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); - - 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. - * @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 discountEntry = this.getDiscountEntry(creditNote, discountAccountId); - const adjustmentEntry = this.getAdjustmentEntry( - creditNote, - adjustmentAccountId - ); - - return [AREntry, discountEntry, adjustmentEntry, ...itemsEntries]; - }; } diff --git a/packages/server-nest/src/modules/CreditNotes/models/CreditNote.ts b/packages/server-nest/src/modules/CreditNotes/models/CreditNote.ts index 88dd5171c..c4ff4a1b8 100644 --- a/packages/server-nest/src/modules/CreditNotes/models/CreditNote.ts +++ b/packages/server-nest/src/modules/CreditNotes/models/CreditNote.ts @@ -24,6 +24,7 @@ export class CreditNote extends BaseModel { public invoicesAmount: number; public creditNoteDate: Date; public creditNoteNumber: string; + public referenceNo: string; public currencyCode: string; public customerId: number; diff --git a/packages/server-nest/src/modules/CreditNotes/subscribers/CreditNoteGLEntriesSubscriber.ts b/packages/server-nest/src/modules/CreditNotes/subscribers/CreditNoteGLEntriesSubscriber.ts index 4e9be8048..66c085c49 100644 --- a/packages/server-nest/src/modules/CreditNotes/subscribers/CreditNoteGLEntriesSubscriber.ts +++ b/packages/server-nest/src/modules/CreditNotes/subscribers/CreditNoteGLEntriesSubscriber.ts @@ -4,13 +4,13 @@ import { ICreditNoteEditedPayload, ICreditNoteOpenedPayload, } from '../types/CreditNotes.types'; -import CreditNoteGLEntries from '../commands/CreditNoteGLEntries'; +import { CreditNoteGLEntries } from '../commands/CreditNoteGLEntries'; import { OnEvent } from '@nestjs/event-emitter'; import { Injectable } from '@nestjs/common'; import { events } from '@/common/events/events'; @Injectable() -export default class CreditNoteGLEntriesSubscriber { +export class CreditNoteGLEntriesSubscriber { constructor(private readonly creditNoteGLEntries: CreditNoteGLEntries) {} /** diff --git a/packages/server-nest/src/modules/Expenses/subscribers/ExpenseGLEntries.service.ts b/packages/server-nest/src/modules/Expenses/subscribers/ExpenseGLEntries.service.ts index eb6da79bd..5cb397241 100644 --- a/packages/server-nest/src/modules/Expenses/subscribers/ExpenseGLEntries.service.ts +++ b/packages/server-nest/src/modules/Expenses/subscribers/ExpenseGLEntries.service.ts @@ -6,6 +6,9 @@ import { ILedger } from '@/modules/Ledger/types/Ledger.types'; @Injectable() export class ExpenseGLEntriesService { + /** + * @param {typeof Expense} expense - Expense model. + */ constructor( @Inject(Expense.name) private readonly expense: typeof Expense, @@ -33,7 +36,7 @@ export class ExpenseGLEntriesService { /** * Retrieves the given expense ledger. - * @param {IExpense} expense + * @param {Expense} expense - Expense model. * @returns {ILedger} */ public getExpenseLedger = (expense: Expense): ILedger => { diff --git a/packages/server-nest/src/modules/Expenses/subscribers/ExpenseGLEntries.subscriber.ts b/packages/server-nest/src/modules/Expenses/subscribers/ExpenseGLEntries.subscriber.ts index 5200a5ce8..a3a640807 100644 --- a/packages/server-nest/src/modules/Expenses/subscribers/ExpenseGLEntries.subscriber.ts +++ b/packages/server-nest/src/modules/Expenses/subscribers/ExpenseGLEntries.subscriber.ts @@ -12,7 +12,7 @@ import { events } from '@/common/events/events'; @Injectable() export class ExpensesWriteGLSubscriber { /** - * @param {ExpenseGLEntriesStorageService} expenseGLEntries - + * @param {ExpenseGLEntriesStorageService} expenseGLEntries - Expense GL entries storage service. */ constructor( private readonly expenseGLEntries: ExpenseGLEntriesStorageService, diff --git a/packages/server-nest/src/modules/Ledger/types/Ledger.types.ts b/packages/server-nest/src/modules/Ledger/types/Ledger.types.ts index 152db4eda..23d84375f 100644 --- a/packages/server-nest/src/modules/Ledger/types/Ledger.types.ts +++ b/packages/server-nest/src/modules/Ledger/types/Ledger.types.ts @@ -62,7 +62,7 @@ export interface ILedgerEntry { taxRate?: number; entryId?: number; - createdAt?: Date; + createdAt?: Date | string; costable?: boolean; } diff --git a/packages/server-nest/src/modules/PaymentReceived/PaymentsReceived.module.ts b/packages/server-nest/src/modules/PaymentReceived/PaymentsReceived.module.ts index 2404f46cb..a269c5168 100644 --- a/packages/server-nest/src/modules/PaymentReceived/PaymentsReceived.module.ts +++ b/packages/server-nest/src/modules/PaymentReceived/PaymentsReceived.module.ts @@ -1,5 +1,4 @@ import { Module } from '@nestjs/common'; - import { PaymentReceivesController } from './PaymentsReceived.controller'; import { PaymentReceivesApplication } from './PaymentReceived.application'; import { CreatePaymentReceivedService } from './commands/CreatePaymentReceived.serivce'; @@ -8,7 +7,7 @@ import { EditPaymentReceivedService } from './commands/EditPaymentReceived.servi import { GetPaymentReceivedStateService } from './queries/GetPaymentReceivedState.service'; import { GetPaymentReceivedService } from './queries/GetPaymentReceived.service'; import { GetPaymentReceivedInvoices } from './queries/GetPaymentReceivedInvoices.service'; -import GetPaymentReceivedPdf from './queries/GetPaymentReceivedPdf.service'; +import { GetPaymentReceivedPdfService } from './queries/GetPaymentReceivedPdf.service'; import { PaymentReceivedValidators } from './commands/PaymentReceivedValidators.service'; import { PaymentReceiveDTOTransformer } from './commands/PaymentReceivedDTOTransformer'; import { TenancyContext } from '../Tenancy/TenancyContext.service'; @@ -20,6 +19,11 @@ import { BranchesModule } from '../Branches/Branches.module'; import { WarehousesModule } from '../Warehouses/Warehouses.module'; import { PdfTemplatesModule } from '../PdfTemplate/PdfTemplates.module'; import { AutoIncrementOrdersModule } from '../AutoIncrementOrders/AutoIncrementOrders.module'; +import { PaymentReceivedAutoIncrementSubscriber } from './subscribers/PaymentReceivedAutoIncrementSubscriber'; +import { PaymentReceivedGLEntriesSubscriber } from './subscribers/PaymentReceivedGLEntriesSubscriber'; +import { PaymentReceivedGLEntries } from './commands/PaymentReceivedGLEntries'; +import { PaymentReceivedSyncInvoicesSubscriber } from './subscribers/PaymentReceivedSyncInvoices'; +import { PaymentReceivedInvoiceSync } from './commands/PaymentReceivedInvoiceSync.service'; @Module({ controllers: [PaymentReceivesController], @@ -31,12 +35,17 @@ import { AutoIncrementOrdersModule } from '../AutoIncrementOrders/AutoIncrementO GetPaymentReceivedStateService, GetPaymentReceivedService, GetPaymentReceivedInvoices, - GetPaymentReceivedPdf, + GetPaymentReceivedPdfService, PaymentReceivedValidators, PaymentReceiveDTOTransformer, PaymentReceivedBrandingTemplate, PaymentReceivedIncrement, + PaymentReceivedGLEntries, TenancyContext, + PaymentReceivedInvoiceSync, + PaymentReceivedAutoIncrementSubscriber, + PaymentReceivedGLEntriesSubscriber, + PaymentReceivedSyncInvoicesSubscriber, ], exports: [PaymentReceivesApplication], imports: [ @@ -45,7 +54,7 @@ import { AutoIncrementOrdersModule } from '../AutoIncrementOrders/AutoIncrementO BranchesModule, WarehousesModule, PdfTemplatesModule, - AutoIncrementOrdersModule + AutoIncrementOrdersModule, ], }) export class PaymentsReceivedModule {} diff --git a/packages/server-nest/src/modules/PaymentReceived/commands/CreatePaymentReceived.serivce.ts b/packages/server-nest/src/modules/PaymentReceived/commands/CreatePaymentReceived.serivce.ts index 844e52461..62bfc573b 100644 --- a/packages/server-nest/src/modules/PaymentReceived/commands/CreatePaymentReceived.serivce.ts +++ b/packages/server-nest/src/modules/PaymentReceived/commands/CreatePaymentReceived.serivce.ts @@ -33,7 +33,7 @@ export class CreatePaymentReceivedService { /** * Creates a new payment receive and store it to the storage * with associated invoices payment and journal transactions. - * @param {IPaymentReceivedCreateDTO} paymentReceiveDTO + * @param {IPaymentReceivedCreateDTO} paymentReceiveDTO - Payment receive create DTO. * @param {Knex.Transaction} trx - Database transaction. */ public async createPaymentReceived( diff --git a/packages/server-nest/src/modules/PaymentReceived/commands/PaymentReceivedGL.ts b/packages/server-nest/src/modules/PaymentReceived/commands/PaymentReceivedGL.ts index cb605b768..92e17e4b7 100644 --- a/packages/server-nest/src/modules/PaymentReceived/commands/PaymentReceivedGL.ts +++ b/packages/server-nest/src/modules/PaymentReceived/commands/PaymentReceivedGL.ts @@ -18,16 +18,31 @@ export class PaymentReceivedGL { this.paymentReceived = paymentReceived; } + /** + * Sets the A/R account ID. + * @param {number} ARAccountId - A/R account ID. + * @returns {PaymentReceivedGL} + */ setARAccountId(ARAccountId: number) { this.ARAccountId = ARAccountId; return this; } + /** + * Sets the exchange gain/loss account ID. + * @param {number} exchangeGainOrLossAccountId - Exchange gain/loss account ID. + * @returns {PaymentReceivedGL} + */ setExchangeGainOrLossAccountId(exchangeGainOrLossAccountId: number) { this.exchangeGainOrLossAccountId = exchangeGainOrLossAccountId; return this; } + /** + * Sets the base currency code. + * @param {string} baseCurrencyCode - Base currency code. + * @returns {PaymentReceivedGL} + */ setBaseCurrencyCode(baseCurrencyCode: string) { this.baseCurrencyCode = baseCurrencyCode; return this; @@ -177,5 +192,5 @@ export class PaymentReceivedGL { */ public getLedger = (): Ledger => { return new Ledger(this.GLEntries()); - }; + }; } diff --git a/packages/server-nest/src/modules/PaymentReceived/queries/GetPaymentReceivedPdf.service.ts b/packages/server-nest/src/modules/PaymentReceived/queries/GetPaymentReceivedPdf.service.ts index 2571879c0..c7831f1d7 100644 --- a/packages/server-nest/src/modules/PaymentReceived/queries/GetPaymentReceivedPdf.service.ts +++ b/packages/server-nest/src/modules/PaymentReceived/queries/GetPaymentReceivedPdf.service.ts @@ -12,7 +12,7 @@ import { PaymentReceivedPdfTemplateAttributes } from '../types/PaymentReceived.t import { events } from '@/common/events/events'; @Injectable() -export default class GetPaymentReceivedPdf { +export class GetPaymentReceivedPdfService { constructor( private chromiumlyTenancy: ChromiumlyTenancy, private templateInjectable: TemplateInjectable, diff --git a/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedAutoIncrementSubscriber.ts b/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedAutoIncrementSubscriber.ts new file mode 100644 index 000000000..51fae26ad --- /dev/null +++ b/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedAutoIncrementSubscriber.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; +import { events } from '@/common/events/events'; +import { PaymentReceivedIncrement } from '../commands/PaymentReceivedIncrement.service'; +import { IPaymentReceivedCreatedPayload } from '../types/PaymentReceived.types'; + +@Injectable() +export class PaymentReceivedAutoIncrementSubscriber { + constructor(private readonly paymentIncrement: PaymentReceivedIncrement) {} + + /** + * Handles increment next number of payment receive once be created. + * @param {IPaymentReceivedCreatedPayload} payload - + */ + @OnEvent(events.paymentReceive.onCreated) + private async handlePaymentNextNumberIncrement({}: IPaymentReceivedCreatedPayload) { + await this.paymentIncrement.incrementNextPaymentReceiveNumber(); + } +} diff --git a/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedGLEntriesSubscriber.ts b/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedGLEntriesSubscriber.ts index e69de29bb..a5721c241 100644 --- a/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedGLEntriesSubscriber.ts +++ b/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedGLEntriesSubscriber.ts @@ -0,0 +1,61 @@ +import { Injectable } from '@nestjs/common'; +import { + IPaymentReceivedCreatedPayload, + IPaymentReceivedDeletedPayload, + IPaymentReceivedEditedPayload, +} from '../types/PaymentReceived.types'; +import { PaymentReceivedGLEntries } from '../commands/PaymentReceivedGLEntries'; +import { OnEvent } from '@nestjs/event-emitter'; +import { events } from '@/common/events/events'; + +@Injectable() +export class PaymentReceivedGLEntriesSubscriber { + /** + * @param {PaymentReceivedGLEntries} paymentReceivedGLEntries - + */ + constructor( + private readonly paymentReceivedGLEntries: PaymentReceivedGLEntries, + ) {} + + /** + * Handle journal entries writing once the payment receive created. + */ + @OnEvent(events.paymentReceive.onCreated) + private async handleWriteJournalEntriesOnceCreated({ + paymentReceiveId, + trx, + }: IPaymentReceivedCreatedPayload) { + await this.paymentReceivedGLEntries.writePaymentGLEntries( + paymentReceiveId, + trx, + ); + } + + /** + * Handle journal entries writing once the payment receive edited. + */ + @OnEvent(events.paymentReceive.onEdited) + private async handleOverwriteJournalEntriesOnceEdited({ + paymentReceive, + trx, + }: IPaymentReceivedEditedPayload) { + await this.paymentReceivedGLEntries.rewritePaymentGLEntries( + paymentReceive.id, + trx, + ); + } + + /** + * Handles revert journal entries once deleted. + */ + @OnEvent(events.paymentReceive.onDeleted) + private async handleRevertJournalEntriesOnceDeleted({ + paymentReceiveId, + trx, + }: IPaymentReceivedDeletedPayload) { + await this.paymentReceivedGLEntries.revertPaymentGLEntries( + paymentReceiveId, + trx, + ); + } +} diff --git a/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSmsNotificationSubscriber.ts b/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSmsNotificationSubscriber.ts new file mode 100644 index 000000000..533273e9c --- /dev/null +++ b/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSmsNotificationSubscriber.ts @@ -0,0 +1,40 @@ +// import { Service, Inject } from 'typedi'; +// import events from '@/subscribers/events'; +// import { PaymentReceiveNotifyBySms } from '@/services/Sales/PaymentReceived/PaymentReceivedSmsNotify'; +// import { IPaymentReceivedCreatedPayload } from '@/interfaces'; +// import { runAfterTransaction } from '@/services/UnitOfWork/TransactionsHooks'; + +// @Service() +// export default class SendSmsNotificationPaymentReceive { +// @Inject() +// private paymentReceiveSmsNotify: PaymentReceiveNotifyBySms; + +// /** +// * Attach events. +// */ +// public attach(bus) { +// bus.subscribe( +// events.paymentReceive.onCreated, +// this.handleNotifyViaSmsOncePaymentPublish +// ); +// } + +// /** +// * Handles send SMS notification after payment transaction creation. +// */ +// private handleNotifyViaSmsOncePaymentPublish = ({ +// tenantId, +// paymentReceiveId, +// trx, +// }: IPaymentReceivedCreatedPayload) => { +// // Notify via Sms after transactions complete running. +// runAfterTransaction(trx, async () => { +// try { +// await this.paymentReceiveSmsNotify.notifyViaSmsNotificationAfterCreation( +// tenantId, +// paymentReceiveId +// ); +// } catch (error) { } +// }); +// }; +// } diff --git a/packages/server-nest/src/modules/PaymentReceived/commands/PaymentReceivedSmsSubscriber.ts b/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSmsSubscriber.ts similarity index 100% rename from packages/server-nest/src/modules/PaymentReceived/commands/PaymentReceivedSmsSubscriber.ts rename to packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSmsSubscriber.ts diff --git a/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSyncInvoices.ts b/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSyncInvoices.ts new file mode 100644 index 000000000..297fd80ef --- /dev/null +++ b/packages/server-nest/src/modules/PaymentReceived/subscribers/PaymentReceivedSyncInvoices.ts @@ -0,0 +1,71 @@ + +import { + IPaymentReceivedCreatedPayload, + IPaymentReceivedDeletedPayload, + IPaymentReceivedEditedPayload, +} from '../types/PaymentReceived.types'; +import { PaymentReceivedInvoiceSync } from '../commands/PaymentReceivedInvoiceSync.service'; +import { Injectable } from '@nestjs/common'; +import { OnEvent } from '@nestjs/event-emitter'; +import { events } from '@/common/events/events'; + +@Injectable() +export class PaymentReceivedSyncInvoicesSubscriber { + /** + * @param {PaymentReceivedInvoiceSync} paymentSyncInvoice - + */ + constructor( + private readonly paymentSyncInvoice: PaymentReceivedInvoiceSync, + ) {} + + /** + * Handle sale invoice increment/decrement payment amount + * once created, edited or deleted. + */ + @OnEvent(events.paymentReceive.onCreated) + private async handleInvoiceIncrementPaymentOnceCreated({ + paymentReceive, + trx, + }: IPaymentReceivedCreatedPayload) { + await this.paymentSyncInvoice.saveChangeInvoicePaymentAmount( + paymentReceive.entries, + null, + trx + ); + } + + /** + * Handle sale invoice increment/decrement payment amount once edited. + */ + @OnEvent(events.paymentReceive.onEdited) + private async handleInvoiceIncrementPaymentOnceEdited({ + paymentReceive, + oldPaymentReceive, + trx, + }: IPaymentReceivedEditedPayload) { + await this.paymentSyncInvoice.saveChangeInvoicePaymentAmount( + paymentReceive.entries, + oldPaymentReceive?.entries || null, + trx + ); + } + + /** + * Handle revert invoices payment amount once payment receive deleted. + */ + @OnEvent(events.paymentReceive.onDeleted) + private async handleInvoiceDecrementPaymentAmount({ + paymentReceiveId, + oldPaymentReceive, + trx, + }: IPaymentReceivedDeletedPayload) { + await this.paymentSyncInvoice.saveChangeInvoicePaymentAmount( + oldPaymentReceive.entries.map((entry) => ({ + ...entry, + paymentAmount: 0, + })), + oldPaymentReceive.entries, + trx + ); + }; +} diff --git a/packages/server-nest/src/modules/VendorCredit/VendorCredits.module.ts b/packages/server-nest/src/modules/VendorCredit/VendorCredits.module.ts index f841e5db0..eb5b15c6c 100644 --- a/packages/server-nest/src/modules/VendorCredit/VendorCredits.module.ts +++ b/packages/server-nest/src/modules/VendorCredit/VendorCredits.module.ts @@ -16,6 +16,8 @@ import { BranchesModule } from '../Branches/Branches.module'; import { WarehousesModule } from '../Warehouses/Warehouses.module'; import { VendorCreditsApplicationService } from './VendorCreditsApplication.service'; import { OpenVendorCreditService } from './commands/OpenVendorCredit.service'; +import { VendorCreditGlEntriesSubscriber } from './subscribers/VendorCreditGLEntriesSubscriber'; +import { VendorCreditGLEntries } from './commands/VendorCreditGLEntries'; @Module({ imports: [ @@ -36,7 +38,9 @@ import { OpenVendorCreditService } from './commands/OpenVendorCredit.service'; GetRefundVendorCreditService, GetVendorCreditService, VendorCreditsApplicationService, - OpenVendorCreditService + OpenVendorCreditService, + VendorCreditGLEntries, + VendorCreditGlEntriesSubscriber, ], exports: [ CreateVendorCreditService, diff --git a/packages/server-nest/src/modules/VendorCredit/commands/VendorCreditGL.ts b/packages/server-nest/src/modules/VendorCredit/commands/VendorCreditGL.ts new file mode 100644 index 000000000..f59683b7c --- /dev/null +++ b/packages/server-nest/src/modules/VendorCredit/commands/VendorCreditGL.ts @@ -0,0 +1,163 @@ +import { ItemEntry } from '@/modules/Items/models/ItemEntry'; +import { VendorCredit } from '../models/VendorCredit'; +import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types'; +import { AccountNormal } from '@/interfaces/Account'; +import { Ledger } from '@/modules/Ledger/Ledger'; + +export class VendorCreditGL { + private APAccountId: number; + private purchaseDiscountAccountId: number; + private otherExpensesAccountId: number; + + constructor(private vendorCredit: VendorCredit) {} + + /** + * Sets the payable account (A/P) ID. + * @param {number} APAccountId + * @returns {VendorCreditGL} + */ + public setAPAccountId(APAccountId: number) { + this.APAccountId = APAccountId; + return this; + } + + /** + * Sets the purchase discount account ID. + * @param {number} purchaseDiscountAccountId + * @returns {VendorCreditGL} + */ + public setPurchaseDiscountAccountId(purchaseDiscountAccountId: number) { + this.purchaseDiscountAccountId = purchaseDiscountAccountId; + return this; + } + + /** + * Sets the other expenses account ID. + * @param {number} otherExpensesAccountId + * @returns {VendorCreditGL} + */ + public setOtherExpensesAccountId(otherExpensesAccountId: number) { + this.otherExpensesAccountId = otherExpensesAccountId; + return this; + } + + /** + * Retrieve the vendor credit GL common entry. + * @param {IVendorCredit} vendorCredit + */ + public get vendorCreditGLCommonEntry() { + return { + date: this.vendorCredit.vendorCreditDate, + currencyCode: this.vendorCredit.currencyCode, + exchangeRate: this.vendorCredit.exchangeRate, + + transactionId: this.vendorCredit.id, + transactionType: 'VendorCredit', + transactionNumber: this.vendorCredit.vendorCreditNumber, + referenceNumber: this.vendorCredit.referenceNo, + + credit: 0, + debit: 0, + + branchId: this.vendorCredit.branchId, + }; + } + + /** + * Retrieves the vendor credit payable GL entry. + * @returns {ILedgerEntry} + */ + public get vendorCreditPayableGLEntry(): ILedgerEntry { + const commonEntity = this.vendorCreditGLCommonEntry; + + return { + ...commonEntity, + debit: this.vendorCredit.totalLocal, + accountId: this.APAccountId, + contactId: this.vendorCredit.vendorId, + accountNormal: AccountNormal.CREDIT, + index: 1, + }; + } + + /** + * Retrieves the vendor credit item GL entry. + * @returns {ILedgerEntry} + */ + public getVendorCreditGLItemEntry( + entry: ItemEntry, + index: number, + ): ILedgerEntry { + const commonEntity = this.vendorCreditGLCommonEntry; + const totalLocal = entry.totalExcludingTax * this.vendorCredit.exchangeRate; + + return { + ...commonEntity, + credit: totalLocal, + index: index + 2, + itemId: entry.itemId, + itemQuantity: entry.quantity, + accountId: + 'inventory' === entry.item.type + ? entry.item.inventoryAccountId + : entry.costAccountId || entry.item.costAccountId, + accountNormal: AccountNormal.DEBIT, + }; + } + + /** + * Retrieves the vendor credit discount GL entry. + * @returns {ILedgerEntry} + */ + public get discountEntry(): ILedgerEntry { + const commonEntry = this.vendorCreditGLCommonEntry; + + return { + ...commonEntry, + debit: this.vendorCredit.discountAmountLocal, + accountId: this.purchaseDiscountAccountId, + accountNormal: AccountNormal.DEBIT, + index: 1, + indexGroup: 40, + }; + } + + /** + * Retrieves the vendor credit adjustment GL entry. + * @returns {ILedgerEntry} + */ + public get adjustmentEntry(): ILedgerEntry { + const commonEntry = this.vendorCreditGLCommonEntry; + const adjustmentAmount = Math.abs(this.vendorCredit.adjustmentLocal); + + return { + ...commonEntry, + credit: this.vendorCredit.adjustmentLocal > 0 ? adjustmentAmount : 0, + debit: this.vendorCredit.adjustmentLocal < 0 ? adjustmentAmount : 0, + accountId: this.otherExpensesAccountId, + accountNormal: AccountNormal.DEBIT, + index: 1, + indexGroup: 40, + }; + } + + /** + * Retrieve the vendor credit GL entries. + * @return {ILedgerEntry[]} + */ + public getVendorCreditGLEntries(): ILedgerEntry[] { + const payableEntry = this.vendorCreditPayableGLEntry; + const getItemEntry = this.getVendorCreditGLItemEntry; + const itemsEntries = this.vendorCredit.entries.map(getItemEntry); + + const discountEntry = this.discountEntry; + const adjustmentEntry = this.adjustmentEntry; + + return [payableEntry, discountEntry, adjustmentEntry, ...itemsEntries]; + } + + public getVendorCreditLedger(): Ledger { + const entries = this.getVendorCreditGLEntries(); + return new Ledger(entries); + } +} diff --git a/packages/server-nest/src/modules/VendorCredit/commands/VendorCreditGLEntries.ts b/packages/server-nest/src/modules/VendorCredit/commands/VendorCreditGLEntries.ts index 6aced9d90..ed2359a60 100644 --- a/packages/server-nest/src/modules/VendorCredit/commands/VendorCreditGLEntries.ts +++ b/packages/server-nest/src/modules/VendorCredit/commands/VendorCreditGLEntries.ts @@ -1,252 +1,88 @@ -// import { Inject, Service } from 'typedi'; -// import { Knex } from 'knex'; -// import * as R from 'ramda'; -// import { -// IVendorCredit, -// ILedgerEntry, -// AccountNormal, -// IItemEntry, -// } from '@/interfaces'; -// import HasTenancyService from '@/services/Tenancy/TenancyService'; -// import LedgerStorageService from '@/services/Accounting/LedgerStorageService'; -// import Ledger from '@/services/Accounting/Ledger'; +import { Knex } from 'knex'; +import { VendorCreditGL } from './VendorCreditGL'; +import { LedgerStorageService } from '@/modules/Ledger/LedgerStorage.service'; +import { Inject, Injectable } from '@nestjs/common'; +import { AccountRepository } from '@/modules/Accounts/repositories/Account.repository'; +import { VendorCredit } from '../models/VendorCredit'; -// @Service() -// export default class VendorCreditGLEntries { -// @Inject() -// private ledgerStorage: LedgerStorageService; +@Injectable() +export class VendorCreditGLEntries { + constructor( + private readonly ledgerStorage: LedgerStorageService, + private readonly accountRepository: AccountRepository, -// @Inject() -// private tenancy: HasTenancyService; + @Inject(VendorCredit.name) + private readonly vendorCreditModel: typeof VendorCredit, + ) {} -// /** -// * Retrieve the vendor credit GL common entry. -// * @param {IVendorCredit} vendorCredit -// * @returns {} -// */ -// public getVendorCreditGLCommonEntry = (vendorCredit: IVendorCredit) => { -// return { -// date: vendorCredit.vendorCreditDate, -// currencyCode: vendorCredit.currencyCode, -// exchangeRate: vendorCredit.exchangeRate, + /** + * Creates vendor credit associated GL entries. + * @param {number} vendorCreditId + * @param {Knex.Transaction} trx + */ + public writeVendorCreditGLEntries = async ( + vendorCreditId: number, + trx?: Knex.Transaction, + ) => { + // Vendor credit with entries items. + const vendorCredit = await this.vendorCreditModel + .query(trx) + .findById(vendorCreditId) + .withGraphFetched('entries.item'); -// transactionId: vendorCredit.id, -// transactionType: 'VendorCredit', -// transactionNumber: vendorCredit.vendorCreditNumber, -// referenceNumber: vendorCredit.referenceNo, + // Retrieve the payable account (A/P) account. + const APAccount = await this.accountRepository.findOrCreateAccountsPayable( + vendorCredit.currencyCode, + {}, + trx, + ); + // Retrieve the purchase discount account. + const purchaseDiscountAccount = + await this.accountRepository.findOrCreatePurchaseDiscountAccount({}, trx); -// credit: 0, -// debit: 0, + // Retrieve the other expenses account. + const otherExpensesAccount = + await this.accountRepository.findOrCreateOtherExpensesAccount({}, trx); -// branchId: vendorCredit.branchId, -// }; -// }; + const vendorCreditLedger = new VendorCreditGL(vendorCredit) + .setAPAccountId(APAccount.id) + .setPurchaseDiscountAccountId(purchaseDiscountAccount.id) + .setOtherExpensesAccountId(otherExpensesAccount.id) + .getVendorCreditLedger(); -// /** -// * Retrieves the vendor credit payable GL entry. -// * @param {IVendorCredit} vendorCredit -// * @param {number} APAccountId -// * @returns {ILedgerEntry} -// */ -// public getVendorCreditPayableGLEntry = ( -// vendorCredit: IVendorCredit, -// APAccountId: number -// ): ILedgerEntry => { -// const commonEntity = this.getVendorCreditGLCommonEntry(vendorCredit); + // Commits the ledger entries to the storage. + await this.ledgerStorage.commit(vendorCreditLedger, trx); + }; -// return { -// ...commonEntity, -// debit: vendorCredit.totalLocal, -// accountId: APAccountId, -// contactId: vendorCredit.vendorId, -// accountNormal: AccountNormal.CREDIT, -// index: 1, -// }; -// }; + /** + * Edits vendor credit associated GL entries. + * @param {number} vendorCreditId + * @param {Knex.Transaction} trx + */ + public rewriteVendorCreditGLEntries = async ( + vendorCreditId: number, + trx?: Knex.Transaction, + ) => { + // Reverts the GL entries. + await this.revertVendorCreditGLEntries(vendorCreditId, trx); -// /** -// * Retrieves the vendor credit item GL entry. -// * @param {IVendorCredit} vendorCredit -// * @param {IItemEntry} entry -// * @returns {ILedgerEntry} -// */ -// public getVendorCreditGLItemEntry = R.curry( -// ( -// vendorCredit: IVendorCredit, -// entry: IItemEntry, -// index: number -// ): ILedgerEntry => { -// const commonEntity = this.getVendorCreditGLCommonEntry(vendorCredit); -// const totalLocal = entry.totalExcludingTax * vendorCredit.exchangeRate; + // Re-write the GL entries. + await this.writeVendorCreditGLEntries(vendorCreditId, trx); + }; -// return { -// ...commonEntity, -// credit: totalLocal, -// index: index + 2, -// itemId: entry.itemId, -// itemQuantity: entry.quantity, -// accountId: -// 'inventory' === entry.item.type -// ? entry.item.inventoryAccountId -// : entry.costAccountId || entry.item.costAccountId, -// accountNormal: AccountNormal.DEBIT, -// }; -// } -// ); - -// /** -// * Retrieves the vendor credit discount GL entry. -// * @param {IVendorCredit} vendorCredit -// * @param {number} discountAccountId -// * @returns {ILedgerEntry} -// */ -// public getDiscountEntry = ( -// vendorCredit: IVendorCredit, -// purchaseDiscountAccountId: number -// ) => { -// const commonEntry = this.getVendorCreditGLCommonEntry(vendorCredit); - -// return { -// ...commonEntry, -// debit: vendorCredit.discountAmountLocal, -// accountId: purchaseDiscountAccountId, -// accountNormal: AccountNormal.DEBIT, -// index: 1, -// indexGroup: 40, -// }; -// }; - -// /** -// * Retrieves the vendor credit adjustment GL entry. -// * @param {IVendorCredit} vendorCredit -// * @param {number} adjustmentAccountId -// * @returns {ILedgerEntry} -// */ -// public getAdjustmentEntry = ( -// vendorCredit: IVendorCredit, -// otherExpensesAccountId: number -// ) => { -// const commonEntry = this.getVendorCreditGLCommonEntry(vendorCredit); -// const adjustmentAmount = Math.abs(vendorCredit.adjustmentLocal); - -// return { -// ...commonEntry, -// credit: vendorCredit.adjustmentLocal > 0 ? adjustmentAmount : 0, -// debit: vendorCredit.adjustmentLocal < 0 ? adjustmentAmount : 0, -// accountId: otherExpensesAccountId, -// accountNormal: AccountNormal.DEBIT, -// index: 1, -// indexGroup: 40, -// }; -// }; - -// /** -// * Retrieve the vendor credit GL entries. -// * @param {IVendorCredit} vendorCredit - -// * @param {number} receivableAccount - -// * @return {ILedgerEntry[]} -// */ -// public getVendorCreditGLEntries = ( -// vendorCredit: IVendorCredit, -// payableAccountId: number, -// purchaseDiscountAccountId: number, -// otherExpensesAccountId: number -// ): ILedgerEntry[] => { -// const payableEntry = this.getVendorCreditPayableGLEntry( -// vendorCredit, -// payableAccountId -// ); -// const getItemEntry = this.getVendorCreditGLItemEntry(vendorCredit); -// const itemsEntries = vendorCredit.entries.map(getItemEntry); - -// const discountEntry = this.getDiscountEntry( -// vendorCredit, -// purchaseDiscountAccountId -// ); -// const adjustmentEntry = this.getAdjustmentEntry( -// vendorCredit, -// otherExpensesAccountId -// ); -// return [payableEntry, discountEntry, adjustmentEntry, ...itemsEntries]; -// }; - -// /** -// * Reverts the vendor credit associated GL entries. -// * @param {number} tenantId -// * @param {number} vendorCreditId -// * @param {Knex.Transaction} trx -// */ -// public revertVendorCreditGLEntries = async ( -// tenantId: number, -// vendorCreditId: number, -// trx?: Knex.Transaction -// ): Promise => { -// await this.ledgerStorage.deleteByReference( -// tenantId, -// vendorCreditId, -// 'VendorCredit', -// trx -// ); -// }; - -// /** -// * Creates vendor credit associated GL entries. -// * @param {number} tenantId -// * @param {number} vendorCreditId -// * @param {Knex.Transaction} trx -// */ -// public writeVendorCreditGLEntries = async ( -// tenantId: number, -// vendorCreditId: number, -// trx?: Knex.Transaction -// ) => { -// const { accountRepository } = this.tenancy.repositories(tenantId); -// const { VendorCredit } = this.tenancy.models(tenantId); - -// // Vendor credit with entries items. -// const vendorCredit = await VendorCredit.query(trx) -// .findById(vendorCreditId) -// .withGraphFetched('entries.item'); - -// // Retrieve the payable account (A/P) account. -// const APAccount = await accountRepository.findOrCreateAccountsPayable( -// vendorCredit.currencyCode, -// {}, -// trx -// ); -// const purchaseDiscountAccount = -// await accountRepository.findOrCreatePurchaseDiscountAccount({}, trx); - -// const otherExpensesAccount = -// await accountRepository.findOrCreateOtherExpensesAccount({}, trx); -// // Saves the vendor credit GL entries. -// const ledgerEntries = this.getVendorCreditGLEntries( -// vendorCredit, -// APAccount.id, -// purchaseDiscountAccount.id, -// otherExpensesAccount.id -// ); -// const ledger = new Ledger(ledgerEntries); - -// // Commits the ledger entries to the storage. -// await this.ledgerStorage.commit(tenantId, ledger, trx); -// }; - -// /** -// * Edits vendor credit associated GL entries. -// * @param {number} tenantId -// * @param {number} vendorCreditId -// * @param {Knex.Transaction} trx -// */ -// public rewriteVendorCreditGLEntries = async ( -// tenantId: number, -// vendorCreditId: number, -// trx?: Knex.Transaction -// ) => { -// // Reverts the GL entries. -// await this.revertVendorCreditGLEntries(tenantId, vendorCreditId, trx); - -// // Re-write the GL entries. -// await this.writeVendorCreditGLEntries(tenantId, vendorCreditId, trx); -// }; -// } + /** + * Reverts the vendor credit associated GL entries. + * @param {number} vendorCreditId - Vendor credit identifier. + * @param {Knex.Transaction} trx + */ + public async revertVendorCreditGLEntries( + vendorCreditId: number, + trx?: Knex.Transaction, + ): Promise { + await this.ledgerStorage.deleteByReference( + vendorCreditId, + 'VendorCredit', + trx, + ); + }; +} diff --git a/packages/server-nest/src/modules/VendorCredit/subscribers/VendorCreditGLEntriesSubscriber.ts b/packages/server-nest/src/modules/VendorCredit/subscribers/VendorCreditGLEntriesSubscriber.ts index 141e8604f..c7d79dc10 100644 --- a/packages/server-nest/src/modules/VendorCredit/subscribers/VendorCreditGLEntriesSubscriber.ts +++ b/packages/server-nest/src/modules/VendorCredit/subscribers/VendorCreditGLEntriesSubscriber.ts @@ -1,110 +1,83 @@ -// import { Service, Inject } from 'typedi'; -// import events from '@/subscribers/events'; -// import { -// IVendorCreditCreatedPayload, -// IVendorCreditDeletedPayload, -// IVendorCreditEditedPayload, -// IVendorCreditOpenedPayload, -// } from '@/interfaces'; -// import VendorCreditGLEntries from '../commands/VendorCreditGLEntries'; +import { Injectable } from '@nestjs/common'; +import { + IVendorCreditCreatedPayload, + IVendorCreditDeletedPayload, + IVendorCreditEditedPayload, + IVendorCreditOpenedPayload, +} from '../types/VendorCredit.types'; +import { OnEvent } from '@nestjs/event-emitter'; +import { VendorCreditGLEntries } from '../commands/VendorCreditGLEntries'; +import { events } from '@/common/events/events'; -// @Service() -// export default class VendorCreditGlEntriesSubscriber { -// @Inject() -// private vendorCreditGLEntries: VendorCreditGLEntries; +@Injectable() +export class VendorCreditGlEntriesSubscriber { + constructor(public readonly vendorCreditGLEntries: VendorCreditGLEntries) {} -// /*** -// * Attaches events with handlers. -// */ -// public attach(bus) { -// bus.subscribe( -// events.vendorCredit.onCreated, -// this.writeGLEntriesOnceVendorCreditCreated -// ); -// bus.subscribe( -// events.vendorCredit.onOpened, -// this.writeGLEntgriesOnceVendorCreditOpened -// ); -// bus.subscribe( -// events.vendorCredit.onEdited, -// this.editGLEntriesOnceVendorCreditEdited -// ); -// bus.subscribe( -// events.vendorCredit.onDeleted, -// this.revertGLEntriesOnceDeleted -// ); -// } + /** + * Writes GL entries of vendor credit once the transaction created. + * @param {IVendorCreditCreatedPayload} payload - + */ + @OnEvent(events.vendorCredit.onCreated) + public async writeGLEntriesOnceVendorCreditCreated({ + vendorCredit, + trx, + }: IVendorCreditCreatedPayload): Promise { + // Can't continue if the vendor credit is not open yet. + if (!vendorCredit.isPublished) return; -// /** -// * Writes GL entries of vendor credit once the transaction created. -// * @param {IVendorCreditCreatedPayload} payload - -// */ -// private writeGLEntriesOnceVendorCreditCreated = async ({ -// tenantId, -// vendorCredit, -// trx, -// }: IVendorCreditCreatedPayload): Promise => { -// // Can't continue if the vendor credit is not open yet. -// if (!vendorCredit.isPublished) return; + await this.vendorCreditGLEntries.writeVendorCreditGLEntries( + vendorCredit.id, + trx, + ); + } -// await this.vendorCreditGLEntries.writeVendorCreditGLEntries( -// tenantId, -// vendorCredit.id, -// trx -// ); -// }; + /** + * Writes Gl entries of vendor credit once the transaction opened. + * @param {IVendorCreditOpenedPayload} payload - + */ + @OnEvent(events.vendorCredit.onOpened) + public async writeGLEntgriesOnceVendorCreditOpened({ + vendorCreditId, + trx, + }: IVendorCreditOpenedPayload): Promise { + await this.vendorCreditGLEntries.writeVendorCreditGLEntries( + vendorCreditId, + trx, + ); + } -// /** -// * Writes Gl entries of vendor credit once the transaction opened. -// * @param {IVendorCreditOpenedPayload} payload - -// */ -// private writeGLEntgriesOnceVendorCreditOpened = async ({ -// tenantId, -// vendorCreditId, -// trx, -// }: IVendorCreditOpenedPayload) => { -// await this.vendorCreditGLEntries.writeVendorCreditGLEntries( -// tenantId, -// vendorCreditId, -// trx -// ); -// }; + /** + * Edits associated GL entries once vendor credit edited. + * @param {IVendorCreditEditedPayload} payload + */ + @OnEvent(events.vendorCredit.onEdited) + public async editGLEntriesOnceVendorCreditEdited({ + vendorCredit, + trx, + }: IVendorCreditEditedPayload): Promise { + // Can't continue if the vendor credit is not open yet. + if (!vendorCredit.isPublished) return; -// /** -// * Edits associated GL entries once vendor credit edited. -// * @param {IVendorCreditEditedPayload} payload -// */ -// private editGLEntriesOnceVendorCreditEdited = async ({ -// tenantId, -// vendorCreditId, -// vendorCredit, -// trx, -// }: IVendorCreditEditedPayload) => { -// // Can't continue if the vendor credit is not open yet. -// if (!vendorCredit.isPublished) return; + await this.vendorCreditGLEntries.rewriteVendorCreditGLEntries( + vendorCredit.id, + trx, + ); + } -// await this.vendorCreditGLEntries.rewriteVendorCreditGLEntries( -// tenantId, -// vendorCreditId, -// trx -// ); -// }; + /** + * Reverts the GL entries once vendor credit deleted. + * @param {IVendorCreditDeletedPayload} payload - + */ + @OnEvent(events.vendorCredit.onDeleted) + public async revertGLEntriesOnceDeleted({ + vendorCreditId, + oldVendorCredit, + }: IVendorCreditDeletedPayload): Promise { + // Can't continue of the vendor credit is not open yet. + if (!oldVendorCredit.isPublished) return; -// /** -// * Reverts the GL entries once vendor credit deleted. -// * @param {IVendorCreditDeletedPayload} payload - -// */ -// private revertGLEntriesOnceDeleted = async ({ -// vendorCreditId, -// tenantId, -// oldVendorCredit, -// }: IVendorCreditDeletedPayload): Promise => { -// // Can't continue of the vendor credit is not open yet. -// if (!oldVendorCredit.isPublished) return; - -// await this.vendorCreditGLEntries.revertVendorCreditGLEntries( -// tenantId, -// vendorCreditId -// ); -// }; -// } + await this.vendorCreditGLEntries.revertVendorCreditGLEntries( + vendorCreditId, + ); + } +}