diff --git a/packages/server/src/interfaces/SaleInvoice.ts b/packages/server/src/interfaces/SaleInvoice.ts index 394319e86..61594306a 100644 --- a/packages/server/src/interfaces/SaleInvoice.ts +++ b/packages/server/src/interfaces/SaleInvoice.ts @@ -201,3 +201,15 @@ export interface ISaleInvoiceNotifyPayload { saleInvoiceId: number; messageDTO: SendInvoiceMailDTO; } + +export interface ISaleInvoiceMailSend { + tenantId: number; + saleInvoiceId: number; + messageOptions: SendInvoiceMailDTO; +} + +export interface ISaleInvoiceMailSent { + tenantId: number; + saleInvoiceId: number; + messageOptions: SendInvoiceMailDTO; +} diff --git a/packages/server/src/loaders/eventEmitter.ts b/packages/server/src/loaders/eventEmitter.ts index fa1942b72..5e052f376 100644 --- a/packages/server/src/loaders/eventEmitter.ts +++ b/packages/server/src/loaders/eventEmitter.ts @@ -84,6 +84,7 @@ import { WriteInvoiceTaxTransactionsSubscriber } from '@/services/TaxRates/subsc import { BillTaxRateValidateSubscriber } from '@/services/TaxRates/subscribers/BillTaxRateValidateSubscriber'; import { WriteBillTaxTransactionsSubscriber } from '@/services/TaxRates/subscribers/WriteBillTaxTransactionsSubscriber'; import { SyncItemTaxRateOnEditTaxSubscriber } from '@/services/TaxRates/SyncItemTaxRateOnEditTaxSubscriber'; +import { InvoiceChangeStatusOnMailSentSubscriber } from '@/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber'; export default () => { return new EventPublisher(); @@ -152,6 +153,7 @@ export const susbcribers = () => { // #Invoices InvoicePaymentGLRewriteSubscriber, InvoiceCostGLEntriesSubscriber, + InvoiceChangeStatusOnMailSentSubscriber, BillPaymentsGLEntriesRewriteSubscriber, diff --git a/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts b/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts index 30ba635a6..f5500a03a 100644 --- a/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts +++ b/packages/server/src/services/Sales/Invoices/DeliverSaleInvoice.ts @@ -4,7 +4,6 @@ import { ServiceError } from '@/exceptions'; import { ISaleInvoiceDeliveringPayload, ISaleInvoiceEventDeliveredPayload, - ISystemUser, } from '@/interfaces'; import { ERRORS } from './constants'; import { Inject, Service } from 'typedi'; @@ -36,8 +35,7 @@ export class DeliverSaleInvoice { */ public async deliverSaleInvoice( tenantId: number, - saleInvoiceId: number, - authorizedUser: ISystemUser + saleInvoiceId: number ): Promise { const { SaleInvoice } = this.tenancy.models(tenantId); diff --git a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts index 05db4f73e..eff8b2603 100644 --- a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts +++ b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts @@ -1,6 +1,6 @@ import { Inject, Service } from 'typedi'; import Mail from '@/lib/Mail'; -import { SendInvoiceMailDTO } from '@/interfaces'; +import { ISaleInvoiceMailSend, SendInvoiceMailDTO } from '@/interfaces'; import { SaleInvoicePdf } from './SaleInvoicePdf'; import { SendSaleInvoiceMailCommon } from './SendInvoiceInvoiceMailCommon'; import { @@ -8,6 +8,8 @@ import { DEFAULT_INVOICE_MAIL_SUBJECT, } from './constants'; import { parseAndValidateMailOptions } from '@/services/MailNotification/utils'; +import events from '@/subscribers/events'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; @Service() export class SendSaleInvoiceMail { @@ -20,6 +22,9 @@ export class SendSaleInvoiceMail { @Inject('agenda') private agenda: any; + @Inject() + private eventPublisher: EventPublisher; + /** * Sends the invoice mail of the given sale invoice. * @param {number} tenantId @@ -29,14 +34,21 @@ export class SendSaleInvoiceMail { public async triggerMail( tenantId: number, saleInvoiceId: number, - messageDTO: SendInvoiceMailDTO + messageOptions: SendInvoiceMailDTO ) { const payload = { tenantId, saleInvoiceId, - messageDTO, + messageOptions, }; await this.agenda.now('sale-invoice-mail-send', payload); + + // Triggers the event `onSaleInvoicePreMailSend`. + await this.eventPublisher.emitAsync(events.saleInvoice.onPreMailSend, { + tenantId, + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSend); } /** @@ -64,7 +76,7 @@ export class SendSaleInvoiceMail { public async sendMail( tenantId: number, saleInvoiceId: number, - messageDTO: SendInvoiceMailDTO + messageOptions: SendInvoiceMailDTO ) { const defaultMessageOpts = await this.getMailOption( tenantId, @@ -73,7 +85,7 @@ export class SendSaleInvoiceMail { // Merge message opts with default options and validate the incoming options. const messageOpts = parseAndValidateMailOptions( defaultMessageOpts, - messageDTO + messageOptions ); const mail = new Mail() .setSubject(messageOpts.subject) @@ -90,6 +102,20 @@ export class SendSaleInvoiceMail { { filename: 'invoice.pdf', content: invoicePdfBuffer }, ]); } + // Triggers the event `onSaleInvoiceSend`. + await this.eventPublisher.emitAsync(events.saleInvoice.onMailSend, { + tenantId, + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSend); + await mail.send(); + + // Triggers the event `onSaleInvoiceSend`. + await this.eventPublisher.emitAsync(events.saleInvoice.onMailSent, { + tenantId, + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSend); } } diff --git a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailJob.ts b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailJob.ts index 3c1e49a6c..9de941f5f 100644 --- a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailJob.ts +++ b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailJob.ts @@ -19,11 +19,11 @@ export class SendSaleInvoiceMailJob { * Triggers sending invoice mail. */ private handler = async (job, done: Function) => { - const { tenantId, saleInvoiceId, messageDTO } = job.attrs.data; + const { tenantId, saleInvoiceId, messageOptions } = job.attrs.data; const sendInvoiceMail = Container.get(SendSaleInvoiceMail); try { - await sendInvoiceMail.sendMail(tenantId, saleInvoiceId, messageDTO); + await sendInvoiceMail.sendMail(tenantId, saleInvoiceId, messageOptions); done(); } catch (error) { console.log(error); diff --git a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailReminder.ts b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailReminder.ts index f16db0172..7829a3bf2 100644 --- a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailReminder.ts +++ b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMailReminder.ts @@ -1,5 +1,9 @@ import { Inject, Service } from 'typedi'; -import { SendInvoiceMailDTO } from '@/interfaces'; +import { + ISaleInvoiceMailSend, + ISaleInvoiceMailSent, + SendInvoiceMailDTO, +} from '@/interfaces'; import Mail from '@/lib/Mail'; import { SaleInvoicePdf } from './SaleInvoicePdf'; import { SendSaleInvoiceMailCommon } from './SendInvoiceInvoiceMailCommon'; @@ -8,6 +12,8 @@ import { DEFAULT_INVOICE_REMINDER_MAIL_SUBJECT, } from './constants'; import { parseAndValidateMailOptions } from '@/services/MailNotification/utils'; +import { EventPublisher } from '@/lib/EventPublisher/EventPublisher'; +import events from '@/subscribers/events'; @Service() export class SendInvoiceMailReminder { @@ -20,6 +26,9 @@ export class SendInvoiceMailReminder { @Inject() private invoiceCommonMail: SendSaleInvoiceMailCommon; + @Inject() + private eventPublisher: EventPublisher; + /** * Triggers the reminder mail of the given sale invoice. * @param {number} tenantId @@ -86,6 +95,18 @@ export class SendInvoiceMailReminder { { filename: 'invoice.pdf', content: invoicePdfBuffer }, ]); } + // Triggers the event `onSaleInvoiceSend`. + await this.eventPublisher.emitAsync(events.saleInvoice.onMailReminderSend, { + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSend); + await mail.send(); + + // Triggers the event `onSaleInvoiceSent`. + await this.eventPublisher.emitAsync(events.saleInvoice.onMailReminderSent, { + saleInvoiceId, + messageOptions, + } as ISaleInvoiceMailSent); } } diff --git a/packages/server/src/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber.ts b/packages/server/src/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber.ts new file mode 100644 index 000000000..fc4392777 --- /dev/null +++ b/packages/server/src/services/Sales/Invoices/subscribers/InvoiceChangeStatusOnMailSentSubscriber.ts @@ -0,0 +1,49 @@ +import { Inject, Service } from 'typedi'; +import events from '@/subscribers/events'; +import { ISaleInvoiceMailSent } from '@/interfaces'; +import { DeliverSaleInvoice } from '../DeliverSaleInvoice'; +import { ServiceError } from '@/exceptions'; +import { ERRORS } from '../constants'; + +@Service() +export class InvoiceChangeStatusOnMailSentSubscriber { + @Inject() + private markInvoiceDelivedService: DeliverSaleInvoice; + + /** + * Attaches events. + */ + public attach(bus) { + bus.subscribe(events.saleInvoice.onPreMailSend, this.markInvoiceDelivered); + bus.subscribe( + events.saleInvoice.onMailReminderSent, + this.markInvoiceDelivered + ); + } + + /** + * Marks the invoice delivered once the invoice mail sent. + * @param {ISaleInvoiceMailSent} + * @returns {Promise} + */ + private markInvoiceDelivered = async ({ + tenantId, + saleInvoiceId, + messageOptions, + }: ISaleInvoiceMailSent) => { + try { + await this.markInvoiceDelivedService.deliverSaleInvoice( + tenantId, + saleInvoiceId + ); + } catch (error) { + if ( + error instanceof ServiceError && + error.errorType === ERRORS.SALE_INVOICE_ALREADY_DELIVERED + ) { + } else { + throw error; + } + } + }; +} diff --git a/packages/server/src/subscribers/events.ts b/packages/server/src/subscribers/events.ts index e54f48152..a46c32696 100644 --- a/packages/server/src/subscribers/events.ts +++ b/packages/server/src/subscribers/events.ts @@ -131,7 +131,14 @@ export default { onNotifiedSms: 'onSaleInvoiceNotifiedSms', onNotifyMail: 'onSaleInvoiceNotifyMail', - onNotifyReminderMail: 'onSaleInvoiceNotifyReminderMail' + onNotifyReminderMail: 'onSaleInvoiceNotifyReminderMail', + + onPreMailSend: 'onSaleInvoicePreMailSend', + onMailSend: 'onSaleInvoiceMailSend', + onMailSent: 'onSaleInvoiceMailSent', + + onMailReminderSend: 'onSaleInvoiceMailReminderSend', + onMailReminderSent: 'onSaleInvoiceMailReminderSent', }, /** @@ -164,7 +171,7 @@ export default { onRejecting: 'onSaleEstimateRejecting', onRejected: 'onSaleEstimateRejected', - onNotifyMail: 'onSaleEstimateNotifyMail' + onNotifyMail: 'onSaleEstimateNotifyMail', }, /** @@ -580,6 +587,6 @@ export default { onActivated: 'onTaxRateActivated', onInactivating: 'onTaxRateInactivating', - onInactivated: 'onTaxRateInactivated' + onInactivated: 'onTaxRateInactivated', }, };