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