Skip to content

Commit

Permalink
Merge pull request #332 from bigcapitalhq/big-105-convert-invoice-sta…
Browse files Browse the repository at this point in the history
…tus-after-sending-mail-notification

feat: convert invoice status after sending mail notification
  • Loading branch information
abouolia authored Feb 21, 2024
2 parents e09f8e4 + b713b69 commit 3faeca2
Show file tree
Hide file tree
Showing 50 changed files with 767 additions and 94 deletions.
6 changes: 6 additions & 0 deletions packages/server/src/interfaces/PaymentReceive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,9 @@ export type IPaymentReceiveGLCommonEntry = Pick<
export interface PaymentReceiveMailOpts extends CommonMailOptions {}

export interface PaymentReceiveMailOptsDTO extends CommonMailOptionsDTO {}

export interface PaymentReceiveMailPresendEvent {
tenantId: number;
paymentReceiveId: number;
messageOptions: PaymentReceiveMailOptsDTO;
}
8 changes: 7 additions & 1 deletion packages/server/src/interfaces/SaleEstimate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,10 @@ export interface SaleEstimateMailOptions extends CommonMailOptions {

export interface SaleEstimateMailOptionsDTO extends CommonMailOptionsDTO {
attachEstimate?: boolean;
}
}

export interface ISaleEstimateMailPresendEvent {
tenantId: number;
saleEstimateId: number;
messageOptions: SaleEstimateMailOptionsDTO;
}
12 changes: 12 additions & 0 deletions packages/server/src/interfaces/SaleInvoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
6 changes: 6 additions & 0 deletions packages/server/src/interfaces/SaleReceipt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,9 @@ export interface SaleReceiptMailOpts extends CommonMailOptions {
export interface SaleReceiptMailOptsDTO extends CommonMailOptionsDTO {
attachReceipt?: boolean;
}

export interface ISaleReceiptMailPresend {
tenantId: number;
saleReceiptId: number;
messageOptions: SaleReceiptMailOptsDTO;
}
11 changes: 10 additions & 1 deletion packages/server/src/loaders/eventEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ 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';
import { SaleReceiptMarkClosedOnMailSentSubcriber } from '@/services/Sales/Receipts/subscribers/SaleReceiptMarkClosedOnMailSentSubcriber';
import { SaleEstimateMarkApprovedOnMailSent } from '@/services/Sales/Estimates/subscribers/SaleEstimateMarkApprovedOnMailSent';

export default () => {
return new EventPublisher();
Expand All @@ -104,8 +107,12 @@ export const susbcribers = () => {
InventorySubscriber,
CustomerWriteGLOpeningBalanceSubscriber,
VendorsWriteGLOpeningSubscriber,

// # Estimate
SaleEstimateAutoSerialSubscriber,
SaleEstimateSmsNotificationSubscriber,
SaleEstimateMarkApprovedOnMailSent,

ExpensesWriteGLSubscriber,
SaleReceiptAutoSerialSubscriber,
SaleInvoiceAutoIncrementSubscriber,
Expand Down Expand Up @@ -152,11 +159,13 @@ export const susbcribers = () => {
// #Invoices
InvoicePaymentGLRewriteSubscriber,
InvoiceCostGLEntriesSubscriber,
InvoiceChangeStatusOnMailSentSubscriber,

BillPaymentsGLEntriesRewriteSubscriber,

// # Receipts
SaleReceiptCostGLEntriesSubscriber,
SaleReceiptMarkClosedOnMailSentSubcriber,

// Transaction locking.
SalesTransactionLockingGuardSubscriber,
Expand Down Expand Up @@ -199,6 +208,6 @@ export const susbcribers = () => {
BillTaxRateValidateSubscriber,
WriteBillTaxTransactionsSubscriber,

SyncItemTaxRateOnEditTaxSubscriber
SyncItemTaxRateOnEditTaxSubscriber,
];
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { IAccountTransaction } from '@/interfaces';
import { Transformer } from '@/lib/Transformer/Transformer';
import { transaction } from 'objection';

export default class AccountTransactionTransformer extends Transformer {
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/services/Accounts/AccountTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class AccountTransformer extends Transformer {

/**
* Retrieve formatted account amount.
* @param {IAccount} invoice
* @param {IAccount} invoice
* @returns {string}
*/
protected formattedAmount = (account: IAccount): string => {
Expand Down
4 changes: 0 additions & 4 deletions packages/server/src/services/Accounts/ActivateAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { IAccountEventActivatedPayload } from '@/interfaces';
import events from '@/subscribers/events';
import UnitOfWork from '@/services/UnitOfWork';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import { CommandAccountValidators } from './CommandAccountValidators';

@Service()
export class ActivateAccount {
Expand All @@ -18,9 +17,6 @@ export class ActivateAccount {
@Inject()
private uow: UnitOfWork;

@Inject()
private validator: CommandAccountValidators;

/**
* Activates/Inactivates the given account.
* @param {number} tenantId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ import {
import { SaleEstimatesPdf } from './SaleEstimatesPdf';
import { GetSaleEstimate } from './GetSaleEstimate';
import {
ISaleEstimateMailPresendEvent,
SaleEstimateMailOptions,
SaleEstimateMailOptionsDTO,
} from '@/interfaces';
import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification';
import { parseAndValidateMailOptions } from '@/services/MailNotification/utils';
import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
import events from '@/subscribers/events';

@Service()
export class SendSaleEstimateMail {
Expand All @@ -31,6 +34,9 @@ export class SendSaleEstimateMail {
@Inject('agenda')
private agenda: any;

@Inject()
private eventPublisher: EventPublisher;

/**
* Triggers the reminder mail of the given sale estimate.
* @param {number} tenantId -
Expand All @@ -49,6 +55,13 @@ export class SendSaleEstimateMail {
messageOptions,
};
await this.agenda.now('sale-estimate-mail-send', payload);

// Triggers `onSaleEstimatePreMailSend` event.
await this.eventPublisher.emitAsync(events.saleEstimate.onPreMailSend, {
tenantId,
saleEstimateId,
messageOptions,
} as ISaleEstimateMailPresendEvent);
}

/**
Expand Down Expand Up @@ -99,7 +112,7 @@ export class SendSaleEstimateMail {
return {
...mailOptions,
data: formatterData,
attachEstimate: true
attachEstimate: true,
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Inject, Service } from 'typedi';
import events from '@/subscribers/events';
import { ISaleEstimateMailPresendEvent } from '@/interfaces';
import { DeliverSaleEstimate } from '../DeliverSaleEstimate';
import { ServiceError } from '@/exceptions';
import { ERRORS } from '../constants';

@Service()
export class SaleEstimateMarkApprovedOnMailSent {
@Inject()
private deliverEstimateService: DeliverSaleEstimate;

/**
* Attaches events.
*/
public attach(bus) {
bus.subscribe(events.saleEstimate.onPreMailSend, this.markEstimateApproved);
}

/**
* Marks the given estimate approved on submitting mail.
* @param {ISaleEstimateMailPresendEvent}
*/
private markEstimateApproved = async ({
tenantId,
saleEstimateId,
}: ISaleEstimateMailPresendEvent) => {
try {
await this.deliverEstimateService.deliverSaleEstimate(
tenantId,
saleEstimateId
);
} catch (error) {
if (
error instanceof ServiceError &&
error.errorType === ERRORS.SALE_ESTIMATE_ALREADY_DELIVERED
) {
} else {
throw error;
}
}
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { ServiceError } from '@/exceptions';
import {
ISaleInvoiceDeliveringPayload,
ISaleInvoiceEventDeliveredPayload,
ISystemUser,
} from '@/interfaces';
import { ERRORS } from './constants';
import { Inject, Service } from 'typedi';
Expand Down Expand Up @@ -36,8 +35,7 @@ export class DeliverSaleInvoice {
*/
public async deliverSaleInvoice(
tenantId: number,
saleInvoiceId: number,
authorizedUser: ISystemUser
saleInvoiceId: number
): Promise<void> {
const { SaleInvoice } = this.tenancy.models(tenantId);

Expand Down
36 changes: 31 additions & 5 deletions packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
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 {
DEFAULT_INVOICE_MAIL_CONTENT,
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 {
Expand All @@ -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
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -64,7 +76,7 @@ export class SendSaleInvoiceMail {
public async sendMail(
tenantId: number,
saleInvoiceId: number,
messageDTO: SendInvoiceMailDTO
messageOptions: SendInvoiceMailDTO
) {
const defaultMessageOpts = await this.getMailOption(
tenantId,
Expand All @@ -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)
Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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);
}
}
Loading

0 comments on commit 3faeca2

Please sign in to comment.