From e521e56f3e1f2795a9d409263d1c089e8681586d Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Sat, 15 Nov 2025 11:54:39 +0330 Subject: [PATCH] schedule --- src/modules/foods/providers/food.service.ts | 7 +- .../restaurants.controller.ts | 6 +- .../controllers/schedule.controller.ts | 68 ++++++++++++++++ .../restaurants/dto/create-schedule.dto.ts | 30 ++++++++ .../restaurants/dto/update-schedule.dto.ts | 4 + .../restaurants/entities/schedule.entity.ts | 2 +- .../{ => providers}/restaurants.service.ts | 8 +- .../restaurants/providers/schedule.service.ts | 77 +++++++++++++++++++ .../repositories/schedule.repository.ts | 10 +++ src/modules/restaurants/restaurants.module.ts | 16 ++-- 10 files changed, 213 insertions(+), 15 deletions(-) rename src/modules/restaurants/{ => controllers}/restaurants.controller.ts (77%) create mode 100644 src/modules/restaurants/controllers/schedule.controller.ts create mode 100644 src/modules/restaurants/dto/create-schedule.dto.ts create mode 100644 src/modules/restaurants/dto/update-schedule.dto.ts rename src/modules/restaurants/{ => providers}/restaurants.service.ts (83%) create mode 100644 src/modules/restaurants/providers/schedule.service.ts create mode 100644 src/modules/restaurants/repositories/schedule.repository.ts diff --git a/src/modules/foods/providers/food.service.ts b/src/modules/foods/providers/food.service.ts index 40bb3a6..46ba3fe 100644 --- a/src/modules/foods/providers/food.service.ts +++ b/src/modules/foods/providers/food.service.ts @@ -7,18 +7,23 @@ import { EntityManager } from '@mikro-orm/postgresql'; import { RequiredEntityData } from '@mikro-orm/core'; import { Food } from '../entities/food.entity'; import { FoodMessage } from 'src/common/enums/message.enum'; +// import { RestRepository } from 'src/modules/restaurants/repositories/rest.repository'; @Injectable() export class FoodService { constructor( private readonly foodRepository: FoodRepository, private readonly categoryRepository: CategoryRepository, + // private readonly restRepository: RestRepository, private readonly em: EntityManager, ) {} async create(createFoodDto: CreateFoodDto): Promise { const { categoryIds, ...rest } = createFoodDto; - + // const restaurant = await this.restRepository.findOne({ id: createFoodDto.restId }); + // if (!restaurant) { + // throw new NotFoundException(RestMessage.NOT_FOUND); + // } // prepare data with defaults for required fields so repository.create typing is satisfied const data: RequiredEntityData = { // boolean/day flags diff --git a/src/modules/restaurants/restaurants.controller.ts b/src/modules/restaurants/controllers/restaurants.controller.ts similarity index 77% rename from src/modules/restaurants/restaurants.controller.ts rename to src/modules/restaurants/controllers/restaurants.controller.ts index bda8ee2..aaa745f 100644 --- a/src/modules/restaurants/restaurants.controller.ts +++ b/src/modules/restaurants/controllers/restaurants.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Post, Body, Patch, Param } from '@nestjs/common'; -import { RestaurantsService } from './restaurants.service'; -import { CreateRestaurantDto } from './dto/create-restaurant.dto'; -import { UpdateRestaurantDto } from './dto/update-restaurant.dto'; +import { RestaurantsService } from '../providers/restaurants.service'; +import { CreateRestaurantDto } from '../dto/create-restaurant.dto'; +import { UpdateRestaurantDto } from '../dto/update-restaurant.dto'; @Controller('admin/restaurants') export class RestaurantsController { diff --git a/src/modules/restaurants/controllers/schedule.controller.ts b/src/modules/restaurants/controllers/schedule.controller.ts new file mode 100644 index 0000000..ffc994a --- /dev/null +++ b/src/modules/restaurants/controllers/schedule.controller.ts @@ -0,0 +1,68 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete, Query, ValidationPipe } from '@nestjs/common'; +import { + ApiTags, + ApiOperation, + ApiCreatedResponse, + ApiOkResponse, + ApiNotFoundResponse, + ApiParam, + ApiBody, + ApiQuery, +} from '@nestjs/swagger'; +import { ScheduleService } from '../providers/schedule.service'; +import { CreateScheduleDto } from '../dto/create-schedule.dto'; +import { UpdateScheduleDto } from '../dto/update-schedule.dto'; +import { Schedule } from '../entities/schedule.entity'; + +@ApiTags('schedules') +@Controller('schedules') +export class ScheduleController { + constructor(private readonly scheduleService: ScheduleService) {} + + @Post() + @ApiOperation({ summary: 'ایجاد برنامه جدید' }) + @ApiBody({ type: CreateScheduleDto }) + @ApiCreatedResponse({ description: 'برنامه ایجاد شد', type: Schedule }) + create(@Body(new ValidationPipe({ transform: true, whitelist: true })) createScheduleDto: CreateScheduleDto) { + return this.scheduleService.create(createScheduleDto); + } + + @Get() + @ApiOperation({ summary: 'لیست همه برنامه‌ها' }) + @ApiQuery({ name: 'restId', required: false, type: String, description: 'شناسه رستوران برای فیلتر کردن' }) + @ApiOkResponse({ description: 'لیست برنامه‌ها', type: [Schedule] }) + findAll(@Query('restId') restId?: string) { + return this.scheduleService.findAll(restId); + } + + @Get(':id') + @ApiOperation({ summary: 'دریافت یک برنامه' }) + @ApiParam({ name: 'id', description: 'شناسه برنامه' }) + @ApiOkResponse({ description: 'جزئیات برنامه', type: Schedule }) + @ApiNotFoundResponse({ description: 'برنامه یافت نشد' }) + findOne(@Param('id') id: string) { + return this.scheduleService.findOne(id); + } + + @Patch(':id') + @ApiOperation({ summary: 'به‌روزرسانی برنامه' }) + @ApiParam({ name: 'id', description: 'شناسه برنامه' }) + @ApiBody({ type: UpdateScheduleDto }) + @ApiOkResponse({ description: 'برنامه به‌روز شد', type: Schedule }) + @ApiNotFoundResponse({ description: 'برنامه یافت نشد' }) + update( + @Param('id') id: string, + @Body(new ValidationPipe({ transform: true, whitelist: true })) updateScheduleDto: UpdateScheduleDto, + ) { + return this.scheduleService.update(id, updateScheduleDto); + } + + @Delete(':id') + @ApiOperation({ summary: 'حذف برنامه' }) + @ApiParam({ name: 'id', description: 'شناسه برنامه' }) + @ApiOkResponse({ description: 'برنامه حذف شد' }) + @ApiNotFoundResponse({ description: 'برنامه یافت نشد' }) + remove(@Param('id') id: string) { + return this.scheduleService.remove(id); + } +} diff --git a/src/modules/restaurants/dto/create-schedule.dto.ts b/src/modules/restaurants/dto/create-schedule.dto.ts new file mode 100644 index 0000000..7d4372b --- /dev/null +++ b/src/modules/restaurants/dto/create-schedule.dto.ts @@ -0,0 +1,30 @@ +import { IsString, IsNumber, IsBoolean, IsOptional, Min, Max } from 'class-validator'; +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; +import { Type } from 'class-transformer'; + +export class CreateScheduleDto { + @ApiProperty({ example: '2024-01-15', description: 'تاریخ برای برنامه' }) + @IsString() + date!: string; + + @ApiProperty({ example: 900, description: 'زمان باز شدن (دقیقه از نیمه شب)' }) + @IsNumber() + @Min(0) + @Max(1440) + @Type(() => Number) + openTime!: number; + + @ApiProperty({ example: 1380, description: 'زمان بستن (دقیقه از نیمه شب)' }) + @IsNumber() + @Min(0) + @Max(1440) + @Type(() => Number) + closeTime!: number; + + @ApiPropertyOptional({ example: true, description: 'آیا این برنامه فعال است؟' }) + @IsOptional() + @IsBoolean() + @Type(() => Boolean) + isActive?: boolean; + +} diff --git a/src/modules/restaurants/dto/update-schedule.dto.ts b/src/modules/restaurants/dto/update-schedule.dto.ts new file mode 100644 index 0000000..c07e905 --- /dev/null +++ b/src/modules/restaurants/dto/update-schedule.dto.ts @@ -0,0 +1,4 @@ +import { PartialType } from '@nestjs/swagger'; +import { CreateScheduleDto } from './create-schedule.dto'; + +export class UpdateScheduleDto extends PartialType(CreateScheduleDto) {} diff --git a/src/modules/restaurants/entities/schedule.entity.ts b/src/modules/restaurants/entities/schedule.entity.ts index ddae562..a444e6a 100644 --- a/src/modules/restaurants/entities/schedule.entity.ts +++ b/src/modules/restaurants/entities/schedule.entity.ts @@ -1,7 +1,7 @@ import { Entity, Property } from '@mikro-orm/core'; import { BaseEntity } from '../../../common/entities/base.entity'; -@Entity({ tableName: 'restaurants' }) +@Entity({ tableName: 'schedules' }) export class Schedule extends BaseEntity { @Property({ type: 'date' }) date!: Date; diff --git a/src/modules/restaurants/restaurants.service.ts b/src/modules/restaurants/providers/restaurants.service.ts similarity index 83% rename from src/modules/restaurants/restaurants.service.ts rename to src/modules/restaurants/providers/restaurants.service.ts index f89867e..87fd473 100644 --- a/src/modules/restaurants/restaurants.service.ts +++ b/src/modules/restaurants/providers/restaurants.service.ts @@ -1,9 +1,9 @@ import { Injectable, NotFoundException } from '@nestjs/common'; -import { CreateRestaurantDto } from './dto/create-restaurant.dto'; -import { UpdateRestaurantDto } from './dto/update-restaurant.dto'; -import { Restaurant } from './entities/restaurant.entity'; +import { CreateRestaurantDto } from '../dto/create-restaurant.dto'; +import { UpdateRestaurantDto } from '../dto/update-restaurant.dto'; +import { Restaurant } from '../entities/restaurant.entity'; import { EntityManager } from '@mikro-orm/postgresql'; -import { RestRepository } from './repositories/rest.repository'; +import { RestRepository } from '../repositories/rest.repository'; import { RestMessage } from 'src/common/enums/message.enum'; @Injectable() diff --git a/src/modules/restaurants/providers/schedule.service.ts b/src/modules/restaurants/providers/schedule.service.ts new file mode 100644 index 0000000..f5e8253 --- /dev/null +++ b/src/modules/restaurants/providers/schedule.service.ts @@ -0,0 +1,77 @@ +import { Injectable, NotFoundException } from '@nestjs/common'; +import { EntityManager, RequiredEntityData } from '@mikro-orm/postgresql'; +import { Schedule } from '../entities/schedule.entity'; +import { ScheduleRepository } from '../repositories/schedule.repository'; +import { CreateScheduleDto } from '../dto/create-schedule.dto'; +import { UpdateScheduleDto } from '../dto/update-schedule.dto'; +import { RestRepository } from '../repositories/rest.repository'; +// import { RestMessage } from 'src/common/enums/message.enum'; + +@Injectable() +export class ScheduleService { + constructor( + private readonly scheduleRepository: ScheduleRepository, + private readonly restRepository: RestRepository, + private readonly em: EntityManager, + ) {} + + async create(createScheduleDto: CreateScheduleDto): Promise { + const data: RequiredEntityData = { + date: new Date(createScheduleDto.date), + openTime: createScheduleDto.openTime, + closeTime: createScheduleDto.closeTime, + isActive: createScheduleDto.isActive ?? true, + restId: '01KA35CFFN0F6VA04DF0W6KCE3', + }; + + const schedule = this.scheduleRepository.create(data); + await this.em.persistAndFlush(schedule); + return schedule; + } + + async findAll(restId?: string): Promise { + const where = restId ? { restId } : {}; + return this.scheduleRepository.find(where); + } + + async findOne(id: string): Promise { + const schedule = await this.scheduleRepository.findOne({ id }); + if (!schedule) { + throw new NotFoundException(`برنامه با شناسه ${id} یافت نشد.`); + } + return schedule; + } + + async update(id: string, updateScheduleDto: UpdateScheduleDto): Promise { + const schedule = await this.scheduleRepository.findOne({ id }); + if (!schedule) { + throw new NotFoundException(`برنامه با شناسه ${id} یافت نشد.`); + } + + const updateData: Partial = {}; + if (updateScheduleDto.date) { + updateData.date = new Date(updateScheduleDto.date); + } + if (updateScheduleDto.openTime !== undefined) { + updateData.openTime = updateScheduleDto.openTime; + } + if (updateScheduleDto.closeTime !== undefined) { + updateData.closeTime = updateScheduleDto.closeTime; + } + if (updateScheduleDto.isActive !== undefined) { + updateData.isActive = updateScheduleDto.isActive; + } + + this.em.assign(schedule, updateData); + await this.em.persistAndFlush(schedule); + return schedule; + } + + async remove(id: string): Promise { + const schedule = await this.scheduleRepository.findOne({ id }); + if (!schedule) { + throw new NotFoundException(`برنامه با شناسه ${id} یافت نشد.`); + } + await this.em.removeAndFlush(schedule); + } +} diff --git a/src/modules/restaurants/repositories/schedule.repository.ts b/src/modules/restaurants/repositories/schedule.repository.ts new file mode 100644 index 0000000..f5fd3ef --- /dev/null +++ b/src/modules/restaurants/repositories/schedule.repository.ts @@ -0,0 +1,10 @@ +import { EntityManager, EntityRepository } from '@mikro-orm/postgresql'; +import { Injectable } from '@nestjs/common'; +import { Schedule } from '../entities/schedule.entity'; + +@Injectable() +export class ScheduleRepository extends EntityRepository { + constructor(readonly em: EntityManager) { + super(em, Schedule); + } +} diff --git a/src/modules/restaurants/restaurants.module.ts b/src/modules/restaurants/restaurants.module.ts index 490812e..43c8d55 100644 --- a/src/modules/restaurants/restaurants.module.ts +++ b/src/modules/restaurants/restaurants.module.ts @@ -1,14 +1,18 @@ import { Module } from '@nestjs/common'; -import { RestaurantsService } from './restaurants.service'; -import { RestaurantsController } from './restaurants.controller'; +import { RestaurantsService } from './providers/restaurants.service'; +import { RestaurantsController } from './controllers/restaurants.controller'; import { MikroOrmModule } from '@mikro-orm/nestjs'; import { Restaurant } from './entities/restaurant.entity'; import { RestRepository } from './repositories/rest.repository'; +import { ScheduleRepository } from './repositories/schedule.repository'; +import { Schedule } from './entities/schedule.entity'; +import { ScheduleService } from './providers/schedule.service'; +import { ScheduleController } from './controllers/schedule.controller'; @Module({ - controllers: [RestaurantsController], - providers: [RestaurantsService, RestRepository], - imports: [MikroOrmModule.forFeature([Restaurant])], - exports: [RestRepository], + controllers: [RestaurantsController, ScheduleController], + providers: [RestaurantsService, RestRepository, ScheduleRepository, ScheduleService], + imports: [MikroOrmModule.forFeature([Restaurant, Schedule])], + exports: [RestRepository, ScheduleRepository, ScheduleService], }) export class RestaurantsModule {}