import { Body, Controller, Post, UseGuards } from '@nestjs/common' import { isNil } from 'lodash' import { BasicAuthorizationGuard } from '../../../guards' import { Booking, VideoCall } from '../domain' import { BookingConditions } from '../types' import { AuthBaseParams, BaseEventParams, SessionVariables } from '../../../params' import { PatientRepository, UserRepository } from '../../../repositories' import { Appointment, Patient, Subscription, User } from '../../../models' import { BookParams, CancelParams, GenerateVideoCallSessionParams, ReallocateNutriParams, RescheduleParams, } from './params' const SUSPENDED_SUBSCRIPTION_EVENT = 'subscription_suspended' @Controller('bookings') export class BookingsController { constructor( private readonly booking: Booking, private readonly videoCall: VideoCall, private readonly patientRepository: PatientRepository, private readonly userRepository: UserRepository, ) {} @UseGuards(BasicAuthorizationGuard) @Post('book') async book(@Body() { input, session_variables }: BookParams): Promise<{ appointment_id: string }> { const requester = await this.getRequester(session_variables) const appointment_id = await this.booking.book( input.patient_id || session_variables['x-hasura-user-id'], input.availability_time_id, undefined, requester, ) return { appointment_id } } @UseGuards(BasicAuthorizationGuard) @Post('reallocateNutri') async reallocateNutri(@Body() { input }: ReallocateNutriParams): Promise<{ appointment_id: string }> { const appointment_id = await this.booking.reallocateNutri( input.from_availability_time_id, input.to_availability_time_id, ) return { appointment_id } } @UseGuards(BasicAuthorizationGuard) @Post('cancel') async cancel(@Body() { input, session_variables }: CancelParams): Promise<{ cancelled: boolean }> { const requester = await this.getRequester(session_variables) await this.booking.cancel( input.appointment_id, requester, input.cancellation_reason && { value: input.cancellation_reason, comment: input.cancellation_comment }, ) return { cancelled: true } } @UseGuards(BasicAuthorizationGuard) @Post('reschedule') async reschedule(@Body() { input, session_variables }: RescheduleParams): Promise<{ appointment_id: string }> { const requester = await this.getRequester(session_variables) const appointment_id = await this.booking.reschedule( input.appointment_id, input.availability_time_id, requester, input.cancellation_reason && { value: input.cancellation_reason, comment: input.cancellation_comment }, ) return { appointment_id } } @UseGuards(BasicAuthorizationGuard) @Post('checkBookingConditions') async checkBookingConditions(@Body() { session_variables }: AuthBaseParams): Promise { return this.booking.checkBookingConditions(session_variables['x-hasura-user-id']) } @UseGuards(BasicAuthorizationGuard) @Post('generateVideoCallSession') async generateVideoCallSession( @Body() { input, session_variables }: GenerateVideoCallSessionParams, ): Promise> { const requester = await this.getRequester(session_variables) const appointment = await this.videoCall.enterVideocall(requester, input.appointment_id) const response = { video_session: appointment?.video_session, patient_video_token: appointment?.patient_video_token, user_video_token: appointment?.user_video_token, state: appointment?.state, } return response } @UseGuards(BasicAuthorizationGuard) @Post('cancelBySubscriptionCancellation') async cancelBySubscriptionCancellation(): Promise { await this.booking.cancelBySubscriptionCancellation() } @UseGuards(BasicAuthorizationGuard) @Post('cancelWithNoNutriArrived') async cancelWithNoNutriArrived(): Promise { await this.booking.cancelAllAppointmentsWithNutriNoArrived() } private async getRequester(session_variables: SessionVariables): Promise { const id = session_variables['x-hasura-user-id'] return await (session_variables['x-hasura-role'] === 'patient' ? this.patientRepository.get(id) : this.userRepository.get(id)) } @Post('cancelBySubscriptionSuspension') async suspended(@Body() { trigger, event }: BaseEventParams): Promise { if ( trigger.name === SUSPENDED_SUBSCRIPTION_EVENT && !event.data.old.suspendedAt && !isNil(event.data.new.suspendedAt) ) await this.booking.cancelBySubscriptionSuspension(event.data.new.patientId) } }