mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 07:10:33 +00:00
fix: sending mail jobs
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
import { JOB_REF, Process, Processor } from '@nestjs/bull';
|
import { JOB_REF, Process, Processor } from '@nestjs/bull';
|
||||||
import { Job } from 'bull';
|
import { Job } from 'bull';
|
||||||
|
import { Inject, Scope } from '@nestjs/common';
|
||||||
|
import { ClsService, UseCls } from 'nestjs-cls';
|
||||||
import {
|
import {
|
||||||
SEND_PAYMENT_RECEIVED_MAIL_JOB,
|
SEND_PAYMENT_RECEIVED_MAIL_JOB,
|
||||||
SEND_PAYMENT_RECEIVED_MAIL_QUEUE,
|
SEND_PAYMENT_RECEIVED_MAIL_QUEUE,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { Inject, Scope } from '@nestjs/common';
|
|
||||||
import { REQUEST } from '@nestjs/core';
|
|
||||||
import { ClsService } from 'nestjs-cls';
|
|
||||||
import { SendPaymentReceiveMailNotification } from '../commands/PaymentReceivedMailNotification';
|
import { SendPaymentReceiveMailNotification } from '../commands/PaymentReceivedMailNotification';
|
||||||
import { SendPaymentReceivedMailPayload } from '../types/PaymentReceived.types';
|
import { SendPaymentReceivedMailPayload } from '../types/PaymentReceived.types';
|
||||||
|
|
||||||
@@ -24,6 +23,7 @@ export class SendPaymentReceivedMailProcessor {
|
|||||||
) { }
|
) { }
|
||||||
|
|
||||||
@Process(SEND_PAYMENT_RECEIVED_MAIL_JOB)
|
@Process(SEND_PAYMENT_RECEIVED_MAIL_JOB)
|
||||||
|
@UseCls()
|
||||||
async handleSendMail() {
|
async handleSendMail() {
|
||||||
const { messageOptions, paymentReceivedId, organizationId, userId } =
|
const { messageOptions, paymentReceivedId, organizationId, userId } =
|
||||||
this.jobRef.data;
|
this.jobRef.data;
|
||||||
@@ -37,7 +37,8 @@ export class SendPaymentReceivedMailProcessor {
|
|||||||
messageOptions,
|
messageOptions,
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error('Failed to process payment received mail job:', error);
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import { GetSaleEstimateMailTemplateService } from './queries/GetSaleEstimateMai
|
|||||||
import { SaleEstimateAutoIncrementSubscriber } from './subscribers/SaleEstimateAutoIncrementSubscriber';
|
import { SaleEstimateAutoIncrementSubscriber } from './subscribers/SaleEstimateAutoIncrementSubscriber';
|
||||||
import { BulkDeleteSaleEstimatesService } from './BulkDeleteSaleEstimates.service';
|
import { BulkDeleteSaleEstimatesService } from './BulkDeleteSaleEstimates.service';
|
||||||
import { ValidateBulkDeleteSaleEstimatesService } from './ValidateBulkDeleteSaleEstimates.service';
|
import { ValidateBulkDeleteSaleEstimatesService } from './ValidateBulkDeleteSaleEstimates.service';
|
||||||
|
import { SendSaleEstimateMailProcess } from './processes/SendSaleEstimateMail.process';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -89,6 +90,7 @@ import { ValidateBulkDeleteSaleEstimatesService } from './ValidateBulkDeleteSale
|
|||||||
SaleEstimateAutoIncrementSubscriber,
|
SaleEstimateAutoIncrementSubscriber,
|
||||||
BulkDeleteSaleEstimatesService,
|
BulkDeleteSaleEstimatesService,
|
||||||
ValidateBulkDeleteSaleEstimatesService,
|
ValidateBulkDeleteSaleEstimatesService,
|
||||||
|
SendSaleEstimateMailProcess,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
SaleEstimatesExportable,
|
SaleEstimatesExportable,
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { Mail } from '@/modules/Mail/Mail';
|
|||||||
import { MailTransporter } from '@/modules/Mail/MailTransporter.service';
|
import { MailTransporter } from '@/modules/Mail/MailTransporter.service';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
import { GetSaleEstimateMailTemplateService } from '../queries/GetSaleEstimateMailTemplate.service';
|
import { GetSaleEstimateMailTemplateService } from '../queries/GetSaleEstimateMailTemplate.service';
|
||||||
|
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SendSaleEstimateMail {
|
export class SendSaleEstimateMail {
|
||||||
@@ -42,6 +43,7 @@ export class SendSaleEstimateMail {
|
|||||||
private readonly getEstimateMailTemplate: GetSaleEstimateMailTemplateService,
|
private readonly getEstimateMailTemplate: GetSaleEstimateMailTemplateService,
|
||||||
private readonly eventPublisher: EventEmitter2,
|
private readonly eventPublisher: EventEmitter2,
|
||||||
private readonly mailTransporter: MailTransporter,
|
private readonly mailTransporter: MailTransporter,
|
||||||
|
private readonly tenancyContext: TenancyContext,
|
||||||
|
|
||||||
@Inject(SaleEstimate.name)
|
@Inject(SaleEstimate.name)
|
||||||
private readonly saleEstimateModel: TenantModelProxy<typeof SaleEstimate>,
|
private readonly saleEstimateModel: TenantModelProxy<typeof SaleEstimate>,
|
||||||
@@ -60,10 +62,19 @@ export class SendSaleEstimateMail {
|
|||||||
saleEstimateId: number,
|
saleEstimateId: number,
|
||||||
messageOptions: SaleEstimateMailOptionsDTO,
|
messageOptions: SaleEstimateMailOptionsDTO,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
const tenant = await this.tenancyContext.getTenant();
|
||||||
|
const user = await this.tenancyContext.getSystemUser();
|
||||||
|
|
||||||
|
const organizationId = tenant.organizationId;
|
||||||
|
const userId = user.id;
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
saleEstimateId,
|
saleEstimateId,
|
||||||
messageOptions,
|
messageOptions,
|
||||||
|
userId,
|
||||||
|
organizationId,
|
||||||
};
|
};
|
||||||
|
|
||||||
await this.sendEstimateMailQueue.add(SendSaleEstimateMailJob, payload);
|
await this.sendEstimateMailQueue.add(SendSaleEstimateMailJob, payload);
|
||||||
|
|
||||||
// Triggers `onSaleEstimatePreMailSend` event.
|
// Triggers `onSaleEstimatePreMailSend` event.
|
||||||
|
|||||||
@@ -1,19 +1,39 @@
|
|||||||
import { Process, Processor } from '@nestjs/bull';
|
import { Process, Processor } from '@nestjs/bull';
|
||||||
import { Job } from 'bull';
|
import { Job } from 'bull';
|
||||||
|
import { Inject, Scope } from '@nestjs/common';
|
||||||
|
import { JOB_REF } from '@nestjs/bull';
|
||||||
import {
|
import {
|
||||||
SendSaleEstimateMailJob,
|
SendSaleEstimateMailJob,
|
||||||
SendSaleEstimateMailQueue,
|
SendSaleEstimateMailQueue,
|
||||||
} from '../types/SaleEstimates.types';
|
} from '../types/SaleEstimates.types';
|
||||||
import { SendSaleEstimateMail } from '../commands/SendSaleEstimateMail';
|
import { SendSaleEstimateMail } from '../commands/SendSaleEstimateMail';
|
||||||
|
import { ClsService, UseCls } from 'nestjs-cls';
|
||||||
|
|
||||||
@Processor(SendSaleEstimateMailQueue)
|
@Processor({
|
||||||
|
name: SendSaleEstimateMailQueue,
|
||||||
|
scope: Scope.REQUEST,
|
||||||
|
})
|
||||||
export class SendSaleEstimateMailProcess {
|
export class SendSaleEstimateMailProcess {
|
||||||
constructor(private readonly sendEstimateMailService: SendSaleEstimateMail) {}
|
constructor(
|
||||||
|
private readonly sendEstimateMailService: SendSaleEstimateMail,
|
||||||
|
private readonly clsService: ClsService,
|
||||||
|
@Inject(JOB_REF)
|
||||||
|
private readonly jobRef: Job,
|
||||||
|
) { }
|
||||||
|
|
||||||
@Process(SendSaleEstimateMailJob)
|
@Process(SendSaleEstimateMailJob)
|
||||||
async handleSendMail(job: Job) {
|
@UseCls()
|
||||||
const { saleEstimateId, messageOptions } = job.data;
|
async handleSendMail() {
|
||||||
|
const { saleEstimateId, messageOptions, organizationId, userId } = this.jobRef.data;
|
||||||
|
|
||||||
|
this.clsService.set('organizationId', organizationId);
|
||||||
|
this.clsService.set('userId', userId);
|
||||||
|
|
||||||
|
try {
|
||||||
await this.sendEstimateMailService.sendMail(saleEstimateId, messageOptions);
|
await this.sendEstimateMailService.sendMail(saleEstimateId, messageOptions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to process estimate mail job:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ export class SaleInvoicesController {
|
|||||||
return this.saleInvoiceApplication.createSaleInvoice(saleInvoiceDTO);
|
return this.saleInvoiceApplication.createSaleInvoice(saleInvoiceDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id/mail')
|
@Post(':id/mail')
|
||||||
|
@HttpCode(200)
|
||||||
@ApiOperation({ summary: 'Send the sale invoice mail.' })
|
@ApiOperation({ summary: 'Send the sale invoice mail.' })
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
|
|||||||
@@ -132,7 +132,13 @@ export class SendSaleInvoiceMail {
|
|||||||
events.saleInvoice.onMailSend,
|
events.saleInvoice.onMailSend,
|
||||||
eventPayload,
|
eventPayload,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
await this.mailTransporter.send(mail);
|
await this.mailTransporter.send(mail);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to send invoice mail:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
// Triggers the event `onSaleInvoiceSend`.
|
// Triggers the event `onSaleInvoiceSend`.
|
||||||
await this.eventEmitter.emitAsync(
|
await this.eventEmitter.emitAsync(
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export class SendSaleInvoiceMailProcessor {
|
|||||||
) { }
|
) { }
|
||||||
|
|
||||||
@Process(SendSaleInvoiceMailJob)
|
@Process(SendSaleInvoiceMailJob)
|
||||||
|
@UseCls()
|
||||||
async handleSendInvoice() {
|
async handleSendInvoice() {
|
||||||
const { messageOptions, saleInvoiceId, organizationId, userId } =
|
const { messageOptions, saleInvoiceId, organizationId, userId } =
|
||||||
this.jobRef.data;
|
this.jobRef.data;
|
||||||
@@ -31,7 +32,8 @@ export class SendSaleInvoiceMailProcessor {
|
|||||||
try {
|
try {
|
||||||
await this.sendSaleInvoiceMail.sendMail(saleInvoiceId, messageOptions);
|
await this.sendSaleInvoiceMail.sendMail(saleInvoiceId, messageOptions);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error('Failed to process invoice mail job:', error);
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,10 @@ import {
|
|||||||
CreateSaleReceiptDto,
|
CreateSaleReceiptDto,
|
||||||
EditSaleReceiptDto,
|
EditSaleReceiptDto,
|
||||||
} from './dtos/SaleReceipt.dto';
|
} from './dtos/SaleReceipt.dto';
|
||||||
import { ISalesReceiptsFilter } from './types/SaleReceipts.types';
|
import {
|
||||||
|
ISalesReceiptsFilter,
|
||||||
|
SaleReceiptMailOptsDTO,
|
||||||
|
} from './types/SaleReceipts.types';
|
||||||
import { AcceptType } from '@/constants/accept-type';
|
import { AcceptType } from '@/constants/accept-type';
|
||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { SaleReceiptResponseDto } from './dtos/SaleReceiptResponse.dto';
|
import { SaleReceiptResponseDto } from './dtos/SaleReceiptResponse.dto';
|
||||||
@@ -87,7 +90,7 @@ export class SaleReceiptsController {
|
|||||||
return this.saleReceiptApplication.createSaleReceipt(saleReceiptDTO);
|
return this.saleReceiptApplication.createSaleReceipt(saleReceiptDTO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id/mail')
|
@Post(':id/mail')
|
||||||
@HttpCode(200)
|
@HttpCode(200)
|
||||||
@ApiOperation({ summary: 'Send the sale receipt mail.' })
|
@ApiOperation({ summary: 'Send the sale receipt mail.' })
|
||||||
@ApiParam({
|
@ApiParam({
|
||||||
@@ -96,8 +99,11 @@ export class SaleReceiptsController {
|
|||||||
type: Number,
|
type: Number,
|
||||||
description: 'The sale receipt id',
|
description: 'The sale receipt id',
|
||||||
})
|
})
|
||||||
sendSaleReceiptMail(@Param('id', ParseIntPipe) id: number) {
|
sendSaleReceiptMail(
|
||||||
return this.saleReceiptApplication.getSaleReceiptMail(id);
|
@Param('id', ParseIntPipe) id: number,
|
||||||
|
@Body() messageOpts: SaleReceiptMailOptsDTO,
|
||||||
|
) {
|
||||||
|
return this.saleReceiptApplication.sendSaleReceiptMail(id, messageOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('state')
|
@Get('state')
|
||||||
|
|||||||
@@ -1,24 +1,42 @@
|
|||||||
import { Process, Processor } from '@nestjs/bull';
|
import { Process, Processor } from '@nestjs/bull';
|
||||||
import { Job } from 'bull';
|
import { Job } from 'bull';
|
||||||
import { SendSaleReceiptMailQueue } from '../constants';
|
import { Inject, Scope } from '@nestjs/common';
|
||||||
|
import { JOB_REF } from '@nestjs/bull';
|
||||||
|
import { SendSaleReceiptMailQueue, SendSaleReceiptMailJob } from '../constants';
|
||||||
import { SaleReceiptMailNotification } from '../commands/SaleReceiptMailNotification';
|
import { SaleReceiptMailNotification } from '../commands/SaleReceiptMailNotification';
|
||||||
import { SaleReceiptSendMailPayload } from '../types/SaleReceipts.types';
|
import { SaleReceiptSendMailPayload } from '../types/SaleReceipts.types';
|
||||||
import { ClsService } from 'nestjs-cls';
|
import { ClsService, UseCls } from 'nestjs-cls';
|
||||||
|
|
||||||
@Processor(SendSaleReceiptMailQueue)
|
@Processor({
|
||||||
|
name: SendSaleReceiptMailQueue,
|
||||||
|
scope: Scope.REQUEST,
|
||||||
|
})
|
||||||
export class SendSaleReceiptMailProcess {
|
export class SendSaleReceiptMailProcess {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly saleReceiptMailNotification: SaleReceiptMailNotification,
|
private readonly saleReceiptMailNotification: SaleReceiptMailNotification,
|
||||||
private readonly clsService: ClsService,
|
private readonly clsService: ClsService,
|
||||||
|
|
||||||
|
@Inject(JOB_REF)
|
||||||
|
private readonly jobRef: Job<SaleReceiptSendMailPayload>,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@Process(SendSaleReceiptMailQueue)
|
@Process(SendSaleReceiptMailJob)
|
||||||
async handleSendMailJob(job: Job<SaleReceiptSendMailPayload>) {
|
@UseCls()
|
||||||
const { messageOpts, saleReceiptId, organizationId, userId } = job.data;
|
async handleSendMailJob() {
|
||||||
|
const { messageOpts, saleReceiptId, organizationId, userId } =
|
||||||
|
this.jobRef.data;
|
||||||
|
|
||||||
this.clsService.set('organizationId', organizationId);
|
this.clsService.set('organizationId', organizationId);
|
||||||
this.clsService.set('userId', userId);
|
this.clsService.set('userId', userId);
|
||||||
|
|
||||||
await this.saleReceiptMailNotification.sendMail(saleReceiptId, messageOpts);
|
try {
|
||||||
|
await this.saleReceiptMailNotification.sendMail(
|
||||||
|
saleReceiptId,
|
||||||
|
messageOpts,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to process receipt mail job:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export class SendInviteUserMailProcessor {
|
|||||||
) { }
|
) { }
|
||||||
|
|
||||||
@Process(SendInviteUserMailJob)
|
@Process(SendInviteUserMailJob)
|
||||||
|
@UseCls()
|
||||||
async handleSendInviteMail() {
|
async handleSendInviteMail() {
|
||||||
const { fromUser, invite, organizationId, userId } = this.jobRef.data;
|
const { fromUser, invite, organizationId, userId } = this.jobRef.data;
|
||||||
|
|
||||||
@@ -33,7 +34,8 @@ export class SendInviteUserMailProcessor {
|
|||||||
try {
|
try {
|
||||||
await this.sendInviteUsersMailService.sendInviteMail(fromUser, invite);
|
await this.sendInviteUsersMailService.sendInviteMail(fromUser, invite);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error('Failed to process invite user mail job:', error);
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ describe('Sale Invoices (e2e)', () => {
|
|||||||
.send(requestSaleInvoiceBody());
|
.send(requestSaleInvoiceBody());
|
||||||
|
|
||||||
return request(app.getHttpServer())
|
return request(app.getHttpServer())
|
||||||
.put(`/sale-invoices/${response.body.id}/mail`)
|
.post(`/sale-invoices/${response.body.id}/mail`)
|
||||||
.set('organization-id', orgainzationId)
|
.set('organization-id', orgainzationId)
|
||||||
.set('Authorization', AuthorizationHeader)
|
.set('Authorization', AuthorizationHeader)
|
||||||
.send({
|
.send({
|
||||||
|
|||||||
Reference in New Issue
Block a user