category
This commit is contained in:
@@ -36,21 +36,17 @@ export class CategoryController {
|
|||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Post('admin/categories')
|
@Post('admin/categories')
|
||||||
create(@Body() dto: CreateCategoryDto) {
|
create(@Body() dto: CreateCategoryDto, @RestId() restId: string) {
|
||||||
return this.categoryService.create(dto);
|
return this.categoryService.create(restId, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation({ summary: 'my restaurant categories' })
|
@ApiOperation({ summary: 'my restaurant categories' })
|
||||||
@ApiOkResponse({ description: 'List of categories' })
|
@ApiOkResponse({ description: 'List of categories' })
|
||||||
@ApiQuery({ name: 'restId', required: false, type: String })
|
|
||||||
@ApiQuery({ name: 'isActive', required: false, type: Boolean })
|
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@Get('admin/categories')
|
@Get('admin/categories')
|
||||||
findAll(@RestId() restId: string, @Query('isActive') isActive?: string) {
|
findAll(@RestId() restId: string) {
|
||||||
// convert isActive from query string to boolean when provided
|
return this.categoryService.findAllByRestaurantId(restId);
|
||||||
const isActiveBool: boolean | undefined = typeof isActive !== 'undefined' ? isActive === 'true' : undefined;
|
|
||||||
return this.categoryService.findAll({ restId, isActive: isActiveBool });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(AdminAuthGuard)
|
@UseGuards(AdminAuthGuard)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Entity, Property, Collection, OneToMany } from '@mikro-orm/core';
|
import { Entity, Property, Collection, OneToMany, ManyToOne } from '@mikro-orm/core';
|
||||||
import { Food } from './food.entity';
|
import { Food } from './food.entity';
|
||||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||||
|
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
|
||||||
|
|
||||||
@Entity({ tableName: 'categories' })
|
@Entity({ tableName: 'categories' })
|
||||||
export class Category extends BaseEntity {
|
export class Category extends BaseEntity {
|
||||||
@@ -13,8 +14,8 @@ export class Category extends BaseEntity {
|
|||||||
@Property({ default: true })
|
@Property({ default: true })
|
||||||
isActive: boolean = true;
|
isActive: boolean = true;
|
||||||
|
|
||||||
@Property({ nullable: true })
|
@ManyToOne(() => Restaurant)
|
||||||
restId?: string;
|
restaurant!: Restaurant;
|
||||||
|
|
||||||
@Property({ nullable: true })
|
@Property({ nullable: true })
|
||||||
avatarUrl?: string;
|
avatarUrl?: string;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ 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';
|
||||||
import { EntityManager } from '@mikro-orm/postgresql';
|
import { EntityManager } from '@mikro-orm/postgresql';
|
||||||
import { RequiredEntityData, FilterQuery } from '@mikro-orm/core';
|
import { RequiredEntityData } from '@mikro-orm/core';
|
||||||
import { Category } from '../entities/category.entity';
|
import { Category } from '../entities/category.entity';
|
||||||
import { CategoryMessage, RestMessage } from 'src/common/enums/message.enum';
|
import { CategoryMessage, RestMessage } from 'src/common/enums/message.enum';
|
||||||
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
|
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
|
||||||
@@ -15,12 +15,15 @@ export class CategoryService {
|
|||||||
private readonly em: EntityManager,
|
private readonly em: EntityManager,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async create(dto: CreateCategoryDto): Promise<Category> {
|
async create(restId: string, dto: CreateCategoryDto): Promise<Category> {
|
||||||
|
const restaurant = await this.em.findOne(Restaurant, { id: restId });
|
||||||
|
if (!restaurant) {
|
||||||
|
throw new NotFoundException(RestMessage.NOT_FOUND);
|
||||||
|
}
|
||||||
const data: RequiredEntityData<Category> = {
|
const data: RequiredEntityData<Category> = {
|
||||||
title: dto.title,
|
title: dto.title,
|
||||||
isActive: dto.isActive ?? true,
|
isActive: dto.isActive ?? true,
|
||||||
//TODO
|
restaurant: restaurant,
|
||||||
restId: '01KA35CFFN0F6VA04DF0W6KCE3',
|
|
||||||
avatarUrl: dto.avatarUrl,
|
avatarUrl: dto.avatarUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -34,37 +37,41 @@ export class CategoryService {
|
|||||||
if (!restaurant || !restaurant.id) {
|
if (!restaurant || !restaurant.id) {
|
||||||
throw new NotFoundException(RestMessage.NOT_FOUND);
|
throw new NotFoundException(RestMessage.NOT_FOUND);
|
||||||
}
|
}
|
||||||
return this.categoryRepository.find({ restId: restaurant.id.toString() });
|
return this.categoryRepository.find({ restaurant: restaurant });
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(opts?: { restId?: string; isActive?: boolean }): Promise<Category[]> {
|
async findAllByRestaurantId(restId: string): Promise<Category[]> {
|
||||||
const where: FilterQuery<Category> = {};
|
return this.categoryRepository.find({ restaurant: { id: restId } });
|
||||||
if (opts?.restId) where.restId = opts.restId;
|
|
||||||
if (opts && typeof opts.isActive === 'boolean') where.isActive = opts.isActive;
|
|
||||||
const cats = await this.categoryRepository.find(where, { populate: ['foods'] });
|
|
||||||
|
|
||||||
// Return plain objects to avoid circular references during JSON serialization
|
|
||||||
return cats.map(cat => ({
|
|
||||||
id: cat.id,
|
|
||||||
title: cat.title,
|
|
||||||
isActive: cat.isActive,
|
|
||||||
restId: cat.restId,
|
|
||||||
avatarUrl: cat.avatarUrl,
|
|
||||||
createdAt: cat.createdAt,
|
|
||||||
updatedAt: cat.updatedAt,
|
|
||||||
foods: cat.foods.getItems().map(f => ({ id: f.id, title: f.title })),
|
|
||||||
})) as unknown as Category[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// async findAll(opts?: { restId?: string; isActive?: boolean }): Promise<Category[]> {
|
||||||
|
// const where: FilterQuery<Category> = {};
|
||||||
|
// if (opts?.restId) where.restId = opts.restId;
|
||||||
|
// if (opts && typeof opts.isActive === 'boolean') where.isActive = opts.isActive;
|
||||||
|
// const cats = await this.categoryRepository.find(where, { populate: ['foods'] });
|
||||||
|
|
||||||
|
// // Return plain objects to avoid circular references during JSON serialization
|
||||||
|
// return cats.map(cat => ({
|
||||||
|
// id: cat.id,
|
||||||
|
// title: cat.title,
|
||||||
|
// isActive: cat.isActive,
|
||||||
|
// restId: cat.restId,
|
||||||
|
// avatarUrl: cat.avatarUrl,
|
||||||
|
// createdAt: cat.createdAt,
|
||||||
|
// updatedAt: cat.updatedAt,
|
||||||
|
// foods: cat.foods.getItems().map(f => ({ id: f.id, title: f.title })),
|
||||||
|
// })) as unknown as Category[];
|
||||||
|
// }
|
||||||
|
|
||||||
async findOne(restId: string, id: string): Promise<Category> {
|
async findOne(restId: string, id: string): Promise<Category> {
|
||||||
const cat = await this.categoryRepository.findOne({ id, restId }, { populate: ['foods'] });
|
const cat = await this.categoryRepository.findOne({ id, restaurant: { id: restId } }, { populate: ['foods'] });
|
||||||
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: cat.id,
|
id: cat.id,
|
||||||
title: cat.title,
|
title: cat.title,
|
||||||
isActive: cat.isActive,
|
isActive: cat.isActive,
|
||||||
restId: cat.restId,
|
restaurant: cat.restaurant,
|
||||||
avatarUrl: cat.avatarUrl,
|
avatarUrl: cat.avatarUrl,
|
||||||
createdAt: cat.createdAt,
|
createdAt: cat.createdAt,
|
||||||
updatedAt: cat.updatedAt,
|
updatedAt: cat.updatedAt,
|
||||||
@@ -73,14 +80,14 @@ export class CategoryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async findRestaurantCategories(restId: string): Promise<Category> {
|
async findRestaurantCategories(restId: string): Promise<Category> {
|
||||||
const cat = await this.categoryRepository.findOne({ restId }, { populate: ['foods'] });
|
const cat = await this.categoryRepository.findOne({ restaurant: { id: restId } }, { populate: ['foods'] });
|
||||||
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: cat.id,
|
id: cat.id,
|
||||||
title: cat.title,
|
title: cat.title,
|
||||||
isActive: cat.isActive,
|
isActive: cat.isActive,
|
||||||
restId: cat.restId,
|
restaurant: cat.restaurant,
|
||||||
avatarUrl: cat.avatarUrl,
|
avatarUrl: cat.avatarUrl,
|
||||||
createdAt: cat.createdAt,
|
createdAt: cat.createdAt,
|
||||||
updatedAt: cat.updatedAt,
|
updatedAt: cat.updatedAt,
|
||||||
@@ -88,7 +95,7 @@ export class CategoryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update(restId: string, id: string, dto: UpdateCategoryDto): Promise<Category> {
|
async update(restId: string, id: string, dto: UpdateCategoryDto): Promise<Category> {
|
||||||
const cat = await this.categoryRepository.findOne({ id, restId });
|
const cat = await this.categoryRepository.findOne({ id, restaurant: { id: restId } });
|
||||||
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
||||||
this.em.assign(cat, dto);
|
this.em.assign(cat, dto);
|
||||||
await this.em.persistAndFlush(cat);
|
await this.em.persistAndFlush(cat);
|
||||||
@@ -96,7 +103,7 @@ export class CategoryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async remove(restId: string, id: string): Promise<void> {
|
async remove(restId: string, id: string): Promise<void> {
|
||||||
const cat = await this.categoryRepository.findOne({ id, restId });
|
const cat = await this.categoryRepository.findOne({ id, restaurant: { id: restId } });
|
||||||
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
|
||||||
cat.deletedAt = new Date();
|
cat.deletedAt = new Date();
|
||||||
await this.em.persistAndFlush(cat);
|
await this.em.persistAndFlush(cat);
|
||||||
|
|||||||
@@ -235,23 +235,28 @@ export class DatabaseSeeder extends Seeder {
|
|||||||
|
|
||||||
// 6. Create Categories (Farsi)
|
// 6. Create Categories (Farsi)
|
||||||
const categories = [
|
const categories = [
|
||||||
{ title: 'غذای اصلی', restId: zhivan?.id },
|
{ title: 'غذای اصلی', restaurant: zhivan },
|
||||||
{ title: 'پیش غذا', restId: zhivan?.id },
|
{ title: 'پیش غذا', restaurant: zhivan },
|
||||||
{ title: 'دسر', restId: zhivan?.id },
|
{ title: 'دسر', restaurant: zhivan },
|
||||||
{ title: 'نوشیدنی', restId: zhivan?.id },
|
{ title: 'نوشیدنی', restaurant: zhivan },
|
||||||
{ title: 'غذای اصلی', restId: boote?.id },
|
{ title: 'غذای اصلی', restaurant: boote },
|
||||||
{ title: 'پیش غذا', restId: boote?.id },
|
{ title: 'پیش غذا', restaurant: boote },
|
||||||
{ title: 'دسر', restId: boote?.id },
|
{ title: 'دسر', restaurant: boote },
|
||||||
{ title: 'نوشیدنی', restId: boote?.id },
|
{ title: 'نوشیدنی', restaurant: boote },
|
||||||
];
|
];
|
||||||
|
|
||||||
const createdCategories: Category[] = [];
|
const createdCategories: Category[] = [];
|
||||||
for (const catData of categories) {
|
for (const catData of categories) {
|
||||||
const existing = await em.findOne(Category, { title: catData.title, restId: catData.restId });
|
if (!catData.restaurant) continue;
|
||||||
|
|
||||||
|
const existing = await em.findOne(Category, {
|
||||||
|
title: catData.title,
|
||||||
|
restaurant: catData.restaurant,
|
||||||
|
});
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
const category = em.create(Category, {
|
const category = em.create(Category, {
|
||||||
title: catData.title,
|
title: catData.title,
|
||||||
restId: catData.restId,
|
restaurant: catData.restaurant,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
});
|
});
|
||||||
em.persist(category);
|
em.persist(category);
|
||||||
|
|||||||
Reference in New Issue
Block a user