diff --git a/packages/server/src/interfaces/Bill.ts b/packages/server/src/interfaces/Bill.ts index fcf89dbda..fa94c3e41 100644 --- a/packages/server/src/interfaces/Bill.ts +++ b/packages/server/src/interfaces/Bill.ts @@ -1,7 +1,7 @@ import { Knex } from 'knex'; import { IDynamicListFilterDTO } from './DynamicFilter'; import { IItemEntry, IItemEntryDTO } from './ItemEntry'; -import { IBillLandedCost } from './LandedCost'; +import { IBillLandedCost } from './LandedCost'; export interface IBillDTO { vendorId: number; billNumber: string; @@ -99,17 +99,17 @@ export interface IBillCreatedPayload { trx: Knex.Transaction; } -export interface IBillCreatingPayload{ +export interface IBillCreatingPayload { tenantId: number; billDTO: IBillDTO; - trx: Knex.Transaction; + trx: Knex.Transaction; } export interface IBillEditingPayload { tenantId: number; oldBill: IBill; billDTO: IBillEditDTO; - trx: Knex.Transaction; + trx: Knex.Transaction; } export interface IBillEditedPayload { tenantId: number; @@ -129,7 +129,7 @@ export interface IBIllEventDeletedPayload { export interface IBillEventDeletingPayload { tenantId: number; oldBill: IBill; - trx: Knex.Transaction; + trx: Knex.Transaction; } export enum BillAction { Create = 'Create', @@ -138,3 +138,16 @@ export enum BillAction { View = 'View', NotifyBySms = 'NotifyBySms', } + +export interface IBillOpeningPayload { + trx: Knex.Transaction; + tenantId: number; + oldBill: IBill; +} + +export interface IBillOpenedPayload { + trx: Knex.Transaction; + bill: IBill; + oldBill: IBill; + tenantId: number; +} diff --git a/packages/server/src/interfaces/PaymentReceive.ts b/packages/server/src/interfaces/PaymentReceive.ts index 658113fb3..6f8d8552a 100644 --- a/packages/server/src/interfaces/PaymentReceive.ts +++ b/packages/server/src/interfaces/PaymentReceive.ts @@ -1,6 +1,5 @@ -import { ISystemUser } from '@/interfaces'; import { Knex } from 'knex'; -import { pick } from 'lodash'; +import { ISystemUser } from '@/interfaces'; import { ILedgerEntry } from './Ledger'; import { ISaleInvoice } from './SaleInvoice'; diff --git a/packages/server/src/interfaces/SaleInvoice.ts b/packages/server/src/interfaces/SaleInvoice.ts index 5dc91b062..4351f90f4 100644 --- a/packages/server/src/interfaces/SaleInvoice.ts +++ b/packages/server/src/interfaces/SaleInvoice.ts @@ -156,6 +156,7 @@ export interface ISaleInvoiceEventDeliveredPayload { tenantId: number; saleInvoiceId: number; saleInvoice: ISaleInvoice; + trx: Knex.Transaction; } export interface ISaleInvoiceDeliveringPayload { diff --git a/packages/server/src/services/Purchases/Bills/BillGLEntriesSubscriber.ts b/packages/server/src/services/Purchases/Bills/BillGLEntriesSubscriber.ts index c38e65cb7..ea7ed5ab4 100644 --- a/packages/server/src/services/Purchases/Bills/BillGLEntriesSubscriber.ts +++ b/packages/server/src/services/Purchases/Bills/BillGLEntriesSubscriber.ts @@ -20,6 +20,10 @@ export class BillGLEntriesSubscriber { events.bill.onCreated, this.handlerWriteJournalEntriesOnCreate ); + bus.subscribe( + events.bill.onOpened, + this.handlerWriteJournalEntriesOnCreate + ); bus.subscribe( events.bill.onEdited, this.handleOverwriteJournalEntriesOnEdit @@ -34,8 +38,11 @@ export class BillGLEntriesSubscriber { private handlerWriteJournalEntriesOnCreate = async ({ tenantId, billId, + bill, trx, }: IBillCreatedPayload) => { + if (!bill.openedAt) return null; + await this.billGLEntries.writeBillGLEntries(tenantId, billId, trx); }; @@ -46,8 +53,11 @@ export class BillGLEntriesSubscriber { private handleOverwriteJournalEntriesOnEdit = async ({ tenantId, billId, + bill, trx, }: IBillEditedPayload) => { + if (!bill.openedAt) return null; + await this.billGLEntries.rewriteBillGLEntries(tenantId, billId, trx); }; diff --git a/packages/server/src/services/Purchases/Bills/EditBill.ts b/packages/server/src/services/Purchases/Bills/EditBill.ts index a7259c730..26121c120 100644 --- a/packages/server/src/services/Purchases/Bills/EditBill.ts +++ b/packages/server/src/services/Purchases/Bills/EditBill.ts @@ -132,7 +132,7 @@ export class EditBill { } as IBillEditingPayload); // Update the bill transaction. - const bill = await Bill.query(trx).upsertGraph({ + const bill = await Bill.query(trx).upsertGraphAndFetch({ id: billId, ...billObj, }); diff --git a/packages/server/src/services/Purchases/Bills/OpenBill.ts b/packages/server/src/services/Purchases/Bills/OpenBill.ts index a2c2039b3..bcd1e397e 100644 --- a/packages/server/src/services/Purchases/Bills/OpenBill.ts +++ b/packages/server/src/services/Purchases/Bills/OpenBill.ts @@ -5,6 +5,9 @@ import { ERRORS } from './constants'; import HasTenancyService from '@/services/Tenancy/TenancyService'; import UnitOfWork from '@/services/UnitOfWork'; import { BillsValidators } from './BillsValidators'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import events from '@/subscribers/events'; +import { IBillOpenedPayload, IBillOpeningPayload } from '@/interfaces'; @Service() export class OpenBill { @@ -17,6 +20,9 @@ export class OpenBill { @Inject() private validators: BillsValidators; + @Inject() + private eventPublisher: EventPublisher; + /** * Mark the bill as open. * @param {number} tenantId @@ -37,10 +43,24 @@ export class OpenBill { throw new ServiceError(ERRORS.BILL_ALREADY_OPEN); } return this.uow.withTransaction(tenantId, async (trx) => { + // Triggers `onBillCreating` event. + await this.eventPublisher.emitAsync(events.bill.onOpening, { + trx, + tenantId, + oldBill, + } as IBillOpeningPayload); + // Record the bill opened at on the storage. - await Bill.query(trx).findById(billId).patch({ + const bill = await Bill.query(trx).patchAndFetchById(billId, { openedAt: moment().toMySqlDateTime(), }); + // Triggers `onBillCreating` event. + await this.eventPublisher.emitAsync(events.bill.onOpened, { + trx, + bill, + oldBill, + tenantId, + } as IBillOpenedPayload); }); } } diff --git a/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts b/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts index 77511af84..30ba635a6 100644 --- a/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts +++ b/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts @@ -63,14 +63,17 @@ export class DeliverSaleInvoice { // Record the delivered at on the storage. const saleInvoice = await SaleInvoice.query(trx) - .where({ id: saleInvoiceId }) - .update({ deliveredAt: moment().toMySqlDateTime() }); + .patchAndFetchById(saleInvoiceId, { + deliveredAt: moment().toMySqlDateTime(), + }) + .withGraphFetched('entries'); // Triggers `onSaleInvoiceDelivered` event. await this.eventPublisher.emitAsync(events.saleInvoice.onDelivered, { tenantId, saleInvoiceId, saleInvoice, + trx, } as ISaleInvoiceEventDeliveredPayload); }); } diff --git a/packages/server/src/services/Sales/Receipts/CloseSaleReceipt.ts b/packages/server/src/services/Sales/Receipts/CloseSaleReceipt.ts index 0566d4733..b678884e3 100644 --- a/packages/server/src/services/Sales/Receipts/CloseSaleReceipt.ts +++ b/packages/server/src/services/Sales/Receipts/CloseSaleReceipt.ts @@ -58,12 +58,12 @@ export class CloseSaleReceipt { } as ISaleReceiptEventClosingPayload); // Mark the sale receipt as closed on the storage. - const saleReceipt = await SaleReceipt.query(trx) - .findById(saleReceiptId) - .patch({ + const saleReceipt = await SaleReceipt.query(trx).patchAndFetchById( + saleReceiptId, + { closedAt: moment().toMySqlDateTime(), - }); - + } + ); // Triggers `onSaleReceiptClosed` event. await this.eventPublisher.emitAsync(events.saleReceipt.onClosed, { saleReceiptId, diff --git a/packages/server/src/subscribers/Bills/WriteInventoryTransactions.ts b/packages/server/src/subscribers/Bills/WriteInventoryTransactions.ts index ee04c98a1..04f6039d6 100644 --- a/packages/server/src/subscribers/Bills/WriteInventoryTransactions.ts +++ b/packages/server/src/subscribers/Bills/WriteInventoryTransactions.ts @@ -36,8 +36,12 @@ export default class BillWriteInventoryTransactionsSubscriber { private handleWritingInventoryTransactions = async ({ tenantId, billId, + bill, trx, }: IBillCreatedPayload) => { + // Can't continue if the bill is not opened yet. + if (!bill.openedAt) return null; + await this.billsInventory.recordInventoryTransactions( tenantId, billId, @@ -52,8 +56,12 @@ export default class BillWriteInventoryTransactionsSubscriber { private handleOverwritingInventoryTransactions = async ({ tenantId, billId, + bill, trx, }: IBillEditedPayload) => { + // Can't continue if the bill is not opened yet. + if (!bill.openedAt) return null; + await this.billsInventory.recordInventoryTransactions( tenantId, billId, diff --git a/packages/server/src/subscribers/Bills/WriteJournalEntries.ts b/packages/server/src/subscribers/Bills/WriteJournalEntries.ts index bb9589f54..23f68c6ad 100644 --- a/packages/server/src/subscribers/Bills/WriteJournalEntries.ts +++ b/packages/server/src/subscribers/Bills/WriteJournalEntries.ts @@ -38,8 +38,12 @@ export default class BillWriteGLEntriesSubscriber { private handlerWriteJournalEntriesOnCreate = async ({ tenantId, billId, + bill, trx, }: IBillCreatedPayload) => { + // Can't continue if the bill is not opened yet. + if (!bill.openedAt) return null; + await this.billsService.recordJournalTransactions( tenantId, billId, @@ -55,8 +59,12 @@ export default class BillWriteGLEntriesSubscriber { private handleOverwriteJournalEntriesOnEdit = async ({ tenantId, billId, + bill, trx, }: IBillEditedPayload) => { + // Can't continue if the bill is not opened yet. + if (!bill.openedAt) return null; + await this.billsService.recordJournalTransactions( tenantId, billId, diff --git a/packages/server/src/subscribers/PaymentReceive/WriteGLEntries.ts b/packages/server/src/subscribers/PaymentReceive/WriteGLEntries.ts index bffe4260f..d9ae3b643 100644 --- a/packages/server/src/subscribers/PaymentReceive/WriteGLEntries.ts +++ b/packages/server/src/subscribers/PaymentReceive/WriteGLEntries.ts @@ -36,8 +36,10 @@ export default class PaymentReceivesWriteGLEntriesSubscriber { private handleWriteJournalEntriesOnceCreated = async ({ tenantId, paymentReceiveId, + paymentReceive, trx, }: IPaymentReceiveCreatedPayload) => { + if (paymentReceive) await this.paymentReceiveGLEntries.writePaymentGLEntries( tenantId, paymentReceiveId, diff --git a/packages/server/src/subscribers/SaleInvoices/WriteInventoryTransactions.ts b/packages/server/src/subscribers/SaleInvoices/WriteInventoryTransactions.ts index b4f620b20..ec3d920a5 100644 --- a/packages/server/src/subscribers/SaleInvoices/WriteInventoryTransactions.ts +++ b/packages/server/src/subscribers/SaleInvoices/WriteInventoryTransactions.ts @@ -4,6 +4,7 @@ import { ISaleInvoiceCreatedPayload, ISaleInvoiceDeletedPayload, ISaleInvoiceEditedPayload, + ISaleInvoiceEventDeliveredPayload, } from '@/interfaces'; import { InvoiceInventoryTransactions } from '@/services/Sales/Invoices/InvoiceInventoryTransactions'; @@ -20,6 +21,10 @@ export default class WriteInventoryTransactions { events.saleInvoice.onCreated, this.handleWritingInventoryTransactions ); + bus.subscribe( + events.saleInvoice.onDelivered, + this.handleWritingInventoryTransactions + ); bus.subscribe( events.saleInvoice.onEdited, this.handleRewritingInventoryTransactions @@ -38,7 +43,10 @@ export default class WriteInventoryTransactions { tenantId, saleInvoice, trx, - }: ISaleInvoiceCreatedPayload) => { + }: ISaleInvoiceCreatedPayload | ISaleInvoiceEventDeliveredPayload) => { + // Can't continue if the sale invoice is not delivered yet. + if (!saleInvoice.deliveredAt) return null; + await this.saleInvoiceInventory.recordInventoryTranscactions( tenantId, saleInvoice, diff --git a/packages/server/src/subscribers/SaleInvoices/WriteJournalEntries.ts b/packages/server/src/subscribers/SaleInvoices/WriteJournalEntries.ts index fc5d9411b..15ba5562b 100644 --- a/packages/server/src/subscribers/SaleInvoices/WriteJournalEntries.ts +++ b/packages/server/src/subscribers/SaleInvoices/WriteJournalEntries.ts @@ -15,11 +15,15 @@ export default class SaleInvoiceWriteGLEntriesSubscriber { /** * Constructor method. */ - attach(bus) { + public attach(bus) { bus.subscribe( events.saleInvoice.onCreated, this.handleWriteJournalEntriesOnInvoiceCreated ); + bus.subscribe( + events.saleInvoice.onDelivered, + this.handleWriteJournalEntriesOnInvoiceCreated + ); bus.subscribe( events.saleInvoice.onEdited, this.handleRewriteJournalEntriesOnceInvoiceEdit @@ -36,8 +40,12 @@ export default class SaleInvoiceWriteGLEntriesSubscriber { private handleWriteJournalEntriesOnInvoiceCreated = async ({ tenantId, saleInvoiceId, + saleInvoice, trx, }: ISaleInvoiceCreatedPayload) => { + // Can't continue if the sale invoice is not delivered yet. + if (!saleInvoice.deliveredAt) return null; + await this.saleInvoiceGLEntries.writeInvoiceGLEntries( tenantId, saleInvoiceId, @@ -53,6 +61,9 @@ export default class SaleInvoiceWriteGLEntriesSubscriber { saleInvoice, trx, }: ISaleInvoiceEditedPayload) => { + // Can't continue if the sale invoice is not delivered yet. + if (!saleInvoice.deliveredAt) return null; + await this.saleInvoiceGLEntries.rewritesInvoiceGLEntries( tenantId, saleInvoice.id, diff --git a/packages/server/src/subscribers/SaleReceipt/WriteInventoryTransactions.ts b/packages/server/src/subscribers/SaleReceipt/WriteInventoryTransactions.ts index 57da23747..bf4fd007a 100644 --- a/packages/server/src/subscribers/SaleReceipt/WriteInventoryTransactions.ts +++ b/packages/server/src/subscribers/SaleReceipt/WriteInventoryTransactions.ts @@ -40,6 +40,9 @@ export default class SaleReceiptInventoryTransactionsSubscriber { saleReceipt, trx, }: ISaleReceiptCreatedPayload) => { + // Can't continue if the sale receipt is not closed yet. + if (!saleReceipt.closedAt) return null; + await this.saleReceiptInventory.recordInventoryTransactions( tenantId, saleReceipt, @@ -57,6 +60,9 @@ export default class SaleReceiptInventoryTransactionsSubscriber { saleReceipt, trx, }: ISaleReceiptEditedPayload) => { + // Can't continue if the sale receipt is not closed yet. + if (!saleReceipt.closedAt) return null; + await this.saleReceiptInventory.recordInventoryTransactions( tenantId, saleReceipt, diff --git a/packages/server/src/subscribers/SaleReceipt/WriteJournalEntries.ts b/packages/server/src/subscribers/SaleReceipt/WriteJournalEntries.ts index 8a14bfcad..32c9c363b 100644 --- a/packages/server/src/subscribers/SaleReceipt/WriteJournalEntries.ts +++ b/packages/server/src/subscribers/SaleReceipt/WriteJournalEntries.ts @@ -21,6 +21,10 @@ export default class SaleReceiptWriteGLEntriesSubscriber { events.saleReceipt.onCreated, this.handleWriteReceiptIncomeJournalEntrieOnCreate ); + bus.subscribe( + events.saleReceipt.onClosed, + this.handleWriteReceiptIncomeJournalEntrieOnCreate + ); bus.subscribe( events.saleReceipt.onEdited, this.handleWriteReceiptIncomeJournalEntrieOnEdited @@ -38,8 +42,12 @@ export default class SaleReceiptWriteGLEntriesSubscriber { public handleWriteReceiptIncomeJournalEntrieOnCreate = async ({ tenantId, saleReceiptId, + saleReceipt, trx, }: ISaleReceiptCreatedPayload) => { + // Can't continue if the sale receipt is not closed yet. + if (!saleReceipt.closedAt) return null; + // Writes the sale receipt income journal entries. await this.saleReceiptGLEntries.writeIncomeGLEntries( tenantId, @@ -71,8 +79,12 @@ export default class SaleReceiptWriteGLEntriesSubscriber { private handleWriteReceiptIncomeJournalEntrieOnEdited = async ({ tenantId, saleReceiptId, + saleReceipt, trx, }: ISaleReceiptEditedPayload) => { + // Can't continue if the sale receipt is not closed yet. + if (!saleReceipt.closedAt) return null; + // Writes the sale receipt income journal entries. await this.saleReceiptGLEntries.rewriteReceiptGLEntries( tenantId, diff --git a/packages/server/src/subscribers/events.ts b/packages/server/src/subscribers/events.ts index 19416b65d..f43366107 100644 --- a/packages/server/src/subscribers/events.ts +++ b/packages/server/src/subscribers/events.ts @@ -220,6 +220,9 @@ export default { onPublishing: 'onBillPublishing', onPublished: 'onBillPublished', + + onOpening: 'onBillOpening', + onOpened: 'onBillOpened', }, /**