From d8370ee4b81e502a78cf32da590a86b8ede41104 Mon Sep 17 00:00:00 2001 From: Collin Duncan <3679940+cgduncan7@users.noreply.github.com> Date: Tue, 10 Oct 2023 11:51:03 +0200 Subject: [PATCH] Updating controllers to use separate req class for transformation and validation --- src/main.ts | 2 +- src/recurringReservations/controller.ts | 41 ++++++++++++----- src/recurringReservations/service.ts | 26 ++++++++++- src/reservations/controller.ts | 59 +++++++++++++++++++------ src/reservations/service.ts | 24 +++++++++- 5 files changed, 121 insertions(+), 31 deletions(-) diff --git a/src/main.ts b/src/main.ts index 6ae2de2..fac4c83 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,7 +10,7 @@ async function bootstrap() { const config = app.get(ConfigService) const port = config.get('PORT', 3000) app.enableShutdownHooks() - app.useGlobalPipes(new ValidationPipe()) + app.useGlobalPipes(new ValidationPipe({ transform: true })) app.useGlobalInterceptors(new CustomResponseTransformInterceptor()) await app.listen(port, () => console.log(`Listening on port ${port}`)) } diff --git a/src/recurringReservations/controller.ts b/src/recurringReservations/controller.ts index 7e50077..fd05268 100644 --- a/src/recurringReservations/controller.ts +++ b/src/recurringReservations/controller.ts @@ -9,13 +9,37 @@ import { Post, Query, UseInterceptors, - UsePipes, - ValidationPipe, } from '@nestjs/common' +import { IsEnum, IsOptional, IsString, Matches } from 'class-validator' -import { DayOfWeek, RecurringReservation } from './entity' +import { DayOfWeek } from './entity' import { RecurringReservationsService } from './service' +export class CreateRecurringReservationRequest { + @IsString() + ownerId: string + + @IsEnum(DayOfWeek) + dayOfWeek: number + + @IsString() + @Matches(/[012][0-9]:[0-5][0-9]/) + timeStart: string + + @IsOptional() + @IsString() + @Matches(/[012][0-9]:[0-5][0-9]/) + timeEnd?: string + + @IsOptional() + @IsString() + opponentId?: string + + @IsOptional() + @IsString() + opponentName?: string +} + @Controller('recurring-reservations') @UseInterceptors(ClassSerializerInterceptor) export class RecurringReservationsController { @@ -38,15 +62,8 @@ export class RecurringReservationsController { } @Post() - @UsePipes( - new ValidationPipe({ - transform: true, - transformOptions: { groups: ['password'] }, - groups: ['password'], - }), - ) - async createReservation(@Body() recurringReservation: RecurringReservation) { - await this.recurringReservationsService.create(recurringReservation) + async createReservation(@Body() req: CreateRecurringReservationRequest) { + await this.recurringReservationsService.create(req) return 'Recurring reservation created' } diff --git a/src/recurringReservations/service.ts b/src/recurringReservations/service.ts index f9b2651..41f961a 100644 --- a/src/recurringReservations/service.ts +++ b/src/recurringReservations/service.ts @@ -30,8 +30,30 @@ export class RecurringReservationsService { .getMany() } - create(recurringReservation: RecurringReservation) { - return this.recurringReservationsRepository.save(recurringReservation) + async create({ + ownerId, + dayOfWeek, + timeStart, + timeEnd, + opponentId = '-1', + opponentName = 'Gast', + }: { + ownerId: string + dayOfWeek: DayOfWeek + timeStart: string + timeEnd?: string + opponentId?: string + opponentName?: string + }) { + const recRes = this.recurringReservationsRepository.create({ + ownerId, + dayOfWeek, + timeStart, + timeEnd: timeEnd ?? timeStart, + opponentId, + opponentName, + }) + return await this.recurringReservationsRepository.save(recRes) } scheduleReservation(recurringReservation: RecurringReservation) { diff --git a/src/reservations/controller.ts b/src/reservations/controller.ts index 2241fdc..cc84050 100644 --- a/src/reservations/controller.ts +++ b/src/reservations/controller.ts @@ -10,14 +10,13 @@ import { Post, Query, UseInterceptors, - UsePipes, - ValidationPipe, } from '@nestjs/common' import { Queue } from 'bull' -import { Transform } from 'class-transformer' -import { IsBoolean, IsOptional } from 'class-validator' +import { Transform, TransformationType } from 'class-transformer' +import { IsBoolean, IsOptional, IsString } from 'class-validator' import { Dayjs } from 'dayjs' +import dayjs from '../common/dayjs' import { LoggerService } from '../logger/service.logger' import { RESERVATIONS_QUEUE_NAME } from './config' import { Reservation } from './entity' @@ -34,6 +33,44 @@ export class GetReservationsQueryParams { readonly schedulable?: boolean } +export class CreateReservationRequest { + @IsString() + ownerId: string + + @Transform(({ value, type }) => { + switch (type) { + case TransformationType.PLAIN_TO_CLASS: + return dayjs(value) + case TransformationType.CLASS_TO_PLAIN: + return value.format() + default: + return value + } + }) + dateRangeStart: Dayjs + + @IsOptional() + @Transform(({ value, type }) => { + switch (type) { + case TransformationType.PLAIN_TO_CLASS: + return dayjs(value) + case TransformationType.CLASS_TO_PLAIN: + return value.format() + default: + return value + } + }) + dateRangeEnd?: Dayjs + + @IsOptional() + @IsString() + opponentId?: string + + @IsOptional() + @IsString() + opponentName?: string +} + @Controller('reservations') @UseInterceptors(ClassSerializerInterceptor) export class ReservationsController { @@ -66,21 +103,15 @@ export class ReservationsController { } @Post() - @UsePipes( - new ValidationPipe({ - transform: true, - transformOptions: { groups: ['password'] }, - groups: ['password'], - }), - ) - async createReservation(@Body() reservation: Reservation) { - await this.reservationsService.create(reservation) + async createReservation(@Body() req: CreateReservationRequest) { + console.log(req) + const reservation = await this.reservationsService.create(req) if (!reservation.isAvailableForReservation()) { this.loggerService.debug('Reservation not available for reservation') return 'Reservation saved' } this.loggerService.debug('Reservation is available for reservation') - await this.reservationsQueue.add(reservation) + // await this.reservationsQueue.add(reservation) return 'Reservation queued' } diff --git a/src/reservations/service.ts b/src/reservations/service.ts index 339aa8d..39e3914 100644 --- a/src/reservations/service.ts +++ b/src/reservations/service.ts @@ -1,5 +1,6 @@ import { Inject, Injectable } from '@nestjs/common' import { InjectRepository } from '@nestjs/typeorm' +import { Dayjs } from 'dayjs' import { Repository } from 'typeorm' import dayjs from '../common/dayjs' @@ -68,8 +69,27 @@ export class ReservationsService { .getMany() } - async create(reservation: Reservation) { - return await this.reservationsRepository.save(reservation) + async create({ + ownerId, + dateRangeStart, + dateRangeEnd, + opponentId = '-1', + opponentName = 'Gast', + }: { + ownerId: string + dateRangeStart: Dayjs + dateRangeEnd?: Dayjs + opponentId?: string + opponentName?: string + }) { + const res = this.reservationsRepository.create({ + ownerId, + dateRangeStart, + dateRangeEnd: dateRangeEnd ?? dateRangeStart, + opponentId, + opponentName, + }) + return await this.reservationsRepository.save(res) } async update(reservationId: string, update: Partial) {