This commit is contained in:
2026-01-15 19:50:48 +03:30
parent 264b6585a8
commit 7229931045
3 changed files with 74 additions and 85 deletions
@@ -20,6 +20,7 @@ import { Permissions } from 'src/common/decorators/permissions.decorator';
import { CreateCategoryDto } from '../dto/create-category.dto';
import { CategoryService } from '../providers/category.service';
import { FindCategoriesDto } from '../dto/find-categories.dto';
import { UpdateCategoryDto } from '../dto/update-category.dto';
@ApiTags('products')
@Controller()
@@ -126,4 +127,36 @@ export class productController {
const result = await this.categoryService.findAll(dto);
return result;
}
@Get('admin/products/category/:id')
// @UseGuards(AdminAuthGuard)
@ApiBearerAuth()
@Permissions(Permission.MANAGE_productS)
@ApiOperation({ summary: 'Get a category by id' })
@ApiParam({ name: 'id', required: true })
findCategoryById(@Param('id') id: string) {
return this.categoryService.findById(+id);
}
@Patch('admin/products/category/:id')
// @UseGuards(AdminAuthGuard)
@ApiBearerAuth()
@Permissions(Permission.MANAGE_productS)
@ApiOperation({ summary: 'Update a category' })
@ApiParam({ name: 'id', required: true })
@ApiBody({ type: UpdateCategoryDto })
updateCategory(@Param('id') id: string, @Body() dto: UpdateCategoryDto) {
return this.categoryService.update(+id, dto);
}
@Delete('admin/products/category/:id')
// @UseGuards(AdminAuthGuard)
@ApiBearerAuth()
@Permissions(Permission.MANAGE_productS)
@ApiOperation({ summary: 'Delete (soft) a category' })
@ApiParam({ name: 'id', required: true })
removeCategory(@Param('id') id: string,) {
return this.categoryService.remove(+id);
}
}
@@ -15,7 +15,7 @@ export class Category extends BaseEntity {
@PrimaryKey({ type: 'bigint', autoincrement: true })
id: number
@Property({ unique: true })
@Property()
title: string;
// @OneToMany(() => Product, product => product.category)
@@ -1,22 +1,18 @@
import { BadGatewayException, Injectable, NotFoundException } from '@nestjs/common';
import { CreateproductDto } from '../dto/create-product.dto';
import { FindproductsDto } from '../dto/find-products.dto';
import { ProductRepository } from '../repositories/product.repository';
import { EntityManager } from '@mikro-orm/postgresql';
import { RequiredEntityData } from '@mikro-orm/core';
import { Product } from '../entities/product.entity';
import { CategoryMessage, productMessage } from 'src/common/enums/message.enum';
import { CategoryMessage, productMessage } from 'src/common/enums/message.enum';
import { CategoryRepository } from '../repositories/category.repository';
import { CreateCategoryDto } from '../dto/create-category.dto';
import { Category } from '../entities/category.entity';
import { FindCategoriesDto } from '../dto/find-categories.dto';
import { UpdateCategoryDto } from '../dto/update-category.dto';
@Injectable()
export class CategoryService {
constructor(
private readonly productRepository: ProductRepository,
private readonly categoryRepository: CategoryRepository,
private readonly categoryRepository: CategoryRepository,
private readonly em: EntityManager,
) { }
@@ -46,97 +42,57 @@ export class CategoryService {
}
// async update(productId: string, createproductDto: Partial<CreateproductDto>) {
// const { categoryId, ...rest } = createproductDto;
// const product = await this.productRepository.findOne({ id: productId })
// if (!product) {
// throw new NotFoundException(productMessage.NOT_FOUND);
// }
async update(categoryId: number, dto: UpdateCategoryDto) {
// if (categoryId) {
// const category = await this.categoryRepository.findOne({ id: categoryId });
// if (!category) {
// throw new NotFoundException(CategoryMessage.NOT_FOUND);
// }
// this.productRepository.assign(product, { category })
// }
const category = await this.categoryRepository.findOne({ id: categoryId })
// this.productRepository.assign(product, rest)
// //TODO : which one od these are correct
// // this.productRepository.nativeUpdate(productId,product)
// this.em.persistAndFlush(product)
if (!category) {
throw new NotFoundException(CategoryMessage.NOT_FOUND);
}
// }
if (dto.parentId) {
console.log('pp', dto.parentId)
const parent = await this.categoryRepository.findOne({ id: dto.parentId })
if (!parent) {
throw new NotFoundException(CategoryMessage.NOT_FOUND);
}
this.categoryRepository.assign(category, { parent })
}
this.categoryRepository.assign(category, dto)
//TODO : which one od these are correct
// this.productRepository.nativeUpdate(productId,product)
this.em.persistAndFlush(category)
return category
}
findAll(dto: FindCategoriesDto) {
return this.categoryRepository.findAllPaginated(dto);
}
async findById(productId: string): Promise<Product> {
const product = await this.productRepository.findOne({ id: productId }, { populate: ['category', 'attributes'] });
async findById(catId: number): Promise<Category> {
const category = await this.categoryRepository.findOne({ id: catId },
{ populate: ['children', 'parent'] });
if (!product) throw new NotFoundException(productMessage.NOT_FOUND);
return product;
if (!category) throw new NotFoundException(CategoryMessage.NOT_FOUND);
return category;
}
// async update( id: string, dto: Partial<CreateproductDto>): Promise<Product> {
// const { categoryId, dailyStock, ...rest } = dto;
// const product = await this.productRepository.findOne({ id, restaurant: { id: } }, { populate: ['restaurant'] });
// if (!product) {
// throw new NotFoundException(productMessage.NOT_FOUND);
// }
// // attach new categories if provided (adds, does not attempt to preserve/remove existing ones)
// if (categoryId) {
// const category = await this.categoryRepository.findOne({ id: categoryId, restaurant: { id: } });
// if (!category) {
// throw new NotFoundException(CategoryMessage.NOT_FOUND);
// }
// this.em.assign(product, { category: category });
// }
// // assign other fields from DTO (excluding dailyStock handled below)
// this.em.assign(product, rest);
// // Persist product and update/create related inventory atomically
// await this.em.transactional(async em => {
// await em.persistAndFlush(product);
// if (typeof dailyStock !== 'undefined') {
// const inventoryRecord = await em.findOne(Inventory, { product: product });
// if (inventoryRecord) {
// inventoryRecord.totalStock = dailyStock;
// } else {
// em.create(Inventory, {
// product: product,
// availableStock: dailyStock,
// totalStock: dailyStock,
// });
// }
// }
// await em.flush();
// });
// // Re-load the product to ensure populated relations and stable instance
// const savedproduct = await this.productRepository.findOne({ id: product.id }, { populate: ['category', 'restaurant'] });
// // Invalidate cache for the restaurant if present (optional)
// // await this.invalidateRestaurantproductsCache(savedproduct?.restaurant?.slug);
// return savedproduct ?? product;
// }
async remove(id: string): Promise<void> {
const product = await this.productRepository.findOne({ id });
if (!product) {
async remove(id: number): Promise<void> {
const category = await this.findById(id);
if (!category) {
throw new NotFoundException(productMessage.NOT_FOUND);
}
product.deletedAt = new Date();
return await this.em.persistAndFlush(product);
if (category.children && category.children.length > 0) {
throw new NotFoundException('Category has children');
}
category.deletedAt = new Date();
return await this.em.persistAndFlush(category);
}