sms logs
This commit is contained in:
@@ -12,6 +12,7 @@ import { MikroOrmModule } from '@mikro-orm/nestjs';
|
|||||||
import { User } from '../users/entities/user.entity';
|
import { User } from '../users/entities/user.entity';
|
||||||
import { AdminAuthGuard } from './guards/adminAuth.guard';
|
import { AdminAuthGuard } from './guards/adminAuth.guard';
|
||||||
import { RefreshToken } from './entities/refresh-token.entity';
|
import { RefreshToken } from './entities/refresh-token.entity';
|
||||||
|
import { NotificationsModule } from '../notifications/notifications.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -34,6 +35,8 @@ import { RefreshToken } from './entities/refresh-token.entity';
|
|||||||
forwardRef(() => AdminModule),
|
forwardRef(() => AdminModule),
|
||||||
forwardRef(() => RestaurantsModule),
|
forwardRef(() => RestaurantsModule),
|
||||||
MikroOrmModule.forFeature([User, RefreshToken]),
|
MikroOrmModule.forFeature([User, RefreshToken]),
|
||||||
|
forwardRef(() => NotificationsModule),
|
||||||
|
|
||||||
],
|
],
|
||||||
controllers: [AuthController],
|
controllers: [AuthController],
|
||||||
providers: [AuthService, TokensService, AdminAuthGuard],
|
providers: [AuthService, TokensService, AdminAuthGuard],
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable, BadRequestException } from '@nestjs/common';
|
import { Injectable, BadRequestException } from '@nestjs/common';
|
||||||
import { RequestOtpDto } from '../dto/request-otp.dto';
|
import { RequestOtpDto } from '../dto/request-otp.dto';
|
||||||
import { CacheService } from '../../utils/cache.service';
|
import { CacheService } from '../../utils/cache.service';
|
||||||
import { SmsService } from '../../utils/sms.service';
|
import { SmsService } from '../../notifications/services/sms.service';
|
||||||
import { UserService } from '../../users/providers/user.service';
|
import { UserService } from '../../users/providers/user.service';
|
||||||
import { randomInt } from 'crypto';
|
import { randomInt } from 'crypto';
|
||||||
import { TokensService } from './tokens.service';
|
import { TokensService } from './tokens.service';
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { Entity, Property, ManyToOne, PrimaryKey } from '@mikro-orm/core';
|
||||||
|
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
||||||
|
|
||||||
|
@Entity({ tableName: 'sms_logs' })
|
||||||
|
export class SmsLog {
|
||||||
|
@PrimaryKey()
|
||||||
|
id!: number;
|
||||||
|
|
||||||
|
@ManyToOne(() => Restaurant)
|
||||||
|
restaurant!: Restaurant;
|
||||||
|
|
||||||
|
@Property()
|
||||||
|
phone!: string;
|
||||||
|
|
||||||
|
@Property()
|
||||||
|
createdAt: Date = new Date();
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
export class SmsSentEvent {
|
||||||
|
constructor(
|
||||||
|
public readonly phoneNumber: string,
|
||||||
|
public readonly restaurantId: string,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -3,6 +3,7 @@ import type { NotifTitleEnum, recipientType } from './notification.interface';
|
|||||||
export interface SmsNotificationQueueJob {
|
export interface SmsNotificationQueueJob {
|
||||||
recipient: recipientType;
|
recipient: recipientType;
|
||||||
templateId: string;
|
templateId: string;
|
||||||
|
restaurantId: string;
|
||||||
parameters?: Record<string, string>;
|
parameters?: Record<string, string>;
|
||||||
}
|
}
|
||||||
export interface PushNotificationQueueJob {
|
export interface PushNotificationQueueJob {
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
import { OnEvent } from '@nestjs/event-emitter';
|
||||||
|
import { SmsSentEvent } from '../events/sms.events';
|
||||||
|
import { RestRepository } from '../../restaurants/repositories/rest.repository';
|
||||||
|
import { EntityManager } from '@mikro-orm/postgresql';
|
||||||
|
import { SmsLog } from '../entities/smsLogs.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SmsListeners {
|
||||||
|
private readonly logger = new Logger(SmsListeners.name);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly restRepository: RestRepository,
|
||||||
|
private readonly em: EntityManager,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnEvent(SmsSentEvent.name)
|
||||||
|
async handleSmsSent(event: SmsSentEvent) {
|
||||||
|
try {
|
||||||
|
this.logger.log(
|
||||||
|
`SMS sent event received: phone ${event.phoneNumber} for restaurant: ${event.restaurantId}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get the restaurant entity
|
||||||
|
const restaurant = await this.restRepository.findOne({ id: event.restaurantId });
|
||||||
|
|
||||||
|
if (!restaurant) {
|
||||||
|
this.logger.warn(
|
||||||
|
`Restaurant not found for SMS log: ${event.restaurantId}`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create SMS log record
|
||||||
|
const smsLog = this.em.create(SmsLog, {
|
||||||
|
restaurant: restaurant,
|
||||||
|
phone: event.phoneNumber,
|
||||||
|
createdAt: new Date(),
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.em.flush();
|
||||||
|
|
||||||
|
this.logger.log(
|
||||||
|
`SMS log created successfully: ${smsLog.id} for phone ${event.phoneNumber}`,
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(
|
||||||
|
`Failed to create SMS log for event: ${event.restaurantId}`,
|
||||||
|
error instanceof Error ? error.stack : String(error),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module, forwardRef } from '@nestjs/common';
|
||||||
import { MikroOrmModule } from '@mikro-orm/nestjs';
|
import { MikroOrmModule } from '@mikro-orm/nestjs';
|
||||||
import { BullModule } from '@nestjs/bullmq';
|
import { BullModule } from '@nestjs/bullmq';
|
||||||
import { JwtModule } from '@nestjs/jwt';
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
@@ -23,13 +23,17 @@ import { InAppProcessor } from './processors/in-app.processor';
|
|||||||
import { AdminModule } from '../admin/admin.module';
|
import { AdminModule } from '../admin/admin.module';
|
||||||
import { UserModule } from '../users/user.module';
|
import { UserModule } from '../users/user.module';
|
||||||
import { NotificationCrone } from './crone/notification.crone';
|
import { NotificationCrone } from './crone/notification.crone';
|
||||||
|
import { SmsService } from './services/sms.service';
|
||||||
|
import { SmsLog } from './entities/smsLogs.entity';
|
||||||
|
import { SmsLogRepository } from './repositories/sms-log.repository';
|
||||||
|
import { RestaurantsModule } from '../restaurants/restaurants.module';
|
||||||
|
import { SmsListeners } from './listeners/sms.listeners';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
AuthModule,
|
forwardRef(() => AuthModule),
|
||||||
UtilsModule,
|
|
||||||
JwtModule,
|
JwtModule,
|
||||||
MikroOrmModule.forFeature([Notification, NotificationPreference, User, Restaurant]),
|
MikroOrmModule.forFeature([Notification, NotificationPreference, User, Restaurant, SmsLog]),
|
||||||
BullModule.registerQueue(
|
BullModule.registerQueue(
|
||||||
{ name: NotificationQueueNameEnum.SMS },
|
{ name: NotificationQueueNameEnum.SMS },
|
||||||
{ name: NotificationQueueNameEnum.PUSH },
|
{ name: NotificationQueueNameEnum.PUSH },
|
||||||
@@ -46,7 +50,9 @@ import { NotificationCrone } from './crone/notification.crone';
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
AdminModule,
|
AdminModule,
|
||||||
UserModule,
|
forwardRef(() => UserModule),
|
||||||
|
UtilsModule,
|
||||||
|
forwardRef(() => RestaurantsModule),
|
||||||
],
|
],
|
||||||
controllers: [NotificationsController],
|
controllers: [NotificationsController],
|
||||||
providers: [
|
providers: [
|
||||||
@@ -60,7 +66,11 @@ import { NotificationCrone } from './crone/notification.crone';
|
|||||||
NotificationsGateway,
|
NotificationsGateway,
|
||||||
WsAdminAuthGuard,
|
WsAdminAuthGuard,
|
||||||
NotificationCrone,
|
NotificationCrone,
|
||||||
|
SmsService,
|
||||||
|
SmsLogRepository,
|
||||||
|
SmsListeners,
|
||||||
],
|
],
|
||||||
exports: [NotificationService, NotificationPreferenceService, NotificationQueueService, PushNotificationService],
|
exports: [NotificationService, NotificationPreferenceService,
|
||||||
|
NotificationQueueService, PushNotificationService, SmsService],
|
||||||
})
|
})
|
||||||
export class NotificationsModule {}
|
export class NotificationsModule { }
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import { UserRepository } from 'src/modules/users/repositories/user.repository';
|
|||||||
import { SmsNotificationQueueJob } from '../interfaces/jobs-queue.interface';
|
import { SmsNotificationQueueJob } from '../interfaces/jobs-queue.interface';
|
||||||
import { AdminRepository } from 'src/modules/admin/repositories/admin.repository';
|
import { AdminRepository } from 'src/modules/admin/repositories/admin.repository';
|
||||||
import { NotificationQueueNameEnum } from '../constants/queue';
|
import { NotificationQueueNameEnum } from '../constants/queue';
|
||||||
import { SmsService } from 'src/modules/utils/sms.service';
|
import { SmsService } from '../services/sms.service';
|
||||||
|
import { SmsSentEvent } from '../events/sms.events';
|
||||||
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
|
|
||||||
@Processor(NotificationQueueNameEnum.SMS)
|
@Processor(NotificationQueueNameEnum.SMS)
|
||||||
export class SmsProcessor extends WorkerHost {
|
export class SmsProcessor extends WorkerHost {
|
||||||
@@ -15,12 +17,13 @@ export class SmsProcessor extends WorkerHost {
|
|||||||
private readonly adminRepository: AdminRepository,
|
private readonly adminRepository: AdminRepository,
|
||||||
private readonly userRepository: UserRepository,
|
private readonly userRepository: UserRepository,
|
||||||
private readonly smsService: SmsService,
|
private readonly smsService: SmsService,
|
||||||
|
private readonly eventEmitter: EventEmitter2,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
async process(job: Job<SmsNotificationQueueJob>) {
|
async process(job: Job<SmsNotificationQueueJob>) {
|
||||||
const { recipient, templateId, parameters } = job.data;
|
const { recipient, templateId, parameters, restaurantId } = job.data;
|
||||||
|
|
||||||
this.logger.log(`Processing SMS notification - Recipient: ${JSON.stringify(recipient)}, templateID: ${templateId}`);
|
this.logger.log(`Processing SMS notification - Recipient: ${JSON.stringify(recipient)}, templateID: ${templateId}`);
|
||||||
|
|
||||||
@@ -55,6 +58,8 @@ export class SmsProcessor extends WorkerHost {
|
|||||||
|
|
||||||
this.logger.log(`SMS notification sent successfully to ${phone}`);
|
this.logger.log(`SMS notification sent successfully to ${phone}`);
|
||||||
|
|
||||||
|
this.eventEmitter.emit(SmsSentEvent.name, new SmsSentEvent(phone, restaurantId));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
|
||||||
|
import { SmsLog } from '../entities/smsLogs.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SmsLogRepository extends EntityRepository<SmsLog> {
|
||||||
|
constructor(readonly em: EntityManager) {
|
||||||
|
super(em, SmsLog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -58,6 +58,7 @@ export class NotificationService {
|
|||||||
recipient,
|
recipient,
|
||||||
templateId: message.sms.templateId,
|
templateId: message.sms.templateId,
|
||||||
parameters: message.sms.parameters,
|
parameters: message.sms.parameters,
|
||||||
|
restaurantId,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { ISmsParams, ISmsResponse, ISmsBodyParameters } from './interface/sms';
|
import { ISmsParams, ISmsResponse, ISmsBodyParameters } from '../interfaces/sms';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SmsService {
|
export class SmsService {
|
||||||
@@ -58,6 +58,7 @@ export class SmsService {
|
|||||||
throw new HttpException('The SMS was not sent. Please try again later.', HttpStatus.BAD_GATEWAY);
|
throw new HttpException('The SMS was not sent. Please try again later.', HttpStatus.BAD_GATEWAY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatPhone(phone: string): string {
|
formatPhone(phone: string): string {
|
||||||
// remove spaces, dashes, parentheses
|
// remove spaces, dashes, parentheses
|
||||||
phone = phone.replace(/[^\d+]/g, '');
|
phone = phone.replace(/[^\d+]/g, '');
|
||||||
@@ -91,15 +91,6 @@ export class OrderListeners {
|
|||||||
`Order status changed event received: ${event.orderId} for restaurant: ${event.restaurantId} and order number: ${event.orderNumber}`,
|
`Order status changed event received: ${event.orderId} for restaurant: ${event.restaurantId} and order number: ${event.orderNumber}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// const order = await this.OrderRepository.findOneById(event.orderId, { populate: ['user'] });
|
|
||||||
// if (!order) {
|
|
||||||
// this.logger.warn(`Order not found: ${event.orderId}`);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// if (order.user && order.user.phoneNumber) {
|
|
||||||
// this.logger.warn(`Order not found: ${event.orderId}`);
|
|
||||||
// }
|
|
||||||
|
|
||||||
const recipients = [
|
const recipients = [
|
||||||
{
|
{
|
||||||
userId: event.userId,
|
userId: event.userId,
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { CacheService } from './cache.service';
|
import { CacheService } from './cache.service';
|
||||||
import { SmsService } from './sms.service';
|
|
||||||
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [],
|
||||||
controllers: [],
|
controllers: [],
|
||||||
providers: [CacheService, SmsService],
|
providers: [CacheService, ],
|
||||||
exports: [CacheService, SmsService],
|
exports: [CacheService],
|
||||||
})
|
})
|
||||||
export class UtilsModule {}
|
export class UtilsModule {}
|
||||||
|
|||||||
Reference in New Issue
Block a user