Skip to content

Commit

Permalink
Merge pull request #746 from bigcapitalhq/fix-mail-services
Browse files Browse the repository at this point in the history
fix: mail services
  • Loading branch information
abouolia authored Nov 9, 2024
2 parents bb482df + aa7e5d4 commit 1f46275
Show file tree
Hide file tree
Showing 15 changed files with 166 additions and 62 deletions.
5 changes: 3 additions & 2 deletions packages/server/src/interfaces/Mailable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ export interface CommonMailOptions {
cc?: Array<string>;
bcc?: Array<string>;
formatArgs?: Record<string, any>;
toOptions: Array<AddressItem>;
fromOptions: Array<AddressItem>;
}

export interface CommonMailOptionsDTO extends Partial<CommonMailOptions> {
}
export interface CommonMailOptionsDTO extends Partial<CommonMailOptions> {}
2 changes: 1 addition & 1 deletion packages/server/src/models/PdfTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export class PdfTemplate extends TenantModel {
* @returns {string}
*/
get companyLogoUri() {
return this.attributes.companyLogoKey
return this.attributes?.companyLogoKey
? getUploadedObjectUri(this.attributes.companyLogoKey)
: '';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,24 @@ export class ContactMailNotification {
public async getDefaultMailOptions(
tenantId: number,
customerId: number
): Promise<Pick<CommonMailOptions, 'to' | 'from'>> {
): Promise<
Pick<CommonMailOptions, 'to' | 'from' | 'toOptions' | 'fromOptions'>
> {
const { Customer } = this.tenancy.models(tenantId);
const customer = await Customer.query()
.findById(customerId)
.throwIfNotFound();

const toAddresses = customer.contactAddresses;
const fromAddresses = await this.mailTenancy.senders(tenantId);
const toOptions = customer.contactAddresses;
const fromOptions = await this.mailTenancy.senders(tenantId);

const toAddress = toAddresses.find((a) => a.primary);
const fromAddress = fromAddresses.find((a) => a.primary);
const toAddress = toOptions.find((a) => a.primary);
const fromAddress = fromOptions.find((a) => a.primary);

const to = toAddress?.mail ? castArray(toAddress?.mail) : [];
const from = fromAddress?.mail ? castArray(fromAddress?.mail) : [];

return { to, from };
return { to, from, toOptions, fromOptions };
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ export class SendSaleInvoiceMailCommon {
...commonArgs,
'Customer Name': invoice.customer.displayName,
'Invoice Number': invoice.invoiceNo,
'Invoice DueAmount': invoice.dueAmountFormatted,
'Invoice DueDate': invoice.dueDateFormatted,
'Invoice Due Amount': invoice.dueAmountFormatted,
'Invoice Due Date': invoice.dueDateFormatted,
'Invoice Date': invoice.invoiceDateFormatted,
'Invoice Amount': invoice.totalFormatted,
'Overdue Days': invoice.overdueDays,
Expand Down
46 changes: 34 additions & 12 deletions packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Inject, Service } from 'typedi';
import Mail from '@/lib/Mail';
import { ISaleInvoiceMailSend, SendInvoiceMailDTO } from '@/interfaces';
import {
ISaleInvoiceMailSend,
SaleInvoiceMailOptions,
SendInvoiceMailDTO,
} from '@/interfaces';
import { SaleInvoicePdf } from './SaleInvoicePdf';
import { SendSaleInvoiceMailCommon } from './SendInvoiceInvoiceMailCommon';
import { mergeAndValidateMailOptions } from '@/services/MailNotification/utils';
Expand Down Expand Up @@ -48,17 +52,17 @@ export class SendSaleInvoiceMail {
}

/**
* Triggers the mail invoice.
* Retrieves the formatted mail options.
* @param {number} tenantId
* @param {number} saleInvoiceId
* @param {SendInvoiceMailDTO} messageDTO
* @returns {Promise<void>}
* @param {SendInvoiceMailDTO} messageOptions
* @returns {Promise<SaleInvoiceMailOptions>}
*/
public async sendMail(
async getFormattedMailOptions(
tenantId: number,
saleInvoiceId: number,
messageOptions: SendInvoiceMailDTO
) {
): Promise<SaleInvoiceMailOptions> {
const defaultMessageOptions = await this.invoiceMail.getInvoiceMailOptions(
tenantId,
saleInvoiceId
Expand All @@ -68,12 +72,30 @@ export class SendSaleInvoiceMail {
defaultMessageOptions,
messageOptions
);
const formattedMessageOptions =
await this.invoiceMail.formatInvoiceMailOptions(
tenantId,
saleInvoiceId,
parsedMessageOptions
);
return this.invoiceMail.formatInvoiceMailOptions(
tenantId,
saleInvoiceId,
parsedMessageOptions
);
}

/**
* Triggers the mail invoice.
* @param {number} tenantId
* @param {number} saleInvoiceId
* @param {SendInvoiceMailDTO} messageDTO
* @returns {Promise<void>}
*/
public async sendMail(
tenantId: number,
saleInvoiceId: number,
messageOptions: SendInvoiceMailDTO
) {
const formattedMessageOptions = await this.getFormattedMailOptions(
tenantId,
saleInvoiceId,
messageOptions
);
const mail = new Mail()
.setSubject(formattedMessageOptions.subject)
.setTo(formattedMessageOptions.to)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,20 @@ export class SendPaymentReceiveMailNotification {
};

/**
* Triggers the mail invoice.
* Retrieves the formatted mail options of the given payment receive.
* @param {number} tenantId
* @param {number} saleInvoiceId
* @param {number} paymentReceiveId
* @param {SendInvoiceMailDTO} messageDTO
* @returns {Promise<void>}
* @returns {Promise<PaymentReceiveMailOpts>}
*/
public async sendMail(
public getFormattedMailOptions = async (
tenantId: number,
paymentReceiveId: number,
messageDTO: SendInvoiceMailDTO
): Promise<void> {
) => {
const formatterArgs = await this.textFormatter(tenantId, paymentReceiveId);

// Default message options.
const defaultMessageOpts = await this.getMailOptions(
tenantId,
paymentReceiveId
Expand All @@ -132,17 +135,43 @@ export class SendPaymentReceiveMailNotification {
defaultMessageOpts,
messageDTO
);
// Formats the message options.
return this.contactMailNotification.formatMailOptions(
tenantId,
parsedMessageOpts,
formatterArgs
);
};

/**
* Triggers the mail invoice.
* @param {number} tenantId
* @param {number} saleInvoiceId - Invoice id.
* @param {SendInvoiceMailDTO} messageDTO - Message options.
* @returns {Promise<void>}
*/
public async sendMail(
tenantId: number,
paymentReceiveId: number,
messageDTO: SendInvoiceMailDTO
): Promise<void> {
// Retrieves the formatted mail options.
const formattedMessageOptions = await this.getFormattedMailOptions(
tenantId,
paymentReceiveId,
messageDTO
);
const mail = new Mail()
.setSubject(parsedMessageOpts.subject)
.setTo(parsedMessageOpts.to)
.setCC(parsedMessageOpts.cc)
.setBCC(parsedMessageOpts.bcc)
.setContent(parsedMessageOpts.message);
.setSubject(formattedMessageOptions.subject)
.setTo(formattedMessageOptions.to)
.setCC(formattedMessageOptions.cc)
.setBCC(formattedMessageOptions.bcc)
.setContent(formattedMessageOptions.message);

const eventPayload = {
tenantId,
paymentReceiveId,
messageOptions: parsedMessageOpts,
messageOptions: formattedMessageOptions,
};
// Triggers `onPaymentReceiveMailSend` event.
await this.eventPublisher.emitAsync(
Expand Down
11 changes: 6 additions & 5 deletions packages/server/src/services/Sales/PaymentReceived/constants.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
export const DEFAULT_PAYMENT_MAIL_SUBJECT = 'Payment Received by {CompanyName}';
export const DEFAULT_PAYMENT_MAIL_SUBJECT =
'Payment Received for {Customer Name} from {Company Name}';
export const DEFAULT_PAYMENT_MAIL_CONTENT = `
<p>Dear {CustomerName}</p>
<p>Dear {Customer Name}</p>
<p>Thank you for your payment. It was a pleasure doing business with you. We look forward to work together again!</p>
<p>
Payment Date : <strong>{PaymentDate}</strong><br />
Amount : <strong>{PaymentAmount}</strong></br />
Payment Date : <strong>{Payment Date}</strong><br />
Amount : <strong>{Payment Amount}</strong></br />
</p>
<p>
<i>Regards</i><br />
<i>{CompanyName}</i>
<i>{Company Name}</i>
</p>
`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,39 @@ export class SaleReceiptMailNotification {
};

/**
* Triggers the mail notification of the given sale receipt.
* @param {number} tenantId - Tenant id.
* @param {number} saleReceiptId - Sale receipt id.
* @param {SaleReceiptMailOpts} messageDTO - message options.
* @returns {Promise<void>}
* Formats the mail options of the given sale receipt.
* @param {number} tenantId
* @param {number} receiptId
* @param {SaleReceiptMailOpts} mailOptions
* @returns {Promise<SaleReceiptMailOpts>}
*/
public async sendMail(
public async formatEstimateMailOptions(
tenantId: number,
receiptId: number,
mailOptions: SaleReceiptMailOpts
): Promise<SaleReceiptMailOpts> {
const formatterArgs = await this.textFormatterArgs(tenantId, receiptId);
const formattedOptions =
(await this.contactMailNotification.formatMailOptions(
tenantId,
mailOptions,
formatterArgs
)) as SaleReceiptMailOpts;
return formattedOptions;
}

/**
* Retrieves the formatted mail options of the given sale receipt.
* @param {number} tenantId
* @param {number} saleReceiptId
* @param {SaleReceiptMailOptsDTO} messageOpts
* @returns {Promise<SaleReceiptMailOpts>}
*/
public getFormatMailOptions = async (
tenantId: number,
saleReceiptId: number,
messageOpts: SaleReceiptMailOptsDTO
) {
): Promise<SaleReceiptMailOpts> => {
const defaultMessageOptions = await this.getMailOptions(
tenantId,
saleReceiptId
Expand All @@ -136,15 +158,41 @@ export class SaleReceiptMailNotification {
messageOpts
) as SaleReceiptMailOpts;

// Formats the message options.
return this.formatEstimateMailOptions(
tenantId,
saleReceiptId,
parsedMessageOpts
);
};

/**
* Triggers the mail notification of the given sale receipt.
* @param {number} tenantId - Tenant id.
* @param {number} saleReceiptId - Sale receipt id.
* @param {SaleReceiptMailOpts} messageDTO - message options.
* @returns {Promise<void>}
*/
public async sendMail(
tenantId: number,
saleReceiptId: number,
messageOpts: SaleReceiptMailOptsDTO
) {
// Formats the message options.
const formattedMessageOptions = await this.getFormatMailOptions(
tenantId,
saleReceiptId,
messageOpts
);
const mail = new Mail()
.setSubject(parsedMessageOpts.subject)
.setTo(parsedMessageOpts.to)
.setCC(parsedMessageOpts.cc)
.setBCC(parsedMessageOpts.bcc)
.setContent(parsedMessageOpts.message);
.setSubject(formattedMessageOptions.subject)
.setTo(formattedMessageOptions.to)
.setCC(formattedMessageOptions.cc)
.setBCC(formattedMessageOptions.bcc)
.setContent(formattedMessageOptions.message);

// Attaches the receipt pdf document.
if (parsedMessageOpts.attachReceipt) {
if (formattedMessageOptions.attachReceipt) {
// Retrieves document buffer of the receipt pdf document.
const [receiptPdfBuffer, filename] =
await this.receiptPdfService.saleReceiptPdf(tenantId, saleReceiptId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function EstimateMailDialogFormRoot({
closeDialog,
}) {
const { mutateAsync: sendEstimateMail } = useSendSaleEstimateMail();
const { mailOptions, saleEstimateId, redirectToEstimatesList } =
const { mailOptions, saleEstimateId, } =
useEstimateMailDialogBoot();

const initialValues = transformMailFormToInitialValues(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export function EstimateMailDialogFormContent({
<Form>
<div className={Classes.DIALOG_BODY}>
<MailNotificationForm
fromAddresses={mailOptions.from_addresses}
toAddresses={mailOptions.to_addresses}
fromAddresses={mailOptions.from_options}
toAddresses={mailOptions.to_options}
/>
<AttachFormGroup name={'attachEstimate'} inline>
<FSwitch name={'attachEstimate'} label={'Attach Estimate'} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface PaymentMailDialogBootProps {
*/
function PaymentMailDialogBoot({
paymentReceiveId,
redirectToPaymentsList,
...props
}: PaymentMailDialogBootProps) {
const { data: mailOptions, isLoading: isMailOptionsLoading } =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export function PaymentMailDialogFormContent({
<Form>
<div className={Classes.DIALOG_BODY}>
<MailNotificationForm
fromAddresses={mailOptions.from_addresses}
toAddresses={mailOptions.to_addresses}
fromAddresses={mailOptions.from_options}
toAddresses={mailOptions.to_options}
/>
<AttachFormGroup name={'attachPayment'} inline>
<FSwitch name={'attachPayment'} label={'Attach Payment'} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ export function ReceiptMailDialogFormContent({
<Form>
<div className={Classes.DIALOG_BODY}>
<MailNotificationForm
fromAddresses={mailOptions.from_addresses}
toAddresses={mailOptions.to_addresses}
fromAddresses={mailOptions.from_options}
toAddresses={mailOptions.to_options}
/>
<AttachFormGroup name={'attachReceipt:'} inline>
<FSwitch name={'attachReceipt:'} label={'Attach Receipt'} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export function MailNotificationForm({
</FFormGroup>
</HeaderBox>

<MailMessageEditor name={'body'} />
<MailMessageEditor name={'message'} />
</Box>
);
}
Expand Down
Loading

0 comments on commit 1f46275

Please sign in to comment.