chore: fix the send email problem
This commit is contained in:
@@ -20,7 +20,7 @@ export function mailerConfig(): MailerAsyncOptions {
|
|||||||
},
|
},
|
||||||
|
|
||||||
template: {
|
template: {
|
||||||
dir: process.cwd() + "/src/templates/email",
|
dir: process.cwd() + "/src/modules/templates/email",
|
||||||
adapter: new HandlebarsAdapter(),
|
adapter: new HandlebarsAdapter(),
|
||||||
options: {
|
options: {
|
||||||
strict: true,
|
strict: true,
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { AdminsService } from "../../users/providers/admins.service";
|
|||||||
import { UsersService } from "../../users/providers/users.service";
|
import { UsersService } from "../../users/providers/users.service";
|
||||||
import { OTPService } from "../../utils/providers/otp.service";
|
import { OTPService } from "../../utils/providers/otp.service";
|
||||||
import { PasswordService } from "../../utils/providers/password.service";
|
import { PasswordService } from "../../utils/providers/password.service";
|
||||||
import { SmsService } from "../../utils/providers/sms.service";
|
|
||||||
import { ChangePasswordDto } from "../DTO/change-password.dto";
|
import { ChangePasswordDto } from "../DTO/change-password.dto";
|
||||||
import { CompleteRegistrationDto } from "../DTO/complete-register.dto";
|
import { CompleteRegistrationDto } from "../DTO/complete-register.dto";
|
||||||
import { CheckUserExistDto, LoginPasswordDTO } from "../DTO/loginPassword.dto";
|
import { CheckUserExistDto, LoginPasswordDTO } from "../DTO/loginPassword.dto";
|
||||||
@@ -26,7 +25,6 @@ export class AuthService {
|
|||||||
private readonly tokensService: TokensService,
|
private readonly tokensService: TokensService,
|
||||||
private readonly dataSource: DataSource,
|
private readonly dataSource: DataSource,
|
||||||
private readonly notificationQueue: NotificationQueue,
|
private readonly notificationQueue: NotificationQueue,
|
||||||
private readonly smsService: SmsService,
|
|
||||||
private readonly referralsService: ReferralsService,
|
private readonly referralsService: ReferralsService,
|
||||||
) {}
|
) {}
|
||||||
//****************** */
|
//****************** */
|
||||||
@@ -45,7 +43,8 @@ export class AuthService {
|
|||||||
}
|
}
|
||||||
const otpCode = await this.otpService.generateAndSetInCache(phone, "REGISTER");
|
const otpCode = await this.otpService.generateAndSetInCache(phone, "REGISTER");
|
||||||
//
|
//
|
||||||
await this.smsService.sendSmsVerifyCode(phone, otpCode);
|
// await this.smsService.sendSmsVerifyCode(phone, otpCode);
|
||||||
|
await this.notificationQueue.addLoginOtpNotification({ phone, code: otpCode });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: AuthMessage.OTP_SENT,
|
message: AuthMessage.OTP_SENT,
|
||||||
@@ -169,7 +168,8 @@ export class AuthService {
|
|||||||
|
|
||||||
const otpCode = await this.otpService.generateAndSetInCache(phone, "LOGIN");
|
const otpCode = await this.otpService.generateAndSetInCache(phone, "LOGIN");
|
||||||
//
|
//
|
||||||
await this.smsService.sendSmsVerifyCode(phone, otpCode);
|
// await this.smsService.sendSmsVerifyCode(phone, otpCode);
|
||||||
|
await this.notificationQueue.addLoginOtpNotification({ phone, code: otpCode });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: AuthMessage.OTP_SENT,
|
message: AuthMessage.OTP_SENT,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export const NOTIFICATION = Object.freeze({
|
export const NOTIFICATION = Object.freeze({
|
||||||
QUEUE_NAME: "notification",
|
QUEUE_NAME: "notification",
|
||||||
SEND_NOTIFICATION_JOB_NAME: "sendNotification",
|
SEND_NOTIFICATION_JOB_NAME: "sendNotification",
|
||||||
|
SEND_LOGIN_OTP_JOB_NAME: "sendLoginOtp",
|
||||||
|
|
||||||
SEND_NOTIFICATION_JOB_DELAY: 1000, // delay after 1 second
|
SEND_NOTIFICATION_JOB_DELAY: 1000, // delay after 1 second
|
||||||
SEND_NOTIFICATION_JOB_PRIORITY: 1, // high priority
|
SEND_NOTIFICATION_JOB_PRIORITY: 1, // high priority
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
IAnnouncementNotificationData,
|
||||||
|
IBlogCommentNotificationData,
|
||||||
|
IInvoiceNotificationData,
|
||||||
|
INewCriticismNotificationData,
|
||||||
|
INewCustomerNotificationData,
|
||||||
|
INewSubscriptionNotificationData,
|
||||||
|
INewTicketNotificationData,
|
||||||
|
IPaymentNotificationData,
|
||||||
|
IServiceReviewNotificationData,
|
||||||
|
ISubscriptionNotificationData,
|
||||||
|
ITicketNotificationData,
|
||||||
|
IWalletNotificationData,
|
||||||
|
} from "./ISendNotificationData";
|
||||||
|
import { NotifType } from "../../settings/enums/notif-settings.enum";
|
||||||
|
|
||||||
|
export type NotificationJobData = {
|
||||||
|
type: NotifType;
|
||||||
|
recipientId: string;
|
||||||
|
data:
|
||||||
|
| IBlogCommentNotificationData
|
||||||
|
| IServiceReviewNotificationData
|
||||||
|
| INewCustomerNotificationData
|
||||||
|
| INewSubscriptionNotificationData
|
||||||
|
| ITicketNotificationData
|
||||||
|
| INewCriticismNotificationData
|
||||||
|
| IInvoiceNotificationData
|
||||||
|
| IAnnouncementNotificationData
|
||||||
|
| IWalletNotificationData
|
||||||
|
| ISubscriptionNotificationData
|
||||||
|
| IPaymentNotificationData
|
||||||
|
| INewTicketNotificationData;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type OtpJobData = {
|
||||||
|
phone: string;
|
||||||
|
code: string;
|
||||||
|
};
|
||||||
@@ -6,7 +6,9 @@ import { DataSource } from "typeorm";
|
|||||||
import { WorkerProcessor } from "../../../common/queues/worker.processor";
|
import { WorkerProcessor } from "../../../common/queues/worker.processor";
|
||||||
import { LoggerService } from "../../logger/logger.service";
|
import { LoggerService } from "../../logger/logger.service";
|
||||||
import { NotifType } from "../../settings/enums/notif-settings.enum";
|
import { NotifType } from "../../settings/enums/notif-settings.enum";
|
||||||
|
import { SmsService } from "../../utils/providers/sms.service";
|
||||||
import { NOTIFICATION } from "../constants";
|
import { NOTIFICATION } from "../constants";
|
||||||
|
import { NotificationJobData, OtpJobData } from "../interfaces/INotification-job-data";
|
||||||
import {
|
import {
|
||||||
IAnnouncementNotificationData,
|
IAnnouncementNotificationData,
|
||||||
IBlogCommentNotificationData,
|
IBlogCommentNotificationData,
|
||||||
@@ -23,24 +25,6 @@ import {
|
|||||||
} from "../interfaces/ISendNotificationData";
|
} from "../interfaces/ISendNotificationData";
|
||||||
import { NotificationsService } from "../providers/notifications.service";
|
import { NotificationsService } from "../providers/notifications.service";
|
||||||
|
|
||||||
type NotificationJobData = {
|
|
||||||
type: NotifType;
|
|
||||||
recipientId: string;
|
|
||||||
data:
|
|
||||||
| IBlogCommentNotificationData
|
|
||||||
| IServiceReviewNotificationData
|
|
||||||
| INewCustomerNotificationData
|
|
||||||
| INewSubscriptionNotificationData
|
|
||||||
| ITicketNotificationData
|
|
||||||
| INewCriticismNotificationData
|
|
||||||
| IInvoiceNotificationData
|
|
||||||
| IAnnouncementNotificationData
|
|
||||||
| IWalletNotificationData
|
|
||||||
| ISubscriptionNotificationData
|
|
||||||
| IPaymentNotificationData
|
|
||||||
| INewTicketNotificationData;
|
|
||||||
};
|
|
||||||
|
|
||||||
@Processor(NOTIFICATION.QUEUE_NAME, {
|
@Processor(NOTIFICATION.QUEUE_NAME, {
|
||||||
concurrency: NOTIFICATION.SEND_NOTIFICATION_JOB_CONCURRENCY,
|
concurrency: NOTIFICATION.SEND_NOTIFICATION_JOB_CONCURRENCY,
|
||||||
lockDuration: NOTIFICATION.SEND_NOTIFICATION_JOB_LOCK_DURATION,
|
lockDuration: NOTIFICATION.SEND_NOTIFICATION_JOB_LOCK_DURATION,
|
||||||
@@ -54,11 +38,12 @@ export class NotificationProcessor extends WorkerProcessor {
|
|||||||
private readonly notificationsService: NotificationsService,
|
private readonly notificationsService: NotificationsService,
|
||||||
private readonly dataSource: DataSource,
|
private readonly dataSource: DataSource,
|
||||||
protected readonly loggerService: LoggerService,
|
protected readonly loggerService: LoggerService,
|
||||||
|
private readonly smsService: SmsService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
async process(job: Job<NotificationJobData>, token?: string) {
|
async process(job: Job<NotificationJobData | OtpJobData>, token?: string) {
|
||||||
this.logger.log(`Processing notification job: ${job.id} ${token ? `with token: ${token}` : ""}`);
|
this.logger.log(`Processing notification job: ${job.id} ${token ? `with token: ${token}` : ""}`);
|
||||||
const queryRunner = this.dataSource.createQueryRunner();
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
let heartbeat: NodeJS.Timeout | undefined;
|
let heartbeat: NodeJS.Timeout | undefined;
|
||||||
@@ -71,91 +56,115 @@ export class NotificationProcessor extends WorkerProcessor {
|
|||||||
heartbeat = setInterval(() => job.updateProgress(50), 10000);
|
heartbeat = setInterval(() => job.updateProgress(50), 10000);
|
||||||
|
|
||||||
//
|
//
|
||||||
const { type, recipientId, data } = job.data;
|
if (job.name === NOTIFICATION.SEND_LOGIN_OTP_JOB_NAME) {
|
||||||
switch (type) {
|
const { phone, code } = job.data as OtpJobData;
|
||||||
// Admin Notifications
|
await this.smsService.sendSmsVerifyCode(phone, code);
|
||||||
case NotifType.NEW_BLOG_COMMENT:
|
//
|
||||||
await this.notificationsService.createNewBlogCommentNotification(recipientId, data as IBlogCommentNotificationData, queryRunner);
|
} else if (job.name === NOTIFICATION.SEND_NOTIFICATION_JOB_NAME) {
|
||||||
break;
|
const { type, recipientId, data } = job.data as NotificationJobData;
|
||||||
case NotifType.NEW_SERVICE_REVIEW:
|
switch (type) {
|
||||||
await this.notificationsService.createNewServiceReviewNotification(
|
// Admin Notifications
|
||||||
recipientId,
|
case NotifType.NEW_BLOG_COMMENT:
|
||||||
data as IServiceReviewNotificationData,
|
await this.notificationsService.createNewBlogCommentNotification(
|
||||||
queryRunner,
|
recipientId,
|
||||||
);
|
data as IBlogCommentNotificationData,
|
||||||
break;
|
queryRunner,
|
||||||
case NotifType.NEW_CUSTOMER:
|
);
|
||||||
await this.notificationsService.createNewCustomerNotification(recipientId, data as INewCustomerNotificationData, queryRunner);
|
break;
|
||||||
break;
|
case NotifType.NEW_SERVICE_REVIEW:
|
||||||
case NotifType.NEW_SUBSCRIPTION:
|
await this.notificationsService.createNewServiceReviewNotification(
|
||||||
await this.notificationsService.createNewSubscriptionNotification(
|
recipientId,
|
||||||
recipientId,
|
data as IServiceReviewNotificationData,
|
||||||
data as INewSubscriptionNotificationData,
|
queryRunner,
|
||||||
queryRunner,
|
);
|
||||||
);
|
break;
|
||||||
break;
|
case NotifType.NEW_CUSTOMER:
|
||||||
case NotifType.NEW_CRITICISM:
|
await this.notificationsService.createNewCustomerNotification(recipientId, data as INewCustomerNotificationData, queryRunner);
|
||||||
await this.notificationsService.createNewCriticismNotification(recipientId, data as INewCriticismNotificationData, queryRunner);
|
break;
|
||||||
break;
|
case NotifType.NEW_SUBSCRIPTION:
|
||||||
case NotifType.NEW_TICKET:
|
await this.notificationsService.createNewSubscriptionNotification(
|
||||||
await this.notificationsService.createNewTicketGlobalNotification(recipientId, data as INewTicketNotificationData, queryRunner);
|
recipientId,
|
||||||
break;
|
data as INewSubscriptionNotificationData,
|
||||||
// User Notifications
|
queryRunner,
|
||||||
case NotifType.USER_LOGIN:
|
);
|
||||||
await this.notificationsService.createLoginNotification(recipientId, data);
|
break;
|
||||||
break;
|
case NotifType.NEW_CRITICISM:
|
||||||
case NotifType.ANNOUNCEMENT:
|
await this.notificationsService.createNewCriticismNotification(recipientId, data as INewCriticismNotificationData, queryRunner);
|
||||||
await this.notificationsService.createAnnouncementNotification(recipientId, data as IAnnouncementNotificationData, queryRunner);
|
break;
|
||||||
break;
|
case NotifType.NEW_TICKET:
|
||||||
// Wallet Notifications
|
await this.notificationsService.createNewTicketGlobalNotification(recipientId, data as INewTicketNotificationData, queryRunner);
|
||||||
case NotifType.WALLET_CHARGE:
|
break;
|
||||||
await this.notificationsService.createWalletChargeNotification(recipientId, data as IWalletNotificationData, queryRunner);
|
// User Notifications
|
||||||
break;
|
case NotifType.USER_LOGIN:
|
||||||
case NotifType.WALLET_DEDUCTION:
|
await this.notificationsService.createLoginNotification(recipientId, data);
|
||||||
await this.notificationsService.createWalletDeductionNotification(recipientId, data as IWalletNotificationData, queryRunner);
|
break;
|
||||||
break;
|
case NotifType.ANNOUNCEMENT:
|
||||||
// Ticket Notifications
|
await this.notificationsService.createAnnouncementNotification(recipientId, data as IAnnouncementNotificationData, queryRunner);
|
||||||
case NotifType.ANSWER_TICKET:
|
break;
|
||||||
await this.notificationsService.createAnswerTicketNotification(recipientId, data as ITicketNotificationData, queryRunner);
|
// Wallet Notifications
|
||||||
break;
|
case NotifType.WALLET_CHARGE:
|
||||||
case NotifType.CREATE_TICKET:
|
await this.notificationsService.createWalletChargeNotification(recipientId, data as IWalletNotificationData, queryRunner);
|
||||||
await this.notificationsService.createTicketNotification(recipientId, data as ITicketNotificationData, queryRunner);
|
break;
|
||||||
break;
|
case NotifType.WALLET_DEDUCTION:
|
||||||
case NotifType.ASSIGN_TICKET:
|
await this.notificationsService.createWalletDeductionNotification(recipientId, data as IWalletNotificationData, queryRunner);
|
||||||
await this.notificationsService.createAssignTicketNotificationForAdmin(recipientId, data as ITicketNotificationData, queryRunner);
|
break;
|
||||||
break;
|
// Ticket Notifications
|
||||||
// Invoice Notifications
|
case NotifType.ANSWER_TICKET:
|
||||||
case NotifType.CREATE_INVOICE:
|
await this.notificationsService.createAnswerTicketNotification(recipientId, data as ITicketNotificationData, queryRunner);
|
||||||
await this.notificationsService.createInvoiceCreationNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
break;
|
||||||
break;
|
case NotifType.CREATE_TICKET:
|
||||||
case NotifType.BILL_INVOICE_REMINDER:
|
await this.notificationsService.createTicketNotification(recipientId, data as ITicketNotificationData, queryRunner);
|
||||||
await this.notificationsService.createBillInvoiceReminderNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
break;
|
||||||
break;
|
case NotifType.ASSIGN_TICKET:
|
||||||
case NotifType.BILL_INVOICE:
|
await this.notificationsService.createAssignTicketNotificationForAdmin(
|
||||||
await this.notificationsService.createBillInvoiceNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
recipientId,
|
||||||
break;
|
data as ITicketNotificationData,
|
||||||
case NotifType.APPROVE_INVOICE:
|
queryRunner,
|
||||||
await this.notificationsService.createApprovedInvoiceNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
);
|
||||||
break;
|
break;
|
||||||
case NotifType.INVOICE_OVERDUE:
|
// Invoice Notifications
|
||||||
await this.notificationsService.createInvoiceOverdueNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
case NotifType.CREATE_INVOICE:
|
||||||
break;
|
await this.notificationsService.createInvoiceCreationNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
||||||
case NotifType.RECURRING_INVOICE:
|
break;
|
||||||
await this.notificationsService.createRecurringInvoiceNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
case NotifType.BILL_INVOICE_REMINDER:
|
||||||
break;
|
await this.notificationsService.createBillInvoiceReminderNotification(
|
||||||
// Service Notifications
|
recipientId,
|
||||||
case NotifType.BLOCK_SERVICE:
|
data as IInvoiceNotificationData,
|
||||||
await this.notificationsService.createBlockServiceNotification(recipientId, data as ISubscriptionNotificationData, queryRunner);
|
queryRunner,
|
||||||
break;
|
);
|
||||||
// Payment Notifications
|
break;
|
||||||
case NotifType.PAYMENT_REMINDER:
|
case NotifType.BILL_INVOICE:
|
||||||
await this.notificationsService.createPaymentReminderNotification(recipientId, data as IPaymentNotificationData, queryRunner);
|
await this.notificationsService.createBillInvoiceNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
||||||
break;
|
break;
|
||||||
case NotifType.PAYMENT_CANCELLATION:
|
case NotifType.APPROVE_INVOICE:
|
||||||
await this.notificationsService.createPaymentCancellationNotification(recipientId, data as IPaymentNotificationData, queryRunner);
|
await this.notificationsService.createApprovedInvoiceNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
||||||
break;
|
break;
|
||||||
default:
|
case NotifType.INVOICE_OVERDUE:
|
||||||
this.logger.warn(`Unknown notification type: ${type}`);
|
await this.notificationsService.createInvoiceOverdueNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
||||||
|
break;
|
||||||
|
case NotifType.RECURRING_INVOICE:
|
||||||
|
await this.notificationsService.createRecurringInvoiceNotification(recipientId, data as IInvoiceNotificationData, queryRunner);
|
||||||
|
break;
|
||||||
|
// Service Notifications
|
||||||
|
case NotifType.BLOCK_SERVICE:
|
||||||
|
await this.notificationsService.createBlockServiceNotification(recipientId, data as ISubscriptionNotificationData, queryRunner);
|
||||||
|
break;
|
||||||
|
// Payment Notifications
|
||||||
|
case NotifType.PAYMENT_REMINDER:
|
||||||
|
await this.notificationsService.createPaymentReminderNotification(recipientId, data as IPaymentNotificationData, queryRunner);
|
||||||
|
break;
|
||||||
|
case NotifType.PAYMENT_CANCELLATION:
|
||||||
|
await this.notificationsService.createPaymentCancellationNotification(
|
||||||
|
recipientId,
|
||||||
|
data as IPaymentNotificationData,
|
||||||
|
queryRunner,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.logger.warn(`Unknown notification type: ${type}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.logger.warn(`Unknown job name: ${job.name}`);
|
||||||
}
|
}
|
||||||
await queryRunner.commitTransaction();
|
await queryRunner.commitTransaction();
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -44,6 +44,18 @@ export class NotificationQueue {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//*********************************** */
|
||||||
|
async addLoginOtpNotification(data: { phone: string; code: string }) {
|
||||||
|
await this.notificationsQueue.add(NOTIFICATION.SEND_LOGIN_OTP_JOB_NAME, data, {
|
||||||
|
delay: NOTIFICATION.SEND_NOTIFICATION_JOB_DELAY,
|
||||||
|
attempts: NOTIFICATION.SEND_NOTIFICATION_JOB_ATTEMPTS,
|
||||||
|
backoff: {
|
||||||
|
type: "exponential",
|
||||||
|
delay: NOTIFICATION.SEND_NOTIFICATION_JOB_BACKOFF,
|
||||||
|
},
|
||||||
|
priority: NOTIFICATION.SEND_NOTIFICATION_JOB_PRIORITY,
|
||||||
|
});
|
||||||
|
}
|
||||||
// Admin notification methods
|
// Admin notification methods
|
||||||
async addNewBlogCommentNotification(recipientId: string, data: IBlogCommentNotificationData) {
|
async addNewBlogCommentNotification(recipientId: string, data: IBlogCommentNotificationData) {
|
||||||
await this.addNotificationJob(NotifType.NEW_BLOG_COMMENT, recipientId, data);
|
await this.addNotificationJob(NotifType.NEW_BLOG_COMMENT, recipientId, data);
|
||||||
@@ -78,8 +90,6 @@ export class NotificationQueue {
|
|||||||
await this.addNotificationJob(NotifType.CREATE_INVOICE, recipientId, data);
|
await this.addNotificationJob(NotifType.CREATE_INVOICE, recipientId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO:USE THIS
|
|
||||||
|
|
||||||
async addAnnouncementNotification(recipientId: string, data: IAnnouncementNotificationData) {
|
async addAnnouncementNotification(recipientId: string, data: IAnnouncementNotificationData) {
|
||||||
await this.addNotificationJob(NotifType.ANNOUNCEMENT, recipientId, data);
|
await this.addNotificationJob(NotifType.ANNOUNCEMENT, recipientId, data);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user