chore: add notif service for new blog and service comment
This commit is contained in:
@@ -9,10 +9,10 @@ import { BlogsService } from "./providers/blogs.service";
|
|||||||
import { BlogCategoriesRepository } from "./repositories/blog-categories.repository";
|
import { BlogCategoriesRepository } from "./repositories/blog-categories.repository";
|
||||||
import { BlogCommentsRepository } from "./repositories/blog-comments.repository";
|
import { BlogCommentsRepository } from "./repositories/blog-comments.repository";
|
||||||
import { BlogsRepository } from "./repositories/blogs.repository";
|
import { BlogsRepository } from "./repositories/blogs.repository";
|
||||||
|
import { NotificationModule } from "../notifications/notifications.module";
|
||||||
import { UsersModule } from "../users/users.module";
|
import { UsersModule } from "../users/users.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([Blog, BlogComment, BlogCategory]), UsersModule],
|
imports: [TypeOrmModule.forFeature([Blog, BlogComment, BlogCategory]), UsersModule, NotificationModule],
|
||||||
controllers: [BlogsController],
|
controllers: [BlogsController],
|
||||||
providers: [BlogsService, BlogsRepository, BlogCommentsRepository, BlogCategoriesRepository],
|
providers: [BlogsService, BlogsRepository, BlogCommentsRepository, BlogCategoriesRepository],
|
||||||
exports: [BlogsService],
|
exports: [BlogsService],
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||||
import { Not } from "typeorm";
|
import { DataSource, IsNull, Not } from "typeorm";
|
||||||
|
|
||||||
import { AdminMessage, BlogMessage, CommonMessage } from "../../../common/enums/message.enum";
|
import { AdminMessage, BlogMessage, CommonMessage } from "../../../common/enums/message.enum";
|
||||||
import { CategoryListSearchQueryDto } from "../../danak-services/DTO/category-search-query.dto";
|
import { CategoryListSearchQueryDto } from "../../danak-services/DTO/category-search-query.dto";
|
||||||
|
import { NotificationsService } from "../../notifications/providers/notifications.service";
|
||||||
|
import { AdminsService } from "../../users/providers/admins.service";
|
||||||
import { UsersService } from "../../users/providers/users.service";
|
import { UsersService } from "../../users/providers/users.service";
|
||||||
import { BlogCommentQueryDto } from "../DTO/blog-comment-query.dto";
|
import { BlogCommentQueryDto } from "../DTO/blog-comment-query.dto";
|
||||||
import { CreateBlogDto } from "../DTO/create-blog.dto";
|
import { CreateBlogDto } from "../DTO/create-blog.dto";
|
||||||
@@ -23,6 +25,9 @@ export class BlogsService {
|
|||||||
private readonly blogCommentsRepository: BlogCommentsRepository,
|
private readonly blogCommentsRepository: BlogCommentsRepository,
|
||||||
private readonly blogCategoriesRepository: BlogCategoriesRepository,
|
private readonly blogCategoriesRepository: BlogCategoriesRepository,
|
||||||
private readonly usersService: UsersService,
|
private readonly usersService: UsersService,
|
||||||
|
private readonly adminsService: AdminsService,
|
||||||
|
private readonly dataSource: DataSource,
|
||||||
|
private readonly notificationsService: NotificationsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
//*********************************** */
|
//*********************************** */
|
||||||
@@ -233,23 +238,53 @@ export class BlogsService {
|
|||||||
//*********************************** */
|
//*********************************** */
|
||||||
|
|
||||||
async createComment(blogId: string, createCommentDto: CreateCommentDto, userId: string) {
|
async createComment(blogId: string, createCommentDto: CreateCommentDto, userId: string) {
|
||||||
const blog = await this.findBlogById(blogId);
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
|
|
||||||
const { user } = await this.usersService.findOneById(userId);
|
try {
|
||||||
|
await queryRunner.connect();
|
||||||
|
await queryRunner.startTransaction();
|
||||||
|
|
||||||
const comment = this.blogCommentsRepository.create({
|
const blog = await queryRunner.manager.findOne(this.blogsRepository.target, { where: { id: blogId, deletedAt: IsNull() } });
|
||||||
|
if (!blog) throw new BadRequestException(BlogMessage.BLOG_NOT_FOUND);
|
||||||
|
|
||||||
|
const user = await this.usersService.findOneByIdWithQueryRunner(userId, queryRunner);
|
||||||
|
|
||||||
|
const comment = queryRunner.manager.create(this.blogCommentsRepository.target, {
|
||||||
...createCommentDto,
|
...createCommentDto,
|
||||||
blog,
|
blog,
|
||||||
user,
|
user,
|
||||||
status: CommentStatus.PENDING,
|
status: CommentStatus.PENDING,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.blogCommentsRepository.save(comment);
|
await queryRunner.manager.save(this.blogCommentsRepository.target, comment);
|
||||||
|
|
||||||
|
const superAdmin = await this.adminsService.getSuperAdmins();
|
||||||
|
|
||||||
|
for (const admin of superAdmin) {
|
||||||
|
await this.notificationsService.createNewBlogCommentNotification(
|
||||||
|
admin.id,
|
||||||
|
{
|
||||||
|
userPhone: user.phone,
|
||||||
|
userEmail: user.email,
|
||||||
|
blogTitle: blog.title,
|
||||||
|
fullName: `${user.firstName} ${user.lastName}`,
|
||||||
|
},
|
||||||
|
queryRunner,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await queryRunner.commitTransaction();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: CommonMessage.CREATED,
|
message: CommonMessage.CREATED,
|
||||||
comment,
|
comment,
|
||||||
};
|
};
|
||||||
|
} catch (error) {
|
||||||
|
await queryRunner.rollbackTransaction();
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
await queryRunner.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//*********************************** */
|
//*********************************** */
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,15 @@ import { DanakServicesCategoryRepository } from "./repositories/danak-services-c
|
|||||||
import { DanakServicesImageRepository } from "./repositories/danak-services-image.repository";
|
import { DanakServicesImageRepository } from "./repositories/danak-services-image.repository";
|
||||||
import { DanakServiceReviewRepository } from "./repositories/danak-services-review.repository";
|
import { DanakServiceReviewRepository } from "./repositories/danak-services-review.repository";
|
||||||
import { DanakServicesRepository } from "./repositories/danak-services.repository";
|
import { DanakServicesRepository } from "./repositories/danak-services.repository";
|
||||||
|
import { NotificationModule } from "../notifications/notifications.module";
|
||||||
|
import { UsersModule } from "../users/users.module";
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([DanakService, DanakServiceImage, DanakServiceCategory, DanakServiceReview])],
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([DanakService, DanakServiceImage, DanakServiceCategory, DanakServiceReview]),
|
||||||
|
UsersModule,
|
||||||
|
NotificationModule,
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
DanakServicesService,
|
DanakServicesService,
|
||||||
DanakServicesRepository,
|
DanakServicesRepository,
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ import { DataSource, FindOptionsWhere, In, IsNull, Not, QueryRunner } from "type
|
|||||||
|
|
||||||
import { ParamDto } from "../../../common/DTO/param.dto";
|
import { ParamDto } from "../../../common/DTO/param.dto";
|
||||||
import { CategoryMessage, CommonMessage, ServiceMessage, SubscriptionMessage } from "../../../common/enums/message.enum";
|
import { CategoryMessage, CommonMessage, ServiceMessage, SubscriptionMessage } from "../../../common/enums/message.enum";
|
||||||
|
import { NotificationsService } from "../../notifications/providers/notifications.service";
|
||||||
import { SubscriptionStatus } from "../../subscriptions/enums/subscription-status.enum";
|
import { SubscriptionStatus } from "../../subscriptions/enums/subscription-status.enum";
|
||||||
|
import { AdminsService } from "../../users/providers/admins.service";
|
||||||
|
import { UsersService } from "../../users/providers/users.service";
|
||||||
import { PaginationUtils } from "../../utils/providers/pagination.utils";
|
import { PaginationUtils } from "../../utils/providers/pagination.utils";
|
||||||
import { AddReviewDto } from "../DTO/add-review.dto";
|
import { AddReviewDto } from "../DTO/add-review.dto";
|
||||||
import { CategoryListSearchQueryDto, CategorySearchQueryDto } from "../DTO/category-search-query.dto";
|
import { CategoryListSearchQueryDto, CategorySearchQueryDto } from "../DTO/category-search-query.dto";
|
||||||
@@ -21,7 +24,6 @@ import { DanakServicesCategoryRepository } from "../repositories/danak-services-
|
|||||||
import { DanakServicesImageRepository } from "../repositories/danak-services-image.repository";
|
import { DanakServicesImageRepository } from "../repositories/danak-services-image.repository";
|
||||||
import { DanakServiceReviewRepository } from "../repositories/danak-services-review.repository";
|
import { DanakServiceReviewRepository } from "../repositories/danak-services-review.repository";
|
||||||
import { DanakServicesRepository } from "../repositories/danak-services.repository";
|
import { DanakServicesRepository } from "../repositories/danak-services.repository";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DanakServicesService {
|
export class DanakServicesService {
|
||||||
private readonly logger = new Logger(DanakServicesService.name);
|
private readonly logger = new Logger(DanakServicesService.name);
|
||||||
@@ -31,6 +33,9 @@ export class DanakServicesService {
|
|||||||
private readonly danakServiceReviewRepository: DanakServiceReviewRepository,
|
private readonly danakServiceReviewRepository: DanakServiceReviewRepository,
|
||||||
private readonly danakServicesImageRepository: DanakServicesImageRepository,
|
private readonly danakServicesImageRepository: DanakServicesImageRepository,
|
||||||
private readonly dataSource: DataSource,
|
private readonly dataSource: DataSource,
|
||||||
|
private readonly adminsService: AdminsService,
|
||||||
|
private readonly notificationsService: NotificationsService,
|
||||||
|
private readonly usersService: UsersService,
|
||||||
) {}
|
) {}
|
||||||
/******************************************** */
|
/******************************************** */
|
||||||
|
|
||||||
@@ -492,26 +497,58 @@ export class DanakServicesService {
|
|||||||
/******************************************** */
|
/******************************************** */
|
||||||
|
|
||||||
async addReview(userId: string, serviceId: string, addReviewDto: AddReviewDto) {
|
async addReview(userId: string, serviceId: string, addReviewDto: AddReviewDto) {
|
||||||
const service = await this.findServiceById(serviceId);
|
const queryRunner = this.dataSource.createQueryRunner();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await queryRunner.connect();
|
||||||
|
await queryRunner.startTransaction();
|
||||||
|
|
||||||
|
const user = await this.usersService.findOneByIdWithQueryRunner(userId, queryRunner);
|
||||||
|
|
||||||
|
const service = await queryRunner.manager.findOne(this.danakServicesRepository.target, {
|
||||||
|
where: { id: serviceId, deletedAt: IsNull() },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!service) throw new BadRequestException(ServiceMessage.SERVICE_NOT_EXIST);
|
||||||
|
|
||||||
const hasSubscription = await this.checkUserPurchasedService(userId, serviceId);
|
const hasSubscription = await this.checkUserPurchasedService(userId, serviceId);
|
||||||
if (!hasSubscription) throw new BadRequestException(SubscriptionMessage.NOT_PURCHASED_CANNOT_REVIEW);
|
if (!hasSubscription) throw new BadRequestException(SubscriptionMessage.NOT_PURCHASED_CANNOT_REVIEW);
|
||||||
|
|
||||||
// // Check if user already reviewed this service
|
const review = queryRunner.manager.create(this.danakServiceReviewRepository.target, {
|
||||||
// const existingReview = await this.danakServiceReviewRepository.findOne({
|
user: { id: userId },
|
||||||
// where: { user: { id: userId }, service: { id: serviceId } },
|
...addReviewDto,
|
||||||
// });
|
service,
|
||||||
|
});
|
||||||
|
|
||||||
// if (existingReview) {
|
await queryRunner.manager.save(this.danakServiceReviewRepository.target, review);
|
||||||
// throw new BadRequestException(ServiceMessage.ALREADY_REVIEWED);
|
|
||||||
// }
|
|
||||||
|
|
||||||
const review = this.danakServiceReviewRepository.create({ user: { id: userId }, ...addReviewDto, service });
|
const superAdmins = await this.adminsService.getSuperAdmins();
|
||||||
await this.danakServiceReviewRepository.save(review);
|
|
||||||
|
for (const admin of superAdmins) {
|
||||||
|
await this.notificationsService.createNewServiceReviewNotification(
|
||||||
|
admin.id,
|
||||||
|
{
|
||||||
|
serviceName: service.name,
|
||||||
|
userPhone: user.phone,
|
||||||
|
userEmail: user.email,
|
||||||
|
fullName: `${user.firstName} ${user.lastName}`,
|
||||||
|
},
|
||||||
|
queryRunner,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await queryRunner.commitTransaction();
|
||||||
return {
|
return {
|
||||||
message: ServiceMessage.REVIEW_ADDED,
|
message: ServiceMessage.REVIEW_ADDED,
|
||||||
review,
|
review,
|
||||||
};
|
};
|
||||||
|
} catch (error) {
|
||||||
|
await queryRunner.rollbackTransaction();
|
||||||
|
this.logger.error("Error in add review", error);
|
||||||
|
throw error;
|
||||||
|
} finally {
|
||||||
|
await queryRunner.release();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************** */
|
/******************************************** */
|
||||||
@@ -578,9 +615,10 @@ export class DanakServicesService {
|
|||||||
.replace(/-+/g, "-") // Replace multiple hyphens with single hyphen
|
.replace(/-+/g, "-") // Replace multiple hyphens with single hyphen
|
||||||
.trim();
|
.trim();
|
||||||
}
|
}
|
||||||
|
/******************************************** */
|
||||||
|
|
||||||
private async checkUserPurchasedService(userId: string, serviceId: string) {
|
private async checkUserPurchasedService(userId: string, serviceId: string, queryRunner?: QueryRunner) {
|
||||||
const subscription = await this.danakServicesRepository
|
const subscription = await (queryRunner ? queryRunner.manager : this.danakServicesRepository)
|
||||||
.createQueryBuilder()
|
.createQueryBuilder()
|
||||||
.select("1")
|
.select("1")
|
||||||
.from("user_subscription", "us")
|
.from("user_subscription", "us")
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { CreateRoleDto } from "../DTO/create-role.dto";
|
|||||||
import { SearchAdminQueryDto } from "../DTO/search-admins-query.dto";
|
import { SearchAdminQueryDto } from "../DTO/search-admins-query.dto";
|
||||||
import { SearchRolesQueryDto } from "../DTO/search-roles.dto";
|
import { SearchRolesQueryDto } from "../DTO/search-roles.dto";
|
||||||
import { UpdateAdminDto } from "../DTO/update-admin.dto";
|
import { UpdateAdminDto } from "../DTO/update-admin.dto";
|
||||||
|
import { RoleEnum } from "../enums/role.enum";
|
||||||
import { PermissionsRepository } from "../repositories/permissions.repository";
|
import { PermissionsRepository } from "../repositories/permissions.repository";
|
||||||
import { RoleRepository } from "../repositories/roles.repository";
|
import { RoleRepository } from "../repositories/roles.repository";
|
||||||
import { UserRepository } from "../repositories/users.repository";
|
import { UserRepository } from "../repositories/users.repository";
|
||||||
@@ -221,4 +222,8 @@ export class AdminsService {
|
|||||||
paginate: true,
|
paginate: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/************************************************************ */
|
||||||
|
async getSuperAdmins() {
|
||||||
|
return this.userRepository.find({ where: { roles: { isAdmin: true, name: RoleEnum.SUPER_ADMIN } } });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user