Files
dmail-api/src/modules/notifications/services/notifications.service.ts
T
2025-07-20 10:15:13 +03:30

143 lines
5.7 KiB
TypeScript
Executable File

import { EntityManager } from "@mikro-orm/postgresql";
import { BadRequestException, Injectable, Logger, NotFoundException } from "@nestjs/common";
import { CommonMessage, NotificationMessage, UserMessage } from "../../../common/enums/message.enum";
import { NotifType } from "../../settings/enums/notif-settings.enum";
import { UserSettingsService } from "../../settings/services/user-settings.service";
import { User } from "../../users/entities/user.entity";
import { CreateNotificationDto } from "../DTO/create-notification.dto";
import { SearchNotificationQueryDto } from "../DTO/search-notification-query.dto";
import { Notification } from "../entities/notification.entity";
import { IBaseNotificationData, IChangePasswordNotificationData, INewEmailNotificationData } from "../interfaces/ISendNotificationData";
import { NotificationRepository } from "../repositories/notifications.repository";
@Injectable()
export class NotificationsService {
private readonly logger = new Logger(NotificationsService.name);
constructor(
private readonly em: EntityManager,
private readonly notificationRepository: NotificationRepository,
private readonly userSettingsService: UserSettingsService,
) {}
//************************ */
async createNotification(createNotificationDto: CreateNotificationDto, em?: EntityManager) {
if (!em) {
const localEm = this.em.fork();
await localEm.begin();
try {
//
const user = await localEm.findOne(User, { id: createNotificationDto.recipientId });
if (!user) throw new NotFoundException(UserMessage.USER_NOT_FOUND);
const notification = localEm.create(Notification, {
...createNotificationDto,
recipient: user,
});
await localEm.persistAndFlush(notification);
await localEm.commit();
return notification;
//
} catch (error) {
this.logger.error("error in createNotification", error);
await localEm.rollback();
throw error;
//
}
//
} else {
//
const user = await em.findOne(User, { id: createNotificationDto.recipientId, deletedAt: null });
if (!user) throw new NotFoundException(UserMessage.USER_NOT_FOUND);
const notification = em.create(Notification, {
...createNotificationDto,
recipient: user,
});
//
await em.persistAndFlush(notification);
return notification;
}
}
//************************ */
async markAsRead(notificationId: string, userId: string) {
const notification = await this.notificationRepository.findOne({ id: notificationId, recipient: { id: userId }, deletedAt: null });
if (!notification) throw new BadRequestException(NotificationMessage.NOTIFICATION_NOT_FOUND_OR_ACCESS_DENIED);
notification.isRead = true;
await this.em.flush();
return {
message: CommonMessage.UPDATE_SUCCESS,
};
}
//************************ */
async getAllNotifications(queryDto: SearchNotificationQueryDto, recipientId: string) {
const [notifications, count] = await this.notificationRepository.getAllNotifications(queryDto, recipientId);
const notificationCount = await this.countUserNotifications(recipientId);
return { notifications, notificationCount, count, paginate: true };
}
//************************ */
async getNotificationById(id: string) {
const notification = await this.notificationRepository.findOne({ id, deletedAt: null });
if (!notification) throw new BadRequestException(NotificationMessage.NOTIFICATION_NOT_FOUND_OR_ACCESS_DENIED);
return { notification };
}
//************************ */
async countUserNotifications(userId: string) {
const notificationCount = await this.notificationRepository.count({ recipient: { id: userId }, isRead: false, deletedAt: null });
return notificationCount;
}
//************************ */
async markAllAsRead(userId: string) {
await this.notificationRepository.nativeUpdate({ recipient: { id: userId }, deletedAt: null }, { isRead: true });
return {
message: CommonMessage.UPDATE_SUCCESS,
};
}
//************************ */
async createLoginNotification(recipientId: string, _data: IBaseNotificationData) {
const loginDate = new Date().toLocaleString("fa-IR");
const message = NotificationMessage.LOGIN_MESSAGE.replace("[loginDate]", loginDate);
//sent notification based on the userSettings
const { isActive } = await this.userSettingsService.getUserNotificationSettingWithType(NotifType.USER_LOGIN, recipientId);
if (isActive) {
return this.createNotification({ title: NotificationMessage.LOGIN, type: NotifType.USER_LOGIN, message, recipientId });
}
}
//************************ */
async createNewEmailNotification(recipientId: string, data: INewEmailNotificationData, em: EntityManager) {
const message = NotificationMessage.NEW_EMAIL_MESSAGE.replace("[subject]", data.newEmail);
const { isActive } = await this.userSettingsService.getUserNotificationSettingWithType(NotifType.NEW_EMAIL, recipientId);
if (isActive) {
return this.createNotification({ title: NotificationMessage.NEW_EMAIL, type: NotifType.NEW_EMAIL, message, recipientId }, em);
}
}
//************************ */
async changePasswordNotification(recipientId: string, _data: IChangePasswordNotificationData, em: EntityManager) {
const message = NotificationMessage.CHANGE_PASSWORD_MESSAGE;
const { isActive } = await this.userSettingsService.getUserNotificationSettingWithType(NotifType.CHANGE_PASSWORD, recipientId);
if (isActive) {
return this.createNotification({ title: NotificationMessage.CHANGE_PASSWORD, type: NotifType.CHANGE_PASSWORD, message, recipientId }, em);
}
}
}