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