feat: mail notifications of sales transactions

This commit is contained in:
Ahmed Bouhuolia
2023-12-30 17:49:02 +02:00
parent 0d15c16d40
commit ab7abfea35
25 changed files with 336 additions and 221 deletions

View File

@@ -300,7 +300,10 @@ export class SaleInvoiceApplication {
* @returns {}
*/
public getSaleInvoiceMailReminder(tenantId: number, saleInvoiceId: number) {
return this.sendInvoiceReminderService.getMailOpts(tenantId, saleInvoiceId);
return this.sendInvoiceReminderService.getMailOption(
tenantId,
saleInvoiceId
);
}
/**
@@ -347,6 +350,9 @@ export class SaleInvoiceApplication {
* @returns {Promise<SendInvoiceMailDTO>}
*/
public getSaleInvoiceMail(tenantId: number, saleInvoiceid: number) {
return this.sendSaleInvoiceMailService.getMailOpts(tenantId, saleInvoiceid);
return this.sendSaleInvoiceMailService.getMailOption(
tenantId,
saleInvoiceid
);
}
}

View File

@@ -1,15 +1,12 @@
import { Inject, Service } from 'typedi';
import { isEmpty } from 'lodash';
import { SaleInvoiceMailOptions } from '@/interfaces';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import { GetSaleInvoice } from './GetSaleInvoice';
import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification';
import {
DEFAULT_INVOICE_MAIL_CONTENT,
DEFAULT_INVOICE_MAIL_SUBJECT,
} from './constants';
import { GetSaleInvoice } from './GetSaleInvoice';
import { Tenant } from '@/system/models';
import { ServiceError } from '@/exceptions';
import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification';
@Service()
export class SendSaleInvoiceMailCommon {
@@ -28,9 +25,9 @@ export class SendSaleInvoiceMailCommon {
* @param {number} invoiceId - Invoice id.
* @param {string} defaultSubject - Subject text.
* @param {string} defaultBody - Subject body.
* @returns {}
* @returns {Promise<SaleInvoiceMailOptions>}
*/
public async getMailOpts(
public async getMailOption(
tenantId: number,
invoiceId: number,
defaultSubject: string = DEFAULT_INVOICE_MAIL_SUBJECT,
@@ -44,13 +41,17 @@ export class SendSaleInvoiceMailCommon {
const formatterData = await this.formatText(tenantId, invoiceId);
return this.contactMailNotification.getMailOptions(
const mailOptions = await this.contactMailNotification.getMailOptions(
tenantId,
saleInvoice.customerId,
defaultSubject,
defaultBody,
formatterData
);
return {
...mailOptions,
attachInvoice: true,
};
}
/**
@@ -68,12 +69,8 @@ export class SendSaleInvoiceMailCommon {
tenantId,
invoiceId
);
const organization = await Tenant.query()
.findById(tenantId)
.withGraphFetched('metadata');
return {
CompanyName: organization.metadata.name,
CustomerName: invoice.customer.displayName,
InvoiceNumber: invoice.invoiceNo,
InvoiceDueAmount: invoice.dueAmountFormatted,
@@ -83,33 +80,4 @@ export class SendSaleInvoiceMailCommon {
OverdueDays: invoice.overdueDays,
};
};
/**
* Validates the mail notification options before sending it.
* @param {Partial<SaleInvoiceMailOptions>} mailNotificationOpts
* @throws {ServiceError}
*/
public validateMailNotification(
mailNotificationOpts: Partial<SaleInvoiceMailOptions>
) {
if (isEmpty(mailNotificationOpts.from)) {
throw new ServiceError(ERRORS.MAIL_FROM_NOT_FOUND);
}
if (isEmpty(mailNotificationOpts.to)) {
throw new ServiceError(ERRORS.MAIL_TO_NOT_FOUND);
}
if (isEmpty(mailNotificationOpts.subject)) {
throw new ServiceError(ERRORS.MAIL_SUBJECT_NOT_FOUND);
}
if (isEmpty(mailNotificationOpts.body)) {
throw new ServiceError(ERRORS.MAIL_BODY_NOT_FOUND);
}
}
}
const ERRORS = {
MAIL_FROM_NOT_FOUND: 'Mail from address not found',
MAIL_TO_NOT_FOUND: 'Mail to address not found',
MAIL_SUBJECT_NOT_FOUND: 'Mail subject not found',
MAIL_BODY_NOT_FOUND: 'Mail body not found',
};

View File

@@ -7,6 +7,7 @@ import {
DEFAULT_INVOICE_MAIL_CONTENT,
DEFAULT_INVOICE_MAIL_SUBJECT,
} from './constants';
import { parseAndValidateMailOptions } from '@/services/MailNotification/utils';
@Service()
export class SendSaleInvoiceMail {
@@ -44,8 +45,8 @@ export class SendSaleInvoiceMail {
* @param {number} saleInvoiceId
* @returns {Promise<SaleInvoiceMailOptions>}
*/
public async getMailOpts(tenantId: number, saleInvoiceId: number) {
return this.invoiceMail.getMailOpts(
public async getMailOption(tenantId: number, saleInvoiceId: number) {
return this.invoiceMail.getMailOption(
tenantId,
saleInvoiceId,
DEFAULT_INVOICE_MAIL_SUBJECT,
@@ -65,15 +66,15 @@ export class SendSaleInvoiceMail {
saleInvoiceId: number,
messageDTO: SendInvoiceMailDTO
) {
const defaultMessageOpts = await this.getMailOpts(tenantId, saleInvoiceId);
// Parsed message opts with default options.
const messageOpts = {
...defaultMessageOpts,
...messageDTO,
};
this.invoiceMail.validateMailNotification(messageOpts);
const defaultMessageOpts = await this.getMailOption(
tenantId,
saleInvoiceId
);
// Merge message opts with default options and validate the incoming options.
const messageOpts = parseAndValidateMailOptions(
defaultMessageOpts,
messageDTO
);
const mail = new Mail()
.setSubject(messageOpts.subject)
.setTo(messageOpts.to)

View File

@@ -43,8 +43,8 @@ export class SendInvoiceMailReminder {
* @param {number} saleInvoiceId
* @returns {Promise<SaleInvoiceMailOptions>}
*/
public async getMailOpts(tenantId: number, saleInvoiceId: number) {
return this.invoiceCommonMail.getMailOpts(
public async getMailOption(tenantId: number, saleInvoiceId: number) {
return this.invoiceCommonMail.getMailOption(
tenantId,
saleInvoiceId,
DEFAULT_INVOICE_REMINDER_MAIL_SUBJECT,
@@ -64,7 +64,7 @@ export class SendInvoiceMailReminder {
saleInvoiceId: number,
messageOptions: SendInvoiceMailDTO
) {
const localMessageOpts = await this.getMailOpts(tenantId, saleInvoiceId);
const localMessageOpts = await this.getMailOption(tenantId, saleInvoiceId);
const messageOpts = {
...localMessageOpts,