update
This commit is contained in:
@@ -15,7 +15,7 @@ export enum NotifTitleEnum {
|
|||||||
REVIEW_CREATED = 'review.created',
|
REVIEW_CREATED = 'review.created',
|
||||||
ORDER_STATUS_CHANGED = 'order.status.changed',
|
ORDER_STATUS_CHANGED = 'order.status.changed',
|
||||||
}
|
}
|
||||||
export type recipientType = { userId: string; restaurantId: string } | { adminId: string; restaurantId: string };
|
export type recipientType = { userId: string } | { adminId: string };
|
||||||
|
|
||||||
export interface NotifRequestMessage {
|
export interface NotifRequestMessage {
|
||||||
subject: NotifTitleEnum;
|
subject: NotifTitleEnum;
|
||||||
@@ -37,6 +37,7 @@ export interface NotifRequest {
|
|||||||
// timestamp: Date;
|
// timestamp: Date;
|
||||||
// notifType: NotifTypeEnum;
|
// notifType: NotifTypeEnum;
|
||||||
// channels: NotifChannelEnum[];
|
// channels: NotifChannelEnum[];
|
||||||
|
restaurantId: string;
|
||||||
recipients: recipientType[];
|
recipients: recipientType[];
|
||||||
message: NotifRequestMessage;
|
message: NotifRequestMessage;
|
||||||
metadata: {
|
metadata: {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ import { WsAdminAuthGuard, type AuthenticatedSocket } from './guards/ws-admin-au
|
|||||||
cors: {
|
cors: {
|
||||||
origin: true,
|
origin: true,
|
||||||
credentials: true,
|
credentials: true,
|
||||||
connectionGuard: WsAdminAuthGuard,
|
|
||||||
},
|
},
|
||||||
|
// connectionGuard: WsAdminAuthGuard,
|
||||||
namespace: '/notifications',
|
namespace: '/notifications',
|
||||||
transports: ['websocket', 'polling'],
|
transports: ['websocket', 'polling'],
|
||||||
})
|
})
|
||||||
@@ -35,21 +35,23 @@ export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisco
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
handleConnection(client: AuthenticatedSocket) {
|
handleConnection(client: AuthenticatedSocket) {
|
||||||
console.log(client);
|
this.logger.log(`Admin connected: ${client.adminId}`);
|
||||||
this.logger.log(`Client connected: ${client.id}`);
|
this.handleJoinRoom(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDisconnect(client: Socket) {
|
handleDisconnect(client: Socket) {
|
||||||
this.logger.log(`Client disconnected: ${client.id}`);
|
this.logger.log(`Client disconnected: ${client.id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendAdminNotification(client: AuthenticatedSocket, event: string, data: any) {
|
sendInAppNotification(repipient: { adminId: string; restaurantId: string }, event: string, data: any) {
|
||||||
const room = this.getRoom(client);
|
this.logger.log(`Sending in app notification to admin: ${repipient.adminId}`);
|
||||||
|
const room = this.getRoom(repipient.adminId, repipient.restaurantId);
|
||||||
this.server.to(room).emit(event, data);
|
this.server.to(room).emit(event, data);
|
||||||
|
this.logger.log(`In app notification sent to admin: ${repipient.adminId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getRoom(client: AuthenticatedSocket) {
|
private getRoom(adminId: string, restaurantId: string) {
|
||||||
return `restaurant:${client.restId}-admin:${client.adminId}`;
|
return `restaurant:${restaurantId}-admin:${adminId}`;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Join a room for a specific restaurant (admin/staff)
|
* Join a room for a specific restaurant (admin/staff)
|
||||||
@@ -57,14 +59,12 @@ export class NotificationsGateway implements OnGatewayConnection, OnGatewayDisco
|
|||||||
* Restaurant ID is extracted from the authenticated admin's token
|
* Restaurant ID is extracted from the authenticated admin's token
|
||||||
* Room format: `restaurant:${restId}`
|
* Room format: `restaurant:${restId}`
|
||||||
*/
|
*/
|
||||||
// @UseGuards(WsAdminAuthGuard)
|
handleJoinRoom(client: AuthenticatedSocket) {
|
||||||
// @SubscribeMessage('join:restaurant')
|
const room = this.getRoom(client.adminId!, client.restId!);
|
||||||
// handleJoinRestaurant(@ConnectedSocket() client: AuthenticatedSocket, @WsRestId() restId: string) {
|
void client.join(room);
|
||||||
// const room = `restaurant:${restId}`;
|
this.logger.log(`Admin ${client.adminId} (Client ${client.id}) joined room: ${room}`);
|
||||||
// void client.join(room);
|
void client.emit('joined', { room, message: 'Successfully Admin joined room' });
|
||||||
// this.logger.log(`Admin ${client.adminId} (Client ${client.id}) joined room: ${room}`);
|
}
|
||||||
// void client.emit('joined', { room, message: 'Successfully joined restaurant room' });
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join a room for a specific cookie/session (public user)
|
* Join a room for a specific cookie/session (public user)
|
||||||
|
|||||||
@@ -3,19 +3,12 @@ import { EntityManager } from '@mikro-orm/postgresql';
|
|||||||
import { Notification } from '../entities/notification.entity';
|
import { Notification } from '../entities/notification.entity';
|
||||||
import { NotificationPreferenceService } from './notification-preference.service';
|
import { NotificationPreferenceService } from './notification-preference.service';
|
||||||
import { NotificationQueueService } from './notification-queue.service';
|
import { NotificationQueueService } from './notification-queue.service';
|
||||||
|
import { NotificationsGateway } from '../notifications.gateway';
|
||||||
import { NotificationQueueJob } from '../interfaces/notification-queue.interface';
|
import { NotificationQueueJob } from '../interfaces/notification-queue.interface';
|
||||||
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
import { Restaurant } from '../../restaurants/entities/restaurant.entity';
|
||||||
import { User } from '../../users/entities/user.entity';
|
import { User } from '../../users/entities/user.entity';
|
||||||
import { NotifChannelEnum, NotifRequest, NotifTitleEnum } from '../interfaces/notification.interface';
|
import { NotifChannelEnum, NotifRequest, NotifTitleEnum } from '../interfaces/notification.interface';
|
||||||
|
|
||||||
export interface SendNotificationParams {
|
|
||||||
restaurantId: string;
|
|
||||||
userId?: string;
|
|
||||||
title: NotifTitleEnum;
|
|
||||||
content: string;
|
|
||||||
idempotencyKey?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NotificationService {
|
export class NotificationService {
|
||||||
private readonly logger = new Logger(NotificationService.name);
|
private readonly logger = new Logger(NotificationService.name);
|
||||||
@@ -24,22 +17,23 @@ export class NotificationService {
|
|||||||
private readonly em: EntityManager,
|
private readonly em: EntityManager,
|
||||||
private readonly preferenceService: NotificationPreferenceService,
|
private readonly preferenceService: NotificationPreferenceService,
|
||||||
private readonly queueService: NotificationQueueService,
|
private readonly queueService: NotificationQueueService,
|
||||||
|
private readonly notificationGateway: NotificationsGateway,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async sendNotification(params: NotifRequest): Promise<Notification[]> {
|
async sendNotification(params: NotifRequest): Promise<Notification[]> {
|
||||||
const { recipients, message, metadata } = params;
|
const { recipients, message, metadata, restaurantId } = params;
|
||||||
|
|
||||||
// create Database notifications
|
// create Database notifications
|
||||||
const notifications = await this.createAdminBulkNotifications(
|
const notifications = await this.createAdminBulkNotifications(
|
||||||
recipients.map(recipient => ({
|
recipients.map(recipient => ({
|
||||||
restaurantId: recipient.restaurantId,
|
restaurantId,
|
||||||
title: message.subject,
|
title: message.subject,
|
||||||
content: message.body,
|
content: message.body,
|
||||||
adminId: 'adminId' in recipient ? recipient.adminId : null,
|
adminId: 'adminId' in recipient ? recipient.adminId : null,
|
||||||
userId: 'userId' in recipient ? recipient.userId : null,
|
userId: 'userId' in recipient ? recipient.userId : null,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
const restaurantId = recipients[0].restaurantId;
|
|
||||||
// get admin prefrences
|
// get admin prefrences
|
||||||
const preference = await this.preferenceService.findByRestaurantAndType(restaurantId, message.subject);
|
const preference = await this.preferenceService.findByRestaurantAndType(restaurantId, message.subject);
|
||||||
|
|
||||||
@@ -48,6 +42,17 @@ export class NotificationService {
|
|||||||
return notifications;
|
return notifications;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send in app notification
|
||||||
|
if (preference?.channels?.includes(NotifChannelEnum.IN_APP)) {
|
||||||
|
recipients.forEach(recipient => {
|
||||||
|
if ('adminId' in recipient) {
|
||||||
|
this.notificationGateway.sendInAppNotification({ adminId: recipient.adminId, restaurantId }, 'notification', {
|
||||||
|
title: message.subject,
|
||||||
|
content: message.body,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
// const job: NotificationQueueJob = {
|
// const job: NotificationQueueJob = {
|
||||||
// restaurantId,
|
// restaurantId,
|
||||||
// userId,
|
// userId,
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ export class PagerListeners {
|
|||||||
// get admnin os restuaraant that have pager permissuins
|
// get admnin os restuaraant that have pager permissuins
|
||||||
const admins = await this.adminService.findAdminsWithPermission(event.restaurantId, Permission.MANAGE_PAGER);
|
const admins = await this.adminService.findAdminsWithPermission(event.restaurantId, Permission.MANAGE_PAGER);
|
||||||
const recipients = admins.map(admin => ({
|
const recipients = admins.map(admin => ({
|
||||||
restaurantId: event.restaurantId,
|
|
||||||
adminId: admin.id,
|
adminId: admin.id,
|
||||||
}));
|
}));
|
||||||
await this.notificationService.sendNotification({
|
await this.notificationService.sendNotification({
|
||||||
|
restaurantId: event.restaurantId,
|
||||||
message: {
|
message: {
|
||||||
subject: NotifTitleEnum.PAGER_CREATED,
|
subject: NotifTitleEnum.PAGER_CREATED,
|
||||||
body: `Your pager has created successfully`,
|
body: `Your pager has created successfully`,
|
||||||
|
|||||||
@@ -48,14 +48,14 @@ export class PagerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const cookieId = userCookieId || ulid().toString();
|
const cookieId = userCookieId || ulid().toString();
|
||||||
const existingPager = await this.em.findOne(Pager, {
|
// const existingPager = await this.em.findOne(Pager, {
|
||||||
restaurant: { id: restaurant!.id },
|
// restaurant: { id: restaurant!.id },
|
||||||
status: PagerStatus.Pending,
|
// status: PagerStatus.Pending,
|
||||||
cookieId,
|
// cookieId,
|
||||||
});
|
// });
|
||||||
if (existingPager) {
|
// if (existingPager) {
|
||||||
throw new BadRequestException('Pager already exists');
|
// throw new BadRequestException('Pager already exists');
|
||||||
}
|
// }
|
||||||
|
|
||||||
const pager = this.em.create(Pager, {
|
const pager = this.em.create(Pager, {
|
||||||
...createPagerDto,
|
...createPagerDto,
|
||||||
|
|||||||
Reference in New Issue
Block a user