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:
Somay Chauhan
2025-05-08 17:23:09 +00:00
committed by GitHub
parent f047799299
commit 8ad62d183c
9 changed files with 162 additions and 27 deletions
@@ -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);
}
@@ -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,
}));
}
}
@@ -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,
+49 -7
View File
@@ -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 @@
}
}
}
}
}
+45 -4
View File
@@ -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",