category
This commit is contained in:
@@ -15,6 +15,6 @@ export const API_HEADER_SLUG = {
|
||||
required: true,
|
||||
schema: {
|
||||
type: 'string',
|
||||
default: 'zhivan',
|
||||
default: 'boote',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -5,11 +5,6 @@ import { UpdateCategoryDto } from '../dto/update-category.dto';
|
||||
import {
|
||||
ApiTags,
|
||||
ApiOperation,
|
||||
ApiCreatedResponse,
|
||||
ApiOkResponse,
|
||||
ApiNotFoundResponse,
|
||||
ApiParam,
|
||||
ApiBody,
|
||||
ApiBearerAuth,
|
||||
ApiHeader,
|
||||
} from '@nestjs/swagger';
|
||||
@@ -28,62 +23,55 @@ export class CategoryController {
|
||||
@Get('public/categories/shop/:slug')
|
||||
@ApiOperation({ summary: 'Get all categories by shop slug' })
|
||||
@ApiHeader(API_HEADER_SLUG)
|
||||
@ApiParam({ name: 'slug', required: true, description: 'Shop Slug' })
|
||||
@ApiOkResponse({ description: 'List of all categories for the shop' })
|
||||
findAllByRestaurant(@Param('slug') slug: string) {
|
||||
return this.categoryService.findAllByShop(slug);
|
||||
return this.categoryService.findAllByShopSlug(slug);
|
||||
}
|
||||
|
||||
/*** Admin ***/
|
||||
|
||||
@Post('admin/categories')
|
||||
@ApiOperation({ summary: 'Create category' })
|
||||
@ApiBody({ type: CreateCategoryDto })
|
||||
@Permissions(Permission.MANAGE_CATEGORIES)
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Post('admin/categories')
|
||||
create(@Body() dto: CreateCategoryDto, @ShopId() restId: string) {
|
||||
return this.categoryService.create(restId, dto);
|
||||
create(@Body() dto: CreateCategoryDto, @ShopId() shopId: string) {
|
||||
return this.categoryService.create(shopId, dto);
|
||||
}
|
||||
|
||||
@Get('admin/categories')
|
||||
@Permissions(Permission.MANAGE_CATEGORIES)
|
||||
@ApiOperation({ summary: 'my shop categories' })
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Get('admin/categories')
|
||||
findAll(@ShopId() restId: string) {
|
||||
return this.categoryService.findAllByShopId(restId);
|
||||
findAll(@ShopId() shopId: string) {
|
||||
return this.categoryService.findAllByShopId(shopId);
|
||||
}
|
||||
|
||||
@Permissions(Permission.MANAGE_CATEGORIES)
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Get('admin/categories/:id')
|
||||
@Permissions(Permission.MANAGE_CATEGORIES)
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@ApiOperation({ summary: 'Get category' })
|
||||
@ApiParam({ name: 'id', required: true, type: String })
|
||||
findOne(@Param('id') id: string, @ShopId() restId: string) {
|
||||
return this.categoryService.findOne(restId, id);
|
||||
findOne(@Param('id') id: string, @ShopId() shopId: string) {
|
||||
return this.categoryService.findOne(shopId, id);
|
||||
}
|
||||
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Permissions(Permission.MANAGE_CATEGORIES)
|
||||
@Patch('admin/categories/:id')
|
||||
@ApiOperation({ summary: 'Update category' })
|
||||
@ApiParam({ name: 'id' })
|
||||
@ApiBody({ type: UpdateCategoryDto })
|
||||
update(@Param('id') id: string, @Body() dto: UpdateCategoryDto, @ShopId() restId: string) {
|
||||
return this.categoryService.update(restId, id, dto);
|
||||
}
|
||||
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Permissions(Permission.MANAGE_CATEGORIES)
|
||||
@ApiOperation({ summary: 'Update category' })
|
||||
update(@Param('id') id: string, @Body() dto: UpdateCategoryDto, @ShopId() shopId: string) {
|
||||
return this.categoryService.update(shopId, id, dto);
|
||||
}
|
||||
|
||||
@Delete('admin/categories/:id')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@Permissions(Permission.MANAGE_CATEGORIES)
|
||||
@ApiOperation({ summary: 'Delete category' })
|
||||
@ApiParam({ name: 'id' })
|
||||
@ApiOkResponse({ description: 'Deleted' })
|
||||
remove(@Param('id') id: string, @ShopId() restId: string) {
|
||||
return this.categoryService.remove(restId, id);
|
||||
remove(@Param('id') id: string, @ShopId() shopId: string) {
|
||||
return this.categoryService.remove(shopId, id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ export class CreateCategoryDto {
|
||||
order?: number;
|
||||
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
@ApiPropertyOptional({ example: '123e4567-e89b-12d3-a456-426614174000' })
|
||||
parentId?: string;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
|
||||
import { CreateCategoryDto } from '../dto/create-category.dto';
|
||||
import { UpdateCategoryDto } from '../dto/update-category.dto';
|
||||
import { CategoryRepository } from '../repositories/category.repository';
|
||||
@@ -44,34 +44,25 @@ export class CategoryService {
|
||||
return category;
|
||||
}
|
||||
|
||||
async findAllByShop(shopSlug: string): Promise<Category[]> {
|
||||
async findAllByShopSlug(shopSlug: string): Promise<Category[]> {
|
||||
return this.categoryRepository.find(
|
||||
{ shop: { slug: shopSlug }, isActive: true, parent: null },
|
||||
{ orderBy: { order: 'ASC' }, populate: ['parent'] });
|
||||
{ orderBy: { order: 'ASC' }, populate: ['children','parent'] });
|
||||
}
|
||||
|
||||
async findAllByShopId(shopId: string): Promise<Category[]> {
|
||||
return this.categoryRepository.find(
|
||||
{ shop: { id: shopId } },
|
||||
{ orderBy: { order: 'asc' }, populate: ['parent'] });
|
||||
{ orderBy: { order: 'asc' }, populate: ['children','parent'] });
|
||||
}
|
||||
|
||||
async findOne(shopId: string, id: string): Promise<Category> {
|
||||
const cat = await this.categoryRepository.findOne({ id, shop: { id: shopId } }, { populate: ['products', 'parent'] });
|
||||
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
||||
async findOne(shopId: string, categoryId: string): Promise<Category> {
|
||||
const category = await this.findOrFail(categoryId)
|
||||
if (category.shop.id !== shopId) {
|
||||
throw new BadRequestException("Category doesnnot belong to shop")
|
||||
}
|
||||
return category
|
||||
|
||||
return {
|
||||
id: cat.id,
|
||||
title: cat.title,
|
||||
isActive: cat.isActive,
|
||||
shop: cat.shop,
|
||||
avatarUrl: cat.avatarUrl,
|
||||
order: cat.order,
|
||||
parent: cat.parent,
|
||||
createdAt: cat.createdAt,
|
||||
updatedAt: cat.updatedAt,
|
||||
products: cat.products.getItems().map(f => ({ id: f.id, title: f.title })),
|
||||
} as unknown as Category;
|
||||
}
|
||||
|
||||
async update(shopId: string, id: string, dto: UpdateCategoryDto): Promise<Category> {
|
||||
@@ -102,4 +93,10 @@ export class CategoryService {
|
||||
cat.deletedAt = new Date();
|
||||
await this.em.persistAndFlush(cat);
|
||||
}
|
||||
|
||||
async findOrFail(categoryId: string) {
|
||||
const category = await this.categoryRepository.findOne({ id: categoryId },{populate:['parent','children']});
|
||||
if (!category) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
||||
return category
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,18 @@ import { CategoryRepository } from '../repositories/category.repository';
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { RequiredEntityData, FilterQuery } from '@mikro-orm/core';
|
||||
import { Product } from '../entities/product.entity';
|
||||
import { CategoryMessage, ProductMessage, RestMessage } from 'src/common/enums/message.enum';
|
||||
import { CategoryMessage, ProductMessage } from 'src/common/enums/message.enum';
|
||||
import { Favorite } from '../entities/favorite.entity';
|
||||
import { Variant } from '../entities/variant.entity';
|
||||
import { ShopService } from 'src/modules/shops/providers/shops.service';
|
||||
import { CategoryService } from './category.service';
|
||||
|
||||
@Injectable()
|
||||
export class ProductService {
|
||||
constructor(
|
||||
private readonly productRepository: ProductRepository,
|
||||
private readonly categoryRepository: CategoryRepository,
|
||||
private readonly categoryService: CategoryService,
|
||||
private readonly shopService: ShopService,
|
||||
private readonly em: EntityManager,
|
||||
) { }
|
||||
@@ -23,13 +25,8 @@ export class ProductService {
|
||||
async create(shopId: string, dto: CreateProductDto) {
|
||||
const { categoryId, variants, ...rest } = dto;
|
||||
const shop = await this.shopService.findOrFail(shopId);
|
||||
if (!shop) {
|
||||
throw new NotFoundException(RestMessage.NOT_FOUND);
|
||||
}
|
||||
const category = await this.categoryRepository.findOne({ id: categoryId, shop: { id: shopId } });
|
||||
if (!category) {
|
||||
throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
||||
}
|
||||
|
||||
const category = await this.categoryService.findOrFail(categoryId)
|
||||
|
||||
const product = await this.em.transactional(async em => {
|
||||
// prepare data with defaults for required fields so repository.create typing is satisfied
|
||||
@@ -50,8 +47,6 @@ export class ProductService {
|
||||
|
||||
const product = em.create(Product, data);
|
||||
|
||||
em.persist(product)
|
||||
|
||||
for (const variant of variants) {
|
||||
const variantRecord = em.create(Variant, {
|
||||
product,
|
||||
@@ -179,7 +174,7 @@ export class ProductService {
|
||||
|
||||
return product;
|
||||
}
|
||||
|
||||
|
||||
|
||||
async remove(shopId: string, id: string): Promise<void> {
|
||||
const product = await this.findOrFail(id)
|
||||
@@ -216,7 +211,7 @@ export class ProductService {
|
||||
* Helper
|
||||
*/
|
||||
async findOrFail(productId: string) {
|
||||
const product = await this.productRepository.findOne({ id: productId, isActive: true },
|
||||
const product = await this.productRepository.findOne({ id: productId },
|
||||
{ populate: ['category', 'variants', 'shop'] });
|
||||
|
||||
if (!product) throw new NotFoundException(ProductMessage.NOT_FOUND);
|
||||
|
||||
Reference in New Issue
Block a user