mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 20:30:33 +00:00
feat: mail notifications of sales transactions
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import * as R from 'ramda';
|
||||
import { SaleInvoiceMailOptions } from '@/interfaces';
|
||||
import { CommonMailOptions } from '@/interfaces';
|
||||
import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
import { MailTenancy } from '@/services/MailTenancy/MailTenancy';
|
||||
import { formatSmsMessage } from '@/utils';
|
||||
import { Tenant } from '@/system/models';
|
||||
|
||||
@Service()
|
||||
export class ContactMailNotification {
|
||||
@@ -15,8 +15,10 @@ export class ContactMailNotification {
|
||||
|
||||
/**
|
||||
* Parses the default message options.
|
||||
* @param {number} tenantId
|
||||
* @param {number} invoiceId
|
||||
* @param {number} tenantId -
|
||||
* @param {number} invoiceId -
|
||||
* @param {string} subject -
|
||||
* @param {string} body -
|
||||
* @returns {Promise<SaleInvoiceMailOptions>}
|
||||
*/
|
||||
public async getDefaultMailOptions(
|
||||
@@ -24,9 +26,11 @@ export class ContactMailNotification {
|
||||
contactId: number,
|
||||
subject: string = '',
|
||||
body: string = ''
|
||||
): Promise<any> {
|
||||
const { Contact, Customer } = this.tenancy.models(tenantId);
|
||||
const contact = await Customer.query().findById(contactId).throwIfNotFound();
|
||||
): Promise<CommonMailOptions> {
|
||||
const { Customer } = this.tenancy.models(tenantId);
|
||||
const contact = await Customer.query()
|
||||
.findById(contactId)
|
||||
.throwIfNotFound();
|
||||
|
||||
const toAddresses = contact.contactAddresses;
|
||||
const fromAddresses = await this.mailTenancy.senders(tenantId);
|
||||
@@ -48,10 +52,12 @@ export class ContactMailNotification {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the mail options.
|
||||
* @param {number}
|
||||
* @param {number} invoiceId
|
||||
* @returns {}
|
||||
* Retrieves the mail options of the given contact.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} invoiceId - Invoice id.
|
||||
* @param {string} defaultSubject - Default subject text.
|
||||
* @param {string} defaultBody - Default body text.
|
||||
* @returns {Promise<CommonMailOptions>}
|
||||
*/
|
||||
public async getMailOptions(
|
||||
tenantId: number,
|
||||
@@ -59,15 +65,20 @@ export class ContactMailNotification {
|
||||
defaultSubject?: string,
|
||||
defaultBody?: string,
|
||||
formatterData?: Record<string, any>
|
||||
): Promise<SaleInvoiceMailOptions> {
|
||||
): Promise<CommonMailOptions> {
|
||||
const mailOpts = await this.getDefaultMailOptions(
|
||||
tenantId,
|
||||
contactId,
|
||||
defaultSubject,
|
||||
defaultBody
|
||||
);
|
||||
const subject = formatSmsMessage(mailOpts.subject, formatterData);
|
||||
const body = formatSmsMessage(mailOpts.body, formatterData);
|
||||
const commonFormatArgs = await this.getCommonFormatArgs(tenantId);
|
||||
const formatArgs = {
|
||||
...commonFormatArgs,
|
||||
...formatterData,
|
||||
};
|
||||
const subject = formatSmsMessage(mailOpts.subject, formatArgs);
|
||||
const body = formatSmsMessage(mailOpts.body, formatArgs);
|
||||
|
||||
return {
|
||||
...mailOpts,
|
||||
@@ -75,4 +86,21 @@ export class ContactMailNotification {
|
||||
body,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the common format args.
|
||||
* @param {number} tenantId
|
||||
* @returns {Promise<Record<string, string>>}
|
||||
*/
|
||||
public async getCommonFormatArgs(
|
||||
tenantId: number
|
||||
): Promise<Record<string, string>> {
|
||||
const organization = await Tenant.query()
|
||||
.findById(tenantId)
|
||||
.withGraphFetched('metadata');
|
||||
|
||||
return {
|
||||
CompanyName: organization.metadata.name,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export 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',
|
||||
};
|
||||
33
packages/server/src/services/MailNotification/utils.ts
Normal file
33
packages/server/src/services/MailNotification/utils.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { isEmpty } from 'lodash';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import { CommonMailOptions, CommonMailOptionsDTO } from '@/interfaces';
|
||||
import { ERRORS } from './constants';
|
||||
|
||||
/**
|
||||
* Merges the mail options with incoming options.
|
||||
* @param {Partial<SaleInvoiceMailOptions>} mailOptions
|
||||
* @param {Partial<SendInvoiceMailDTO>} overridedOptions
|
||||
* @throws {ServiceError}
|
||||
*/
|
||||
export function parseAndValidateMailOptions(
|
||||
mailOptions: Partial<CommonMailOptions>,
|
||||
overridedOptions: Partial<CommonMailOptionsDTO>
|
||||
) {
|
||||
const mergedMessageOptions = {
|
||||
...mailOptions,
|
||||
...overridedOptions,
|
||||
};
|
||||
if (isEmpty(mergedMessageOptions.from)) {
|
||||
throw new ServiceError(ERRORS.MAIL_FROM_NOT_FOUND);
|
||||
}
|
||||
if (isEmpty(mergedMessageOptions.to)) {
|
||||
throw new ServiceError(ERRORS.MAIL_TO_NOT_FOUND);
|
||||
}
|
||||
if (isEmpty(mergedMessageOptions.subject)) {
|
||||
throw new ServiceError(ERRORS.MAIL_SUBJECT_NOT_FOUND);
|
||||
}
|
||||
if (isEmpty(mergedMessageOptions.body)) {
|
||||
throw new ServiceError(ERRORS.MAIL_BODY_NOT_FOUND);
|
||||
}
|
||||
return mergedMessageOptions;
|
||||
}
|
||||
Reference in New Issue
Block a user