From f0b2b6ce1764a1c810451401a6cf5d04698ce9ca Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Sat, 20 Dec 2025 19:43:29 +0330 Subject: [PATCH] refactor food service --- src/modules/foods/providers/food.service.ts | 96 ++++++++++++--------- 1 file changed, 56 insertions(+), 40 deletions(-) diff --git a/src/modules/foods/providers/food.service.ts b/src/modules/foods/providers/food.service.ts index fc36254..06e13fe 100644 --- a/src/modules/foods/providers/food.service.ts +++ b/src/modules/foods/providers/food.service.ts @@ -110,59 +110,75 @@ export class FoodService { return food; } + /** + * Find active foods for a restaurant based on current week day and meal type in Iran timezone. + * @param slug - Restaurant slug identifier + * @returns Array of active foods matching current day and meal time + */ async findByWeekDateAndMealType(slug: string): Promise { - // const cacheKey = `${this.FOODS_BY_RESTAURANT_CACHE_KEY_PREFIX}${slug}`; - - // Try to get from cache first - // const cachedFoods = await this.cacheService.get(cacheKey); - // if (cachedFoods) { - // try { - // const parsed: unknown = JSON.parse(cachedFoods); - // if (Array.isArray(parsed)) { - // return parsed as Food[]; - // } - // } catch { - // // If parsing fails, continue to fetch from DB - // } - // } - - // If not in cache, fetch from database const restaurant = await this.restRepository.findOne({ slug }); if (!restaurant) { throw new NotFoundException(RestMessage.NOT_FOUND); } - const nowInIran = new Date(new Date().toLocaleString('en-US', { timeZone: 'Asia/Tehran' })); + const { iranWeekDay, mealType } = this.getCurrentIranTimeContext(); + + const queryFilter: FilterQuery = { + restaurant: { slug }, + isActive: true, + weekDays: { $contains: iranWeekDay }, + ...(mealType ? { mealTypes: { $contains: mealType } } : {}), + } as unknown as FilterQuery; + + return this.foodRepository.find(queryFilter, { populate: ['category'] }); + } + + /** + * Get current Iran timezone context (weekday and meal type). + * @returns Object containing Iran weekday (0-6, where 0=Saturday) and current meal type + */ + private getCurrentIranTimeContext(): { iranWeekDay: number; mealType: MealType | null } { + const nowInIran = new Date(new Date().toLocaleString('en-US', { timeZone: 'Asia/Tehran' })); const weekDay = nowInIran.getDay(); // 0 = Sunday, 6 = Saturday const currentHour = nowInIran.getHours(); + // Convert to Iran weekday: Saturday=0, Sunday=1, ..., Friday=6 + // JavaScript: Sunday=0, Monday=1, ..., Saturday=6 + // Iran week: Saturday=0, Sunday=1, ..., Friday=6 const iranWeekDay = (weekDay + 1) % 7; - let mealType: string | null = null; - if (currentHour >= 6 && currentHour < 11) { - mealType = MealType.BREAKFAST; - } else if (currentHour >= 11 && currentHour < 15) { - mealType = MealType.LUNCH; - } else if (currentHour >= 15 && currentHour < 19) { - mealType = MealType.SNACK; - } else if (currentHour >= 19 && currentHour < 24) { - mealType = MealType.DINNER; + const mealType = this.getMealTypeByHour(currentHour); + + return { iranWeekDay, mealType }; + } + + /** + * Determine meal type based on current hour in Iran timezone. + * @param hour - Current hour (0-23) + * @returns Meal type or null if outside meal hours + */ + private getMealTypeByHour(hour: number): MealType | null { + const MEAL_TIME_RANGES = { + BREAKFAST: { start: 6, end: 11 }, + LUNCH: { start: 11, end: 15 }, + SNACK: { start: 15, end: 19 }, + DINNER: { start: 19, end: 24 }, + } as const; + + if (hour >= MEAL_TIME_RANGES.BREAKFAST.start && hour < MEAL_TIME_RANGES.BREAKFAST.end) { + return MealType.BREAKFAST; + } + if (hour >= MEAL_TIME_RANGES.LUNCH.start && hour < MEAL_TIME_RANGES.LUNCH.end) { + return MealType.LUNCH; + } + if (hour >= MEAL_TIME_RANGES.SNACK.start && hour < MEAL_TIME_RANGES.SNACK.end) { + return MealType.SNACK; + } + if (hour >= MEAL_TIME_RANGES.DINNER.start && hour < MEAL_TIME_RANGES.DINNER.end) { + return MealType.DINNER; } - const foods = await this.foodRepository.find( - // cast to FilterQuery because MikroORM types don't accept a numeric $contains value for jsonb number[] - { - restaurant: { slug }, - isActive: true, - ...(mealType ? { mealTypes: { $contains: mealType } } : {}), - weekDays: { $contains: iranWeekDay }, - } as unknown as FilterQuery, - { populate: ['category'] }, - ); - // Cache the result - // await this.cacheService.set(cacheKey, JSON.stringify(foods), this.FOODS_CACHE_TTL); - - return foods; + return null; } async update(restId: string, id: string, dto: Partial): Promise {