feat: payment received mail preview

This commit is contained in:
Ahmed Bouhuolia
2024-11-21 14:32:28 +02:00
parent c5c85bdfbe
commit b6f3c0145f
27 changed files with 422 additions and 366 deletions

View File

@@ -29,7 +29,7 @@ export default class PaymentReceive extends mixin(TenantModel, [
* Virtual attributes.
*/
static get virtualAttributes() {
return ['localAmount'];
return ['localAmount', 'total'];
}
/**
@@ -40,6 +40,10 @@ export default class PaymentReceive extends mixin(TenantModel, [
return this.amount * this.exchangeRate;
}
get total() {
return this.paymentAmount;
}
/**
* Resourcable model.
*/

View File

@@ -0,0 +1,53 @@
import { PaymentReceiveMailOpts } from '@/interfaces';
import HasTenancyService from '@/services/Tenancy/TenancyService';
import { GetPaymentReceivedMailStateTransformer } from './GetPaymentReceivedMailStateTransformer';
import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
import { Inject, Service } from 'typedi';
import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification';
@Service()
export class GetPaymentReceivedMailState {
@Inject()
private tenancy: HasTenancyService;
@Inject()
private contactMailNotification: ContactMailNotification;
@Inject()
private transformer: TransformerInjectable;
/**
* Retrieves the default payment mail options.
* @param {number} tenantId - Tenant id.
* @param {number} paymentReceiveId - Payment receive id.
* @returns {Promise<PaymentReceiveMailOpts>}
*/
public getMailOptions = async (
tenantId: number,
paymentId: number
): Promise<PaymentReceiveMailOpts> => {
const { PaymentReceive } = this.tenancy.models(tenantId);
const paymentReceive = await PaymentReceive.query()
.findById(paymentId)
.withGraphFetched('customer')
.withGraphFetched('entries.invoice')
.throwIfNotFound();
const mailOptions =
await this.contactMailNotification.getDefaultMailOptions(
tenantId,
paymentReceive.customerId
);
const transformed = await this.transformer.transform(
tenantId,
paymentReceive,
new GetPaymentReceivedMailStateTransformer(),
{
mailOptions,
}
);
return transformed;
};
}

View File

@@ -0,0 +1,134 @@
import { PaymentReceiveEntry } from '@/models';
import { PaymentReceiveTransfromer } from './PaymentReceivedTransformer';
import { PaymentReceivedEntryTransfromer } from './PaymentReceivedEntryTransformer';
export class GetPaymentReceivedMailStateTransformer extends PaymentReceiveTransfromer {
/**
* Exclude these attributes from user object.
* @returns {Array}
*/
public excludeAttributes = (): string[] => {
return ['*'];
};
/**
* Included attributes.
* @returns {Array}
*/
public includeAttributes = (): string[] => {
return [
'paymentDate',
'paymentDateFormatted',
'paymentAmount',
'paymentAmountFormatted',
'total',
'totalFormatted',
'paymentNo',
'entries',
'companyName',
'companyLogoUri',
'primaryColor',
'customerName',
];
};
/**
* Retrieves the customer name of the payment.
* @returns {string}
*/
protected customerName = (payment) => {
return payment.customer.displayName;
};
/**
* Retrieves the company name.
* @returns {string}
*/
protected companyName = () => {
return this.context.organization.name;
};
/**
* Retrieves the company logo uri.
* @returns {string | null}
*/
protected companyLogoUri = (payment) => {
return payment.pdfTemplate?.companyLogoUri;
};
/**
* Retrieves the primary color.
* @returns {string}
*/
protected primaryColor = (payment) => {
return payment.pdfTemplate?.attributes?.primaryColor;
};
/**
* Retrieves the formatted payment date.
* @returns {string}
*/
protected paymentDateFormatted = (payment) => {
return this.formatDate(payment.paymentDate);
};
/**
* Retrieves the formatted payment amount.
* @returns {string}
*/
protected paymentAmountFormatted = (payment) => {
return this.formatMoney(payment.paymentAmount);
};
/**
* Retrieves the formatted payment amount.
* @returns {string}
*/
protected totalFormatted = (payment) => {
return this.formatMoney(payment.total);
};
/**
* Retrieves the payment entries.
* @param {IPaymentReceived} payment
* @returns {IPaymentReceivedEntry[]}
*/
protected entries = (payment) => {
return this.item(payment.entries, new GetPaymentReceivedEntryMailState());
};
/**
* Merges the mail options with the invoice object.
*/
public transform = (object: any) => {
return {
...this.options.mailOptions,
...object,
};
};
}
export class GetPaymentReceivedEntryMailState extends PaymentReceivedEntryTransfromer {
/**
* Include these attributes to payment receive entry object.
* @returns {Array}
*/
public includeAttributes = (): string[] => {
return ['paymentAmountFormatted'];
};
/**
* Exclude these attributes from user object.
* @returns {Array}
*/
public excludeAttributes = (): string[] => {
return ['*'];
};
}

View File

@@ -20,6 +20,7 @@ import { PaymentReceiveNotifyBySms } from './PaymentReceivedSmsNotify';
import GetPaymentReceivedPdf from './GetPaymentReceivedPdf';
import { SendPaymentReceiveMailNotification } from './PaymentReceivedMailNotification';
import { GetPaymentReceivedState } from './GetPaymentReceivedState';
import { GetPaymentReceivedMailState } from './GetPaymentReceivedMailState';
@Service()
export class PaymentReceivesApplication {
@@ -53,6 +54,9 @@ export class PaymentReceivesApplication {
@Inject()
private getPaymentReceivedStateService: GetPaymentReceivedState;
@Inject()
private getPaymentReceivedMailStateService: GetPaymentReceivedMailState;
/**
* Creates a new payment receive.
* @param {number} tenantId
@@ -204,12 +208,15 @@ export class PaymentReceivesApplication {
/**
* Retrieves the default mail options of the given payment transaction.
* @param {number} tenantId
* @param {number} paymentReceiveId
* @param {number} tenantId - Tenant id.
* @param {number} paymentReceiveId - Payment received id.
* @returns {Promise<void>}
*/
public getPaymentMailOptions(tenantId: number, paymentReceiveId: number) {
return this.paymentMailNotify.getMailOptions(tenantId, paymentReceiveId);
return this.getPaymentReceivedMailStateService.getMailOptions(
tenantId,
paymentReceiveId
);
}
/**

View File

@@ -62,37 +62,6 @@ export class SendPaymentReceiveMailNotification {
} as PaymentReceiveMailPresendEvent);
}
/**
* Retrieves the default payment mail options.
* @param {number} tenantId - Tenant id.
* @param {number} paymentReceiveId - Payment receive id.
* @returns {Promise<PaymentReceiveMailOpts>}
*/
public getMailOptions = async (
tenantId: number,
paymentId: number
): Promise<PaymentReceiveMailOpts> => {
const { PaymentReceive } = this.tenancy.models(tenantId);
const paymentReceive = await PaymentReceive.query()
.findById(paymentId)
.throwIfNotFound();
const formatArgs = await this.textFormatter(tenantId, paymentId);
const mailOptions =
await this.contactMailNotification.getDefaultMailOptions(
tenantId,
paymentReceive.customerId
);
return {
...mailOptions,
subject: DEFAULT_PAYMENT_MAIL_SUBJECT,
message: DEFAULT_PAYMENT_MAIL_CONTENT,
...formatArgs,
};
};
/**
* Retrieves the formatted text of the given sale invoice.
* @param {number} tenantId - Tenant id.