This commit is contained in:
2026-04-07 16:31:06 +03:30
parent 055ba55586
commit 0386082d5f
5 changed files with 23 additions and 46 deletions
@@ -49,10 +49,10 @@ export class CategoryController {
@ApiOperation({ summary: 'my restaurant categories' })
@UseGuards(AdminAuthGuard)
@ApiBearerAuth()
@Get('admin/categories')
@Get('admin/categories')
findAll(@RestId() restId: string) {
return this.categoryService.findAllByRestaurantId(restId);
}
}
@Permissions(Permission.MANAGE_CATEGORIES)
@UseGuards(AdminAuthGuard)
@@ -61,7 +61,7 @@ export class CategoryController {
@ApiOperation({ summary: 'Get category' })
@ApiParam({ name: 'id', required: true, type: String })
findOne(@Param('id') id: string, @RestId() restId: string) {
return this.categoryService.findOne(restId, id);
return this.categoryService.findOneOrFail(restId, id);
}
@UseGuards(AdminAuthGuard)
@@ -40,7 +40,7 @@ export class FoodController {
@ApiOperation({ summary: 'Get a food by id' })
@ApiParam({ name: 'foodId', required: true })
findPublicFoodById(@Param('foodId') foodId: string, @UserId() userId?: string): Promise<any> {
const a = this.foodsService.findPublicById(foodId, userId);
const a = this.foodsService.findByIdPublic(foodId, userId);
return a;
}
@@ -5,6 +5,7 @@ import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
@Entity({ tableName: 'categories' })
@Index({ properties: ['restaurant', 'isActive'] })
@Index({ properties: ['restaurant', 'id'] })
@Index({ properties: ['isActive'] })
export class Category extends BaseEntity {
@Property()
@@ -7,11 +7,13 @@ import { RequiredEntityData } from '@mikro-orm/core';
import { Category } from '../entities/category.entity';
import { CategoryMessage, RestMessage } from 'src/common/enums/message.enum';
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
import { RestaurantsService } from 'src/modules/restaurants/providers/restaurants.service';
@Injectable()
export class CategoryService {
constructor(
private readonly categoryRepository: CategoryRepository,
private readonly restaurantsService: RestaurantsService,
private readonly em: EntityManager,
) { }
@@ -33,10 +35,8 @@ export class CategoryService {
}
async findAllByRestaurant(slug: string): Promise<Category[]> {
const restaurant = await this.em.findOne(Restaurant, { slug });
if (!restaurant || !restaurant.id) {
throw new NotFoundException(RestMessage.NOT_FOUND);
}
const restaurant = await this.restaurantsService.findBySlug(slug)
return this.categoryRepository.find(
{ restaurant: restaurant, isActive: true }, { orderBy: { order: 'ASC' } });
}
@@ -47,34 +47,22 @@ export class CategoryService {
{ orderBy: { order: 'asc' } });
}
async findOne(restId: string, id: string): Promise<Category> {
const cat = await this.categoryRepository.findOne({ id, restaurant: { id: restId } }, { populate: ['foods'] });
async findOneOrFail(restId: string, id: string): Promise<Category> {
const cat = await this.categoryRepository.findOne({ id, restaurant: { id: restId } });
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
return {
id: cat.id,
title: cat.title,
isActive: cat.isActive,
restaurant: cat.restaurant,
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;
return cat
}
async update(restId: string, id: string, dto: UpdateCategoryDto): Promise<Category> {
const cat = await this.categoryRepository.findOne({ id, restaurant: { id: restId } });
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
const cat = await this.findOneOrFail(restId, id)
this.em.assign(cat, dto);
await this.em.persistAndFlush(cat);
return cat;
}
async remove(restId: string, id: string): Promise<void> {
const cat = await this.categoryRepository.findOne({ id, restaurant: { id: restId } });
if (!cat) throw new NotFoundException(CategoryMessage.NOT_FOUND);
const cat = await this.findOneOrFail(restId, id)
cat.deletedAt = new Date();
await this.em.persistAndFlush(cat);
}
+9 -21
View File
@@ -7,27 +7,24 @@ import { EntityManager } from '@mikro-orm/postgresql';
import { RequiredEntityData, FilterQuery } from '@mikro-orm/core';
import { Food } from '../entities/food.entity';
import { CategoryMessage, FoodMessage, RestMessage } from 'src/common/enums/message.enum';
import { RestRepository } from 'src/modules/restaurants/repositories/rest.repository';
import { CacheService } from '../../utils/cache.service';
import { Favorite } from '../entities/favorite.entity';
import { MealType } from '../interface/food.interface';
import { Inventory } from 'src/modules/inventory/entities/inventory.entity';
import { RestaurantsService } from 'src/modules/restaurants/providers/restaurants.service';
@Injectable()
export class FoodService {
constructor(
private readonly foodRepository: FoodRepository,
private readonly categoryRepository: CategoryRepository,
private readonly restRepository: RestRepository,
private readonly restService: RestaurantsService,
private readonly em: EntityManager,
) { }
async create(restId: string, createFoodDto: CreateFoodDto) {
const { categoryId, dailyStock = 0, ...rest } = createFoodDto;
const restaurant = await this.restRepository.findOne({ id: restId });
if (!restaurant) {
throw new NotFoundException(RestMessage.NOT_FOUND);
}
const restaurant = await this.restService.findOneOrFail(restId);
const category = await this.categoryRepository.findOne({ id: categoryId, restaurant: { id: restId } });
if (!category) {
throw new NotFoundException(CategoryMessage.NOT_FOUND);
@@ -84,7 +81,7 @@ export class FoodService {
/**
* Public food detail (only active foods are visible).
*/
async findPublicById(foodId: string, userId?: string): Promise<any> {
async findByIdPublic(foodId: string, userId?: string): Promise<any> {
const food = await this.foodRepository.findOne({ id: foodId, isActive: true }, { populate: ['category', 'inventory'] });
if (!food) throw new NotFoundException(FoodMessage.NOT_FOUND);
let isFavorite = false;
@@ -101,7 +98,8 @@ export class FoodService {
* Admin food detail (scoped to the authenticated restaurant).
*/
async findAdminById(restId: string, id: string): Promise<Food> {
const food = await this.foodRepository.findOne({ id, restaurant: { id: restId } }, { populate: ['category', 'inventory'] });
const food = await this.foodRepository.findOne({ id, restaurant: { id: restId } },
{ populate: ['category', 'inventory'] });
if (!food) throw new NotFoundException(FoodMessage.NOT_FOUND);
return food;
@@ -113,11 +111,6 @@ export class FoodService {
* @returns Array of active foods matching current day and meal time
*/
async findByWeekDateAndMealType(slug: string): Promise<Food[]> {
const restaurant = await this.restRepository.findOne({ slug });
if (!restaurant) {
throw new NotFoundException(RestMessage.NOT_FOUND);
}
const { iranWeekDay, mealType } = this.getCurrentIranTimeContext();
const queryFilter: FilterQuery<Food> = {
@@ -263,11 +256,6 @@ export class FoodService {
async getMyFavorites(userId: string, restId: string) {
return this.em.find(Favorite, { user: userId, food: { restaurant: { id: restId } } }, { populate: ['food'] });
}
/**
* Invalidate cache for restaurant foods
*/
// private async invalidateRestaurantFoodsCache(slug: string): Promise<void> {
// const cacheKey = `${this.FOODS_BY_RESTAURANT_CACHE_KEY_PREFIX}${slug}`;
// await this.cacheService.del(cacheKey);
// }
}