diff --git a/src/modules/shifts/controllers/shifts.controller.ts b/src/modules/shifts/controllers/shifts.controller.ts index b245a82..b323988 100644 --- a/src/modules/shifts/controllers/shifts.controller.ts +++ b/src/modules/shifts/controllers/shifts.controller.ts @@ -28,9 +28,7 @@ export class ShiftsController { @Param('date') date_param: string, @Body() payload: UpsertShiftDto, ) { - const email = decodeURIComponent(email_param); - const date = date_param; - return this.shiftsCommandService.upsertShfitsByDate(email, date, payload); + return this.shiftsCommandService.upsertShfitsByDate(email_param, date_param, payload); } @Post() diff --git a/src/modules/shifts/dtos/upsert-shift.dto.ts b/src/modules/shifts/dtos/upsert-shift.dto.ts index 4af789c..83900dd 100644 --- a/src/modules/shifts/dtos/upsert-shift.dto.ts +++ b/src/modules/shifts/dtos/upsert-shift.dto.ts @@ -1,13 +1,14 @@ -import { IsBoolean, IsOptional, IsString, Matches, MaxLength } from "class-validator"; +import { Type } from "class-transformer"; +import { IsBoolean, IsOptional, IsString, Matches, MaxLength, ValidateNested } from "class-validator"; export const COMMENT_MAX_LENGTH = 512; export class ShiftPayloadDto { - @Matches(/^\d{2}:\d{2}$/, {message: 'start_time must be HH:mm' }) + @Matches(/^([01]\d|2[0-3]):([0-5]\d)$/) start_time!: string; - @Matches(/^\d{2}:\d{2}$/, {message: 'start_time must be HH:mm' }) + @Matches(/^([01]\d|2[0-3]):([0-5]\d)$/) end_time!: string; @IsString() @@ -24,6 +25,13 @@ export class ShiftPayloadDto { export class UpsertShiftDto { + @IsOptional() + @ValidateNested() + @Type(()=> ShiftPayloadDto) old_shift?: ShiftPayloadDto; + + @IsOptional() + @ValidateNested() + @Type(()=> ShiftPayloadDto) new_shift?: ShiftPayloadDto; }; \ No newline at end of file diff --git a/src/modules/shifts/services/shifts-command.service.ts b/src/modules/shifts/services/shifts-command.service.ts index 451c189..e0c55af 100644 --- a/src/modules/shifts/services/shifts-command.service.ts +++ b/src/modules/shifts/services/shifts-command.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, ConflictException, Injectable, NotFoundException, ParseUUIDPipe, UnprocessableEntityException } from "@nestjs/common"; +import { BadRequestException, ConflictException, Injectable, NotFoundException, UnprocessableEntityException } from "@nestjs/common"; import { Prisma, Shifts } from "@prisma/client"; import { BaseApprovalService } from "src/common/shared/base-approval.service"; import { PrismaService } from "src/prisma/prisma.service"; @@ -22,6 +22,8 @@ export class ShiftsCommandService extends BaseApprovalService { //create/update/delete master method async upsertShfitsByDate(email:string, date_string: string, dto: UpsertShiftDto): Promise<{ action: UpsertAction; day: DayShiftResponse[] }> { + const { old_shift, new_shift } = dto; + if(!dto.old_shift && !dto.new_shift) { throw new BadRequestException('At least one of old or new shift must be provided'); } @@ -145,7 +147,7 @@ async upsertShfitsByDate(email:string, date_string: string, dto: UpsertShiftDto) }; // DELETE - if ( dto.old_shift && !dto.new_shift ) { + if ( old_shift && !new_shift ) { const existing = await find_exact_old_shift(); if(!existing) { throw new NotFoundException({ @@ -157,7 +159,7 @@ async upsertShfitsByDate(email:string, date_string: string, dto: UpsertShiftDto) action = 'deleted'; } // CREATE - else if (!dto.old_shift && dto.new_shift) { + else if (!old_shift && new_shift) { assert_no_overlap(); await transaction.shifts.create({ data: { @@ -173,7 +175,7 @@ async upsertShfitsByDate(email:string, date_string: string, dto: UpsertShiftDto) action = 'created'; } //UPDATE - else { + else if (old_shift && new_shift){ const existing = await find_exact_old_shift(); if(!existing) { throw new NotFoundException({ @@ -195,6 +197,8 @@ async upsertShfitsByDate(email:string, date_string: string, dto: UpsertShiftDto) }, }); action = 'updated'; + } else { + throw new BadRequestException('At least one of old_shift or new_shift must be provided'); } //Reload the day (truth source)