feat: booking references api type filter (#21179)
* feat: add `type` filter for booking references API endpointa * Update openapi.json * feat: add enum validation for booking reference types in filter input * refactor: rename externalUid to eventUid and add destinationCalendarId in booking references * refactor: replace enum with const array for BookingReferenceType * fix: type safety for booking references where clause using Prisma types * refactor: rename BookingReferenceType to BookingReferences
This commit is contained in:
@@ -1,19 +1,26 @@
|
||||
import { BookingReferencesFilterInput_2024_08_13 } from "@/ee/bookings/2024-08-13/inputs/booking-references-filter.input";
|
||||
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
|
||||
@Injectable()
|
||||
export class BookingReferencesRepository_2024_08_13 {
|
||||
constructor(private readonly dbRead: PrismaReadService) {}
|
||||
|
||||
async getBookingReferences(bookingId: number) {
|
||||
async getBookingReferences(bookingId: number, filter?: BookingReferencesFilterInput_2024_08_13) {
|
||||
const whereClause: Prisma.BookingReferenceWhereInput = { bookingId };
|
||||
|
||||
if (filter?.type) {
|
||||
whereClause.type = filter.type;
|
||||
}
|
||||
|
||||
return this.dbRead.prisma.bookingReference.findMany({
|
||||
where: {
|
||||
bookingId,
|
||||
},
|
||||
where: whereClause,
|
||||
select: {
|
||||
type: true,
|
||||
uid: true,
|
||||
id: true,
|
||||
externalCalendarId: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { BookingUidGuard } from "@/ee/bookings/2024-08-13/guards/booking-uid.guard";
|
||||
import { BookingReferencesFilterInput_2024_08_13 } from "@/ee/bookings/2024-08-13/inputs/booking-references-filter.input";
|
||||
import { BookingReferencesOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/booking-references.output";
|
||||
import { CalendarLinksOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/calendar-links.output";
|
||||
import { CancelBookingOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/cancel-booking.output";
|
||||
@@ -403,9 +404,14 @@ export class BookingsController_2024_08_13 {
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async getBookingReferences(
|
||||
@Param("bookingUid") bookingUid: string,
|
||||
@GetUser("id") userId: number
|
||||
@GetUser("id") userId: number,
|
||||
@Query() filter: BookingReferencesFilterInput_2024_08_13
|
||||
): Promise<BookingReferencesOutput_2024_08_13> {
|
||||
const bookingReferences = await this.bookingReferencesService.getBookingReferences(bookingUid, userId);
|
||||
const bookingReferences = await this.bookingReferencesService.getBookingReferences(
|
||||
bookingUid,
|
||||
userId,
|
||||
filter
|
||||
);
|
||||
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsIn, IsOptional } from "class-validator";
|
||||
|
||||
export const BookingReferences = [
|
||||
"google_calendar",
|
||||
"office365_calendar",
|
||||
"daily_video",
|
||||
"google_video",
|
||||
"office365_video",
|
||||
"zoom_video",
|
||||
] as const;
|
||||
|
||||
export class BookingReferencesFilterInput_2024_08_13 {
|
||||
@ApiProperty({
|
||||
description: "Filter booking references by type",
|
||||
required: false,
|
||||
enum: BookingReferences,
|
||||
example: "google_calendar",
|
||||
})
|
||||
@IsOptional()
|
||||
@IsIn(BookingReferences)
|
||||
type?: (typeof BookingReferences)[number];
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import { IsEnum, IsNumber, IsString } from "class-validator";
|
||||
|
||||
import { SUCCESS_STATUS, ERROR_STATUS } from "@calcom/platform-constants";
|
||||
@@ -12,9 +12,16 @@ export class BookingReference {
|
||||
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: "The external uid of the booking reference",
|
||||
description: "The event uid of the booking",
|
||||
})
|
||||
externalUid!: string;
|
||||
eventUid!: string;
|
||||
|
||||
@IsString()
|
||||
@ApiProperty({
|
||||
description: "The id of the calendar the event is created in",
|
||||
nullable: true,
|
||||
})
|
||||
destinationCalendarId!: string | null;
|
||||
|
||||
@IsNumber()
|
||||
@ApiProperty({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { BookingReferencesRepository_2024_08_13 } from "@/ee/bookings/2024-08-13/booking-references.repository";
|
||||
import { BookingsRepository_2024_08_13 } from "@/ee/bookings/2024-08-13/bookings.repository";
|
||||
import { BookingReferencesFilterInput_2024_08_13 } from "@/ee/bookings/2024-08-13/inputs/booking-references-filter.input";
|
||||
import { OutputBookingReferencesService_2024_08_13 } from "@/ee/bookings/2024-08-13/services/output-booking-references.service";
|
||||
import { Injectable, NotFoundException, BadRequestException } from "@nestjs/common";
|
||||
|
||||
@@ -11,7 +12,11 @@ export class BookingReferencesService_2024_08_13 {
|
||||
private readonly outputBookingReferencesService: OutputBookingReferencesService_2024_08_13
|
||||
) {}
|
||||
|
||||
async getBookingReferences(bookingUid: string, userId: number) {
|
||||
async getBookingReferences(
|
||||
bookingUid: string,
|
||||
userId: number,
|
||||
filter?: BookingReferencesFilterInput_2024_08_13
|
||||
) {
|
||||
const booking = await this.bookingsRepository.getByUidWithUser(bookingUid);
|
||||
|
||||
if (!booking) {
|
||||
@@ -22,19 +27,19 @@ export class BookingReferencesService_2024_08_13 {
|
||||
throw new BadRequestException(`Booking with uid ${bookingUid} does not belong to user`);
|
||||
}
|
||||
|
||||
const bookingReferences = await this.bookingReferencesRepository.getBookingReferences(booking.id);
|
||||
const bookingReferences = await this.bookingReferencesRepository.getBookingReferences(booking.id, filter);
|
||||
|
||||
return this.outputBookingReferencesService.getOutputBookingReferences(bookingReferences);
|
||||
}
|
||||
|
||||
async getOrgBookingReferences(bookingUid: string) {
|
||||
async getOrgBookingReferences(bookingUid: string, filter?: BookingReferencesFilterInput_2024_08_13) {
|
||||
const booking = await this.bookingsRepository.getByUidWithUser(bookingUid);
|
||||
|
||||
if (!booking) {
|
||||
throw new NotFoundException(`Booking with uid ${bookingUid} not found`);
|
||||
}
|
||||
|
||||
const bookingReferences = await this.bookingReferencesRepository.getBookingReferences(booking.id);
|
||||
const bookingReferences = await this.bookingReferencesRepository.getBookingReferences(booking.id, filter);
|
||||
|
||||
return this.outputBookingReferencesService.getOutputBookingReferences(bookingReferences);
|
||||
}
|
||||
|
||||
+3
-1
@@ -4,6 +4,7 @@ interface IBookingReference {
|
||||
type: string;
|
||||
uid: string;
|
||||
id: number;
|
||||
externalCalendarId: string | null;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
@@ -11,8 +12,9 @@ export class OutputBookingReferencesService_2024_08_13 {
|
||||
getOutputBookingReferences(bookingReferences: IBookingReference[]) {
|
||||
return bookingReferences.map((bookingReference) => ({
|
||||
type: bookingReference.type,
|
||||
externalUid: bookingReference.uid,
|
||||
eventUid: bookingReference.uid,
|
||||
id: bookingReference.id,
|
||||
destinationCalendarId: bookingReference?.externalCalendarId,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -1,4 +1,5 @@
|
||||
import { BookingUidGuard } from "@/ee/bookings/2024-08-13/guards/booking-uid.guard";
|
||||
import { BookingReferencesFilterInput_2024_08_13 } from "@/ee/bookings/2024-08-13/inputs/booking-references-filter.input";
|
||||
import { BookingReferencesOutput_2024_08_13 } from "@/ee/bookings/2024-08-13/outputs/booking-references.output";
|
||||
import { BookingReferencesService_2024_08_13 } from "@/ee/bookings/2024-08-13/services/booking-references.service";
|
||||
import { BookingsService_2024_08_13 } from "@/ee/bookings/2024-08-13/services/bookings.service";
|
||||
@@ -82,9 +83,10 @@ export class OrganizationsTeamsBookingsController {
|
||||
})
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async getBookingReferences(
|
||||
@Param("bookingUid") bookingUid: string
|
||||
@Param("bookingUid") bookingUid: string,
|
||||
@Query() filter: BookingReferencesFilterInput_2024_08_13
|
||||
): Promise<BookingReferencesOutput_2024_08_13> {
|
||||
const bookingReferences = await this.bookingReferencesService.getOrgBookingReferences(bookingUid);
|
||||
const bookingReferences = await this.bookingReferencesService.getOrgBookingReferences(bookingUid, filter);
|
||||
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
|
||||
@@ -3321,6 +3321,24 @@
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Filter booking references by type",
|
||||
"example": "google_calendar",
|
||||
"schema": {
|
||||
"enum": [
|
||||
"google_calendar",
|
||||
"office365_calendar",
|
||||
"daily_video",
|
||||
"google_video",
|
||||
"office365_video",
|
||||
"zoom_video"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -7529,6 +7547,24 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Filter booking references by type",
|
||||
"example": "google_calendar",
|
||||
"schema": {
|
||||
"enum": [
|
||||
"google_calendar",
|
||||
"office365_calendar",
|
||||
"daily_video",
|
||||
"google_video",
|
||||
"office365_video",
|
||||
"zoom_video"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
@@ -15063,7 +15099,7 @@
|
||||
"eightxeight-video",
|
||||
"discord-video",
|
||||
"demodesk-video",
|
||||
"campfire-video",
|
||||
"campfire-video"
|
||||
],
|
||||
"example": "cal-video"
|
||||
},
|
||||
@@ -21743,7 +21779,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
"type": "number"
|
||||
},
|
||||
"formId": {
|
||||
"type": "string"
|
||||
@@ -22296,7 +22332,7 @@
|
||||
"eightxeight-video",
|
||||
"discord-video",
|
||||
"demodesk-video",
|
||||
"campfire-video",
|
||||
"campfire-video"
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -24257,9 +24293,14 @@
|
||||
"type": "string",
|
||||
"description": "The type of the booking reference"
|
||||
},
|
||||
"externalUid": {
|
||||
"eventUid": {
|
||||
"type": "string",
|
||||
"description": "The external uid of the booking reference"
|
||||
"description": "The event uid of the booking"
|
||||
},
|
||||
"destinationCalendarId": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "The id of the calendar the event is created in"
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
@@ -24268,7 +24309,8 @@
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"externalUid",
|
||||
"eventUid",
|
||||
"destinationCalendarId",
|
||||
"id"
|
||||
]
|
||||
},
|
||||
@@ -25168,4 +25210,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3184,6 +3184,24 @@
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Filter booking references by type",
|
||||
"example": "google_calendar",
|
||||
"schema": {
|
||||
"enum": [
|
||||
"google_calendar",
|
||||
"office365_calendar",
|
||||
"daily_video",
|
||||
"google_video",
|
||||
"office365_video",
|
||||
"zoom_video"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -7197,6 +7215,24 @@
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"description": "Filter booking references by type",
|
||||
"example": "google_calendar",
|
||||
"schema": {
|
||||
"enum": [
|
||||
"google_calendar",
|
||||
"office365_calendar",
|
||||
"daily_video",
|
||||
"google_video",
|
||||
"office365_video",
|
||||
"zoom_video"
|
||||
],
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Authorization",
|
||||
"in": "header",
|
||||
@@ -19940,7 +19976,7 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
"type": "number"
|
||||
},
|
||||
"formId": {
|
||||
"type": "string"
|
||||
@@ -22237,16 +22273,21 @@
|
||||
"type": "string",
|
||||
"description": "The type of the booking reference"
|
||||
},
|
||||
"externalUid": {
|
||||
"eventUid": {
|
||||
"type": "string",
|
||||
"description": "The external uid of the booking reference"
|
||||
"description": "The event uid of the booking"
|
||||
},
|
||||
"destinationCalendarId": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "The id of the calendar the event is created in"
|
||||
},
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "The id of the booking reference"
|
||||
}
|
||||
},
|
||||
"required": ["type", "externalUid", "id"]
|
||||
"required": ["type", "eventUid", "destinationCalendarId", "id"]
|
||||
},
|
||||
"BookingReferencesOutput_2024_08_13": {
|
||||
"type": "object",
|
||||
|
||||
Reference in New Issue
Block a user