diff --git a/backend/src/services/dto/service.dto.ts b/backend/src/services/dto/service.dto.ts index 7e3bc55..bd135bf 100644 --- a/backend/src/services/dto/service.dto.ts +++ b/backend/src/services/dto/service.dto.ts @@ -64,3 +64,11 @@ export class UpdateServiceStatusDto { @IsEnum(ServiceStatus) status: ServiceStatus; } + +export class BlockSlotDto { + @IsDateString() + day: string; + + @Matches(/^\d{2}:\d{2}$/) + range1_hour1: string; +} diff --git a/backend/src/services/services.controller.ts b/backend/src/services/services.controller.ts index e8cbf46..2afdf8b 100644 --- a/backend/src/services/services.controller.ts +++ b/backend/src/services/services.controller.ts @@ -2,7 +2,7 @@ import { Controller, Get, Post, Patch, Param, Body, UseGuards, Req, Query } from import { ApiTags, ApiBearerAuth, ApiQuery } from '@nestjs/swagger'; import { ServicesService } from './services.service'; import { JwtAuthGuard } from '../auth/jwt-auth.guard'; -import { CreateServiceDto, UpdateServiceStatusDto } from './dto/service.dto'; +import { CreateServiceDto, UpdateServiceStatusDto, BlockSlotDto } from './dto/service.dto'; @ApiTags('Services') @Controller('services') @@ -16,6 +16,13 @@ export class ServicesController { return this.services.create({ ...dto, user_id: req.user.sub }); } + @Post('block') + @UseGuards(JwtAuthGuard) + @ApiBearerAuth() + blockSlot(@Req() req, @Body() dto: BlockSlotDto) { + return this.services.blockSlot(req.user.sub, dto); + } + @Get() @UseGuards(JwtAuthGuard) @ApiBearerAuth() diff --git a/backend/src/services/services.service.ts b/backend/src/services/services.service.ts index f96bf11..ed06c67 100644 --- a/backend/src/services/services.service.ts +++ b/backend/src/services/services.service.ts @@ -150,6 +150,32 @@ export class ServicesService { return updated; } + async blockSlot(userId: string, data: { day: string; range1_hour1: string }) { + const prof = await this.prisma.professionals.findUnique({ where: { user_id: userId } }); + if (!prof) throw new NotFoundException('No eres un profesional'); + + const slotTime = new Date(`1970-01-01T${data.range1_hour1}:00`); + const conflict = await this.prisma.services.findFirst({ + where: { + professional_id: prof.id, + day: new Date(data.day), + range1_hour1: slotTime, + status: { notIn: ['denied', 'cancelled'] }, + }, + }); + if (conflict) throw new BadRequestException('Este horario ya está ocupado o bloqueado'); + + return this.prisma.services.create({ + data: { + professional_id: prof.id, + user_id: prof.user_id, + day: new Date(data.day), + range1_hour1: slotTime, + status: 'self_booked' as any, + }, + }); + } + async findByUser(userId: string, page = 1, limit = 20) { const skip = (page - 1) * limit; const where = { user_id: userId, status: { notIn: ['completed' as const, 'cancelled' as const, 'denied' as const] } };