From aa7e5d4ae9ccaeaa21a1afd464faa6f84c5b423b Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sat, 9 Nov 2024 22:23:52 +0200 Subject: [PATCH] fix: mail services --- packages/server/src/interfaces/Mailable.ts | 5 +- packages/server/src/models/PdfTemplate.ts | 2 +- .../ContactMailNotification.ts | 14 ++-- .../Invoices/SendInvoiceInvoiceMailCommon.ts | 4 +- .../Sales/Invoices/SendSaleInvoiceMail.ts | 48 ++++++++---- .../PaymentReceivedMailNotification.ts | 51 ++++++++++--- .../Sales/PaymentReceived/constants.ts | 11 +-- .../Receipts/SaleReceiptMailNotification.ts | 76 +++++++++++++++---- .../EstimateMailDialogForm.tsx | 2 +- .../EstimateMailDialogFormContent.tsx | 4 +- .../PaymentMailDialogBoot.tsx | 1 + .../PaymentMailDialogFormContent.tsx | 4 +- .../ReceiptMailDialogFormContent.tsx | 4 +- .../MailNotificationForm.tsx | 2 +- .../containers/SendMailNotification/utils.ts | 4 +- 15 files changed, 168 insertions(+), 64 deletions(-) diff --git a/packages/server/src/interfaces/Mailable.ts b/packages/server/src/interfaces/Mailable.ts index c77895225..faae8437e 100644 --- a/packages/server/src/interfaces/Mailable.ts +++ b/packages/server/src/interfaces/Mailable.ts @@ -37,7 +37,8 @@ export interface CommonMailOptions { cc?: Array; bcc?: Array; formatArgs?: Record; + toOptions: Array; + fromOptions: Array; } -export interface CommonMailOptionsDTO extends Partial { -} +export interface CommonMailOptionsDTO extends Partial {} diff --git a/packages/server/src/models/PdfTemplate.ts b/packages/server/src/models/PdfTemplate.ts index ccf5f48d2..55f1556b3 100644 --- a/packages/server/src/models/PdfTemplate.ts +++ b/packages/server/src/models/PdfTemplate.ts @@ -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) : ''; } diff --git a/packages/server/src/services/MailNotification/ContactMailNotification.ts b/packages/server/src/services/MailNotification/ContactMailNotification.ts index d798adce5..d6e8a1e04 100644 --- a/packages/server/src/services/MailNotification/ContactMailNotification.ts +++ b/packages/server/src/services/MailNotification/ContactMailNotification.ts @@ -23,22 +23,24 @@ export class ContactMailNotification { public async getDefaultMailOptions( tenantId: number, customerId: number - ): Promise> { + ): Promise< + Pick + > { 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 }; } /** diff --git a/packages/server/src/services/Sales/Invoices/SendInvoiceInvoiceMailCommon.ts b/packages/server/src/services/Sales/Invoices/SendInvoiceInvoiceMailCommon.ts index c69bc5ef4..519cf3a0c 100644 --- a/packages/server/src/services/Sales/Invoices/SendInvoiceInvoiceMailCommon.ts +++ b/packages/server/src/services/Sales/Invoices/SendInvoiceInvoiceMailCommon.ts @@ -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, diff --git a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts index 2d2a45424..baa85968b 100644 --- a/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts +++ b/packages/server/src/services/Sales/Invoices/SendSaleInvoiceMail.ts @@ -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'; @@ -47,6 +51,34 @@ export class SendSaleInvoiceMail { } as ISaleInvoiceMailSend); } + /** + * Retrieves the formatted mail options. + * @param {number} tenantId + * @param {number} saleInvoiceId + * @param {SendInvoiceMailDTO} messageOptions + * @returns {Promise} + */ + async getFormattedMailOptions( + tenantId: number, + saleInvoiceId: number, + messageOptions: SendInvoiceMailDTO + ): Promise { + const defaultMessageOptions = await this.invoiceMail.getInvoiceMailOptions( + tenantId, + saleInvoiceId + ); + // Merges message options with default options and parses the options values. + const parsedMessageOptions = mergeAndValidateMailOptions( + defaultMessageOptions, + messageOptions + ); + return this.invoiceMail.formatInvoiceMailOptions( + tenantId, + saleInvoiceId, + parsedMessageOptions + ); + } + /** * Triggers the mail invoice. * @param {number} tenantId @@ -59,21 +91,11 @@ export class SendSaleInvoiceMail { saleInvoiceId: number, messageOptions: SendInvoiceMailDTO ) { - const defaultMessageOptions = await this.invoiceMail.getInvoiceMailOptions( + const formattedMessageOptions = await this.getFormattedMailOptions( tenantId, - saleInvoiceId - ); - // Merges message options with default options and parses the options values. - const parsedMessageOptions = mergeAndValidateMailOptions( - defaultMessageOptions, + saleInvoiceId, messageOptions ); - const formattedMessageOptions = - await this.invoiceMail.formatInvoiceMailOptions( - tenantId, - saleInvoiceId, - parsedMessageOptions - ); const mail = new Mail() .setSubject(formattedMessageOptions.subject) .setTo(formattedMessageOptions.to) diff --git a/packages/server/src/services/Sales/PaymentReceived/PaymentReceivedMailNotification.ts b/packages/server/src/services/Sales/PaymentReceived/PaymentReceivedMailNotification.ts index 7cd045f34..a02db9143 100644 --- a/packages/server/src/services/Sales/PaymentReceived/PaymentReceivedMailNotification.ts +++ b/packages/server/src/services/Sales/PaymentReceived/PaymentReceivedMailNotification.ts @@ -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} + * @returns {Promise} */ - public async sendMail( + public getFormattedMailOptions = async ( tenantId: number, paymentReceiveId: number, messageDTO: SendInvoiceMailDTO - ): Promise { + ) => { + const formatterArgs = await this.textFormatter(tenantId, paymentReceiveId); + + // Default message options. const defaultMessageOpts = await this.getMailOptions( tenantId, paymentReceiveId @@ -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} + */ + public async sendMail( + tenantId: number, + paymentReceiveId: number, + messageDTO: SendInvoiceMailDTO + ): Promise { + // 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( diff --git a/packages/server/src/services/Sales/PaymentReceived/constants.ts b/packages/server/src/services/Sales/PaymentReceived/constants.ts index 739cea048..ffbce4a9f 100644 --- a/packages/server/src/services/Sales/PaymentReceived/constants.ts +++ b/packages/server/src/services/Sales/PaymentReceived/constants.ts @@ -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 = ` -

Dear {CustomerName}

+

Dear {Customer Name}

Thank you for your payment. It was a pleasure doing business with you. We look forward to work together again!

-Payment Date : {PaymentDate}
-Amount : {PaymentAmount}
+Payment Date : {Payment Date}
+Amount : {Payment Amount}

Regards
-{CompanyName} +{Company Name}

`; diff --git a/packages/server/src/services/Sales/Receipts/SaleReceiptMailNotification.ts b/packages/server/src/services/Sales/Receipts/SaleReceiptMailNotification.ts index 81ca4c19e..8fc1478d7 100644 --- a/packages/server/src/services/Sales/Receipts/SaleReceiptMailNotification.ts +++ b/packages/server/src/services/Sales/Receipts/SaleReceiptMailNotification.ts @@ -114,6 +114,58 @@ export class SaleReceiptMailNotification { return transformReceiptToMailDataArgs(receipt); }; + /** + * Formats the mail options of the given sale receipt. + * @param {number} tenantId + * @param {number} receiptId + * @param {SaleReceiptMailOpts} mailOptions + * @returns {Promise} + */ + public async formatEstimateMailOptions( + tenantId: number, + receiptId: number, + mailOptions: SaleReceiptMailOpts + ): Promise { + 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} + */ + public getFormatMailOptions = async ( + tenantId: number, + saleReceiptId: number, + messageOpts: SaleReceiptMailOptsDTO + ): Promise => { + const defaultMessageOptions = await this.getMailOptions( + tenantId, + saleReceiptId + ); + // Merges message opts with default options. + const parsedMessageOpts = mergeAndValidateMailOptions( + defaultMessageOptions, + 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. @@ -126,25 +178,21 @@ export class SaleReceiptMailNotification { saleReceiptId: number, messageOpts: SaleReceiptMailOptsDTO ) { - const defaultMessageOptions = await this.getMailOptions( + // Formats the message options. + const formattedMessageOptions = await this.getFormatMailOptions( tenantId, - saleReceiptId - ); - // Merges message opts with default options. - const parsedMessageOpts = mergeAndValidateMailOptions( - defaultMessageOptions, + saleReceiptId, messageOpts - ) as SaleReceiptMailOpts; - + ); 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); diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx index 8f51add43..a4d1324e5 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogForm.tsx @@ -32,7 +32,7 @@ function EstimateMailDialogFormRoot({ closeDialog, }) { const { mutateAsync: sendEstimateMail } = useSendSaleEstimateMail(); - const { mailOptions, saleEstimateId, redirectToEstimatesList } = + const { mailOptions, saleEstimateId, } = useEstimateMailDialogBoot(); const initialValues = transformMailFormToInitialValues( diff --git a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogFormContent.tsx b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogFormContent.tsx index 668c7a4c9..405c73c0f 100644 --- a/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogFormContent.tsx +++ b/packages/webapp/src/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialogFormContent.tsx @@ -25,8 +25,8 @@ export function EstimateMailDialogFormContent({
diff --git a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentMailDialog/PaymentMailDialogBoot.tsx b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentMailDialog/PaymentMailDialogBoot.tsx index 5fcbd4afa..61171b41f 100644 --- a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentMailDialog/PaymentMailDialogBoot.tsx +++ b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentMailDialog/PaymentMailDialogBoot.tsx @@ -22,6 +22,7 @@ interface PaymentMailDialogBootProps { */ function PaymentMailDialogBoot({ paymentReceiveId, + redirectToPaymentsList, ...props }: PaymentMailDialogBootProps) { const { data: mailOptions, isLoading: isMailOptionsLoading } = diff --git a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentMailDialog/PaymentMailDialogFormContent.tsx b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentMailDialog/PaymentMailDialogFormContent.tsx index 5a04f0f28..5e84bf99c 100644 --- a/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentMailDialog/PaymentMailDialogFormContent.tsx +++ b/packages/webapp/src/containers/Sales/PaymentsReceived/PaymentMailDialog/PaymentMailDialogFormContent.tsx @@ -25,8 +25,8 @@ export function PaymentMailDialogFormContent({
diff --git a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogFormContent.tsx b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogFormContent.tsx index d824d35af..fed55f094 100644 --- a/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogFormContent.tsx +++ b/packages/webapp/src/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialogFormContent.tsx @@ -25,8 +25,8 @@ export function ReceiptMailDialogFormContent({
diff --git a/packages/webapp/src/containers/SendMailNotification/MailNotificationForm.tsx b/packages/webapp/src/containers/SendMailNotification/MailNotificationForm.tsx index 74712a606..a31507080 100644 --- a/packages/webapp/src/containers/SendMailNotification/MailNotificationForm.tsx +++ b/packages/webapp/src/containers/SendMailNotification/MailNotificationForm.tsx @@ -66,7 +66,7 @@ export function MailNotificationForm({ - + ); } diff --git a/packages/webapp/src/containers/SendMailNotification/utils.ts b/packages/webapp/src/containers/SendMailNotification/utils.ts index 59d0f6420..215e851e5 100644 --- a/packages/webapp/src/containers/SendMailNotification/utils.ts +++ b/packages/webapp/src/containers/SendMailNotification/utils.ts @@ -5,7 +5,7 @@ export const initialMailNotificationValues = { from: [], to: [], subject: '', - body: '', + message: '', }; export interface MailNotificationFormValues { @@ -26,7 +26,7 @@ export const transformMailFormToRequest = ( }; /** - * Transformes the mail options response values to form initial values. + * Transforms the mail options response values to form initial values. * @param {any} mailOptions * @param {MailNotificationFormValues} initialValues * @returns {MailNotificationFormValues}