find all rest

This commit is contained in:
2026-06-21 16:34:23 +03:30
parent d6e3f78e41
commit 449cd89287
16 changed files with 75 additions and 93019 deletions
@@ -11,4 +11,5 @@ export const CacheKeys = {
foodsByRestaurant: (slug: string) => `${CacheKeyPrefixes.FOODS_BY_RESTAURANT}:${slug}`,
categoriesByRestaurant: (slug: string) => `${CacheKeyPrefixes.CATEGORIES_BY_RESTAURANT}:${slug}`,
restaurantSpec: (slug: string) => `${CacheKeyPrefixes.RESTAURANT_SPEC}:${slug}`,
activeRestaurantsList: () => CacheKeyPrefixes.RESTAURANT_SPEC,
} as const;
@@ -9,11 +9,13 @@ import {
ApiBearerAuth,
ApiBody,
ApiNotFoundResponse,
ApiOkResponse,
ApiOperation,
ApiParam,
ApiTags,
ApiHeader,
} from '@nestjs/swagger';
import { ActiveRestaurantListItemDto } from '../dto/active-restaurant-list-item.dto';
import { RestId } from 'src/common/decorators';
import { API_HEADER_SLUG } from 'src/common/constants';
import { SuperAdminAuthGuard } from 'src/modules/auth/guards/superAdminAuth.guard';
@@ -28,6 +30,14 @@ import { UpdateRestaurantBgDto } from '../dto/update-restaurant-bg.dto';
export class RestaurantsController {
constructor(private readonly restaurantsService: RestaurantsService) { }
@Get('public/restaurants')
@CacheResponse({ keyPrefix: CacheKeyPrefixes.RESTAURANT_SPEC, params: [] })
@ApiOperation({ summary: 'Get all active restaurants (summary fields)' })
@ApiOkResponse({ description: 'List of active restaurants', type: [ActiveRestaurantListItemDto] })
findAllActiveRestaurants() {
return this.restaurantsService.findAllActiveRestaurants();
}
@Get('public/restaurants/:slug')
@CacheResponse({ keyPrefix: CacheKeyPrefixes.RESTAURANT_SPEC, params: ['slug'] })
@ApiOperation({ summary: 'Get restaurant specification by slug' })
@@ -0,0 +1,22 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class ActiveRestaurantListItemDto {
@ApiProperty({ example: 'zhivan', description: 'Restaurant slug' })
slug!: string;
@ApiProperty({ example: 'کافه ژیوان', description: 'Restaurant name' })
name!: string;
@ApiPropertyOptional({ example: 'بهترین کافه تهران', description: 'SEO title' })
title?: string;
@ApiPropertyOptional({ example: 'تهران، خیابان ولیعصر پلاک ۱۲۳', description: 'Address' })
address?: string;
@ApiPropertyOptional({ example: 'https://example.com/logo.png', description: 'Logo URL' })
logo?: string;
@ApiPropertyOptional({ example: 2020, description: 'Established year' })
establishedYear?: number;
}
@@ -31,6 +31,7 @@ import { Notification } from '../../notifications/entities/notification.entity';
import { CacheService } from 'src/modules/utils/cache.service';
import { CacheKeys } from 'src/common/constants/cache-keys.constant';
import { BackgroundRepository } from '../repositories/background.repository';
import { ActiveRestaurantListItemDto } from '../dto/active-restaurant-list-item.dto';
@Injectable()
@@ -108,6 +109,8 @@ export class RestaurantsService {
em.persist([restaurant, admin, adminRole, ...notificationPreferences]);
await em.flush();
await this.invalidateActiveRestaurantsListCache();
return restaurant;
});
}
@@ -156,6 +159,19 @@ export class RestaurantsService {
const restaurant = await this.findBySlug(slug);
return restaurant;
}
async findAllActiveRestaurants(): Promise<ActiveRestaurantListItemDto[]> {
const restaurants = await this.restRepository.findAllActive();
return restaurants.map(({ slug, name, seoTitle, address, score, logo, establishedYear }) => ({
slug,
name,
title: seoTitle,
address,
logo,
establishedYear,
}));
}
// TODO : it must be done inside transaction
async update(id: string, dto: UpdateRestaurantDto): Promise<Restaurant> {
@@ -204,12 +220,21 @@ export class RestaurantsService {
}
private async invalidateRestaurantCache(slug?: string): Promise<void> {
if (!slug) return;
await Promise.all([
this.cacheService.del(CacheKeys.restaurantSpec(slug)),
this.cacheService.del(CacheKeys.foodsByRestaurant(slug)),
this.cacheService.del(CacheKeys.categoriesByRestaurant(slug)),
]);
const tasks = [this.invalidateActiveRestaurantsListCache()];
if (slug) {
tasks.push(
this.cacheService.del(CacheKeys.restaurantSpec(slug)),
this.cacheService.del(CacheKeys.foodsByRestaurant(slug)),
this.cacheService.del(CacheKeys.categoriesByRestaurant(slug)),
);
}
await Promise.all(tasks);
}
private async invalidateActiveRestaurantsListCache(): Promise<void> {
await this.cacheService.del(CacheKeys.activeRestaurantsList());
}
async remove(id: string) {
@@ -222,6 +247,7 @@ export class RestaurantsService {
restaurant.isActive = false;
await this.em.persistAndFlush(restaurant);
await this.invalidateRestaurantCache(restaurant.slug);
return restaurant;
}
@@ -76,4 +76,14 @@ export class RestRepository extends EntityRepository<Restaurant> {
},
};
}
findAllActive() {
return this.find(
{ isActive: true },
{
fields: ['slug', 'name', 'seoTitle', 'address', 'logo', 'establishedYear'],
orderBy: { name: 'asc' },
},
);
}
}