chore: add order to the service category
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsBoolean, IsNotEmpty, IsOptional, IsString, IsUUID, IsUrl, Length } from "class-validator";
|
||||
import { IsBoolean, IsInt, IsNotEmpty, IsOptional, IsString, IsUUID, IsUrl, Length } from "class-validator";
|
||||
|
||||
import { CategoryMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
@@ -25,4 +25,9 @@ export class CreateCategoryDto {
|
||||
@IsUUID("4", { message: CategoryMessage.PARENT_ID_SHOULD_BE_UUID })
|
||||
@ApiPropertyOptional({ description: "Parent category id", example: "8b1e8b1e-8b1e-8b1e-8b1e-8b1e8b1e8b1e" })
|
||||
parentId?: string;
|
||||
|
||||
@IsNotEmpty({ message: CategoryMessage.ORDER_REQUIRED })
|
||||
@IsInt({ message: CategoryMessage.ORDER_SHOULD_BE_INT })
|
||||
@ApiProperty({ description: "Category order", example: 1 })
|
||||
order: number;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@ export class DanakServiceCategory extends BaseEntity {
|
||||
@Column({ type: "boolean", default: true })
|
||||
isActive: boolean;
|
||||
|
||||
@Column({ type: "int", default: 1 })
|
||||
order: number;
|
||||
|
||||
@ManyToOne(() => DanakServiceCategory, (category) => category.children)
|
||||
@JoinColumn({ name: "parentId" })
|
||||
parent: DanakServiceCategory;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||
import { FindOptionsWhere, In, IsNull } from "typeorm";
|
||||
import { BadRequestException, Injectable, Logger } from "@nestjs/common";
|
||||
import { DataSource, FindOptionsWhere, In, IsNull, Not, QueryRunner } from "typeorm";
|
||||
|
||||
import { ParamDto } from "../../../common/DTO/param.dto";
|
||||
import { CategoryMessage, CommonMessage, ServiceMessage, SubscriptionMessage } from "../../../common/enums/message.enum";
|
||||
@@ -24,24 +24,67 @@ import { DanakServicesRepository } from "../repositories/danak-services.reposito
|
||||
|
||||
@Injectable()
|
||||
export class DanakServicesService {
|
||||
// private readonly logger = new Logger(DanakServicesService.name);
|
||||
private readonly logger = new Logger(DanakServicesService.name);
|
||||
constructor(
|
||||
private readonly danakServicesRepository: DanakServicesRepository,
|
||||
private readonly danakServicesCategoryRepository: DanakServicesCategoryRepository,
|
||||
private readonly danakServiceReviewRepository: DanakServiceReviewRepository,
|
||||
private readonly danakServicesImageRepository: DanakServicesImageRepository,
|
||||
private readonly dataSource: DataSource,
|
||||
) {}
|
||||
/******************************************** */
|
||||
|
||||
async createCategory(createDto: CreateCategoryDto) {
|
||||
const existCategory = await this.danakServicesCategoryRepository.findOneByTitle(createDto.title);
|
||||
if (existCategory) throw new BadRequestException(CategoryMessage.TITLE_EXIST);
|
||||
const category = this.danakServicesCategoryRepository.create(createDto);
|
||||
await this.danakServicesCategoryRepository.save(category);
|
||||
return {
|
||||
message: CommonMessage.CREATED,
|
||||
category,
|
||||
};
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
const existCategory = await queryRunner.manager.findOne(this.danakServicesCategoryRepository.target, {
|
||||
where: { title: createDto.title },
|
||||
});
|
||||
|
||||
if (existCategory) {
|
||||
throw new BadRequestException(CategoryMessage.TITLE_EXIST);
|
||||
}
|
||||
|
||||
const category = queryRunner.manager.create(this.danakServicesCategoryRepository.target, createDto);
|
||||
await queryRunner.manager.save(this.danakServicesCategoryRepository.target, category);
|
||||
|
||||
await this.handleOrderCollision(queryRunner, category);
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
return {
|
||||
message: CommonMessage.CREATED,
|
||||
category,
|
||||
};
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
this.logger.error("Error in create category", error);
|
||||
throw new BadRequestException(CategoryMessage.CREATION_FAILED);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
//*********************************** */
|
||||
private async handleOrderCollision(queryRunner: QueryRunner, newCategory: DanakServiceCategory): Promise<void> {
|
||||
const conflictingCategory = await queryRunner.manager.findOne(this.danakServicesCategoryRepository.target, {
|
||||
where: {
|
||||
order: newCategory.order,
|
||||
id: Not(newCategory.id),
|
||||
deletedAt: IsNull(),
|
||||
},
|
||||
});
|
||||
|
||||
if (conflictingCategory) {
|
||||
const highestOrderCategory = await queryRunner.manager.findOne(this.danakServicesCategoryRepository.target, {
|
||||
order: { order: "DESC" },
|
||||
where: { deletedAt: IsNull() },
|
||||
});
|
||||
|
||||
const newOrder = highestOrderCategory ? highestOrderCategory.order + 1 : newCategory.order + 1;
|
||||
await queryRunner.manager.update(this.danakServicesCategoryRepository.target, conflictingCategory.id, { order: newOrder });
|
||||
}
|
||||
}
|
||||
/******************************************** */
|
||||
|
||||
@@ -56,20 +99,42 @@ export class DanakServicesService {
|
||||
/******************************************** */
|
||||
|
||||
async updateCategory(categoryId: string, updateDto: UpdateCategoryDto) {
|
||||
const category = await this.danakServicesCategoryRepository.findOneById(categoryId);
|
||||
if (!category) throw new BadRequestException(CategoryMessage.CATEGORY_NOT_EXIST);
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
if (updateDto.title) {
|
||||
const existCategory = await this.danakServicesCategoryRepository.findOneByTitle(updateDto.title, categoryId);
|
||||
if (existCategory) throw new BadRequestException(CategoryMessage.TITLE_EXIST);
|
||||
try {
|
||||
const category = await queryRunner.manager.findOne(DanakServiceCategory, { where: { id: categoryId } });
|
||||
if (!category) throw new BadRequestException(CategoryMessage.CATEGORY_NOT_EXIST);
|
||||
|
||||
if (updateDto.title) {
|
||||
const existCategory = await queryRunner.manager.findOne(DanakServiceCategory, {
|
||||
where: { title: updateDto.title, id: Not(categoryId) },
|
||||
});
|
||||
if (existCategory) throw new BadRequestException(CategoryMessage.TITLE_EXIST);
|
||||
}
|
||||
|
||||
await queryRunner.manager.update(DanakServiceCategory, categoryId, updateDto);
|
||||
|
||||
if (updateDto.order !== undefined && updateDto.order !== category.order) {
|
||||
await this.handleOrderCollision(queryRunner, { ...category, ...updateDto });
|
||||
}
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
return {
|
||||
message: CommonMessage.UPDATE_SUCCESS,
|
||||
};
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
this.logger.error("Error in update category", error);
|
||||
throw new BadRequestException(CategoryMessage.UPDATE_FAILED);
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
|
||||
await this.danakServicesCategoryRepository.save({ ...category, ...updateDto });
|
||||
return {
|
||||
message: CommonMessage.UPDATE_SUCCESS,
|
||||
};
|
||||
}
|
||||
|
||||
/******************************************** */
|
||||
|
||||
async deleteCategoryById(categoryId: string) {
|
||||
const category = await this.danakServicesCategoryRepository.findOneById(categoryId);
|
||||
if (!category) throw new BadRequestException(CategoryMessage.CATEGORY_NOT_EXIST);
|
||||
@@ -131,7 +196,7 @@ export class DanakServicesService {
|
||||
async getCategoriesUserSide() {
|
||||
const categories = await this.danakServicesCategoryRepository.find({
|
||||
where: { isActive: true, deletedAt: IsNull() },
|
||||
order: { createdAt: "DESC" },
|
||||
order: { order: "DESC" },
|
||||
});
|
||||
return {
|
||||
categories,
|
||||
|
||||
Reference in New Issue
Block a user