Compare commits
1 Commits
bugs-bashi
...
migrate-se
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a10b58a7c6 |
@@ -36,6 +36,7 @@
|
||||
"@nestjs/swagger": "^7.4.2",
|
||||
"@nestjs/throttler": "^6.2.1",
|
||||
"@supercharge/promise-pool": "^3.2.0",
|
||||
"@types/nodemailer": "^6.4.17",
|
||||
"@types/passport-local": "^1.0.38",
|
||||
"@types/ramda": "^0.30.2",
|
||||
"accounting": "^0.4.1",
|
||||
@@ -51,8 +52,8 @@
|
||||
"express-validator": "^7.2.0",
|
||||
"form-data": "^4.0.0",
|
||||
"fp-ts": "^2.16.9",
|
||||
"js-money": "^0.6.3",
|
||||
"is-my-json-valid": "^2.20.5",
|
||||
"js-money": "^0.6.3",
|
||||
"knex": "^3.1.0",
|
||||
"lamda": "^0.4.1",
|
||||
"lodash": "^4.17.21",
|
||||
@@ -61,6 +62,7 @@
|
||||
"mysql2": "^3.11.3",
|
||||
"nestjs-cls": "^4.4.1",
|
||||
"nestjs-i18n": "^10.4.9",
|
||||
"nodemailer": "^6.3.0",
|
||||
"object-hash": "^2.0.3",
|
||||
"objection": "^3.1.5",
|
||||
"passport": "^0.7.0",
|
||||
|
||||
@@ -65,6 +65,7 @@ import { SettingsModule } from '../Settings/Settings.module';
|
||||
import { InventoryAdjustmentsModule } from '../InventoryAdjutments/InventoryAdjustments.module';
|
||||
import { PostHogModule } from '../EventsTracker/postHog.module';
|
||||
import { EventTrackerModule } from '../EventsTracker/EventTracker.module';
|
||||
import { MailModule } from '../Mail/Mail.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -120,6 +121,7 @@ import { EventTrackerModule } from '../EventsTracker/EventTracker.module';
|
||||
TenancyModelsModule,
|
||||
ChromiumlyTenancyModule,
|
||||
TransformerModule,
|
||||
MailModule,
|
||||
ItemsModule,
|
||||
ItemCategoryModule,
|
||||
AccountsModule,
|
||||
|
||||
@@ -8,7 +8,10 @@ import {
|
||||
Query,
|
||||
} from '@nestjs/common';
|
||||
import { BankingTransactionsApplication } from './BankingTransactionsApplication.service';
|
||||
import { ICashflowNewCommandDTO } from './types/BankingTransactions.types';
|
||||
import {
|
||||
IBankAccountsFilter,
|
||||
ICashflowNewCommandDTO,
|
||||
} from './types/BankingTransactions.types';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
|
||||
@Controller('banking/transactions')
|
||||
@@ -19,7 +22,7 @@ export class BankingTransactionsController {
|
||||
) {}
|
||||
|
||||
@Get('')
|
||||
async getBankAccounts(@Query() filterDTO: ICashflowAccountsFilter) {
|
||||
async getBankAccounts(@Query() filterDTO: IBankAccountsFilter) {
|
||||
return this.bankingTransactionsApplication.getBankAccounts(filterDTO);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Knex } from 'knex';
|
||||
import { DeleteCashflowTransaction } from './commands/DeleteCashflowTransaction.service';
|
||||
import { CreateBankTransactionService } from './commands/CreateBankTransaction.service';
|
||||
import { GetBankTransactionService } from './queries/GetBankTransaction.service';
|
||||
import { ICashflowNewCommandDTO } from './types/BankingTransactions.types';
|
||||
import { IBankAccountsFilter, ICashflowNewCommandDTO } from './types/BankingTransactions.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { GetBankAccountsService } from './queries/GetBankAccounts.service';
|
||||
|
||||
@@ -48,9 +48,9 @@ export class BankingTransactionsApplication {
|
||||
|
||||
/**
|
||||
* Retrieves the cashflow accounts.
|
||||
* @param {ICashflowAccountsFilter} filterDTO
|
||||
* @param {IBankAccountsFilter} filterDTO
|
||||
*/
|
||||
public getBankAccounts(filterDTO: ICashflowAccountsFilter) {
|
||||
public getBankAccounts(filterDTO: IBankAccountsFilter) {
|
||||
return this.getBankAccountsService.getBankAccounts(filterDTO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
import { CashflowAccountTransformer } from './BankAccountTransformer';
|
||||
import { ACCOUNT_TYPE } from '@/constants/accounts';
|
||||
import { IBankAccountsFilter } from '../types/BankingTransactions.types';
|
||||
|
||||
@Injectable()
|
||||
export class GetBankAccountsService {
|
||||
@@ -12,7 +13,7 @@ export class GetBankAccountsService {
|
||||
private readonly transformer: TransformerInjectable,
|
||||
|
||||
@Inject(BankAccount.name)
|
||||
private readonly bankAccountModel: typeof BankAccount
|
||||
private readonly bankAccountModel: typeof BankAccount,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -21,7 +22,7 @@ export class GetBankAccountsService {
|
||||
* @returns {ICashflowAccount[]}
|
||||
*/
|
||||
public async getBankAccounts(
|
||||
filterDTO: ICashflowAccountsFilter,
|
||||
filterDTO: IBankAccountsFilter,
|
||||
): Promise<BankAccount[]> {
|
||||
// Parsees accounts list filter DTO.
|
||||
const filter = this.dynamicListService.parseStringifiedFilter(filterDTO);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Knex } from "knex";
|
||||
import { UncategorizedBankTransaction } from "../models/UncategorizedBankTransaction";
|
||||
import { BankTransaction } from "../models/BankTransaction";
|
||||
import { Knex } from 'knex';
|
||||
import { UncategorizedBankTransaction } from '../models/UncategorizedBankTransaction';
|
||||
import { BankTransaction } from '../models/BankTransaction';
|
||||
|
||||
export interface IPendingTransactionRemovingEventPayload {
|
||||
uncategorizedTransactionId: number;
|
||||
@@ -49,6 +49,13 @@ export interface ICashflowNewCommandDTO extends ICashflowCommandDTO {
|
||||
uncategorizedTransactionId?: number;
|
||||
}
|
||||
|
||||
export interface IBankAccountsFilter {
|
||||
inactiveMode: boolean;
|
||||
stringifiedFilterRoles?: string;
|
||||
sortOrder: string;
|
||||
columnSortBy: string;
|
||||
}
|
||||
|
||||
export enum CashflowDirection {
|
||||
IN = 'in',
|
||||
OUT = 'out',
|
||||
|
||||
@@ -6,6 +6,7 @@ import { EditBillPayment } from './commands/EditBillPayment.service';
|
||||
import { GetBillPayment } from './queries/GetBillPayment.service';
|
||||
import { GetPaymentBills } from './queries/GetPaymentBills.service';
|
||||
import { IBillPaymentDTO } from './types/BillPayments.types';
|
||||
import { GetBillPayments } from '../Bills/queries/GetBillPayments';
|
||||
|
||||
/**
|
||||
* Bill payments application.
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { CreateBill } from './commands/CreateBill.service';
|
||||
import { EditBillService } from './commands/EditBill.service';
|
||||
import { GetBill } from './queries/GetBill';
|
||||
// import { GetBills } from './queries/GetBills';
|
||||
import { DeleteBill } from './commands/DeleteBill.service';
|
||||
import { IBillDTO, IBillEditDTO } from './Bills.types';
|
||||
import { IBillDTO, IBillEditDTO, IBillsFilter } from './Bills.types';
|
||||
import { GetDueBills } from './queries/GetDueBills.service';
|
||||
import { OpenBillService } from './commands/OpenBill.service';
|
||||
import { GetBillPayments } from './queries/GetBillPayments';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { GetBillsService } from './queries/GetBills.service';
|
||||
// import { GetBillPayments } from './queries/GetBillPayments';
|
||||
// import { GetBills } from './queries/GetBills';
|
||||
|
||||
@Injectable()
|
||||
export class BillsApplication {
|
||||
|
||||
@@ -18,7 +18,7 @@ export class GetBillsService {
|
||||
|
||||
/**
|
||||
* Retrieve bills data table list.
|
||||
* @param {IBillsFilter} billsFilter -
|
||||
* @param {IBillsFilter} billsFilter -
|
||||
*/
|
||||
public async getBills(filterDTO: IBillsFilter): Promise<{
|
||||
bills: Bill;
|
||||
|
||||
@@ -14,12 +14,12 @@ import { GetCreditNotesService } from './queries/GetCreditNotes.service';
|
||||
@Injectable()
|
||||
export class CreditNoteApplication {
|
||||
constructor(
|
||||
private createCreditNoteService: CreateCreditNoteService,
|
||||
private editCreditNoteService: EditCreditNoteService,
|
||||
private openCreditNoteService: OpenCreditNoteService,
|
||||
private deleteCreditNoteService: DeleteCreditNoteService,
|
||||
private getCreditNotePdfService: GetCreditNotePdf,
|
||||
private getCreditNotesService: GetCreditNotesService,
|
||||
private readonly createCreditNoteService: CreateCreditNoteService,
|
||||
private readonly editCreditNoteService: EditCreditNoteService,
|
||||
private readonly openCreditNoteService: OpenCreditNoteService,
|
||||
private readonly deleteCreditNoteService: DeleteCreditNoteService,
|
||||
private readonly getCreditNotePdfService: GetCreditNotePdf,
|
||||
private readonly getCreditNotesService: GetCreditNotesService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as R from 'ramda';
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
|
||||
import { ICreditNotesQueryDTO } from '../types/CreditNotes.types';
|
||||
import { GetCreditNotesResponse, ICreditNotesQueryDTO } from '../types/CreditNotes.types';
|
||||
import { CreditNote } from '../models/CreditNote';
|
||||
import { CreditNoteTransformer } from './CreditNoteTransformer';
|
||||
import { Inject } from '@nestjs/common';
|
||||
|
||||
@@ -3,6 +3,8 @@ import { CreditNote } from '../models/CreditNote';
|
||||
import { RefundCreditNote } from '../../CreditNoteRefunds/models/RefundCreditNote';
|
||||
import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types';
|
||||
import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types';
|
||||
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
||||
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||
|
||||
export interface ICreditNoteEntryNewDTO extends IItemEntryDTO {}
|
||||
|
||||
@@ -91,17 +93,12 @@ export interface ICreditNoteOpenedPayload {
|
||||
oldCreditNote: CreditNote;
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
export interface ICreditNotesQueryDTO {
|
||||
filterQuery?: (query: any) => void;
|
||||
export interface ICreditNotesQueryDTO extends IDynamicListFilter {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
searchKeyword?: string;
|
||||
}
|
||||
|
||||
// export interface ICreditNotesQueryDTO extends IDynamicListFilter {
|
||||
// page: number;
|
||||
// pageSize: number;
|
||||
// searchKeyword?: string;
|
||||
// }
|
||||
|
||||
export interface ICreditNoteRefundDTO {
|
||||
fromAccountId: number;
|
||||
amount: number;
|
||||
@@ -129,6 +126,12 @@ export interface ICreditNoteRefundDTO {
|
||||
// | 'branchId'
|
||||
// >;
|
||||
|
||||
export interface GetCreditNotesResponse {
|
||||
creditNotes: CreditNote[];
|
||||
pagination: IPaginationMeta;
|
||||
filterMeta: IFilterMeta;
|
||||
}
|
||||
|
||||
export interface CreditNotePdfTemplateAttributes {
|
||||
// # Primary color
|
||||
primaryColor: string;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Model } from 'objection';
|
||||
import { castArray } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import moment, { unitOfTime } from 'moment';
|
||||
import { SaleInvoice } from '@/modules/SaleInvoices/models/SaleInvoice';
|
||||
import { SaleReceipt } from '@/modules/SaleReceipts/models/SaleReceipt';
|
||||
import { Item } from '@/modules/Items/models/Item';
|
||||
@@ -55,7 +55,7 @@ export class InventoryCostLotTracker extends BaseModel {
|
||||
query.groupBy('date');
|
||||
query.groupBy('item_id');
|
||||
},
|
||||
filterDateRange(query, startDate, endDate, type = 'day') {
|
||||
filterDateRange(query, startDate, endDate, type: unitOfTime.StartOf = 'day') {
|
||||
const dateFormat = 'YYYY-MM-DD';
|
||||
const fromDate = moment(startDate).startOf(type).format(dateFormat);
|
||||
const toDate = moment(endDate).endOf(type).format(dateFormat);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Model, raw } from 'objection';
|
||||
import { castArray } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import moment, { unitOfTime } from 'moment';
|
||||
import { BaseModel } from '@/models/Model';
|
||||
import { getTransactionTypeLabel } from '@/modules/BankingTransactions/utils';
|
||||
import { TInventoryTransactionDirection } from '../types/InventoryCost.types';
|
||||
@@ -48,7 +48,12 @@ export class InventoryTransaction extends BaseModel {
|
||||
*/
|
||||
static get modifiers() {
|
||||
return {
|
||||
filterDateRange(query, startDate, endDate, type = 'day') {
|
||||
filterDateRange(
|
||||
query,
|
||||
startDate,
|
||||
endDate,
|
||||
type: unitOfTime.StartOf = 'day',
|
||||
) {
|
||||
const dateFormat = 'YYYY-MM-DD';
|
||||
const fromDate = moment(startDate).startOf(type).format(dateFormat);
|
||||
const toDate = moment(endDate).endOf(type).format(dateFormat);
|
||||
|
||||
1
packages/server-nest/src/modules/Mail/Mail.constants.ts
Normal file
1
packages/server-nest/src/modules/Mail/Mail.constants.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const MAIL_TRANSPORTER_PROVIDER = 'MAIL_TRANSPORTER';
|
||||
33
packages/server-nest/src/modules/Mail/Mail.module.ts
Normal file
33
packages/server-nest/src/modules/Mail/Mail.module.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { createTransport } from 'nodemailer';
|
||||
import { MAIL_TRANSPORTER_PROVIDER } from './Mail.constants';
|
||||
import { MailTransporter } from './MailTransporter.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
{
|
||||
module: MailModule,
|
||||
providers: [
|
||||
{
|
||||
provide: MAIL_TRANSPORTER_PROVIDER,
|
||||
useFactory: (configService: ConfigService) => {
|
||||
// Create reusable transporter object using the default SMTP transport
|
||||
const transporter = createTransport({
|
||||
host: configService.get('mail.host'),
|
||||
port: configService.get('mail.port'),
|
||||
secure: configService.get('mail.secure'), // true for 465, false for other ports
|
||||
auth: {
|
||||
user: configService.get('mail.username'),
|
||||
pass: configService.get('mail.password'),
|
||||
},
|
||||
});
|
||||
return transporter;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
MailTransporter
|
||||
],
|
||||
})
|
||||
export class MailModule {}
|
||||
131
packages/server-nest/src/modules/Mail/Mail.ts
Normal file
131
packages/server-nest/src/modules/Mail/Mail.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import * as fs from 'fs';
|
||||
import * as Mustache from 'mustache';
|
||||
import * as path from 'path';
|
||||
import { IMailAttachment } from './Mail.types';
|
||||
|
||||
export class Mail {
|
||||
view: string;
|
||||
subject: string = '';
|
||||
content: string = '';
|
||||
to: string | string[];
|
||||
cc: string | string[];
|
||||
bcc: string | string[];
|
||||
replyTo: string | string[];
|
||||
from: string = `${process.env.MAIL_FROM_NAME} ${process.env.MAIL_FROM_ADDRESS}`;
|
||||
data: { [key: string]: string | number };
|
||||
attachments: IMailAttachment[];
|
||||
|
||||
/**
|
||||
* Mail options.
|
||||
*/
|
||||
public get mailOptions() {
|
||||
return {
|
||||
to: this.to,
|
||||
from: this.from,
|
||||
cc: this.cc,
|
||||
bcc: this.bcc,
|
||||
subject: this.subject,
|
||||
html: this.html,
|
||||
attachments: this.attachments,
|
||||
replyTo: this.replyTo,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the html content of the mail.
|
||||
* @returns {string}
|
||||
*/
|
||||
public get html() {
|
||||
return this.view ? Mail.render(this.view, this.data) : this.content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set send mail to address.
|
||||
* @param {string} to -
|
||||
*/
|
||||
setTo(to: string | string[]) {
|
||||
this.to = to;
|
||||
return this;
|
||||
}
|
||||
|
||||
setCC(cc: string | string[]) {
|
||||
this.cc = cc;
|
||||
return this;
|
||||
}
|
||||
|
||||
setBCC(bcc: string | string[]) {
|
||||
this.bcc = bcc;
|
||||
return this;
|
||||
}
|
||||
|
||||
setReplyTo(replyTo: string | string[]) {
|
||||
this.replyTo = replyTo;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets from address to the mail.
|
||||
* @param {string} from
|
||||
* @return {}
|
||||
*/
|
||||
setFrom(from: string) {
|
||||
this.from = from;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set attachments to the mail.
|
||||
* @param {IMailAttachment[]} attachments
|
||||
* @returns {Mail}
|
||||
*/
|
||||
setAttachments(attachments: IMailAttachment[]) {
|
||||
this.attachments = attachments;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mail subject.
|
||||
* @param {string} subject
|
||||
*/
|
||||
setSubject(subject: string) {
|
||||
this.subject = subject;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set view directory.
|
||||
* @param {string} view
|
||||
*/
|
||||
setView(view: string) {
|
||||
this.view = view;
|
||||
return this;
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
setContent(content: string) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the view template with the given data.
|
||||
* @param {object} data
|
||||
* @return {string}
|
||||
*/
|
||||
static render(view: string, data: Record<string, any>): string {
|
||||
const viewContent = Mail.getViewContent(view);
|
||||
return Mustache.render(viewContent, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve view content from the view directory.
|
||||
*/
|
||||
static getViewContent(view: string): string {
|
||||
const filePath = path.join(global.__views_dir, `/${view}`);
|
||||
return fs.readFileSync(filePath, 'utf8');
|
||||
}
|
||||
}
|
||||
11
packages/server-nest/src/modules/Mail/Mail.types.ts
Normal file
11
packages/server-nest/src/modules/Mail/Mail.types.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export type IMailAttachment = MailAttachmentPath | MailAttachmentContent;
|
||||
|
||||
export interface MailAttachmentPath {
|
||||
filename: string;
|
||||
path: string;
|
||||
cid: string;
|
||||
}
|
||||
export interface MailAttachmentContent {
|
||||
filename: string;
|
||||
content: Buffer;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Transporter } from 'nodemailer';
|
||||
import { Mail } from './Mail';
|
||||
import { Inject } from '@nestjs/common';
|
||||
import { MAIL_TRANSPORTER_PROVIDER } from './Mail.constants';
|
||||
|
||||
export class MailTransporter {
|
||||
constructor(
|
||||
@Inject(MAIL_TRANSPORTER_PROVIDER)
|
||||
private readonly transporter: Transporter,
|
||||
) {}
|
||||
|
||||
send(mail: Mail) {
|
||||
return this.transporter.sendMail(mail.mailOptions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { castArray } from 'lodash';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { MailTenancy } from '../MailTenancy/MailTenancy.service';
|
||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||
import { Customer } from '../Customers/models/Customer';
|
||||
import { CommonMailOptions } from './MailNotification.types';
|
||||
|
||||
@Injectable()
|
||||
export class ContactMailNotification {
|
||||
constructor(
|
||||
private readonly mailTenancy: MailTenancy,
|
||||
private readonly tenantContext: TenancyContext,
|
||||
|
||||
@Inject(Customer.name)
|
||||
private readonly customerModel: typeof Customer,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Gets the default mail address of the given contact.
|
||||
* @param {number} invoiceId - Contact id.
|
||||
* @returns {Promise<Pick<CommonMailOptions, 'to' | 'from'>>}
|
||||
*/
|
||||
public async getDefaultMailOptions(
|
||||
customerId: number,
|
||||
): Promise<
|
||||
Pick<CommonMailOptions, 'to' | 'from' | 'toOptions' | 'fromOptions'>
|
||||
> {
|
||||
const customer = await this.customerModel
|
||||
.query()
|
||||
.findById(customerId)
|
||||
.throwIfNotFound();
|
||||
|
||||
const toOptions = customer.contactAddresses;
|
||||
const fromOptions = await this.mailTenancy.senders();
|
||||
|
||||
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, toOptions, fromOptions };
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the mail options of the given contact.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @returns {Promise<CommonMailOptions>}
|
||||
*/
|
||||
public async formatMailOptions(
|
||||
mailOptions: CommonMailOptions,
|
||||
formatterArgs?: Record<string, any>,
|
||||
): Promise<CommonMailOptions> {
|
||||
const commonFormatArgs = await this.getCommonFormatArgs();
|
||||
const formatArgs = {
|
||||
...commonFormatArgs,
|
||||
...formatterArgs,
|
||||
};
|
||||
const subjectFormatted = formatSmsMessage(mailOptions?.subject, formatArgs);
|
||||
const messageFormatted = formatSmsMessage(mailOptions?.message, formatArgs);
|
||||
|
||||
return {
|
||||
...mailOptions,
|
||||
subject: subjectFormatted,
|
||||
message: messageFormatted,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the common format args.
|
||||
* @returns {Promise<Record<string, string>>}
|
||||
*/
|
||||
public async getCommonFormatArgs(): Promise<Record<string, string>> {
|
||||
const tenantMetadata = await this.tenantContext.getTenantMetadata();
|
||||
|
||||
return {
|
||||
['Company Name']: tenantMetadata.name,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ContactMailNotification } from './ContactMailNotification';
|
||||
|
||||
@Module({
|
||||
imports: [ContactMailNotification],
|
||||
exports: [ContactMailNotification],
|
||||
})
|
||||
export class MailNotificationModule {}
|
||||
@@ -0,0 +1,44 @@
|
||||
export type IMailAttachment = MailAttachmentPath | MailAttachmentContent;
|
||||
|
||||
export interface MailAttachmentPath {
|
||||
filename: string;
|
||||
path: string;
|
||||
cid: string;
|
||||
}
|
||||
export interface MailAttachmentContent {
|
||||
filename: string;
|
||||
content: Buffer;
|
||||
}
|
||||
|
||||
export interface IMailable {
|
||||
constructor(view: string, data?: { [key: string]: string | number });
|
||||
send(): Promise<any>;
|
||||
build(): void;
|
||||
setData(data: { [key: string]: string | number }): IMailable;
|
||||
setTo(to: string): IMailable;
|
||||
setFrom(from: string): IMailable;
|
||||
setSubject(subject: string): IMailable;
|
||||
setView(view: string): IMailable;
|
||||
render(data?: { [key: string]: string | number }): string;
|
||||
getViewContent(): string;
|
||||
}
|
||||
|
||||
export interface AddressItem {
|
||||
label: string;
|
||||
mail: string;
|
||||
primary?: boolean;
|
||||
}
|
||||
|
||||
export interface CommonMailOptions {
|
||||
from: Array<string>;
|
||||
subject: string;
|
||||
message: string;
|
||||
to: Array<string>;
|
||||
cc?: Array<string>;
|
||||
bcc?: Array<string>;
|
||||
formatArgs?: Record<string, any>;
|
||||
toOptions: Array<AddressItem>;
|
||||
fromOptions: Array<AddressItem>;
|
||||
}
|
||||
|
||||
export interface CommonMailOptionsDTO extends Partial<CommonMailOptions> {}
|
||||
@@ -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',
|
||||
};
|
||||
56
packages/server-nest/src/modules/MailNotification/utils.ts
Normal file
56
packages/server-nest/src/modules/MailNotification/utils.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { castArray, isEmpty } from 'lodash';
|
||||
import { ServiceError } from '@/exceptions';
|
||||
import { CommonMailOptions } from '@/interfaces';
|
||||
import { ERRORS } from './constants';
|
||||
|
||||
/**
|
||||
* Merges the mail options with incoming options.
|
||||
* @param {Partial<SaleInvoiceMailOptions>} mailOptions
|
||||
* @param {Partial<SendInvoiceMailDTO>} overridedOptions
|
||||
*/
|
||||
export function parseMailOptions(
|
||||
mailOptions: CommonMailOptions,
|
||||
overridedOptions: Partial<CommonMailOptions>
|
||||
): CommonMailOptions {
|
||||
const mergedMessageOptions = {
|
||||
...mailOptions,
|
||||
...overridedOptions,
|
||||
};
|
||||
const parsedMessageOptions = {
|
||||
...mergedMessageOptions,
|
||||
from: mergedMessageOptions?.from
|
||||
? castArray(mergedMessageOptions?.from)
|
||||
: [],
|
||||
to: mergedMessageOptions?.to ? castArray(mergedMessageOptions?.to) : [],
|
||||
cc: mergedMessageOptions?.cc ? castArray(mergedMessageOptions?.cc) : [],
|
||||
bcc: mergedMessageOptions?.bcc ? castArray(mergedMessageOptions?.bcc) : [],
|
||||
};
|
||||
return parsedMessageOptions;
|
||||
}
|
||||
|
||||
export function validateRequiredMailOptions(
|
||||
mailOptions: Partial<CommonMailOptions>
|
||||
) {
|
||||
if (isEmpty(mailOptions.from)) {
|
||||
throw new ServiceError(ERRORS.MAIL_FROM_NOT_FOUND);
|
||||
}
|
||||
if (isEmpty(mailOptions.to)) {
|
||||
throw new ServiceError(ERRORS.MAIL_TO_NOT_FOUND);
|
||||
}
|
||||
if (isEmpty(mailOptions.subject)) {
|
||||
throw new ServiceError(ERRORS.MAIL_SUBJECT_NOT_FOUND);
|
||||
}
|
||||
if (isEmpty(mailOptions.message)) {
|
||||
throw new ServiceError(ERRORS.MAIL_BODY_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
export const mergeAndValidateMailOptions = (
|
||||
mailOptions: CommonMailOptions,
|
||||
overridedOptions: Partial<CommonMailOptions>
|
||||
): CommonMailOptions => {
|
||||
const parsedMessageOptions = parseMailOptions(mailOptions, overridedOptions);
|
||||
validateRequiredMailOptions(parsedMessageOptions);
|
||||
|
||||
return parsedMessageOptions;
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { MailTenancy } from './MailTenancy.service';
|
||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
providers: [MailTenancy, TenancyContext],
|
||||
})
|
||||
export class MailTenancyModule {}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { TenancyContext } from '../Tenancy/TenancyContext.service';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
@Injectable()
|
||||
export class MailTenancy {
|
||||
constructor(
|
||||
private readonly tenancyContext: TenancyContext,
|
||||
private readonly config: ConfigService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieves the senders mails of the given tenant.
|
||||
*/
|
||||
public async senders() {
|
||||
const tenantMetadata = await this.tenancyContext.getTenantMetadata();
|
||||
const from = this.config.get('mail.from');
|
||||
|
||||
return [
|
||||
{
|
||||
mail: from,
|
||||
label: tenantMetadata.name,
|
||||
primary: true,
|
||||
}
|
||||
].filter((item) => item.mail)
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectab
|
||||
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
|
||||
import { ManualJournal } from '../models/ManualJournal';
|
||||
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
||||
import { IManualJournalsFilter } from '../types/ManualJournals.types';
|
||||
|
||||
@Injectable()
|
||||
export class GetManualJournals {
|
||||
@@ -26,7 +27,6 @@ export class GetManualJournals {
|
||||
|
||||
/**
|
||||
* Retrieve manual journals datatable list.
|
||||
* @param {number} tenantId -
|
||||
* @param {IManualJournalsFilter} filter -
|
||||
*/
|
||||
public getManualJournals = async (
|
||||
@@ -44,7 +44,8 @@ export class GetManualJournals {
|
||||
ManualJournal,
|
||||
filter,
|
||||
);
|
||||
const { results, pagination } = await this.manualJournalModel.query()
|
||||
const { results, pagination } = await this.manualJournalModel
|
||||
.query()
|
||||
.onBuild((builder) => {
|
||||
dynamicService.buildQuery()(builder);
|
||||
builder.withGraphFetched('entries.account');
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Knex } from 'knex';
|
||||
// import { AttachmentLinkDTO } from './Attachments';
|
||||
import { ManualJournal } from '../models/ManualJournal';
|
||||
import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types';
|
||||
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||
|
||||
export interface IManualJournalEntryDTO {
|
||||
index: number;
|
||||
@@ -31,11 +32,11 @@ export interface IManualJournalDTO {
|
||||
attachments?: AttachmentLinkDTO[];
|
||||
}
|
||||
|
||||
// export interface IManualJournalsFilter extends IDynamicListFilterDTO {
|
||||
// stringifiedFilterRoles?: string;
|
||||
// page: number;
|
||||
// pageSize: number;
|
||||
// }
|
||||
export interface IManualJournalsFilter extends IDynamicListFilter {
|
||||
stringifiedFilterRoles?: string;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
export interface IManualJournalEventPublishedPayload {
|
||||
// tenantId: number;
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
IPaymentReceivedCreateDTO,
|
||||
IPaymentReceivedEditDTO,
|
||||
IPaymentReceivedSmsDetails,
|
||||
IPaymentsReceivedFilter,
|
||||
// IPaymentsReceivedFilter,
|
||||
// ISystemUser,
|
||||
// PaymentReceiveMailOptsDTO,
|
||||
|
||||
@@ -78,11 +78,10 @@ export class PaymentReceivesController {
|
||||
|
||||
@Get(':id/pdf')
|
||||
public getPaymentReceivePdf(
|
||||
@Param('id', ParseIntPipe) paymentReceiveId: number,
|
||||
@Param('id', ParseIntPipe) paymentReceivedId: number,
|
||||
) {
|
||||
return this.paymentReceivesApplication.getPaymentReceivePdf(
|
||||
1,
|
||||
paymentReceiveId,
|
||||
paymentReceivedId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import { PaymentReceivedSyncInvoicesSubscriber } from './subscribers/PaymentRece
|
||||
import { PaymentReceivedInvoiceSync } from './commands/PaymentReceivedInvoiceSync.service';
|
||||
import { LedgerModule } from '../Ledger/Ledger.module';
|
||||
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||
import { SendPaymentReceiveMailNotification } from './commands/PaymentReceivedMailNotification';
|
||||
|
||||
@Module({
|
||||
controllers: [PaymentReceivesController],
|
||||
@@ -48,6 +49,7 @@ import { AccountsModule } from '../Accounts/Accounts.module';
|
||||
PaymentReceivedAutoIncrementSubscriber,
|
||||
PaymentReceivedGLEntriesSubscriber,
|
||||
PaymentReceivedSyncInvoicesSubscriber,
|
||||
SendPaymentReceiveMailNotification
|
||||
],
|
||||
exports: [PaymentReceivesApplication, CreatePaymentReceivedService],
|
||||
imports: [
|
||||
|
||||
@@ -1,162 +1,159 @@
|
||||
// import { Inject, Injectable } from '@nestjs/common';
|
||||
// import {
|
||||
// PaymentReceiveMailOpts,
|
||||
// PaymentReceiveMailOptsDTO,
|
||||
// PaymentReceiveMailPresendEvent,
|
||||
// SendInvoiceMailDTO,
|
||||
// } from './types/PaymentReceived.types';
|
||||
// import Mail from '@/lib/Mail';
|
||||
// import {
|
||||
// DEFAULT_PAYMENT_MAIL_CONTENT,
|
||||
// DEFAULT_PAYMENT_MAIL_SUBJECT,
|
||||
// } from './constants';
|
||||
// import { GetPaymentReceived } from './queries/GetPaymentReceived.service';
|
||||
// import { transformPaymentReceivedToMailDataArgs } from './utils';
|
||||
// import { PaymentReceived } from './models/PaymentReceived';
|
||||
// import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
// import { events } from '@/common/events/events';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
DEFAULT_PAYMENT_MAIL_CONTENT,
|
||||
DEFAULT_PAYMENT_MAIL_SUBJECT,
|
||||
} from '../constants';
|
||||
import { transformPaymentReceivedToMailDataArgs } from './utils';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ContactMailNotification } from '@/modules/MailNotification/ContactMailNotification';
|
||||
import { PaymentReceived } from '../models/PaymentReceived';
|
||||
import { GetPaymentReceivedService } from '../queries/GetPaymentReceived.service';
|
||||
import { mergeAndValidateMailOptions } from '@/modules/MailNotification/utils';
|
||||
import { PaymentReceiveMailOptsDTO } from '../types/PaymentReceived.types';
|
||||
import { PaymentReceiveMailOpts } from '../types/PaymentReceived.types';
|
||||
import { PaymentReceiveMailPresendEvent } from '../types/PaymentReceived.types';
|
||||
import { SendInvoiceMailDTO } from '@/modules/SaleInvoices/SaleInvoice.types';
|
||||
|
||||
// @Injectable()
|
||||
// export class SendPaymentReceiveMailNotification {
|
||||
// constructor(
|
||||
// private getPaymentService: GetPaymentReceived,
|
||||
// private contactMailNotification: ContactMailNotification,
|
||||
@Injectable()
|
||||
export class SendPaymentReceiveMailNotification {
|
||||
constructor(
|
||||
private getPaymentService: GetPaymentReceivedService,
|
||||
private contactMailNotification: ContactMailNotification,
|
||||
private eventEmitter: EventEmitter2,
|
||||
|
||||
// @Inject('agenda') private agenda: any,
|
||||
// private eventPublisher: EventEmitter2,
|
||||
@Inject(PaymentReceived.name)
|
||||
private paymentReceiveModel: typeof PaymentReceived,
|
||||
) {}
|
||||
|
||||
// @Inject(PaymentReceived.name)
|
||||
// private paymentReceiveModel: typeof PaymentReceived,
|
||||
// ) {}
|
||||
/**
|
||||
* Sends the mail of the given payment receive.
|
||||
* @param {number} tenantId
|
||||
* @param {number} paymentReceiveId
|
||||
* @param {PaymentReceiveMailOptsDTO} messageDTO
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async triggerMail(
|
||||
paymentReceiveId: number,
|
||||
messageDTO: PaymentReceiveMailOptsDTO,
|
||||
): Promise<void> {
|
||||
const payload = {
|
||||
paymentReceiveId,
|
||||
messageDTO,
|
||||
};
|
||||
// await this.agenda.now('payment-receive-mail-send', payload);
|
||||
|
||||
// /**
|
||||
// * Sends the mail of the given payment receive.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} paymentReceiveId
|
||||
// * @param {PaymentReceiveMailOptsDTO} messageDTO
|
||||
// * @returns {Promise<void>}
|
||||
// */
|
||||
// public async triggerMail(
|
||||
// paymentReceiveId: number,
|
||||
// messageDTO: PaymentReceiveMailOptsDTO,
|
||||
// ): Promise<void> {
|
||||
// const payload = {
|
||||
// paymentReceiveId,
|
||||
// messageDTO,
|
||||
// };
|
||||
// await this.agenda.now('payment-receive-mail-send', payload);
|
||||
// Triggers `onPaymentReceivePreMailSend` event.
|
||||
await this.eventEmitter.emitAsync(events.paymentReceive.onPreMailSend, {
|
||||
paymentReceiveId,
|
||||
messageOptions: messageDTO,
|
||||
} as PaymentReceiveMailPresendEvent);
|
||||
}
|
||||
|
||||
// // Triggers `onPaymentReceivePreMailSend` event.
|
||||
// await this.eventPublisher.emitAsync(events.paymentReceive.onPreMailSend, {
|
||||
// paymentReceiveId,
|
||||
// messageOptions: messageDTO,
|
||||
// } as PaymentReceiveMailPresendEvent);
|
||||
// }
|
||||
/**
|
||||
* Retrieves the default payment mail options.
|
||||
* @param {number} paymentReceiveId - Payment receive id.
|
||||
* @returns {Promise<PaymentReceiveMailOpts>}
|
||||
*/
|
||||
public getMailOptions = async (
|
||||
paymentId: number,
|
||||
): Promise<PaymentReceiveMailOpts> => {
|
||||
const paymentReceive = await this.paymentReceiveModel
|
||||
.query()
|
||||
.findById(paymentId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// /**
|
||||
// * Retrieves the default payment mail options.
|
||||
// * @param {number} paymentReceiveId - Payment receive id.
|
||||
// * @returns {Promise<PaymentReceiveMailOpts>}
|
||||
// */
|
||||
// public getMailOptions = async (
|
||||
// paymentId: number,
|
||||
// ): Promise<PaymentReceiveMailOpts> => {
|
||||
// const paymentReceive = await this.paymentReceiveModel
|
||||
// .query()
|
||||
// .findById(paymentId)
|
||||
// .throwIfNotFound();
|
||||
const formatArgs = await this.textFormatter(paymentId);
|
||||
|
||||
// const formatArgs = await this.textFormatter(paymentId);
|
||||
const mailOptions =
|
||||
await this.contactMailNotification.getDefaultMailOptions(
|
||||
paymentReceive.customerId,
|
||||
);
|
||||
return {
|
||||
...mailOptions,
|
||||
subject: DEFAULT_PAYMENT_MAIL_SUBJECT,
|
||||
message: DEFAULT_PAYMENT_MAIL_CONTENT,
|
||||
...formatArgs,
|
||||
};
|
||||
};
|
||||
|
||||
// const mailOptions =
|
||||
// await this.contactMailNotification.getDefaultMailOptions(
|
||||
// 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} invoiceId - Sale invoice id.
|
||||
* @returns {Promise<Record<string, string>>}
|
||||
*/
|
||||
public textFormatter = async (
|
||||
invoiceId: number,
|
||||
): Promise<Record<string, string>> => {
|
||||
const payment = await this.getPaymentService.getPaymentReceive(invoiceId);
|
||||
return transformPaymentReceivedToMailDataArgs(payment);
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the formatted text of the given sale invoice.
|
||||
// * @param {number} invoiceId - Sale invoice id.
|
||||
// * @returns {Promise<Record<string, string>>}
|
||||
// */
|
||||
// public textFormatter = async (
|
||||
// invoiceId: number,
|
||||
// ): Promise<Record<string, string>> => {
|
||||
// const payment = await this.getPaymentService.getPaymentReceive(invoiceId);
|
||||
// return transformPaymentReceivedToMailDataArgs(payment);
|
||||
// };
|
||||
/**
|
||||
* Retrieves the formatted mail options of the given payment receive.
|
||||
* @param {number} tenantId
|
||||
* @param {number} paymentReceiveId
|
||||
* @param {SendInvoiceMailDTO} messageDTO
|
||||
* @returns {Promise<PaymentReceiveMailOpts>}
|
||||
*/
|
||||
public getFormattedMailOptions = async (
|
||||
paymentReceiveId: number,
|
||||
messageDTO: SendInvoiceMailDTO,
|
||||
) => {
|
||||
const formatterArgs = await this.textFormatter(paymentReceiveId);
|
||||
|
||||
// /**
|
||||
// * Retrieves the formatted mail options of the given payment receive.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} paymentReceiveId
|
||||
// * @param {SendInvoiceMailDTO} messageDTO
|
||||
// * @returns {Promise<PaymentReceiveMailOpts>}
|
||||
// */
|
||||
// public getFormattedMailOptions = async (
|
||||
// paymentReceiveId: number,
|
||||
// messageDTO: SendInvoiceMailDTO,
|
||||
// ) => {
|
||||
// const formatterArgs = await this.textFormatter(paymentReceiveId);
|
||||
// Default message options.
|
||||
const defaultMessageOpts = await this.getMailOptions(paymentReceiveId);
|
||||
// Parsed message opts with default options.
|
||||
const parsedMessageOpts = mergeAndValidateMailOptions(
|
||||
defaultMessageOpts,
|
||||
messageDTO,
|
||||
);
|
||||
// Formats the message options.
|
||||
return this.contactMailNotification.formatMailOptions(
|
||||
parsedMessageOpts,
|
||||
formatterArgs,
|
||||
);
|
||||
};
|
||||
|
||||
// // Default message options.
|
||||
// const defaultMessageOpts = await this.getMailOptions(paymentReceiveId);
|
||||
// // Parsed message opts with default options.
|
||||
// const parsedMessageOpts = mergeAndValidateMailOptions(
|
||||
// defaultMessageOpts,
|
||||
// messageDTO,
|
||||
// );
|
||||
// // Formats the message options.
|
||||
// return this.contactMailNotification.formatMailOptions(
|
||||
// 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(
|
||||
paymentReceiveId: number,
|
||||
messageDTO: PaymentReceiveMailOptsDTO,
|
||||
): Promise<void> {
|
||||
// Retrieves the formatted mail options.
|
||||
const formattedMessageOptions = await this.getFormattedMailOptions(
|
||||
paymentReceiveId,
|
||||
messageDTO,
|
||||
);
|
||||
const mail = new Mail()
|
||||
.setSubject(formattedMessageOptions.subject)
|
||||
.setTo(formattedMessageOptions.to)
|
||||
.setCC(formattedMessageOptions.cc)
|
||||
.setBCC(formattedMessageOptions.bcc)
|
||||
.setContent(formattedMessageOptions.message);
|
||||
|
||||
// /**
|
||||
// * Triggers the mail invoice.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleInvoiceId - Invoice id.
|
||||
// * @param {SendInvoiceMailDTO} messageDTO - Message options.
|
||||
// * @returns {Promise<void>}
|
||||
// */
|
||||
// public async sendMail(
|
||||
// paymentReceiveId: number,
|
||||
// messageDTO: SendInvoiceMailDTO,
|
||||
// ): Promise<void> {
|
||||
// // Retrieves the formatted mail options.
|
||||
// const formattedMessageOptions = await this.getFormattedMailOptions(
|
||||
// paymentReceiveId,
|
||||
// messageDTO,
|
||||
// );
|
||||
// const mail = new Mail()
|
||||
// .setSubject(formattedMessageOptions.subject)
|
||||
// .setTo(formattedMessageOptions.to)
|
||||
// .setCC(formattedMessageOptions.cc)
|
||||
// .setBCC(formattedMessageOptions.bcc)
|
||||
// .setContent(formattedMessageOptions.message);
|
||||
const eventPayload = {
|
||||
paymentReceiveId,
|
||||
messageOptions: formattedMessageOptions,
|
||||
};
|
||||
// Triggers `onPaymentReceiveMailSend` event.
|
||||
await this.eventEmitter.emitAsync(
|
||||
events.paymentReceive.onMailSend,
|
||||
eventPayload,
|
||||
);
|
||||
await mail.send();
|
||||
|
||||
// const eventPayload = {
|
||||
// paymentReceiveId,
|
||||
// messageOptions: formattedMessageOptions,
|
||||
// };
|
||||
// // Triggers `onPaymentReceiveMailSend` event.
|
||||
// await this.eventPublisher.emitAsync(
|
||||
// events.paymentReceive.onMailSend,
|
||||
// eventPayload,
|
||||
// );
|
||||
// await mail.send();
|
||||
|
||||
// // Triggers `onPaymentReceiveMailSent` event.
|
||||
// await this.eventPublisher.emitAsync(
|
||||
// events.paymentReceive.onMailSent,
|
||||
// eventPayload,
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// Triggers `onPaymentReceiveMailSent` event.
|
||||
await this.eventEmitter.emitAsync(
|
||||
events.paymentReceive.onMailSent,
|
||||
eventPayload,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types';
|
||||
import { Knex } from 'knex';
|
||||
import { PaymentReceived } from '../models/PaymentReceived';
|
||||
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||
import { CommonMailOptions, CommonMailOptionsDTO } from '@/modules/MailNotification/MailNotification.types';
|
||||
|
||||
export interface IPaymentReceivedCreateDTO {
|
||||
customerId: number;
|
||||
@@ -144,15 +145,12 @@ export enum PaymentReceiveAction {
|
||||
// | 'branchId'
|
||||
// >;
|
||||
|
||||
// export interface PaymentReceiveMailOpts extends CommonMailOptions {}
|
||||
|
||||
// export interface PaymentReceiveMailOptsDTO extends CommonMailOptionsDTO {}
|
||||
|
||||
// export interface PaymentReceiveMailPresendEvent {
|
||||
// tenantId: number;
|
||||
// paymentReceiveId: number;
|
||||
// messageOptions: PaymentReceiveMailOptsDTO;
|
||||
// }
|
||||
export interface PaymentReceiveMailOpts extends CommonMailOptions {}
|
||||
export interface PaymentReceiveMailOptsDTO extends CommonMailOptionsDTO {}
|
||||
export interface PaymentReceiveMailPresendEvent {
|
||||
paymentReceiveId: number;
|
||||
messageOptions: PaymentReceiveMailOptsDTO;
|
||||
}
|
||||
|
||||
export interface PaymentReceivedPdfLineItem {
|
||||
item: string;
|
||||
|
||||
@@ -4,6 +4,8 @@ import {
|
||||
// IPaginationMeta,
|
||||
// IPaymentReceivedSmsDetails,
|
||||
ISaleEstimateDTO,
|
||||
ISalesEstimatesFilter,
|
||||
SaleEstimateMailOptionsDTO,
|
||||
// ISalesEstimatesFilter,
|
||||
// SaleEstimateMailOptions,
|
||||
// SaleEstimateMailOptionsDTO,
|
||||
@@ -16,12 +18,12 @@ import { DeliverSaleEstimateService } from './commands/DeliverSaleEstimate.servi
|
||||
import { ApproveSaleEstimateService } from './commands/ApproveSaleEstimate.service';
|
||||
import { RejectSaleEstimateService } from './commands/RejectSaleEstimate.service';
|
||||
// import { SaleEstimateNotifyBySms } from './commands/SaleEstimateSmsNotify';
|
||||
// import { SaleEstimatesPdf } from './queries/SaleEstimatesPdf';
|
||||
// import { SendSaleEstimateMail } from './commands/SendSaleEstimateMail';
|
||||
import { SendSaleEstimateMail } from './commands/SendSaleEstimateMail';
|
||||
import { GetSaleEstimateState } from './queries/GetSaleEstimateState.service';
|
||||
import { GetSaleEstimatesService } from './queries/GetSaleEstimates.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
||||
import { GetSaleEstimatesService } from './queries/GetSaleEstimates.service';
|
||||
import { GetSaleEstimatePdf } from './queries/GetSaleEstimatePdf';
|
||||
|
||||
@Injectable()
|
||||
export class SaleEstimatesApplication {
|
||||
@@ -34,10 +36,10 @@ export class SaleEstimatesApplication {
|
||||
private readonly deliverSaleEstimateService: DeliverSaleEstimateService,
|
||||
private readonly approveSaleEstimateService: ApproveSaleEstimateService,
|
||||
private readonly rejectSaleEstimateService: RejectSaleEstimateService,
|
||||
// private readonly saleEstimateNotifyBySmsService: SaleEstimateNotifyBySms,
|
||||
// private readonly saleEstimatesPdfService: SaleEstimatesPdf,
|
||||
// private readonly sendEstimateMailService: SendSaleEstimateMail,
|
||||
private readonly sendEstimateMailService: SendSaleEstimateMail,
|
||||
private readonly getSaleEstimateStateService: GetSaleEstimateState,
|
||||
private readonly saleEstimatesPdfService: GetSaleEstimatePdf,
|
||||
// private readonly saleEstimateNotifyBySmsService: SaleEstimateNotifyBySms,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -136,25 +138,28 @@ export class SaleEstimatesApplication {
|
||||
/**
|
||||
* Retrieve the PDF content of the given sale estimate.
|
||||
* @param {number} saleEstimateId - Sale estimate ID.
|
||||
* @returns
|
||||
* @returns {Promise<[Buffer, string]>}
|
||||
*/
|
||||
public getSaleEstimatePdf(saleEstimateId: number) {
|
||||
// return this.saleEstimatesPdfService.getSaleEstimatePdf(
|
||||
// saleEstimateId,
|
||||
// );
|
||||
return this.saleEstimatesPdfService.getSaleEstimatePdf(
|
||||
saleEstimateId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the reminder mail of the given sale estimate.
|
||||
* @param {number} saleEstimateId - Sale estimate ID.
|
||||
* @param {SaleEstimateMailOptionsDTO} saleEstimateMailOpts - Sale estimate mail options.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public sendSaleEstimateMail() // saleEstimateMailOpts: SaleEstimateMailOptionsDTO, // saleEstimateId: number,
|
||||
{
|
||||
// return this.sendEstimateMailService.triggerMail(
|
||||
// saleEstimateId,
|
||||
// saleEstimateMailOpts,
|
||||
// );
|
||||
public sendSaleEstimateMail(
|
||||
saleEstimateId: number,
|
||||
saleEstimateMailOpts: SaleEstimateMailOptionsDTO,
|
||||
) {
|
||||
return this.sendEstimateMailService.triggerMail(
|
||||
saleEstimateId,
|
||||
saleEstimateMailOpts,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,9 +168,9 @@ export class SaleEstimatesApplication {
|
||||
* @returns {Promise<SaleEstimateMailOptions>}
|
||||
*/
|
||||
public getSaleEstimateMail(saleEstimateId: number) {
|
||||
// return this.sendEstimateMailService.getMailOptions(
|
||||
// saleEstimateId,
|
||||
// );
|
||||
return this.sendEstimateMailService.getMailOptions(
|
||||
saleEstimateId,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,8 +12,8 @@ import {
|
||||
import { SaleEstimatesApplication } from './SaleEstimates.application';
|
||||
import {
|
||||
ISaleEstimateDTO,
|
||||
// ISalesEstimatesFilter,
|
||||
// SaleEstimateMailOptionsDTO,
|
||||
ISalesEstimatesFilter,
|
||||
SaleEstimateMailOptionsDTO,
|
||||
} from './types/SaleEstimates.types';
|
||||
import { SaleEstimate } from './models/SaleEstimate';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
@@ -107,16 +107,16 @@ export class SaleEstimatesController {
|
||||
return this.saleEstimatesApplication.getSaleEstimatePdf(saleEstimateId);
|
||||
}
|
||||
|
||||
// @Post(':id/mail')
|
||||
// public sendSaleEstimateMail(
|
||||
// @Param('id', ParseIntPipe) saleEstimateId: number,
|
||||
// @Body() mailOptions: SaleEstimateMailOptionsDTO,
|
||||
// ) {
|
||||
// return this.saleEstimatesApplication.sendSaleEstimateMail(
|
||||
// saleEstimateId,
|
||||
// mailOptions,
|
||||
// );
|
||||
// }
|
||||
@Post(':id/mail')
|
||||
public sendSaleEstimateMail(
|
||||
@Param('id', ParseIntPipe) saleEstimateId: number,
|
||||
@Body() mailOptions: SaleEstimateMailOptionsDTO,
|
||||
) {
|
||||
return this.saleEstimatesApplication.sendSaleEstimateMail(
|
||||
saleEstimateId,
|
||||
mailOptions,
|
||||
);
|
||||
}
|
||||
|
||||
@Get(':id/mail')
|
||||
public getSaleEstimateMail(
|
||||
|
||||
@@ -23,6 +23,7 @@ import { SaleEstimatesApplication } from './SaleEstimates.application';
|
||||
import { DeleteSaleEstimate } from './commands/DeleteSaleEstimate.service';
|
||||
import { GetSaleEstimate } from './queries/GetSaleEstimate.service';
|
||||
import { GetSaleEstimateState } from './queries/GetSaleEstimateState.service';
|
||||
import { SendSaleEstimateMail } from './commands/SendSaleEstimateMail';
|
||||
// import { SaleEstimateNotifyBySms } from './commands/SaleEstimateSmsNotify';
|
||||
// import { SendSaleEstimateMail } from './commands/SendSaleEstimateMail';
|
||||
//
|
||||
@@ -51,9 +52,9 @@ import { GetSaleEstimateState } from './queries/GetSaleEstimateState.service';
|
||||
SaleEstimateDTOTransformer,
|
||||
TenancyContext,
|
||||
TransformerInjectable,
|
||||
SaleEstimatesApplication
|
||||
SaleEstimatesApplication,
|
||||
SendSaleEstimateMail,
|
||||
// SaleEstimateNotifyBySms,
|
||||
// SendSaleEstimateMail,p
|
||||
],
|
||||
})
|
||||
export class SaleEstimatesModule {}
|
||||
|
||||
@@ -1,205 +1,187 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import Mail from '@/lib/Mail';
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
// import {
|
||||
// DEFAULT_ESTIMATE_REMINDER_MAIL_CONTENT,
|
||||
// DEFAULT_ESTIMATE_REMINDER_MAIL_SUBJECT,
|
||||
// } from '../constants';
|
||||
// import { SaleEstimatesPdf } from '../queries/SaleEstimatesPdf';
|
||||
// import { GetSaleEstimate } from '../queries/GetSaleEstimate.service';
|
||||
// import {
|
||||
// ISaleEstimateMailPresendEvent,
|
||||
// SaleEstimateMailOptions,
|
||||
// SaleEstimateMailOptionsDTO,
|
||||
// } from '@/interfaces';
|
||||
// import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification';
|
||||
// import { mergeAndValidateMailOptions } from '@/services/MailNotification/utils';
|
||||
// import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
// import events from '@/subscribers/events';
|
||||
// import { transformEstimateToMailDataArgs } from '../utils';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { ContactMailNotification } from '@/modules/MailNotification/ContactMailNotification';
|
||||
import {
|
||||
DEFAULT_ESTIMATE_REMINDER_MAIL_CONTENT,
|
||||
DEFAULT_ESTIMATE_REMINDER_MAIL_SUBJECT,
|
||||
} from '../constants';
|
||||
import { GetSaleEstimate } from '../queries/GetSaleEstimate.service';
|
||||
import { transformEstimateToMailDataArgs } from '../utils';
|
||||
import { GetSaleEstimatePdf } from '../queries/GetSaleEstimatePdf';
|
||||
import { events } from '@/common/events/events';
|
||||
import { SaleEstimate } from '../models/SaleEstimate';
|
||||
import { mergeAndValidateMailOptions } from '@/modules/MailNotification/utils';
|
||||
import {
|
||||
ISaleEstimateMailPresendEvent,
|
||||
SaleEstimateMailOptionsDTO,
|
||||
} from '../types/SaleEstimates.types';
|
||||
import { SaleEstimateMailOptions } from '../types/SaleEstimates.types';
|
||||
import { Mail } from '@/modules/Mail/Mail';
|
||||
import { MailTransporter } from '@/modules/Mail/MailTransporter.service';
|
||||
|
||||
// @Service()
|
||||
// export class SendSaleEstimateMail {
|
||||
// @Inject()
|
||||
// private tenancy: HasTenancyService;
|
||||
@Injectable()
|
||||
export class SendSaleEstimateMail {
|
||||
/**
|
||||
* @param {GetSaleEstimatePdf} estimatePdf - Estimate pdf service.
|
||||
* @param {GetSaleEstimate} getSaleEstimateService - Get sale estimate service.
|
||||
* @param {ContactMailNotification} contactMailNotification - Contact mail notification service.
|
||||
* @param {EventEmitter2} eventPublisher - Event emitter.
|
||||
* @param {MailTransporter} mailTransporter - Mail transporter service.
|
||||
* @param {typeof SaleEstimate} saleEstimateModel - Sale estimate model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly estimatePdf: GetSaleEstimatePdf,
|
||||
private readonly getSaleEstimateService: GetSaleEstimate,
|
||||
private readonly contactMailNotification: ContactMailNotification,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly mailTransporter: MailTransporter,
|
||||
|
||||
// @Inject()
|
||||
// private estimatePdf: SaleEstimatesPdf;
|
||||
@Inject(SaleEstimate.name)
|
||||
private readonly saleEstimateModel: typeof SaleEstimate,
|
||||
) {}
|
||||
|
||||
// @Inject()
|
||||
// private getSaleEstimateService: GetSaleEstimate;
|
||||
/**
|
||||
* Triggers the reminder mail of the given sale estimate.
|
||||
* @param {number} saleEstimateId - Sale estimate id.
|
||||
* @param {SaleEstimateMailOptionsDTO} messageOptions - Sale estimate mail options.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async triggerMail(
|
||||
saleEstimateId: number,
|
||||
messageOptions: SaleEstimateMailOptionsDTO,
|
||||
): Promise<void> {
|
||||
const payload = {
|
||||
saleEstimateId,
|
||||
messageOptions,
|
||||
};
|
||||
// await this.agenda.now('sale-estimate-mail-send', payload);
|
||||
|
||||
// @Inject()
|
||||
// private contactMailNotification: ContactMailNotification;
|
||||
// Triggers `onSaleEstimatePreMailSend` event.
|
||||
await this.eventPublisher.emitAsync(events.saleEstimate.onPreMailSend, {
|
||||
saleEstimateId,
|
||||
messageOptions,
|
||||
} as ISaleEstimateMailPresendEvent);
|
||||
}
|
||||
|
||||
// @Inject('agenda')
|
||||
// private agenda: any;
|
||||
/**
|
||||
* Formate the text of the mail.
|
||||
* @param {number} estimateId - Estimate id.
|
||||
* @returns {Promise<Record<string, any>>}
|
||||
*/
|
||||
public formatterArgs = async (estimateId: number) => {
|
||||
const estimate = await this.getSaleEstimateService.getEstimate(estimateId);
|
||||
return transformEstimateToMailDataArgs(estimate);
|
||||
};
|
||||
|
||||
// @Inject()
|
||||
// private eventPublisher: EventPublisher;
|
||||
/**
|
||||
* Retrieves the mail options.
|
||||
* @param {number} saleEstimateId - Sale estimate id.
|
||||
* @param {string} defaultSubject - Default subject.
|
||||
* @param {string} defaultMessage - Default message.
|
||||
* @returns {Promise<SaleEstimateMailOptions>}
|
||||
*/
|
||||
public getMailOptions = async (
|
||||
saleEstimateId: number,
|
||||
defaultSubject: string = DEFAULT_ESTIMATE_REMINDER_MAIL_SUBJECT,
|
||||
defaultMessage: string = DEFAULT_ESTIMATE_REMINDER_MAIL_CONTENT,
|
||||
): Promise<SaleEstimateMailOptions> => {
|
||||
const saleEstimate = await this.saleEstimateModel
|
||||
.query()
|
||||
.findById(saleEstimateId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// /**
|
||||
// * Triggers the reminder mail of the given sale estimate.
|
||||
// * @param {number} tenantId -
|
||||
// * @param {number} saleEstimateId -
|
||||
// * @param {SaleEstimateMailOptionsDTO} messageOptions -
|
||||
// * @returns {Promise<void>}
|
||||
// */
|
||||
// public async triggerMail(
|
||||
// tenantId: number,
|
||||
// saleEstimateId: number,
|
||||
// messageOptions: SaleEstimateMailOptionsDTO
|
||||
// ): Promise<void> {
|
||||
// const payload = {
|
||||
// tenantId,
|
||||
// saleEstimateId,
|
||||
// messageOptions,
|
||||
// };
|
||||
// await this.agenda.now('sale-estimate-mail-send', payload);
|
||||
const formatArgs = await this.formatterArgs(saleEstimateId);
|
||||
|
||||
// // Triggers `onSaleEstimatePreMailSend` event.
|
||||
// await this.eventPublisher.emitAsync(events.saleEstimate.onPreMailSend, {
|
||||
// tenantId,
|
||||
// saleEstimateId,
|
||||
// messageOptions,
|
||||
// } as ISaleEstimateMailPresendEvent);
|
||||
// }
|
||||
const mailOptions =
|
||||
await this.contactMailNotification.getDefaultMailOptions(
|
||||
saleEstimate.customerId,
|
||||
);
|
||||
return {
|
||||
...mailOptions,
|
||||
message: defaultMessage,
|
||||
subject: defaultSubject,
|
||||
attachEstimate: true,
|
||||
formatArgs,
|
||||
};
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Formate the text of the mail.
|
||||
// * @param {number} tenantId - Tenant id.
|
||||
// * @param {number} estimateId - Estimate id.
|
||||
// * @returns {Promise<Record<string, any>>}
|
||||
// */
|
||||
// public formatterArgs = async (tenantId: number, estimateId: number) => {
|
||||
// const estimate = await this.getSaleEstimateService.getEstimate(
|
||||
// tenantId,
|
||||
// estimateId
|
||||
// );
|
||||
// return transformEstimateToMailDataArgs(estimate);
|
||||
// };
|
||||
/**
|
||||
* Formats the given mail options.
|
||||
* @param {number} saleEstimateId - Sale estimate id.
|
||||
* @param {SaleEstimateMailOptions} mailOptions - Sale estimate mail options.
|
||||
* @returns {Promise<SaleEstimateMailOptions>}
|
||||
*/
|
||||
public formatMailOptions = async (
|
||||
saleEstimateId: number,
|
||||
mailOptions: SaleEstimateMailOptions,
|
||||
): Promise<SaleEstimateMailOptions> => {
|
||||
const formatterArgs = await this.formatterArgs(saleEstimateId);
|
||||
const formattedOptions =
|
||||
await this.contactMailNotification.formatMailOptions(
|
||||
mailOptions,
|
||||
formatterArgs,
|
||||
);
|
||||
return { ...formattedOptions };
|
||||
};
|
||||
|
||||
// /**
|
||||
// * Retrieves the mail options.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleEstimateId
|
||||
// * @returns {Promise<SaleEstimateMailOptions>}
|
||||
// */
|
||||
// public getMailOptions = async (
|
||||
// tenantId: number,
|
||||
// saleEstimateId: number,
|
||||
// defaultSubject: string = DEFAULT_ESTIMATE_REMINDER_MAIL_SUBJECT,
|
||||
// defaultMessage: string = DEFAULT_ESTIMATE_REMINDER_MAIL_CONTENT
|
||||
// ): Promise<SaleEstimateMailOptions> => {
|
||||
// const { SaleEstimate } = this.tenancy.models(tenantId);
|
||||
/**
|
||||
* Sends the mail notification of the given sale estimate.
|
||||
* @param {number} saleEstimateId - Sale estimate id.
|
||||
* @param {SaleEstimateMailOptions} messageOptions - Sale estimate mail options.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async sendMail(
|
||||
saleEstimateId: number,
|
||||
messageOptions: SaleEstimateMailOptionsDTO,
|
||||
): Promise<void> {
|
||||
const localMessageOpts = await this.getMailOptions(saleEstimateId);
|
||||
// Overrides and validates the given mail options.
|
||||
const parsedMessageOptions = mergeAndValidateMailOptions(
|
||||
localMessageOpts,
|
||||
messageOptions,
|
||||
) as SaleEstimateMailOptions;
|
||||
|
||||
// const saleEstimate = await SaleEstimate.query()
|
||||
// .findById(saleEstimateId)
|
||||
// .throwIfNotFound();
|
||||
const formattedOptions = await this.formatMailOptions(
|
||||
saleEstimateId,
|
||||
parsedMessageOptions,
|
||||
);
|
||||
const mail = new Mail()
|
||||
.setSubject(formattedOptions.subject)
|
||||
.setTo(formattedOptions.to)
|
||||
.setCC(formattedOptions.cc)
|
||||
.setBCC(formattedOptions.bcc)
|
||||
.setContent(formattedOptions.message);
|
||||
|
||||
// const formatArgs = await this.formatterArgs(tenantId, saleEstimateId);
|
||||
// Attaches the estimate pdf to the mail.
|
||||
if (formattedOptions.attachEstimate) {
|
||||
// Retrieves the estimate pdf and attaches it to the mail.
|
||||
const [estimatePdfBuffer, estimateFilename] =
|
||||
await this.estimatePdf.getSaleEstimatePdf(saleEstimateId);
|
||||
|
||||
// const mailOptions =
|
||||
// await this.contactMailNotification.getDefaultMailOptions(
|
||||
// tenantId,
|
||||
// saleEstimate.customerId
|
||||
// );
|
||||
// return {
|
||||
// ...mailOptions,
|
||||
// message: defaultMessage,
|
||||
// subject: defaultSubject,
|
||||
// attachEstimate: true,
|
||||
// formatArgs,
|
||||
// };
|
||||
// };
|
||||
mail.setAttachments([
|
||||
{
|
||||
filename: `${estimateFilename}.pdf`,
|
||||
content: estimatePdfBuffer,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Formats the given mail options.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleEstimateId
|
||||
// * @param {SaleEstimateMailOptions} mailOptions
|
||||
// * @returns {Promise<SaleEstimateMailOptions>}
|
||||
// */
|
||||
// public formatMailOptions = async (
|
||||
// tenantId: number,
|
||||
// saleEstimateId: number,
|
||||
// mailOptions: SaleEstimateMailOptions
|
||||
// ): Promise<SaleEstimateMailOptions> => {
|
||||
// const formatterArgs = await this.formatterArgs(tenantId, saleEstimateId);
|
||||
// const formattedOptions =
|
||||
// await this.contactMailNotification.formatMailOptions(
|
||||
// tenantId,
|
||||
// mailOptions,
|
||||
// formatterArgs
|
||||
// );
|
||||
// return { ...formattedOptions };
|
||||
// };
|
||||
const eventPayload = {
|
||||
saleEstimateId,
|
||||
messageOptions,
|
||||
formattedOptions,
|
||||
};
|
||||
// Triggers `onSaleEstimateMailSend` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.saleEstimate.onMailSend,
|
||||
eventPayload as ISaleEstimateMailPresendEvent,
|
||||
);
|
||||
await this.mailTransporter.send(mail);
|
||||
|
||||
// /**
|
||||
// * Sends the mail notification of the given sale estimate.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleEstimateId
|
||||
// * @param {SaleEstimateMailOptions} messageOptions
|
||||
// * @returns {Promise<void>}
|
||||
// */
|
||||
// public async sendMail(
|
||||
// tenantId: number,
|
||||
// saleEstimateId: number,
|
||||
// messageOptions: SaleEstimateMailOptionsDTO
|
||||
// ): Promise<void> {
|
||||
// const localMessageOpts = await this.getMailOptions(
|
||||
// tenantId,
|
||||
// saleEstimateId
|
||||
// );
|
||||
// // Overrides and validates the given mail options.
|
||||
// const parsedMessageOptions = mergeAndValidateMailOptions(
|
||||
// localMessageOpts,
|
||||
// messageOptions
|
||||
// ) as SaleEstimateMailOptions;
|
||||
|
||||
// const formattedOptions = await this.formatMailOptions(
|
||||
// tenantId,
|
||||
// saleEstimateId,
|
||||
// parsedMessageOptions
|
||||
// );
|
||||
// const mail = new Mail()
|
||||
// .setSubject(formattedOptions.subject)
|
||||
// .setTo(formattedOptions.to)
|
||||
// .setCC(formattedOptions.cc)
|
||||
// .setBCC(formattedOptions.bcc)
|
||||
// .setContent(formattedOptions.message);
|
||||
|
||||
// // Attaches the estimate pdf to the mail.
|
||||
// if (formattedOptions.attachEstimate) {
|
||||
// // Retrieves the estimate pdf and attaches it to the mail.
|
||||
// const [estimatePdfBuffer, estimateFilename] =
|
||||
// await this.estimatePdf.getSaleEstimatePdf(tenantId, saleEstimateId);
|
||||
|
||||
// mail.setAttachments([
|
||||
// {
|
||||
// filename: `${estimateFilename}.pdf`,
|
||||
// content: estimatePdfBuffer,
|
||||
// },
|
||||
// ]);
|
||||
// }
|
||||
|
||||
// const eventPayload = {
|
||||
// tenantId,
|
||||
// saleEstimateId,
|
||||
// messageOptions,
|
||||
// formattedOptions,
|
||||
// };
|
||||
// // Triggers `onSaleEstimateMailSend` event.
|
||||
// await this.eventPublisher.emitAsync(
|
||||
// events.saleEstimate.onMailSend,
|
||||
// eventPayload as ISaleEstimateMailPresendEvent
|
||||
// );
|
||||
// await mail.send();
|
||||
|
||||
// // Triggers `onSaleEstimateMailSent` event.
|
||||
// await this.eventPublisher.emitAsync(
|
||||
// events.saleEstimate.onMailSent,
|
||||
// eventPayload as ISaleEstimateMailPresendEvent
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// Triggers `onSaleEstimateMailSent` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.saleEstimate.onMailSent,
|
||||
eventPayload as ISaleEstimateMailPresendEvent,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
import { GetSaleEstimate } from './GetSaleEstimate.service';
|
||||
import { transformEstimateToPdfTemplate } from '../utils';
|
||||
import { EstimatePdfBrandingAttributes } from '../constants';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { SaleEstimatePdfTemplate } from '@/modules/SaleInvoices/queries/SaleEstimatePdfTemplate.service';
|
||||
import { TemplateInjectable } from '@/modules/TemplateInjectable/TemplateInjectable.service';
|
||||
import { ChromiumlyTenancy } from '@/modules/ChromiumlyTenancy/ChromiumlyTenancy.service';
|
||||
import { PdfTemplateModel } from '@/modules/PdfTemplate/models/PdfTemplate';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { events } from '@/common/events/events';
|
||||
import { SaleEstimate } from '../models/SaleEstimate';
|
||||
|
||||
@Injectable()
|
||||
export class GetSaleEstimatePdf {
|
||||
constructor(
|
||||
private readonly chromiumlyTenancy: ChromiumlyTenancy,
|
||||
private readonly templateInjectable: TemplateInjectable,
|
||||
private readonly getSaleEstimate: GetSaleEstimate,
|
||||
private readonly estimatePdfTemplate: SaleEstimatePdfTemplate,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
|
||||
@Inject(PdfTemplateModel.name)
|
||||
private readonly pdfTemplateModel: typeof PdfTemplateModel,
|
||||
|
||||
@Inject(SaleEstimate.name)
|
||||
private readonly saleEstimateModel: typeof SaleEstimate,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Retrieve sale invoice pdf content.
|
||||
* @param {number} tenantId -
|
||||
* @param {ISaleInvoice} saleInvoice -
|
||||
*/
|
||||
public async getSaleEstimatePdf(
|
||||
saleEstimateId: number,
|
||||
): Promise<[Buffer, string]> {
|
||||
const filename = await this.getSaleEstimateFilename(saleEstimateId);
|
||||
const brandingAttributes =
|
||||
await this.getEstimateBrandingAttributes(saleEstimateId);
|
||||
const htmlContent = await this.templateInjectable.render(
|
||||
'modules/estimate-regular',
|
||||
brandingAttributes,
|
||||
);
|
||||
const content =
|
||||
await this.chromiumlyTenancy.convertHtmlContent(htmlContent);
|
||||
const eventPayload = { saleEstimateId };
|
||||
|
||||
// Triggers the `onSaleEstimatePdfViewed` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.saleEstimate.onPdfViewed,
|
||||
eventPayload,
|
||||
);
|
||||
return [content, filename];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the filename file document of the given estimate.
|
||||
* @param {number} estimateId - Estimate id.
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
private async getSaleEstimateFilename(estimateId: number) {
|
||||
const estimate = await this.saleEstimateModel.query().findById(estimateId);
|
||||
|
||||
return `Estimate-${estimate.estimateNumber}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the given estimate branding attributes.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} estimateId - Estimate id.
|
||||
* @returns {Promise<EstimatePdfBrandingAttributes>}
|
||||
*/
|
||||
async getEstimateBrandingAttributes(
|
||||
estimateId: number,
|
||||
): Promise<EstimatePdfBrandingAttributes> {
|
||||
const saleEstimate = await this.getSaleEstimate.getEstimate(estimateId);
|
||||
// Retrieve the invoice template id of not found get the default template id.
|
||||
const templateId =
|
||||
saleEstimate.pdfTemplateId ??
|
||||
(
|
||||
await this.pdfTemplateModel.query().findOne({
|
||||
resource: 'SaleEstimate',
|
||||
default: true,
|
||||
})
|
||||
)?.id;
|
||||
const brandingTemplate =
|
||||
await this.estimatePdfTemplate.getEstimatePdfTemplate(templateId);
|
||||
return {
|
||||
...brandingTemplate.attributes,
|
||||
...transformEstimateToPdfTemplate(saleEstimate),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import { ChromiumlyTenancy } from '@/services/ChromiumlyTenancy/ChromiumlyTenancy';
|
||||
// import { TemplateInjectable } from '@/services/TemplateInjectable/TemplateInjectable';
|
||||
// import { GetSaleEstimate } from './GetSaleEstimate.service';
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
// import { SaleEstimatePdfTemplate } from '../Invoices/SaleEstimatePdfTemplate';
|
||||
// import { transformEstimateToPdfTemplate } from '../utils';
|
||||
// import { EstimatePdfBrandingAttributes } from '../constants';
|
||||
// import events from '@/subscribers/events';
|
||||
// import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
|
||||
// @Service()
|
||||
// export class SaleEstimatesPdf {
|
||||
// @Inject()
|
||||
// private tenancy: HasTenancyService;
|
||||
|
||||
// @Inject()
|
||||
// private chromiumlyTenancy: ChromiumlyTenancy;
|
||||
|
||||
// @Inject()
|
||||
// private templateInjectable: TemplateInjectable;
|
||||
|
||||
// @Inject()
|
||||
// private getSaleEstimate: GetSaleEstimate;
|
||||
|
||||
// @Inject()
|
||||
// private estimatePdfTemplate: SaleEstimatePdfTemplate;
|
||||
|
||||
// @Inject()
|
||||
// private eventPublisher: EventPublisher;
|
||||
|
||||
// /**
|
||||
// * Retrieve sale invoice pdf content.
|
||||
// * @param {number} tenantId -
|
||||
// * @param {ISaleInvoice} saleInvoice -
|
||||
// */
|
||||
// public async getSaleEstimatePdf(
|
||||
// tenantId: number,
|
||||
// saleEstimateId: number
|
||||
// ): Promise<[Buffer, string]> {
|
||||
// const filename = await this.getSaleEstimateFilename(
|
||||
// tenantId,
|
||||
// saleEstimateId
|
||||
// );
|
||||
// const brandingAttributes = await this.getEstimateBrandingAttributes(
|
||||
// tenantId,
|
||||
// saleEstimateId
|
||||
// );
|
||||
// const htmlContent = await this.templateInjectable.render(
|
||||
// tenantId,
|
||||
// 'modules/estimate-regular',
|
||||
// brandingAttributes
|
||||
// );
|
||||
// const content = await this.chromiumlyTenancy.convertHtmlContent(
|
||||
// tenantId,
|
||||
// htmlContent
|
||||
// );
|
||||
// const eventPayload = { tenantId, saleEstimateId };
|
||||
|
||||
// // Triggers the `onSaleEstimatePdfViewed` event.
|
||||
// await this.eventPublisher.emitAsync(
|
||||
// events.saleEstimate.onPdfViewed,
|
||||
// eventPayload
|
||||
// );
|
||||
// return [content, filename];
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Retrieves the filename file document of the given estimate.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} estimateId
|
||||
// * @returns {Promise<string>}
|
||||
// */
|
||||
// private async getSaleEstimateFilename(tenantId: number, estimateId: number) {
|
||||
// const { SaleEstimate } = this.tenancy.models(tenantId);
|
||||
|
||||
// const estimate = await SaleEstimate.query().findById(estimateId);
|
||||
|
||||
// return `Estimate-${estimate.estimateNumber}`;
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Retrieves the given estimate branding attributes.
|
||||
// * @param {number} tenantId - Tenant id.
|
||||
// * @param {number} estimateId - Estimate id.
|
||||
// * @returns {Promise<EstimatePdfBrandingAttributes>}
|
||||
// */
|
||||
// async getEstimateBrandingAttributes(
|
||||
// tenantId: number,
|
||||
// estimateId: number
|
||||
// ): Promise<EstimatePdfBrandingAttributes> {
|
||||
// const { PdfTemplate } = this.tenancy.models(tenantId);
|
||||
// const saleEstimate = await this.getSaleEstimate.getEstimate(
|
||||
// tenantId,
|
||||
// estimateId
|
||||
// );
|
||||
// // Retrieve the invoice template id of not found get the default template id.
|
||||
// const templateId =
|
||||
// saleEstimate.pdfTemplateId ??
|
||||
// (
|
||||
// await PdfTemplate.query().findOne({
|
||||
// resource: 'SaleEstimate',
|
||||
// default: true,
|
||||
// })
|
||||
// )?.id;
|
||||
// const brandingTemplate =
|
||||
// await this.estimatePdfTemplate.getEstimatePdfTemplate(
|
||||
// tenantId,
|
||||
// templateId
|
||||
// );
|
||||
// return {
|
||||
// ...brandingTemplate.attributes,
|
||||
// ...transformEstimateToPdfTemplate(saleEstimate),
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
@@ -5,6 +5,8 @@ import { SaleEstimate } from '../models/SaleEstimate';
|
||||
import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types';
|
||||
import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types';
|
||||
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||
import { CommonMailOptionsDTO } from '@/modules/MailNotification/MailNotification.types';
|
||||
import { CommonMailOptions } from '@/modules/MailNotification/MailNotification.types';
|
||||
|
||||
export interface ISaleEstimateDTO {
|
||||
customerId: number;
|
||||
@@ -104,19 +106,18 @@ export interface ISaleEstimateApprovedEvent {
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
// export interface SaleEstimateMailOptions extends CommonMailOptions {
|
||||
// attachEstimate?: boolean;
|
||||
// }
|
||||
export interface SaleEstimateMailOptions extends CommonMailOptions {
|
||||
attachEstimate?: boolean;
|
||||
}
|
||||
|
||||
// export interface SaleEstimateMailOptionsDTO extends CommonMailOptionsDTO {
|
||||
// attachEstimate?: boolean;
|
||||
// }
|
||||
export interface SaleEstimateMailOptionsDTO extends CommonMailOptionsDTO {
|
||||
attachEstimate?: boolean;
|
||||
}
|
||||
|
||||
// export interface ISaleEstimateMailPresendEvent {
|
||||
// // tenantId: number;
|
||||
// saleEstimateId: number;
|
||||
// messageOptions: SaleEstimateMailOptionsDTO;
|
||||
// }
|
||||
export interface ISaleEstimateMailPresendEvent {
|
||||
saleEstimateId: number;
|
||||
messageOptions: SaleEstimateMailOptionsDTO;
|
||||
}
|
||||
|
||||
export interface ISaleEstimateState {
|
||||
defaultTemplateId: number;
|
||||
|
||||
@@ -2,6 +2,8 @@ import { Knex } from 'knex';
|
||||
import { IItemEntryDTO } from '../TransactionItemEntry/ItemEntry.types';
|
||||
import { AttachmentLinkDTO } from '../Attachments/Attachments.types';
|
||||
import { SaleInvoice } from './models/SaleInvoice';
|
||||
import { IDynamicListFilter } from '../DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||
import { CommonMailOptionsDTO } from '../MailNotification/MailNotification.types';
|
||||
// import SaleInvoice from './models/SaleInvoice';
|
||||
// import { SystemUser } from '../System/models/SystemUser';
|
||||
// import { ISystemUser, IAccount, ITaxTransaction } from '@/interfaces';
|
||||
@@ -66,12 +68,12 @@ export interface ISaleInvoiceCreateDTO extends ISaleInvoiceDTO {
|
||||
|
||||
export interface ISaleInvoiceEditDTO extends ISaleInvoiceDTO {}
|
||||
|
||||
// export interface ISalesInvoicesFilter extends IDynamicListFilter {
|
||||
// page: number;
|
||||
// pageSize: number;
|
||||
// searchKeyword?: string;
|
||||
// filterQuery?: (q: Knex.QueryBuilder) => void;
|
||||
// }
|
||||
export interface ISalesInvoicesFilter extends IDynamicListFilter {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
searchKeyword?: string;
|
||||
filterQuery?: (q: Knex.QueryBuilder) => void;
|
||||
}
|
||||
|
||||
export interface ISaleInvoiceWriteoffDTO {
|
||||
expenseAccountId: number;
|
||||
@@ -212,28 +214,25 @@ export enum SaleInvoiceAction {
|
||||
// entries?: Array<{ label: string; total: string; quantity: string | number }>;
|
||||
// }
|
||||
|
||||
// export interface SendInvoiceMailDTO extends CommonMailOptionsDTO {
|
||||
// attachInvoice?: boolean;
|
||||
// }
|
||||
export interface SendInvoiceMailDTO extends CommonMailOptionsDTO {
|
||||
attachInvoice?: boolean;
|
||||
}
|
||||
|
||||
// export interface ISaleInvoiceNotifyPayload {
|
||||
// tenantId: number;
|
||||
// saleInvoiceId: number;
|
||||
// messageDTO: SendInvoiceMailDTO;
|
||||
// }
|
||||
export interface ISaleInvoiceNotifyPayload {
|
||||
saleInvoiceId: number;
|
||||
messageDTO: SendInvoiceMailDTO;
|
||||
}
|
||||
|
||||
// export interface ISaleInvoiceMailSend {
|
||||
// tenantId: number;
|
||||
// saleInvoiceId: number;
|
||||
// messageOptions: SendInvoiceMailDTO;
|
||||
// formattedMessageOptions: SaleInvoiceMailOptions;
|
||||
// }
|
||||
export interface ISaleInvoiceMailSend {
|
||||
saleInvoiceId: number;
|
||||
messageOptions: SendInvoiceMailDTO;
|
||||
// formattedMessageOptions: SaleInvoiceMailOptions;
|
||||
}
|
||||
|
||||
// export interface ISaleInvoiceMailSent {
|
||||
// tenantId: number;
|
||||
// saleInvoiceId: number;
|
||||
// messageOptions: SendInvoiceMailDTO;
|
||||
// }
|
||||
export interface ISaleInvoiceMailSent {
|
||||
saleInvoiceId: number;
|
||||
messageOptions: SendInvoiceMailDTO;
|
||||
}
|
||||
|
||||
// Invoice Pdf Document
|
||||
export interface InvoicePdfLine {
|
||||
|
||||
@@ -18,7 +18,9 @@ import {
|
||||
ISaleInvoiceCreateDTO,
|
||||
ISaleInvoiceEditDTO,
|
||||
ISaleInvoiceWriteoffDTO,
|
||||
ISalesInvoicesFilter,
|
||||
} from './SaleInvoice.types';
|
||||
import { GetSaleInvoicesService } from './queries/GetSaleInvoices';
|
||||
|
||||
@Injectable()
|
||||
export class SaleInvoiceApplication {
|
||||
@@ -26,18 +28,18 @@ export class SaleInvoiceApplication {
|
||||
private createSaleInvoiceService: CreateSaleInvoice,
|
||||
private deleteSaleInvoiceService: DeleteSaleInvoice,
|
||||
private getSaleInvoiceService: GetSaleInvoice,
|
||||
// private getSaleInvoicesService: GetSaleInvoices,
|
||||
private getSaleInvoicesService: GetSaleInvoicesService,
|
||||
private editSaleInvoiceService: EditSaleInvoice,
|
||||
private deliverSaleInvoiceService: DeliverSaleInvoice,
|
||||
private getReceivableSaleInvoicesService: GetSaleInvoicesPayable,
|
||||
private writeoffInvoiceService: WriteoffSaleInvoice,
|
||||
private getInvoicePaymentsService: GetInvoicePaymentsService,
|
||||
private pdfSaleInvoiceService: SaleInvoicePdf,
|
||||
private getSaleInvoiceStateService: GetSaleInvoiceState,
|
||||
// private invoiceSms: SaleInvoiceNotifyBySms,
|
||||
// private sendInvoiceReminderService: SendInvoiceMailReminder,
|
||||
private sendInvoiceReminderService: SendInvoiceMailReminder,
|
||||
// private sendSaleInvoiceMailService: SendSaleInvoiceMail,
|
||||
// private getSaleInvoiceMailStateService: GetSaleInvoiceMailState,
|
||||
private getSaleInvoiceStateService: GetSaleInvoiceState,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -77,13 +79,12 @@ export class SaleInvoiceApplication {
|
||||
|
||||
/**
|
||||
* Retrieves the given sale invoice details.
|
||||
* @param {number} tenantId
|
||||
* @param {ISalesInvoicesFilter} filterDTO
|
||||
* @returns
|
||||
* @returns {Promise<{ salesInvoices: SaleInvoice[]; pagination: IPaginationMeta; filterMeta: IFilterMeta; }>}
|
||||
*/
|
||||
// public getSaleInvoices(filterDTO: ISalesInvoicesFilter) {
|
||||
// return this.getSaleInvoicesService.getSaleInvoices(filterDTO);
|
||||
// }
|
||||
public getSaleInvoices(filterDTO: ISalesInvoicesFilter) {
|
||||
return this.getSaleInvoicesService.getSaleInvoices(filterDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves sale invoice details.
|
||||
|
||||
@@ -8,8 +8,6 @@ import { DeliverSaleInvoice } from './commands/DeliverSaleInvoice.service';
|
||||
import { EditSaleInvoice } from './commands/EditSaleInvoice.service';
|
||||
import { GenerateShareLink } from './commands/GenerateInvoicePaymentLink.service';
|
||||
import { SaleInvoiceIncrement } from './commands/SaleInvoiceIncrement.service';
|
||||
// import { SendSaleInvoiceMail } from './commands/SendSaleInvoiceMail';
|
||||
// import { SendSaleInvoiceReminderMailJob } from './commands/SendSaleInvoiceMailReminderJob';
|
||||
import { GetInvoicePaymentMail } from './queries/GetInvoicePaymentMail.service';
|
||||
import { GetSaleInvoice } from './queries/GetSaleInvoice.service';
|
||||
import { GetSaleInvoicesPayable } from './queries/GetSaleInvoicesPayable.service';
|
||||
@@ -37,6 +35,10 @@ import { LedgerModule } from '../Ledger/Ledger.module';
|
||||
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||
import SaleInvoiceWriteoffSubscriber from './subscribers/SaleInvoiceWriteoffSubscriber';
|
||||
import { SaleInvoiceWriteoffGLStorage } from './commands/writeoff/SaleInvoiceWriteoffGLStorage';
|
||||
import { InvoiceInventoryTransactions } from './commands/inventory/InvoiceInventoryTransactions';
|
||||
import { SendSaleEstimateMail } from '../SaleEstimates/commands/SendSaleEstimateMail';
|
||||
import { SendInvoiceMailReminder } from './commands/SendSaleInvoiceMailReminder';
|
||||
import { MailModule } from '../Mail/Mail.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -48,7 +50,8 @@ import { SaleInvoiceWriteoffGLStorage } from './commands/writeoff/SaleInvoiceWri
|
||||
WarehousesModule,
|
||||
TaxRatesModule,
|
||||
LedgerModule,
|
||||
AccountsModule
|
||||
AccountsModule,
|
||||
MailModule,
|
||||
],
|
||||
controllers: [SaleInvoicesController],
|
||||
providers: [
|
||||
@@ -57,7 +60,6 @@ import { SaleInvoiceWriteoffGLStorage } from './commands/writeoff/SaleInvoiceWri
|
||||
DeleteSaleInvoice,
|
||||
GetSaleInvoicesPayable,
|
||||
DeliverSaleInvoice,
|
||||
// SendSaleInvoiceMail,
|
||||
GenerateShareLink,
|
||||
GetInvoicePaymentMail,
|
||||
SaleInvoiceIncrement,
|
||||
@@ -79,7 +81,10 @@ import { SaleInvoiceWriteoffGLStorage } from './commands/writeoff/SaleInvoiceWri
|
||||
SaleInvoiceGLEntries,
|
||||
InvoiceGLEntriesSubscriber,
|
||||
SaleInvoiceWriteoffGLStorage,
|
||||
SaleInvoiceWriteoffSubscriber
|
||||
SaleInvoiceWriteoffSubscriber,
|
||||
InvoiceInventoryTransactions,
|
||||
SendSaleEstimateMail,
|
||||
SendInvoiceMailReminder,
|
||||
],
|
||||
})
|
||||
export class SaleInvoicesModule {}
|
||||
|
||||
@@ -1,129 +1,117 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import { SaleInvoiceMailOptions } from '@/interfaces';
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
// import { GetSaleInvoice } from '../queries/GetSaleInvoice.service';
|
||||
// import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification';
|
||||
// import {
|
||||
// DEFAULT_INVOICE_MAIL_CONTENT,
|
||||
// DEFAULT_INVOICE_MAIL_SUBJECT,
|
||||
// } from '../constants';
|
||||
// import { GetInvoicePaymentMail } from '../queries/GetInvoicePaymentMail.service';
|
||||
// import { GenerateShareLink } from './GenerateInvoicePaymentLink.service';
|
||||
import { GetSaleInvoice } from '../queries/GetSaleInvoice.service';
|
||||
import {
|
||||
DEFAULT_INVOICE_MAIL_CONTENT,
|
||||
DEFAULT_INVOICE_MAIL_SUBJECT,
|
||||
} from '../constants';
|
||||
import { GetInvoicePaymentMail } from '../queries/GetInvoicePaymentMail.service';
|
||||
import { GenerateShareLink } from './GenerateInvoicePaymentLink.service';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { SaleInvoice } from '../models/SaleInvoice';
|
||||
import { ContactMailNotification } from '@/modules/MailNotification/ContactMailNotification';
|
||||
|
||||
// @Service()
|
||||
// export class SendSaleInvoiceMailCommon {
|
||||
// constructor(
|
||||
// private getSaleInvoiceService: GetSaleInvoice,
|
||||
// private contactMailNotification: ContactMailNotification,
|
||||
// private getInvoicePaymentMail: GetInvoicePaymentMail,
|
||||
// private generatePaymentLinkService: GenerateShareLink,
|
||||
// ) {}
|
||||
@Injectable()
|
||||
export class SendSaleInvoiceMailCommon {
|
||||
constructor(
|
||||
private getSaleInvoiceService: GetSaleInvoice,
|
||||
private contactMailNotification: ContactMailNotification,
|
||||
private getInvoicePaymentMail: GetInvoicePaymentMail,
|
||||
private generatePaymentLinkService: GenerateShareLink,
|
||||
|
||||
// /**
|
||||
// * Retrieves the mail options.
|
||||
// * @param {number} tenantId - Tenant id.
|
||||
// * @param {number} invoiceId - Invoice id.
|
||||
// * @param {string} defaultSubject - Subject text.
|
||||
// * @param {string} defaultBody - Subject body.
|
||||
// * @returns {Promise<SaleInvoiceMailOptions>}
|
||||
// */
|
||||
// public async getInvoiceMailOptions(
|
||||
// invoiceId: number,
|
||||
// defaultSubject: string = DEFAULT_INVOICE_MAIL_SUBJECT,
|
||||
// defaultMessage: string = DEFAULT_INVOICE_MAIL_CONTENT,
|
||||
// ): Promise<SaleInvoiceMailOptions> {
|
||||
// const { SaleInvoice } = this.tenancy.models(tenantId);
|
||||
@Inject(SaleInvoice.name)
|
||||
private readonly saleInvoiceModel: typeof SaleInvoice,
|
||||
) {}
|
||||
|
||||
// const saleInvoice = await SaleInvoice.query()
|
||||
// .findById(invoiceId)
|
||||
// .throwIfNotFound();
|
||||
/**
|
||||
* Retrieves the mail options.
|
||||
* @param {number} invoiceId - Invoice id.
|
||||
* @param {string} defaultSubject - Subject text.
|
||||
* @param {string} defaultBody - Subject body.
|
||||
* @returns {Promise<SaleInvoiceMailOptions>}
|
||||
*/
|
||||
public async getInvoiceMailOptions(
|
||||
invoiceId: number,
|
||||
defaultSubject: string = DEFAULT_INVOICE_MAIL_SUBJECT,
|
||||
defaultMessage: string = DEFAULT_INVOICE_MAIL_CONTENT,
|
||||
): Promise<SaleInvoiceMailOptions> {
|
||||
const saleInvoice = await this.saleInvoiceModel
|
||||
.query()
|
||||
.findById(invoiceId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// const contactMailDefaultOptions =
|
||||
// await this.contactMailNotification.getDefaultMailOptions(
|
||||
// tenantId,
|
||||
// saleInvoice.customerId,
|
||||
// );
|
||||
// const formatArgs = await this.getInvoiceFormatterArgs(tenantId, invoiceId);
|
||||
const contactMailDefaultOptions =
|
||||
await this.contactMailNotification.getDefaultMailOptions(
|
||||
saleInvoice.customerId,
|
||||
);
|
||||
const formatArgs = await this.getInvoiceFormatterArgs(invoiceId);
|
||||
|
||||
// return {
|
||||
// ...contactMailDefaultOptions,
|
||||
// subject: defaultSubject,
|
||||
// message: defaultMessage,
|
||||
// attachInvoice: true,
|
||||
// formatArgs,
|
||||
// };
|
||||
// }
|
||||
return {
|
||||
...contactMailDefaultOptions,
|
||||
subject: defaultSubject,
|
||||
message: defaultMessage,
|
||||
attachInvoice: true,
|
||||
formatArgs,
|
||||
};
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Formats the given invoice mail options.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} invoiceId
|
||||
// * @param {SaleInvoiceMailOptions} mailOptions
|
||||
// * @returns {Promise<SaleInvoiceMailOptions>}
|
||||
// */
|
||||
// public async formatInvoiceMailOptions(
|
||||
// tenantId: number,
|
||||
// invoiceId: number,
|
||||
// mailOptions: SaleInvoiceMailOptions,
|
||||
// ): Promise<SaleInvoiceMailOptions> {
|
||||
// const formatterArgs = await this.getInvoiceFormatterArgs(
|
||||
// tenantId,
|
||||
// invoiceId,
|
||||
// );
|
||||
// const formattedOptions =
|
||||
// await this.contactMailNotification.formatMailOptions(
|
||||
// tenantId,
|
||||
// mailOptions,
|
||||
// formatterArgs,
|
||||
// );
|
||||
// // Generates the a new payment link for the given invoice.
|
||||
// const paymentLink =
|
||||
// await this.generatePaymentLinkService.generatePaymentLink(
|
||||
// tenantId,
|
||||
// invoiceId,
|
||||
// 'public',
|
||||
// );
|
||||
// const message = await this.getInvoicePaymentMail.getMailTemplate(
|
||||
// tenantId,
|
||||
// invoiceId,
|
||||
// {
|
||||
// // # Invoice message
|
||||
// invoiceMessage: formattedOptions.message,
|
||||
// preview: formattedOptions.message,
|
||||
/**
|
||||
* Formats the given invoice mail options.
|
||||
* @param {number} invoiceId
|
||||
* @param {SaleInvoiceMailOptions} mailOptions
|
||||
* @returns {Promise<SaleInvoiceMailOptions>}
|
||||
*/
|
||||
public async formatInvoiceMailOptions(
|
||||
invoiceId: number,
|
||||
mailOptions: SaleInvoiceMailOptions,
|
||||
): Promise<SaleInvoiceMailOptions> {
|
||||
const formatterArgs = await this.getInvoiceFormatterArgs(invoiceId);
|
||||
const formattedOptions =
|
||||
await this.contactMailNotification.formatMailOptions(
|
||||
mailOptions,
|
||||
formatterArgs,
|
||||
);
|
||||
// Generates the a new payment link for the given invoice.
|
||||
const paymentLink =
|
||||
await this.generatePaymentLinkService.generatePaymentLink(
|
||||
invoiceId,
|
||||
'public',
|
||||
);
|
||||
const message = await this.getInvoicePaymentMail.getMailTemplate(
|
||||
invoiceId,
|
||||
{
|
||||
// # Invoice message
|
||||
invoiceMessage: formattedOptions.message,
|
||||
preview: formattedOptions.message,
|
||||
|
||||
// // # Payment link
|
||||
// viewInvoiceButtonUrl: paymentLink.link,
|
||||
// },
|
||||
// );
|
||||
// return { ...formattedOptions, message };
|
||||
// }
|
||||
// # Payment link
|
||||
viewInvoiceButtonUrl: paymentLink.link,
|
||||
},
|
||||
);
|
||||
return { ...formattedOptions, message };
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Retrieves the formatted text of the given sale invoice.
|
||||
// * @param {number} tenantId - Tenant id.
|
||||
// * @param {number} invoiceId - Sale invoice id.
|
||||
// * @param {string} text - The given text.
|
||||
// * @returns {Promise<string>}
|
||||
// */
|
||||
// public getInvoiceFormatterArgs = async (
|
||||
// tenantId: number,
|
||||
// invoiceId: number,
|
||||
// ): Promise<Record<string, string | number>> => {
|
||||
// const invoice = await this.getSaleInvoiceService.getSaleInvoice(
|
||||
// tenantId,
|
||||
// invoiceId,
|
||||
// );
|
||||
// const commonArgs =
|
||||
// await this.contactMailNotification.getCommonFormatArgs(tenantId);
|
||||
// return {
|
||||
// ...commonArgs,
|
||||
// 'Customer Name': invoice.customer.displayName,
|
||||
// 'Invoice Number': invoice.invoiceNo,
|
||||
// 'Invoice Due Amount': invoice.dueAmountFormatted,
|
||||
// 'Invoice Due Date': invoice.dueDateFormatted,
|
||||
// 'Invoice Date': invoice.invoiceDateFormatted,
|
||||
// 'Invoice Amount': invoice.totalFormatted,
|
||||
// 'Overdue Days': invoice.overdueDays,
|
||||
// };
|
||||
// };
|
||||
// }
|
||||
/**
|
||||
* Retrieves the formatted text of the given sale invoice.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} invoiceId - Sale invoice id.
|
||||
* @param {string} text - The given text.
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
public getInvoiceFormatterArgs = async (
|
||||
invoiceId: number,
|
||||
): Promise<Record<string, string | number>> => {
|
||||
const invoice = await this.getSaleInvoiceService.getSaleInvoice(invoiceId);
|
||||
const commonArgs =
|
||||
await this.contactMailNotification.getCommonFormatArgs(tenantId);
|
||||
return {
|
||||
...commonArgs,
|
||||
'Customer Name': invoice.customer.displayName,
|
||||
'Invoice Number': invoice.invoiceNo,
|
||||
'Invoice Due Amount': invoice.dueAmountFormatted,
|
||||
'Invoice Due Date': invoice.dueDateFormatted,
|
||||
'Invoice Date': invoice.invoiceDateFormatted,
|
||||
'Invoice Amount': invoice.totalFormatted,
|
||||
'Overdue Days': invoice.overdueDays,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,136 +1,124 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import Mail from '@/lib/Mail';
|
||||
// import {
|
||||
// ISaleInvoiceMailSend,
|
||||
// SaleInvoiceMailOptions,
|
||||
// SendInvoiceMailDTO,
|
||||
// } from '@/interfaces';
|
||||
// import { SaleInvoicePdf } from '../queries/SaleInvoicePdf.service';
|
||||
// import { SendSaleInvoiceMailCommon } from './SendInvoiceInvoiceMailCommon.service';
|
||||
// import { mergeAndValidateMailOptions } from '@/services/MailNotification/utils';
|
||||
// import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
// import events from '@/subscribers/events';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { SaleInvoicePdf } from '../queries/SaleInvoicePdf.service';
|
||||
import { SendSaleInvoiceMailCommon } from './SendInvoiceInvoiceMailCommon.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { mergeAndValidateMailOptions } from '@/modules/MailNotification/utils';
|
||||
import { SendInvoiceMailDTO } from '../SaleInvoice.types';
|
||||
import { ISaleInvoiceMailSend } from '../SaleInvoice.types';
|
||||
import { Mail } from '@/modules/Mail/Mail';
|
||||
import { MailTransporter } from '@/modules/Mail/MailTransporter.service';
|
||||
|
||||
// @Service()
|
||||
// export class SendSaleInvoiceMail {
|
||||
// @Inject()
|
||||
// private invoicePdf: SaleInvoicePdf;
|
||||
@Injectable()
|
||||
export class SendSaleInvoiceMail {
|
||||
/**
|
||||
* @param {SaleInvoicePdf} invoicePdf - Sale invoice pdf service.
|
||||
* @param {SendSaleInvoiceMailCommon} invoiceMail - Sale invoice mail service.
|
||||
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||
* @param {MailTransporter} mailTransporter - Mail transporter service.
|
||||
*/
|
||||
constructor(
|
||||
private readonly invoicePdf: SaleInvoicePdf,
|
||||
private readonly invoiceMail: SendSaleInvoiceMailCommon,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly mailTransporter: MailTransporter,
|
||||
) {}
|
||||
|
||||
// @Inject()
|
||||
// private invoiceMail: SendSaleInvoiceMailCommon;
|
||||
/**
|
||||
* Sends the invoice mail of the given sale invoice.
|
||||
* @param {number} tenantId
|
||||
* @param {number} saleInvoiceId
|
||||
* @param {SendInvoiceMailDTO} messageDTO
|
||||
*/
|
||||
public async triggerMail(
|
||||
saleInvoiceId: number,
|
||||
messageOptions: SendInvoiceMailDTO,
|
||||
) {
|
||||
const payload = {
|
||||
saleInvoiceId,
|
||||
messageOptions,
|
||||
};
|
||||
// await this.agenda.now('sale-invoice-mail-send', payload);
|
||||
|
||||
// @Inject()
|
||||
// private eventPublisher: EventPublisher;
|
||||
// Triggers the event `onSaleInvoicePreMailSend`.
|
||||
await this.eventEmitter.emitAsync(events.saleInvoice.onPreMailSend, {
|
||||
saleInvoiceId,
|
||||
messageOptions,
|
||||
} as ISaleInvoiceMailSend);
|
||||
}
|
||||
|
||||
// @Inject('agenda')
|
||||
// private agenda: any;
|
||||
/**
|
||||
* Retrieves the formatted mail options.
|
||||
* @param {number} saleInvoiceId
|
||||
* @param {SendInvoiceMailDTO} messageOptions
|
||||
* @returns {Promise<SaleInvoiceMailOptions>}
|
||||
*/
|
||||
async getFormattedMailOptions(
|
||||
saleInvoiceId: number,
|
||||
messageOptions: SendInvoiceMailDTO,
|
||||
): Promise<SaleInvoiceMailOptions> {
|
||||
const defaultMessageOptions =
|
||||
await this.invoiceMail.getInvoiceMailOptions(saleInvoiceId);
|
||||
|
||||
// /**
|
||||
// * Sends the invoice mail of the given sale invoice.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleInvoiceId
|
||||
// * @param {SendInvoiceMailDTO} messageDTO
|
||||
// */
|
||||
// public async triggerMail(
|
||||
// tenantId: number,
|
||||
// saleInvoiceId: number,
|
||||
// messageOptions: SendInvoiceMailDTO
|
||||
// ) {
|
||||
// const payload = {
|
||||
// tenantId,
|
||||
// saleInvoiceId,
|
||||
// messageOptions,
|
||||
// };
|
||||
// await this.agenda.now('sale-invoice-mail-send', payload);
|
||||
// Merges message options with default options and parses the options values.
|
||||
const parsedMessageOptions = mergeAndValidateMailOptions(
|
||||
defaultMessageOptions,
|
||||
messageOptions,
|
||||
);
|
||||
return this.invoiceMail.formatInvoiceMailOptions(
|
||||
saleInvoiceId,
|
||||
parsedMessageOptions,
|
||||
);
|
||||
}
|
||||
|
||||
// // Triggers the event `onSaleInvoicePreMailSend`.
|
||||
// await this.eventPublisher.emitAsync(events.saleInvoice.onPreMailSend, {
|
||||
// tenantId,
|
||||
// saleInvoiceId,
|
||||
// messageOptions,
|
||||
// } as ISaleInvoiceMailSend);
|
||||
// }
|
||||
/**
|
||||
* Triggers the mail invoice.
|
||||
* @param {number} saleInvoiceId - Sale invoice id.
|
||||
* @param {SendInvoiceMailDTO} messageDTO - Message options.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async sendMail(
|
||||
saleInvoiceId: number,
|
||||
messageOptions: SendInvoiceMailDTO,
|
||||
) {
|
||||
const formattedMessageOptions = await this.getFormattedMailOptions(
|
||||
saleInvoiceId,
|
||||
messageOptions,
|
||||
);
|
||||
const mail = new Mail()
|
||||
.setSubject(formattedMessageOptions.subject)
|
||||
.setTo(formattedMessageOptions.to)
|
||||
.setCC(formattedMessageOptions.cc)
|
||||
.setBCC(formattedMessageOptions.bcc)
|
||||
.setContent(formattedMessageOptions.message);
|
||||
|
||||
// /**
|
||||
// * Retrieves the formatted mail options.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleInvoiceId
|
||||
// * @param {SendInvoiceMailDTO} messageOptions
|
||||
// * @returns {Promise<SaleInvoiceMailOptions>}
|
||||
// */
|
||||
// async getFormattedMailOptions(
|
||||
// tenantId: number,
|
||||
// saleInvoiceId: number,
|
||||
// messageOptions: SendInvoiceMailDTO
|
||||
// ): Promise<SaleInvoiceMailOptions> {
|
||||
// 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
|
||||
// );
|
||||
// }
|
||||
// Attach invoice document.
|
||||
if (formattedMessageOptions.attachInvoice) {
|
||||
// Retrieves document buffer of the invoice pdf document.
|
||||
const [invoicePdfBuffer, invoiceFilename] =
|
||||
await this.invoicePdf.getSaleInvoicePdf(saleInvoiceId);
|
||||
|
||||
// /**
|
||||
// * 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)
|
||||
// .setCC(formattedMessageOptions.cc)
|
||||
// .setBCC(formattedMessageOptions.bcc)
|
||||
// .setContent(formattedMessageOptions.message);
|
||||
mail.setAttachments([
|
||||
{ filename: `${invoiceFilename}.pdf`, content: invoicePdfBuffer },
|
||||
]);
|
||||
}
|
||||
const eventPayload = {
|
||||
saleInvoiceId,
|
||||
messageOptions,
|
||||
formattedMessageOptions,
|
||||
} as ISaleInvoiceMailSend;
|
||||
|
||||
// // Attach invoice document.
|
||||
// if (formattedMessageOptions.attachInvoice) {
|
||||
// // Retrieves document buffer of the invoice pdf document.
|
||||
// const [invoicePdfBuffer, invoiceFilename] =
|
||||
// await this.invoicePdf.saleInvoicePdf(tenantId, saleInvoiceId);
|
||||
// Triggers the event `onSaleInvoiceSend`.
|
||||
await this.eventEmitter.emitAsync(
|
||||
events.saleInvoice.onMailSend,
|
||||
eventPayload,
|
||||
);
|
||||
await this.mailTransporter.send(mail);
|
||||
|
||||
// mail.setAttachments([
|
||||
// { filename: `${invoiceFilename}.pdf`, content: invoicePdfBuffer },
|
||||
// ]);
|
||||
// }
|
||||
// const eventPayload = {
|
||||
// tenantId,
|
||||
// saleInvoiceId,
|
||||
// messageOptions,
|
||||
// formattedMessageOptions,
|
||||
// } as ISaleInvoiceMailSend;
|
||||
|
||||
// // Triggers the event `onSaleInvoiceSend`.
|
||||
// await this.eventPublisher.emitAsync(
|
||||
// events.saleInvoice.onMailSend,
|
||||
// eventPayload
|
||||
// );
|
||||
// await mail.send();
|
||||
|
||||
// // Triggers the event `onSaleInvoiceSend`.
|
||||
// await this.eventPublisher.emitAsync(
|
||||
// events.saleInvoice.onMailSent,
|
||||
// eventPayload
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// Triggers the event `onSaleInvoiceSend`.
|
||||
await this.eventEmitter.emitAsync(
|
||||
events.saleInvoice.onMailSent,
|
||||
eventPayload,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,112 +1,96 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import {
|
||||
// ISaleInvoiceMailSend,
|
||||
// ISaleInvoiceMailSent,
|
||||
// SendInvoiceMailDTO,
|
||||
// } from '@/interfaces';
|
||||
// import Mail from '@/lib/Mail';
|
||||
// import { SaleInvoicePdf } from '../queries/SaleInvoicePdf';
|
||||
// import { SendSaleInvoiceMailCommon } from './SendInvoiceInvoiceMailCommon';
|
||||
// import {
|
||||
// DEFAULT_INVOICE_REMINDER_MAIL_CONTENT,
|
||||
// DEFAULT_INVOICE_REMINDER_MAIL_SUBJECT,
|
||||
// } from '../constants';
|
||||
// import { parseAndValidateMailOptions } from '@/services/MailNotification/utils';
|
||||
// import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
// import events from '@/subscribers/events';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import {
|
||||
DEFAULT_INVOICE_REMINDER_MAIL_CONTENT,
|
||||
DEFAULT_INVOICE_REMINDER_MAIL_SUBJECT,
|
||||
} from '../constants';
|
||||
import { SaleInvoicePdf } from '../queries/SaleInvoicePdf.service';
|
||||
import { SendSaleInvoiceMailCommon } from './SendInvoiceInvoiceMailCommon.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ISaleInvoiceMailSend, ISaleInvoiceMailSent, SendInvoiceMailDTO } from '../SaleInvoice.types';
|
||||
import { mergeAndValidateMailOptions } from '@/modules/MailNotification/utils';
|
||||
import { MailTransporter } from '@/modules/Mail/MailTransporter.service';
|
||||
import { Mail } from '@/modules/Mail/Mail';
|
||||
|
||||
// @Service()
|
||||
// export class SendInvoiceMailReminder {
|
||||
// @Inject('agenda')
|
||||
// private agenda: any;
|
||||
@Injectable()
|
||||
export class SendInvoiceMailReminder {
|
||||
constructor(
|
||||
private readonly invoicePdf: SaleInvoicePdf,
|
||||
private readonly invoiceCommonMail: SendSaleInvoiceMailCommon,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly mailTransporter: MailTransporter,
|
||||
) {}
|
||||
|
||||
// @Inject()
|
||||
// private invoicePdf: SaleInvoicePdf;
|
||||
/**
|
||||
* Triggers the reminder mail of the given sale invoice.
|
||||
* @param {number} saleInvoiceId
|
||||
*/
|
||||
public async triggerMail(
|
||||
saleInvoiceId: number,
|
||||
messageOptions: SendInvoiceMailDTO,
|
||||
) {
|
||||
const payload = {
|
||||
saleInvoiceId,
|
||||
messageOptions,
|
||||
};
|
||||
// await this.agenda.now('sale-invoice-reminder-mail-send', payload);
|
||||
}
|
||||
|
||||
// @Inject()
|
||||
// private invoiceCommonMail: SendSaleInvoiceMailCommon;
|
||||
/**
|
||||
* Retrieves the mail options of the given sale invoice.
|
||||
* @param {number} saleInvoiceId - The sale invocie id.
|
||||
* @returns {Promise<SaleInvoiceMailOptions>}
|
||||
*/
|
||||
public async getMailOption(saleInvoiceId: number) {
|
||||
return this.invoiceCommonMail.getMailOption(
|
||||
saleInvoiceId,
|
||||
DEFAULT_INVOICE_REMINDER_MAIL_SUBJECT,
|
||||
DEFAULT_INVOICE_REMINDER_MAIL_CONTENT,
|
||||
);
|
||||
}
|
||||
|
||||
// @Inject()
|
||||
// private eventPublisher: EventPublisher;
|
||||
/**
|
||||
* Triggers the mail invoice.
|
||||
* @param {number} saleInvoiceId - Sale invoice id.
|
||||
* @param {SendInvoiceMailDTO} messageOptions - The message options.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async sendMail(
|
||||
saleInvoiceId: number,
|
||||
messageOptions: SendInvoiceMailDTO,
|
||||
) {
|
||||
const localMessageOpts = await this.getMailOption(saleInvoiceId);
|
||||
|
||||
// /**
|
||||
// * Triggers the reminder mail of the given sale invoice.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleInvoiceId
|
||||
// */
|
||||
// public async triggerMail(
|
||||
// tenantId: number,
|
||||
// saleInvoiceId: number,
|
||||
// messageOptions: SendInvoiceMailDTO
|
||||
// ) {
|
||||
// const payload = {
|
||||
// tenantId,
|
||||
// saleInvoiceId,
|
||||
// messageOptions,
|
||||
// };
|
||||
// await this.agenda.now('sale-invoice-reminder-mail-send', payload);
|
||||
// }
|
||||
const messageOpts = mergeAndValidateMailOptions(
|
||||
localMessageOpts,
|
||||
messageOptions,
|
||||
);
|
||||
const mail = new Mail()
|
||||
.setSubject(messageOpts.subject)
|
||||
.setTo(messageOpts.to)
|
||||
.setContent(messageOpts.body);
|
||||
|
||||
// /**
|
||||
// * Retrieves the mail options of the given sale invoice.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleInvoiceId
|
||||
// * @returns {Promise<SaleInvoiceMailOptions>}
|
||||
// */
|
||||
// public async getMailOption(tenantId: number, saleInvoiceId: number) {
|
||||
// return this.invoiceCommonMail.getMailOption(
|
||||
// tenantId,
|
||||
// saleInvoiceId,
|
||||
// DEFAULT_INVOICE_REMINDER_MAIL_SUBJECT,
|
||||
// DEFAULT_INVOICE_REMINDER_MAIL_CONTENT
|
||||
// );
|
||||
// }
|
||||
if (messageOpts.attachInvoice) {
|
||||
// Retrieves document buffer of the invoice pdf document.
|
||||
const [invoicePdfBuffer, filename] = await this.invoicePdf.getSaleInvoicePdf(
|
||||
saleInvoiceId,
|
||||
);
|
||||
mail.setAttachments([
|
||||
{ filename, content: invoicePdfBuffer },
|
||||
]);
|
||||
}
|
||||
// Triggers the event `onSaleInvoiceSend`.
|
||||
await this.eventEmitter.emitAsync(events.saleInvoice.onMailReminderSend, {
|
||||
saleInvoiceId,
|
||||
messageOptions,
|
||||
} as ISaleInvoiceMailSend);
|
||||
|
||||
// /**
|
||||
// * Triggers the mail invoice.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleInvoiceId
|
||||
// * @param {SendInvoiceMailDTO} messageOptions
|
||||
// * @returns {Promise<void>}
|
||||
// */
|
||||
// public async sendMail(
|
||||
// tenantId: number,
|
||||
// saleInvoiceId: number,
|
||||
// messageOptions: SendInvoiceMailDTO
|
||||
// ) {
|
||||
// const localMessageOpts = await this.getMailOption(tenantId, saleInvoiceId);
|
||||
await this.mailTransporter.send(mail);
|
||||
|
||||
// const messageOpts = parseAndValidateMailOptions(
|
||||
// localMessageOpts,
|
||||
// messageOptions
|
||||
// );
|
||||
// const mail = new Mail()
|
||||
// .setSubject(messageOpts.subject)
|
||||
// .setTo(messageOpts.to)
|
||||
// .setContent(messageOpts.body);
|
||||
|
||||
// if (messageOpts.attachInvoice) {
|
||||
// // Retrieves document buffer of the invoice pdf document.
|
||||
// const invoicePdfBuffer = await this.invoicePdf.saleInvoicePdf(
|
||||
// tenantId,
|
||||
// saleInvoiceId
|
||||
// );
|
||||
// mail.setAttachments([
|
||||
// { filename: 'invoice.pdf', content: invoicePdfBuffer },
|
||||
// ]);
|
||||
// }
|
||||
// // Triggers the event `onSaleInvoiceSend`.
|
||||
// await this.eventPublisher.emitAsync(events.saleInvoice.onMailReminderSend, {
|
||||
// saleInvoiceId,
|
||||
// messageOptions,
|
||||
// } as ISaleInvoiceMailSend);
|
||||
|
||||
// await mail.send();
|
||||
|
||||
// // Triggers the event `onSaleInvoiceSent`.
|
||||
// await this.eventPublisher.emitAsync(events.saleInvoice.onMailReminderSent, {
|
||||
// saleInvoiceId,
|
||||
// messageOptions,
|
||||
// } as ISaleInvoiceMailSent);
|
||||
// }
|
||||
// }
|
||||
// Triggers the event `onSaleInvoiceSent`.
|
||||
await this.eventEmitter.emitAsync(events.saleInvoice.onMailReminderSent, {
|
||||
saleInvoiceId,
|
||||
messageOptions,
|
||||
} as ISaleInvoiceMailSent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,12 @@ import { ServiceError } from '../../Items/ServiceError';
|
||||
|
||||
@Injectable()
|
||||
export class WriteoffSaleInvoice {
|
||||
/**
|
||||
* @param {EventEmitter2} eventPublisher - Event emitter.
|
||||
* @param {UnitOfWork} uow - Unit of work.
|
||||
* @param {CommandSaleInvoiceValidators} validators - Command sale invoice validators.
|
||||
* @param {typeof SaleInvoice} saleInvoiceModel - Sale invoice model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly uow: UnitOfWork,
|
||||
|
||||
@@ -1,38 +1,34 @@
|
||||
import { Inject, Service } from 'typedi';
|
||||
import { InventoryService } from '@/modules/InventoryCost/Inventory';
|
||||
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { ISaleInvoice } from '@/interfaces';
|
||||
import ItemsEntriesService from '@/services/Items/ItemsEntriesService';
|
||||
import InventoryService from '@/services/Inventory/Inventory';
|
||||
import { SaleInvoice } from '../../models/SaleInvoice';
|
||||
|
||||
@Service()
|
||||
@Injectable()
|
||||
export class InvoiceInventoryTransactions {
|
||||
@Inject()
|
||||
private itemsEntriesService: ItemsEntriesService;
|
||||
|
||||
@Inject()
|
||||
private inventoryService: InventoryService;
|
||||
constructor(
|
||||
private readonly itemsEntriesService: ItemsEntriesService,
|
||||
private readonly inventoryService: InventoryService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Records the inventory transactions of the given sale invoice in case
|
||||
* the invoice has inventory entries only.
|
||||
*
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {SaleInvoice} saleInvoice - Sale invoice DTO.
|
||||
* @param {number} saleInvoiceId - Sale invoice id.
|
||||
* @param {boolean} override - Allow to override old transactions.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async recordInventoryTranscactions(
|
||||
saleInvoice: ISaleInvoice,
|
||||
saleInvoice: SaleInvoice,
|
||||
override?: boolean,
|
||||
trx?: Knex.Transaction
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> {
|
||||
// Loads the inventory items entries of the given sale invoice.
|
||||
const inventoryEntries =
|
||||
await this.itemsEntriesService.filterInventoryEntries(
|
||||
tenantId,
|
||||
saleInvoice.entries,
|
||||
trx
|
||||
trx,
|
||||
);
|
||||
const transaction = {
|
||||
transactionId: saleInvoice.id,
|
||||
@@ -48,30 +44,27 @@ export class InvoiceInventoryTransactions {
|
||||
createdAt: saleInvoice.createdAt,
|
||||
};
|
||||
await this.inventoryService.recordInventoryTransactionsFromItemsEntries(
|
||||
tenantId,
|
||||
transaction,
|
||||
override,
|
||||
trx
|
||||
trx,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverting the inventory transactions once the invoice deleted.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} billId - Bill id.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
public async revertInventoryTransactions(
|
||||
saleInvoiceId: number,
|
||||
trx?: Knex.Transaction
|
||||
trx?: Knex.Transaction,
|
||||
): Promise<void> {
|
||||
// Delete the inventory transaction of the given sale invoice.
|
||||
const { oldInventoryTransactions } =
|
||||
await this.inventoryService.deleteInventoryTransactions(
|
||||
tenantId,
|
||||
saleInvoiceId,
|
||||
'SaleInvoice',
|
||||
trx
|
||||
trx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +1,65 @@
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import * as R from 'ramda';
|
||||
// import {
|
||||
// IFilterMeta,
|
||||
// IPaginationMeta,
|
||||
// ISaleInvoice,
|
||||
// ISalesInvoicesFilter,
|
||||
// } from '@/interfaces';
|
||||
// import { TransformerInjectable } from '@/lib/Transformer/TransformerInjectable';
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
// import DynamicListingService from '@/services/DynamicListing/DynamicListService';
|
||||
// import { SaleInvoiceTransformer } from './SaleInvoice.transformer';
|
||||
import * as R from 'ramda';
|
||||
import { SaleInvoiceTransformer } from './SaleInvoice.transformer';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
|
||||
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
||||
import { SaleInvoice } from '../models/SaleInvoice';
|
||||
import { ISalesInvoicesFilter } from '../SaleInvoice.types';
|
||||
|
||||
// @Service()
|
||||
// export class GetSaleInvoices {
|
||||
// @Inject()
|
||||
// private tenancy: HasTenancyService;
|
||||
@Injectable()
|
||||
export class GetSaleInvoicesService {
|
||||
constructor(
|
||||
private readonly dynamicListService: DynamicListService,
|
||||
private readonly transformer: TransformerInjectable,
|
||||
) {}
|
||||
|
||||
// @Inject()
|
||||
// private dynamicListService: DynamicListingService;
|
||||
/**
|
||||
* Retrieve sales invoices filterable and paginated list.
|
||||
* @param {ISalesInvoicesFilter} filterDTO -
|
||||
* @returns {Promise<{ salesInvoices: SaleInvoice[]; pagination: IPaginationMeta; filterMeta: IFilterMeta; }>}
|
||||
*/
|
||||
public async getSaleInvoices(filterDTO: ISalesInvoicesFilter): Promise<{
|
||||
salesInvoices: SaleInvoice[];
|
||||
pagination: IPaginationMeta;
|
||||
filterMeta: IFilterMeta;
|
||||
}> {
|
||||
// Parses stringified filter roles.
|
||||
const filter = this.parseListFilterDTO(filterDTO);
|
||||
|
||||
// @Inject()
|
||||
// private transformer: TransformerInjectable;
|
||||
// Dynamic list service.
|
||||
const dynamicFilter = await this.dynamicListService.dynamicList(
|
||||
SaleInvoice,
|
||||
filter,
|
||||
);
|
||||
const { results, pagination } = await SaleInvoice.query()
|
||||
.onBuild((builder) => {
|
||||
builder.withGraphFetched('entries.item');
|
||||
builder.withGraphFetched('customer');
|
||||
dynamicFilter.buildQuery()(builder);
|
||||
filterDTO?.filterQuery && filterDTO?.filterQuery(builder);
|
||||
})
|
||||
.pagination(filter.page - 1, filter.pageSize);
|
||||
|
||||
// /**
|
||||
// * Retrieve sales invoices filterable and paginated list.
|
||||
// * @param {Request} req
|
||||
// * @param {Response} res
|
||||
// * @param {NextFunction} next
|
||||
// */
|
||||
// public async getSaleInvoices(
|
||||
// filterDTO: ISalesInvoicesFilter
|
||||
// ): Promise<{
|
||||
// salesInvoices: ISaleInvoice[];
|
||||
// pagination: IPaginationMeta;
|
||||
// filterMeta: IFilterMeta;
|
||||
// }> {
|
||||
// const { SaleInvoice } = this.tenancy.models(tenantId);
|
||||
// Retrieves the transformed sale invoices.
|
||||
const salesInvoices = await this.transformer.transform(
|
||||
results,
|
||||
new SaleInvoiceTransformer(),
|
||||
);
|
||||
|
||||
// // Parses stringified filter roles.
|
||||
// const filter = this.parseListFilterDTO(filterDTO);
|
||||
return {
|
||||
salesInvoices,
|
||||
pagination,
|
||||
filterMeta: dynamicFilter.getResponseMeta(),
|
||||
};
|
||||
}
|
||||
|
||||
// // Dynamic list service.
|
||||
// const dynamicFilter = await this.dynamicListService.dynamicList(
|
||||
// tenantId,
|
||||
// SaleInvoice,
|
||||
// filter
|
||||
// );
|
||||
// const { results, pagination } = await SaleInvoice.query()
|
||||
// .onBuild((builder) => {
|
||||
// builder.withGraphFetched('entries.item');
|
||||
// builder.withGraphFetched('customer');
|
||||
// dynamicFilter.buildQuery()(builder);
|
||||
// filterDTO?.filterQuery && filterDTO?.filterQuery(builder);
|
||||
// })
|
||||
// .pagination(filter.page - 1, filter.pageSize);
|
||||
|
||||
// // Retrieves the transformed sale invoices.
|
||||
// const salesInvoices = await this.transformer.transform(
|
||||
// tenantId,
|
||||
// results,
|
||||
// new SaleInvoiceTransformer()
|
||||
// );
|
||||
|
||||
// return {
|
||||
// salesInvoices,
|
||||
// pagination,
|
||||
// filterMeta: dynamicFilter.getResponseMeta(),
|
||||
// };
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Parses the sale invoice list filter DTO.
|
||||
// * @param filterDTO
|
||||
// * @returns
|
||||
// */
|
||||
// private parseListFilterDTO(filterDTO) {
|
||||
// return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
|
||||
// }
|
||||
// }
|
||||
/**
|
||||
* Parses the sale invoice list filter DTO.
|
||||
* @param filterDTO
|
||||
* @returns
|
||||
*/
|
||||
private parseListFilterDTO(filterDTO) {
|
||||
return R.compose(this.dynamicListService.parseStringifiedFilter)(filterDTO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@ import {
|
||||
ISaleReceiptDTO,
|
||||
ISaleReceiptState,
|
||||
ISalesReceiptsFilter,
|
||||
SaleReceiptMailOpts,
|
||||
} from './types/SaleReceipts.types';
|
||||
import { GetSaleReceiptsService } from './queries/GetSaleReceipts.service';
|
||||
import { SaleReceipt } from './models/SaleReceipt';
|
||||
import { IPaginationMeta } from '@/interfaces/Model';
|
||||
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
||||
import { SaleReceiptMailNotification } from './commands/SaleReceiptMailNotification';
|
||||
|
||||
@Injectable()
|
||||
export class SaleReceiptApplication {
|
||||
@@ -28,8 +30,8 @@ export class SaleReceiptApplication {
|
||||
private closeSaleReceiptService: CloseSaleReceipt,
|
||||
private getSaleReceiptPdfService: SaleReceiptsPdfService,
|
||||
// private saleReceiptNotifyBySmsService: SaleReceiptNotifyBySms,
|
||||
// private saleReceiptNotifyByMailService: SaleReceiptMailNotification,
|
||||
private getSaleReceiptStateService: GetSaleReceiptState,
|
||||
private saleReceiptNotifyByMailService: SaleReceiptMailNotification,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -158,19 +160,14 @@ export class SaleReceiptApplication {
|
||||
|
||||
/**
|
||||
* Retrieves the default mail options of the given sale receipt.
|
||||
* @param {number} tenantId
|
||||
* @param {number} saleReceiptId
|
||||
* @param {number} saleReceiptId - Sale receipt identifier.
|
||||
* @returns {Promise<SaleReceiptMailOpts>}
|
||||
*/
|
||||
// public getSaleReceiptMail(
|
||||
// tenantId: number,
|
||||
// saleReceiptId: number,
|
||||
// ): Promise<SaleReceiptMailOpts> {
|
||||
// return this.saleReceiptNotifyByMailService.getMailOptions(
|
||||
// tenantId,
|
||||
// saleReceiptId,
|
||||
// );
|
||||
// }
|
||||
public getSaleReceiptMail(
|
||||
saleReceiptId: number,
|
||||
): Promise<SaleReceiptMailOpts> {
|
||||
return this.saleReceiptNotifyByMailService.getMailOptions(saleReceiptId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current state of the sale receipt.
|
||||
|
||||
@@ -26,6 +26,7 @@ import { LedgerModule } from '../Ledger/Ledger.module';
|
||||
import { AccountsModule } from '../Accounts/Accounts.module';
|
||||
import { SaleReceiptInventoryTransactionsSubscriber } from './inventory/SaleReceiptWriteInventoryTransactions';
|
||||
import { GetSaleReceiptsService } from './queries/GetSaleReceipts.service';
|
||||
import { SaleReceiptMailNotification } from './commands/SaleReceiptMailNotification';
|
||||
|
||||
@Module({
|
||||
controllers: [SaleReceiptsController],
|
||||
@@ -57,7 +58,8 @@ import { GetSaleReceiptsService } from './queries/GetSaleReceipts.service';
|
||||
SaleReceiptGLEntries,
|
||||
SaleReceiptGLEntriesSubscriber,
|
||||
SaleReceiptInventoryTransactionsSubscriber,
|
||||
GetSaleReceiptsService
|
||||
GetSaleReceiptsService,
|
||||
SaleReceiptMailNotification
|
||||
],
|
||||
})
|
||||
export class SaleReceiptsModule {}
|
||||
|
||||
@@ -1,220 +1,192 @@
|
||||
// import HasTenancyService from '@/services/Tenancy/TenancyService';
|
||||
// import { Inject, Service } from 'typedi';
|
||||
// import Mail from '@/lib/Mail';
|
||||
// import { GetSaleReceipt } from '../queries/GetSaleReceipt';
|
||||
// import { SaleReceiptsPdf } from '../queries/SaleReceiptsPdfService';
|
||||
// import {
|
||||
// DEFAULT_RECEIPT_MAIL_CONTENT,
|
||||
// DEFAULT_RECEIPT_MAIL_SUBJECT,
|
||||
// } from '../constants';
|
||||
// import {
|
||||
// ISaleReceiptMailPresend,
|
||||
// SaleReceiptMailOpts,
|
||||
// SaleReceiptMailOptsDTO,
|
||||
// } from '@/interfaces';
|
||||
// import { ContactMailNotification } from '@/services/MailNotification/ContactMailNotification';
|
||||
// import { mergeAndValidateMailOptions } from '@/services/MailNotification/utils';
|
||||
// import { EventPublisher } from '@/lib/EventPublisher/EventPublisher';
|
||||
// import events from '@/subscribers/events';
|
||||
// import { transformReceiptToMailDataArgs } from '../utils';
|
||||
import {
|
||||
DEFAULT_RECEIPT_MAIL_CONTENT,
|
||||
DEFAULT_RECEIPT_MAIL_SUBJECT,
|
||||
} from '../constants';
|
||||
import { mergeAndValidateMailOptions } from '@/modules/MailNotification/utils';
|
||||
import { transformReceiptToMailDataArgs } from '../utils';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { GetSaleReceipt } from '../queries/GetSaleReceipt.service';
|
||||
import { SaleReceiptsPdfService } from '../queries/SaleReceiptsPdf.service';
|
||||
import { ContactMailNotification } from '@/modules/MailNotification/ContactMailNotification';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { events } from '@/common/events/events';
|
||||
import {
|
||||
ISaleReceiptMailPresend,
|
||||
SaleReceiptMailOpts,
|
||||
SaleReceiptMailOptsDTO,
|
||||
} from '../types/SaleReceipts.types';
|
||||
import { SaleReceipt } from '../models/SaleReceipt';
|
||||
import { MailTransporter } from '@/modules/Mail/MailTransporter.service';
|
||||
import { Mail } from '@/modules/Mail/Mail';
|
||||
|
||||
// @Service()
|
||||
// export class SaleReceiptMailNotification {
|
||||
// @Inject()
|
||||
// private tenancy: HasTenancyService;
|
||||
@Injectable()
|
||||
export class SaleReceiptMailNotification {
|
||||
/**
|
||||
* @param {GetSaleReceipt} getSaleReceiptService - Get sale receipt service.
|
||||
* @param {SaleReceiptsPdfService} receiptPdfService - Sale receipt pdf service.
|
||||
* @param {ContactMailNotification} contactMailNotification - Contact mail notification service.
|
||||
* @param {EventEmitter2} eventEmitter - Event emitter.
|
||||
* @param {MailTransporter} mailTransporter - Mail transporter service.
|
||||
*/
|
||||
constructor(
|
||||
private readonly getSaleReceiptService: GetSaleReceipt,
|
||||
private readonly receiptPdfService: SaleReceiptsPdfService,
|
||||
private readonly contactMailNotification: ContactMailNotification,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
private readonly mailTransporter: MailTransporter,
|
||||
) {}
|
||||
|
||||
// @Inject()
|
||||
// private getSaleReceiptService: GetSaleReceipt;
|
||||
/**
|
||||
* Sends the receipt mail of the given sale receipt.
|
||||
* @param {number} tenantId
|
||||
* @param {number} saleReceiptId
|
||||
* @param {SaleReceiptMailOptsDTO} messageDTO
|
||||
*/
|
||||
public async triggerMail(
|
||||
saleReceiptId: number,
|
||||
messageOptions: SaleReceiptMailOptsDTO,
|
||||
) {
|
||||
const payload = {
|
||||
saleReceiptId,
|
||||
messageOpts: messageOptions,
|
||||
};
|
||||
// await this.agenda.now('sale-receipt-mail-send', payload);
|
||||
|
||||
// @Inject()
|
||||
// private receiptPdfService: SaleReceiptsPdf;
|
||||
// Triggers the event `onSaleReceiptPreMailSend`.
|
||||
await this.eventEmitter.emitAsync(events.saleReceipt.onPreMailSend, {
|
||||
saleReceiptId,
|
||||
messageOptions,
|
||||
} as ISaleReceiptMailPresend);
|
||||
}
|
||||
|
||||
// @Inject()
|
||||
// private contactMailNotification: ContactMailNotification;
|
||||
/**
|
||||
* Retrieves the mail options of the given sale receipt.
|
||||
* @param {number} saleReceiptId
|
||||
* @returns {Promise<SaleReceiptMailOptsDTO>}
|
||||
*/
|
||||
public async getMailOptions(
|
||||
saleReceiptId: number,
|
||||
): Promise<SaleReceiptMailOpts> {
|
||||
const saleReceipt = await SaleReceipt.query()
|
||||
.findById(saleReceiptId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// @Inject()
|
||||
// private eventPublisher: EventPublisher;
|
||||
const formatArgs = await this.textFormatterArgs(saleReceiptId);
|
||||
const mailOptions =
|
||||
await this.contactMailNotification.getDefaultMailOptions(
|
||||
saleReceipt.customerId,
|
||||
);
|
||||
return {
|
||||
...mailOptions,
|
||||
message: DEFAULT_RECEIPT_MAIL_CONTENT,
|
||||
subject: DEFAULT_RECEIPT_MAIL_SUBJECT,
|
||||
attachReceipt: true,
|
||||
formatArgs,
|
||||
};
|
||||
}
|
||||
|
||||
// @Inject('agenda')
|
||||
// private agenda: any;
|
||||
/**
|
||||
* Retrieves the formatted text of the given sale receipt.
|
||||
* @param {number} tenantId - Tenant id.
|
||||
* @param {number} receiptId - Sale receipt id.
|
||||
* @param {string} text - The given text.
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
public textFormatterArgs = async (
|
||||
receiptId: number,
|
||||
): Promise<Record<string, string>> => {
|
||||
const receipt = await this.getSaleReceiptService.getSaleReceipt(receiptId);
|
||||
|
||||
// /**
|
||||
// * Sends the receipt mail of the given sale receipt.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleReceiptId
|
||||
// * @param {SaleReceiptMailOptsDTO} messageDTO
|
||||
// */
|
||||
// public async triggerMail(
|
||||
// tenantId: number,
|
||||
// saleReceiptId: number,
|
||||
// messageOptions: SaleReceiptMailOptsDTO
|
||||
// ) {
|
||||
// const payload = {
|
||||
// tenantId,
|
||||
// saleReceiptId,
|
||||
// messageOpts: messageOptions,
|
||||
// };
|
||||
// await this.agenda.now('sale-receipt-mail-send', payload);
|
||||
return transformReceiptToMailDataArgs(receipt);
|
||||
};
|
||||
|
||||
// // Triggers the event `onSaleReceiptPreMailSend`.
|
||||
// await this.eventPublisher.emitAsync(events.saleReceipt.onPreMailSend, {
|
||||
// tenantId,
|
||||
// saleReceiptId,
|
||||
// messageOptions,
|
||||
// } as ISaleReceiptMailPresend);
|
||||
// }
|
||||
/**
|
||||
* Formats the mail options of the given sale receipt.
|
||||
* @param {number} tenantId
|
||||
* @param {number} receiptId
|
||||
* @param {SaleReceiptMailOpts} mailOptions
|
||||
* @returns {Promise<SaleReceiptMailOpts>}
|
||||
*/
|
||||
public async formatEstimateMailOptions(
|
||||
receiptId: number,
|
||||
mailOptions: SaleReceiptMailOpts,
|
||||
): Promise<SaleReceiptMailOpts> {
|
||||
const formatterArgs = await this.textFormatterArgs(receiptId);
|
||||
const formattedOptions =
|
||||
(await this.contactMailNotification.formatMailOptions(
|
||||
mailOptions,
|
||||
formatterArgs,
|
||||
)) as SaleReceiptMailOpts;
|
||||
return formattedOptions;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Retrieves the mail options of the given sale receipt.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} saleReceiptId
|
||||
// * @returns {Promise<SaleReceiptMailOptsDTO>}
|
||||
// */
|
||||
// public async getMailOptions(
|
||||
// tenantId: number,
|
||||
// saleReceiptId: number
|
||||
// ): Promise<SaleReceiptMailOpts> {
|
||||
// const { SaleReceipt } = this.tenancy.models(tenantId);
|
||||
/**
|
||||
* 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 (
|
||||
saleReceiptId: number,
|
||||
messageOpts: SaleReceiptMailOptsDTO,
|
||||
): Promise<SaleReceiptMailOpts> => {
|
||||
const defaultMessageOptions = await this.getMailOptions(saleReceiptId);
|
||||
// Merges message opts with default options.
|
||||
const parsedMessageOpts = mergeAndValidateMailOptions(
|
||||
defaultMessageOptions,
|
||||
messageOpts,
|
||||
) as SaleReceiptMailOpts;
|
||||
|
||||
// const saleReceipt = await SaleReceipt.query()
|
||||
// .findById(saleReceiptId)
|
||||
// .throwIfNotFound();
|
||||
// Formats the message options.
|
||||
return this.formatEstimateMailOptions(saleReceiptId, parsedMessageOpts);
|
||||
};
|
||||
|
||||
// const formatArgs = await this.textFormatterArgs(tenantId, saleReceiptId);
|
||||
/**
|
||||
* Triggers the mail notification of the given sale receipt.
|
||||
* @param {number} saleReceiptId - Sale receipt id.
|
||||
* @param {SaleReceiptMailOpts} messageDTO - message options.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public async sendMail(
|
||||
saleReceiptId: number,
|
||||
messageOpts: SaleReceiptMailOptsDTO,
|
||||
) {
|
||||
// Formats the message options.
|
||||
const formattedMessageOptions = await this.getFormatMailOptions(
|
||||
saleReceiptId,
|
||||
messageOpts,
|
||||
);
|
||||
const mail = new Mail()
|
||||
.setSubject(formattedMessageOptions.subject)
|
||||
.setTo(formattedMessageOptions.to)
|
||||
.setCC(formattedMessageOptions.cc)
|
||||
.setBCC(formattedMessageOptions.bcc)
|
||||
.setContent(formattedMessageOptions.message);
|
||||
|
||||
// const mailOptions =
|
||||
// await this.contactMailNotification.getDefaultMailOptions(
|
||||
// tenantId,
|
||||
// saleReceipt.customerId
|
||||
// );
|
||||
// return {
|
||||
// ...mailOptions,
|
||||
// message: DEFAULT_RECEIPT_MAIL_CONTENT,
|
||||
// subject: DEFAULT_RECEIPT_MAIL_SUBJECT,
|
||||
// attachReceipt: true,
|
||||
// formatArgs,
|
||||
// };
|
||||
// }
|
||||
// Attaches the receipt pdf document.
|
||||
if (formattedMessageOptions.attachReceipt) {
|
||||
// Retrieves document buffer of the receipt pdf document.
|
||||
const [receiptPdfBuffer, filename] =
|
||||
await this.receiptPdfService.saleReceiptPdf(saleReceiptId);
|
||||
|
||||
// /**
|
||||
// * Retrieves the formatted text of the given sale receipt.
|
||||
// * @param {number} tenantId - Tenant id.
|
||||
// * @param {number} receiptId - Sale receipt id.
|
||||
// * @param {string} text - The given text.
|
||||
// * @returns {Promise<string>}
|
||||
// */
|
||||
// public textFormatterArgs = async (
|
||||
// tenantId: number,
|
||||
// receiptId: number
|
||||
// ): Promise<Record<string, string>> => {
|
||||
// const receipt = await this.getSaleReceiptService.getSaleReceipt(
|
||||
// tenantId,
|
||||
// receiptId
|
||||
// );
|
||||
// return transformReceiptToMailDataArgs(receipt);
|
||||
// };
|
||||
mail.setAttachments([
|
||||
{ filename: `${filename}.pdf`, content: receiptPdfBuffer },
|
||||
]);
|
||||
}
|
||||
const eventPayload = {
|
||||
saleReceiptId,
|
||||
messageOptions: {},
|
||||
};
|
||||
await this.eventEmitter.emitAsync(
|
||||
events.saleReceipt.onMailSend,
|
||||
eventPayload,
|
||||
);
|
||||
await this.mailTransporter.send(mail);
|
||||
|
||||
// /**
|
||||
// * Formats the mail options of the given sale receipt.
|
||||
// * @param {number} tenantId
|
||||
// * @param {number} receiptId
|
||||
// * @param {SaleReceiptMailOpts} mailOptions
|
||||
// * @returns {Promise<SaleReceiptMailOpts>}
|
||||
// */
|
||||
// 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
|
||||
// );
|
||||
// // 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.
|
||||
// * @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(formattedMessageOptions.subject)
|
||||
// .setTo(formattedMessageOptions.to)
|
||||
// .setCC(formattedMessageOptions.cc)
|
||||
// .setBCC(formattedMessageOptions.bcc)
|
||||
// .setContent(formattedMessageOptions.message);
|
||||
|
||||
// // Attaches the receipt pdf document.
|
||||
// if (formattedMessageOptions.attachReceipt) {
|
||||
// // Retrieves document buffer of the receipt pdf document.
|
||||
// const [receiptPdfBuffer, filename] =
|
||||
// await this.receiptPdfService.saleReceiptPdf(tenantId, saleReceiptId);
|
||||
|
||||
// mail.setAttachments([
|
||||
// { filename: `${filename}.pdf`, content: receiptPdfBuffer },
|
||||
// ]);
|
||||
// }
|
||||
// const eventPayload = {
|
||||
// tenantId,
|
||||
// saleReceiptId,
|
||||
// messageOptions: {},
|
||||
// };
|
||||
// await this.eventPublisher.emitAsync(
|
||||
// events.saleReceipt.onMailSend,
|
||||
// eventPayload
|
||||
// );
|
||||
// await mail.send();
|
||||
|
||||
// await this.eventPublisher.emitAsync(
|
||||
// events.saleReceipt.onMailSent,
|
||||
// eventPayload
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
await this.eventEmitter.emitAsync(
|
||||
events.saleReceipt.onMailSent,
|
||||
eventPayload,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import * as R from 'ramda';
|
||||
import { SaleReceiptTransformer } from './SaleReceiptTransformer';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { SaleReceiptTransformer } from './SaleReceiptTransformer';
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
|
||||
import { IFilterMeta, IPaginationMeta } from '@/interfaces/Model';
|
||||
import { ISalesReceiptsFilter } from '../types/SaleReceipts.types';
|
||||
import { SaleReceipt } from '../models/SaleReceipt';
|
||||
import { IPaginationMeta } from '@/interfaces/Model';
|
||||
|
||||
interface GetSaleReceiptsSettings {
|
||||
fetchEntriesGraph?: boolean;
|
||||
@@ -22,8 +22,7 @@ export class GetSaleReceiptsService {
|
||||
|
||||
/**
|
||||
* Retrieve sales receipts paginated and filterable list.
|
||||
* @param {number} tenantId
|
||||
* @param {ISaleReceiptFilter} salesReceiptsFilter
|
||||
* @param {ISalesReceiptsFilter} salesReceiptsFilter - Sales receipts filter.
|
||||
*/
|
||||
public async getSaleReceipts(filterDTO: ISalesReceiptsFilter): Promise<{
|
||||
data: SaleReceipt[];
|
||||
|
||||
@@ -3,6 +3,8 @@ import { Knex } from 'knex';
|
||||
// import { CommonMailOptions, CommonMailOptionsDTO } from '../SaleInvoices/types/Mailable';
|
||||
import { AttachmentLinkDTO } from '../../Attachments/Attachments.types';
|
||||
import { SaleReceipt } from '../models/SaleReceipt';
|
||||
import { CommonMailOptionsDTO } from '@/modules/MailNotification/MailNotification.types';
|
||||
import { CommonMailOptions } from '@/modules/MailNotification/MailNotification.types';
|
||||
|
||||
export interface ISalesReceiptsFilter {
|
||||
filterQuery?: (query: any) => void;
|
||||
@@ -92,19 +94,19 @@ export interface ISaleReceiptDeletingPayload {
|
||||
trx: Knex.Transaction;
|
||||
}
|
||||
|
||||
// export interface SaleReceiptMailOpts extends CommonMailOptions {
|
||||
// attachReceipt: boolean;
|
||||
// }
|
||||
export interface SaleReceiptMailOpts extends CommonMailOptions {
|
||||
attachReceipt: boolean;
|
||||
}
|
||||
|
||||
// export interface SaleReceiptMailOptsDTO extends CommonMailOptionsDTO {
|
||||
// attachReceipt?: boolean;
|
||||
// }
|
||||
export interface SaleReceiptMailOptsDTO extends CommonMailOptionsDTO {
|
||||
attachReceipt?: boolean;
|
||||
}
|
||||
|
||||
// export interface ISaleReceiptMailPresend {
|
||||
// tenantId: number;
|
||||
// saleReceiptId: number;
|
||||
// messageOptions: SaleReceiptMailOptsDTO;
|
||||
// }
|
||||
export interface ISaleReceiptMailPresend {
|
||||
tenantId: number;
|
||||
saleReceiptId: number;
|
||||
messageOptions: SaleReceiptMailOptsDTO;
|
||||
}
|
||||
|
||||
export interface ISaleReceiptBrandingTemplateAttributes {
|
||||
primaryColor: string;
|
||||
@@ -162,7 +164,6 @@ export interface ISaleReceiptBrandingTemplateAttributes {
|
||||
receiptDateLabel: string;
|
||||
}
|
||||
|
||||
|
||||
export interface ISaleReceiptState {
|
||||
defaultTemplateId: number;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { VendorCreditsApplicationService } from './VendorCreditsApplication.serv
|
||||
import {
|
||||
IVendorCreditCreateDTO,
|
||||
IVendorCreditEditDTO,
|
||||
IVendorCreditsQueryDTO,
|
||||
} from './types/VendorCredit.types';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
|
||||
@@ -33,7 +34,7 @@ export class VendorCreditsController {
|
||||
}
|
||||
|
||||
@Get()
|
||||
async getVendorCredits(@Query() filterDTO: IVendorCreditsFilter) {
|
||||
async getVendorCredits(@Query() filterDTO: IVendorCreditsQueryDTO) {
|
||||
return this.vendorCreditsApplication.getVendorCredits(filterDTO);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CreateVendorCreditService } from './commands/CreateVendorCredit.service
|
||||
import { DeleteVendorCreditService } from './commands/DeleteVendorCredit.service';
|
||||
import { EditVendorCreditService } from './commands/EditVendorCredit.service';
|
||||
import { GetVendorCreditService } from './queries/GetVendorCredit.service';
|
||||
import { IVendorCreditEditDTO } from './types/VendorCredit.types';
|
||||
import { IVendorCreditEditDTO, IVendorCreditsQueryDTO } from './types/VendorCredit.types';
|
||||
import { IVendorCreditCreateDTO } from './types/VendorCredit.types';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { OpenVendorCreditService } from './commands/OpenVendorCredit.service';
|
||||
|
||||
@@ -4,6 +4,7 @@ import { VendorCreditTransformer } from './VendorCreditTransformer';
|
||||
import { DynamicListService } from '@/modules/DynamicListing/DynamicList.service';
|
||||
import { TransformerInjectable } from '@/modules/Transformer/TransformerInjectable.service';
|
||||
import { VendorCredit } from '../models/VendorCredit';
|
||||
import { IVendorCreditsQueryDTO } from '../types/VendorCredit.types';
|
||||
|
||||
@Injectable()
|
||||
export class GetVendorCreditsService {
|
||||
|
||||
@@ -38,7 +38,7 @@ export default class VendorCreditInventoryTransactionsSubscriber {
|
||||
*/
|
||||
@OnEvent(events.vendorCredit.onEdited)
|
||||
public async rewriteInventroyTransactionsOnceEdited({
|
||||
vendorCreditId,
|
||||
oldVendorCredit,
|
||||
vendorCredit,
|
||||
trx,
|
||||
}: IVendorCreditEditedPayload) {
|
||||
@@ -46,7 +46,7 @@ export default class VendorCreditInventoryTransactionsSubscriber {
|
||||
if (!vendorCredit.openedAt) return null;
|
||||
|
||||
await this.inventoryTransactions.editInventoryTransactions(
|
||||
vendorCreditId,
|
||||
oldVendorCredit.id,
|
||||
vendorCredit,
|
||||
trx,
|
||||
);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { AttachmentLinkDTO } from '@/modules/Attachments/Attachments.types';
|
||||
import { IRefundVendorCreditDTO } from '@/modules/VendorCreditsRefund/types/VendorCreditRefund.types';
|
||||
import { IItemEntryDTO } from '@/modules/TransactionItemEntry/ItemEntry.types';
|
||||
import { DiscountType } from '@/common/types/Discount';
|
||||
import { IDynamicListFilter } from '@/modules/DynamicListing/DynamicFilter/DynamicFilter.types';
|
||||
|
||||
export enum VendorCreditAction {
|
||||
Create = 'Create',
|
||||
@@ -15,12 +16,12 @@ export enum VendorCreditAction {
|
||||
|
||||
export interface IVendorCreditEntryDTO extends IItemEntryDTO {}
|
||||
|
||||
// export interface IVendorCreditsQueryDTO extends IDynamicListFilter {
|
||||
// page: number;
|
||||
// pageSize: number;
|
||||
// searchKeyword?: string;
|
||||
// filterQuery?: (q: any) => void;
|
||||
// }
|
||||
export interface IVendorCreditsQueryDTO extends IDynamicListFilter {
|
||||
page: number;
|
||||
pageSize: number;
|
||||
searchKeyword?: string;
|
||||
filterQuery?: (q: any) => void;
|
||||
}
|
||||
|
||||
export interface IVendorCreditDTO {
|
||||
vendorId: number;
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
IVendorEditDTO,
|
||||
IVendorNewDTO,
|
||||
IVendorOpeningBalanceEditDTO,
|
||||
IVendorsFilter,
|
||||
} from './types/Vendors.types';
|
||||
import { PublicRoute } from '../Auth/Jwt.guard';
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import fs from 'fs';
|
||||
import * as fs from 'fs';
|
||||
import Mustache from 'mustache';
|
||||
import { Container } from 'typedi';
|
||||
import path from 'path';
|
||||
import { IMailAttachment } from '@/interfaces';
|
||||
|
||||
@@ -40,23 +39,6 @@ export default class Mail {
|
||||
return this.view ? Mail.render(this.view, this.data) : this.content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the given mail to the target address.
|
||||
*/
|
||||
public send() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const Mail = Container.get('mail');
|
||||
|
||||
Mail.sendMail(this.mailOptions, (error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
return;
|
||||
}
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set send mail to address.
|
||||
* @param {string} to -
|
||||
|
||||
Reference in New Issue
Block a user