send notif after chat

This commit is contained in:
2026-02-24 12:02:41 +03:30
parent 3e78ac2d8a
commit a1fe186c5f
6 changed files with 107 additions and 9 deletions
-1
View File
@@ -44,7 +44,6 @@ import { TicketModule } from './modules/ticket/ticket.module';
ProductModule,
RolesModule,
PaymentModule,
// OrderModule,
NotificationsModule,
EventEmitterModule.forRoot(),
PrintModule,
+1 -1
View File
@@ -7,7 +7,7 @@ import { TicketMessageEnum } from "../../../common/enums/message.enum";
export class CreateChatDto {
@IsNotEmpty({ message: TicketMessageEnum.MESSAGE_REQUIRED })
@IsString({ message: TicketMessageEnum.MESSAGE_STRING })
@Length(5, 5000, { message: TicketMessageEnum.MESSAGE_LENGTH })
@Length(1, 5000, { message: TicketMessageEnum.MESSAGE_LENGTH })
@ApiProperty({ description: "The message content of the ticket" })
content: string;
+8 -5
View File
@@ -7,17 +7,20 @@ import { MikroOrmModule } from "@mikro-orm/nestjs";
import { AdminModule } from "../admin/admin.module";
import { UserModule } from "../user/user.module";
import { JwtModule } from "@nestjs/jwt";
import { Request } from "../request/entities/request.entity";
import { Order } from "../order/entities/order.entity";
import { NotificationsModule } from "../notification/notifications.module";
import { ChatListeners } from "./listeners/chat.listeners";
@Module({
imports: [
MikroOrmModule.forFeature([Chat]),
MikroOrmModule.forFeature([Chat, Request, Order]),
AdminModule,
UserModule,
JwtModule.register({})
JwtModule.register({}),
NotificationsModule,
],
providers: [ChattService, ChatRepository],
providers: [ChattService, ChatRepository, ChatListeners],
controllers: [ChatController],
exports: [ChattService, ChatRepository],
})
+6
View File
@@ -0,0 +1,6 @@
export class ChatCreatedByAdminEvent {
constructor(
public readonly refId: string,
public readonly chatId: string,
) {}
}
@@ -0,0 +1,84 @@
import { Injectable, Logger } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { EntityManager } from '@mikro-orm/postgresql';
import { Request } from 'src/modules/request/entities/request.entity';
import { Order } from 'src/modules/order/entities/order.entity';
import { NotificationService } from 'src/modules/notification/services/notification.service';
import { NotifChannelEnum, NotifTitle } from 'src/modules/notification/interfaces/notification.interface';
import { ChatCreatedByAdminEvent } from '../events/chat.events';
@Injectable()
export class ChatListeners {
private readonly logger = new Logger(ChatListeners.name);
constructor(
private readonly em: EntityManager,
private readonly notificationService: NotificationService,
) {}
@OnEvent(ChatCreatedByAdminEvent.name)
async handleChatCreatedByAdmin(event: ChatCreatedByAdminEvent) {
try {
this.logger.log(
`Chat created by admin: refId=${event.refId}, chatId=${event.chatId}`,
);
const user = await this.findUserByRefId(event.refId);
if (!user) {
this.logger.warn(
`No user found for refId=${event.refId}, skipping notification`,
);
return;
}
const body = 'پیام جدید از پشتیبانی برای شما ارسال شده است.';
await this.notificationService.sendNotification({
channels: [NotifChannelEnum.SMS],
recipients: [{ userId: user.id }],
message: {
title: NotifTitle.NEW_TICKET,
content: body,
sms: {
templateId: '',
parameters: {},
},
},
});
this.logger.log(
`Notification sent to user ${user.id} for admin chat on refId=${event.refId}`,
);
} catch (error) {
this.logger.error(
`Failed to send notification for chat created by admin: refId=${event.refId}`,
error instanceof Error ? error.stack : String(error),
);
}
}
/**
* Find the user associated with refId: first search in requests, then in orders.
*/
private async findUserByRefId(refId: string): Promise<{ id: string } | null> {
const request = await this.em.findOne(
Request,
{ id: refId },
{ populate: ['user'], fields: ['id', 'user'] },
);
if (request?.user?.id) {
return { id: request.user.id };
}
const order = await this.em.findOne(
Order,
{ id: refId },
{ populate: ['user'], fields: ['id', 'user'] },
);
if (order?.user?.id) {
return { id: order.user.id };
}
return null;
}
}
+8 -2
View File
@@ -9,6 +9,8 @@ import { UpdateChatDto } from "../DTO/update-chat.dto";
import { Chat } from "../entities/ticket.entity";
import { AdminService } from "src/modules/admin/providers/admin.service";
import { UserService } from "src/modules/user/providers/user.service";
import { EventEmitter2 } from "@nestjs/event-emitter";
import { ChatCreatedByAdminEvent } from "../events/chat.events";
@Injectable()
export class ChattService {
@@ -18,18 +20,22 @@ export class ChattService {
private readonly adminService: AdminService,
private readonly userService: UserService,
private readonly em: EntityManager,
private readonly eventEmitter: EventEmitter2,
) { }
async createChatAsAdmin(refId: string, dto: CreateChatDto, adminId: string) {
// const orderItem = await this.findOrderItemOrFail(refId)
let admin: null | Admin = null
admin = await this.adminService.findOrFail(adminId)
const ticket = await this.createChat(refId, dto, undefined, admin)
this.eventEmitter.emit(
ChatCreatedByAdminEvent.name,
new ChatCreatedByAdminEvent(refId, ticket.id),
);
return ticket
}