fix: Code Quality improvements to response record endpoint and added unit tests (#22264)

* chore: remove unnecessary logs and fix documentation

* refactor: extract GetSlotsInputWithRouting type and eliminate code duplication

- Move GetSlotsInputWithRouting_2024_09_04 type to platform-types package for reuse
- Refactor slots service to eliminate duplicate error handling logic
- Fix TypeScript errors in slots service tests by adding missing type property
- Update test expectations to match new implementation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: improve type safety in slots service

- Export explicit types from slots-input.service for transformed queries
- Replace 'any' type with proper TransformedSlotsQuery union type
- Re-implement fetchAndFormatSlots abstraction to eliminate code duplication
- Revert unrelated console.log in router.controller.ts

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* refactor: simplify slots service implementation

- Remove intermediate variable assignment in getAvailableSlotsWithRouting
- Update test to match simplified routing parameters structure

* test: add comprehensive error handling and edge case tests for slots service

- Add error scenario tests for NotFoundException, invalid time range, and generic errors
- Add edge case tests for null/undefined parameters and empty arrays
- Improve test coverage for getAvailableSlotsWithRouting method
- Mock SlotsInputService properly to enable isolated unit testing

* 📝 CodeRabbit Chat: Rename TransformedGetSlotsQuery types to InternalGetSlotsQuery in slot services

* fix: correct import path for AvailableSlotsService in slots service test

- Fix import path from '@/lib/services/AvailableSlots' to '@/lib/services/available-slots.service'
- Resolves unit test failure due to case sensitivity/naming mismatch
- All API v2 tests now pass (9 test suites, 142 tests)

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Hariom Balhara
2025-07-18 16:26:53 +05:30
committed by GitHub
co-authored by hariom@cal.com <hariombalhara@gmail.com> Claude coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent cf392562da
commit 05e1ad0c91
9 changed files with 477 additions and 51 deletions
@@ -86,11 +86,10 @@ export class CreateRoutingFormResponseOutputData {
eventTypeId?: number;
@ValidateNested()
@ApiProperty({ type: Routing })
@Type(() => Routing)
@ApiPropertyOptional({
type: Routing,
description: "The routing information.",
description: "The routing information that could be passed as is to the booking API.",
example: {
eventTypeId: 123,
routing: {
@@ -100,8 +99,6 @@ export class CreateRoutingFormResponseOutputData {
},
},
})
@ValidateNested()
@Type(() => Routing)
routing?: Routing;
@IsString()
@@ -55,15 +55,14 @@ export class SharedRoutingFormResponseService {
// Extract event type information from the routed URL
const { eventTypeId, crmParams } = await this.extractEventTypeAndCrmParams(user.id, redirectUrl);
const paramsForGetAvailableSlots = {
// Get available slots using the slots service with CRM parameters
const slots = await this.slotsService.getAvailableSlotsWithRouting({
type: ById_2024_09_04_type,
eventTypeId,
...slotsQuery,
...crmParams,
} as const;
});
// Get available slots using the slots service with CRM parameters
const slots = await this.slotsService.getAvailableSlots(paramsForGetAvailableSlots);
const teamMemberIds = crmParams.routedTeamMemberIds ?? [];
const teamMemberEmail = crmParams.teamMemberEmail ?? undefined;
const skipContactOwner = crmParams.skipContactOwner ?? undefined;
@@ -13,11 +13,32 @@ import {
ByUsernameAndEventTypeSlug_2024_09_04,
ByTeamSlugAndEventTypeSlug_2024_09_04,
GetSlotsInput_2024_09_04,
GetSlotsInputWithRouting_2024_09_04,
ById_2024_09_04_type,
ByUsernameAndEventTypeSlug_2024_09_04_type,
ByTeamSlugAndEventTypeSlug_2024_09_04_type,
} from "@calcom/platform-types";
export type InternalGetSlotsQuery = {
isTeamEvent: boolean;
startTime: string;
endTime: string;
duration?: number;
eventTypeId: number;
eventTypeSlug: string;
usernameList: string[];
timeZone: string | undefined;
orgSlug: string | null | undefined;
rescheduleUid: string | null;
};
export type InternalGetSlotsQueryWithRouting = InternalGetSlotsQuery & {
routedTeamMemberIds: number[] | null;
skipContactOwner: boolean;
teamMemberEmail: string | null;
routingFormResponseId: number | undefined;
};
@Injectable()
export class SlotsInputService_2024_09_04 {
constructor(
@@ -30,7 +51,7 @@ export class SlotsInputService_2024_09_04 {
private readonly teamsEventTypesRepository: TeamsEventTypesRepository
) {}
async transformGetSlotsQuery(query: GetSlotsInput_2024_09_04) {
async transformGetSlotsQuery(query: GetSlotsInput_2024_09_04): Promise<InternalGetSlotsQuery> {
const eventType = await this.getEventType(query);
if (!eventType) {
throw new NotFoundException(`Event Type not found`);
@@ -46,10 +67,6 @@ export class SlotsInputService_2024_09_04 {
const timeZone = query.timeZone;
const orgSlug = "organizationSlug" in query ? query.organizationSlug : null;
const rescheduleUid = query.bookingUidToReschedule || null;
const routedTeamMemberIds = query.routedTeamMemberIds || null;
const skipContactOwner = query.skipContactOwner || false;
const teamMemberEmail = query.teamMemberEmail || null;
const routingFormResponseId = query.routingFormResponseId || null;
return {
isTeamEvent,
@@ -62,10 +79,23 @@ export class SlotsInputService_2024_09_04 {
timeZone,
orgSlug,
rescheduleUid,
routedTeamMemberIds,
skipContactOwner,
teamMemberEmail,
routingFormResponseId,
};
}
async transformRoutingGetSlotsQuery(
query: GetSlotsInputWithRouting_2024_09_04
): Promise<InternalGetSlotsQueryWithRouting> {
const { routedTeamMemberIds, skipContactOwner, teamMemberEmail, routingFormResponseId, ...baseQuery } =
query;
const baseTransformation = await this.transformGetSlotsQuery(baseQuery);
return {
...baseTransformation,
routedTeamMemberIds: routedTeamMemberIds || null,
skipContactOwner: skipContactOwner || false,
teamMemberEmail: teamMemberEmail || null,
routingFormResponseId: routingFormResponseId ?? undefined,
};
}
@@ -0,0 +1,397 @@
import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.repository";
import { AvailableSlotsService } from "@/lib/services/available-slots.service";
import { MembershipsRepository } from "@/modules/memberships/memberships.repository";
import { MembershipsService } from "@/modules/memberships/services/memberships.service";
import { SlotsInputService_2024_09_04 } from "@/modules/slots/slots-2024-09-04/services/slots-input.service";
import { SlotsOutputService_2024_09_04 } from "@/modules/slots/slots-2024-09-04/services/slots-output.service";
import { SlotsRepository_2024_09_04 } from "@/modules/slots/slots-2024-09-04/slots.repository";
import { TeamsRepository } from "@/modules/teams/teams/teams.repository";
import { BadRequestException, NotFoundException } from "@nestjs/common";
import { Test, TestingModule } from "@nestjs/testing";
import { SlotsService_2024_09_04 } from "./slots.service";
describe("SlotsService_2024_09_04", () => {
let service: SlotsService_2024_09_04;
let eventTypesRepository: EventTypesRepository_2024_06_14;
let availableSlotsService: AvailableSlotsService;
let slotsInputService: SlotsInputService_2024_09_04;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
SlotsService_2024_09_04,
{
provide: SlotsInputService_2024_09_04,
useValue: {
transformGetSlotsQuery: jest.fn(),
transformRoutingGetSlotsQuery: jest.fn(),
},
},
{
provide: EventTypesRepository_2024_06_14,
useValue: {
getEventTypeById: jest.fn(),
},
},
{
provide: SlotsRepository_2024_09_04,
useValue: {},
},
{
provide: SlotsOutputService_2024_09_04,
useValue: {
getAvailableSlots: jest.fn().mockResolvedValue({
slots: {
"2024-01-15": [{ time: "2024-01-15T10:00:00.000Z" }, { time: "2024-01-15T11:00:00.000Z" }],
},
}),
},
},
{
provide: AvailableSlotsService,
useValue: {
getAvailableSlots: jest.fn(),
},
},
{
provide: MembershipsService,
useValue: {},
},
{
provide: MembershipsRepository,
useValue: {},
},
{
provide: TeamsRepository,
useValue: {},
},
],
}).compile();
service = module.get<SlotsService_2024_09_04>(SlotsService_2024_09_04);
slotsInputService = module.get<SlotsInputService_2024_09_04>(SlotsInputService_2024_09_04);
eventTypesRepository = module.get<EventTypesRepository_2024_06_14>(EventTypesRepository_2024_06_14);
availableSlotsService = module.get<AvailableSlotsService>(AvailableSlotsService);
jest.clearAllMocks();
});
describe("getAvailableSlotsWithRouting", () => {
const sharedTestData = {
eventTypeId: 123,
start: "2024-01-15T00:00:00.000Z",
end: "2024-01-16T00:00:00.000Z",
timeZone: "America/New_York",
mockEventType: {
id: 123,
slug: "test-event",
teamId: null, // Not a team event
length: 30,
},
mockSlotsResponse: {
slots: {},
},
baseInputQuery: {
type: "byEventTypeId" as const,
isTeamEvent: false,
start: "2024-01-15T00:00:00.000Z",
end: "2024-01-16T00:00:00.000Z",
duration: undefined,
eventTypeId: 123,
eventTypeSlug: "test-event",
usernameList: [],
timeZone: "America/New_York",
orgSlug: null,
rescheduleUid: null,
},
routingParams: {
routedTeamMemberIds: [456, 789],
skipContactOwner: true,
teamMemberEmail: "test@example.com",
routingFormResponseId: 999,
},
};
beforeEach(() => {
// Setup shared mocks
(eventTypesRepository.getEventTypeById as jest.Mock).mockResolvedValue(sharedTestData.mockEventType);
(availableSlotsService.getAvailableSlots as jest.Mock).mockResolvedValue(
sharedTestData.mockSlotsResponse
);
});
it("should call getAvailableSlots with correct routing parameters", async () => {
const inputQuery = {
...sharedTestData.baseInputQuery,
...sharedTestData.routingParams,
};
// Mock the transform method to return the expected transformed query
const transformedQuery = {
isTeamEvent: false,
startTime: "2024-01-15T00:00:00.000Z",
endTime: "2024-01-16T23:59:59.000Z",
eventTypeId: 123,
eventTypeSlug: "test-event",
usernameList: [],
timeZone: "America/New_York",
orgSlug: null,
rescheduleUid: null,
...sharedTestData.routingParams,
};
(slotsInputService.transformRoutingGetSlotsQuery as jest.Mock).mockResolvedValue(transformedQuery);
await service.getAvailableSlotsWithRouting({
...inputQuery,
});
const { start: _1, end: _2, type: _3, ...queryWithoutStartEndAndType } = sharedTestData.baseInputQuery;
expect(availableSlotsService.getAvailableSlots).toHaveBeenCalledWith({
input: {
...queryWithoutStartEndAndType,
startTime: "2024-01-15T00:00:00.000Z",
endTime: "2024-01-16T23:59:59.000Z",
...sharedTestData.routingParams,
},
ctx: {},
});
});
});
describe("getAvailableSlotsWithRouting - Error Scenarios", () => {
const baseInputQuery = {
type: "byEventTypeId" as const,
eventTypeId: 123,
start: "2024-01-15T00:00:00.000Z",
end: "2024-01-16T00:00:00.000Z",
timeZone: "America/New_York",
};
it("should handle when event type is not found", async () => {
const notFoundError = new NotFoundException("Event Type not found");
(slotsInputService.transformRoutingGetSlotsQuery as jest.Mock).mockRejectedValue(notFoundError);
await expect(
service.getAvailableSlotsWithRouting({
...baseInputQuery,
teamMemberEmail: "test@example.com",
})
).rejects.toThrow(NotFoundException);
expect(slotsInputService.transformRoutingGetSlotsQuery).toHaveBeenCalledWith({
...baseInputQuery,
teamMemberEmail: "test@example.com",
});
});
it("should handle invalid time range error and throw BadRequestException", async () => {
const transformedQuery = {
isTeamEvent: false,
startTime: "2024-01-16T00:00:00.000Z",
endTime: "2024-01-15T23:59:59.000Z",
eventTypeId: 123,
eventTypeSlug: "test-event",
usernameList: [],
timeZone: "America/New_York",
orgSlug: null,
rescheduleUid: null,
routedTeamMemberIds: null,
skipContactOwner: false,
teamMemberEmail: null,
routingFormResponseId: undefined,
};
(slotsInputService.transformRoutingGetSlotsQuery as jest.Mock).mockResolvedValue(transformedQuery);
(availableSlotsService.getAvailableSlots as jest.Mock).mockRejectedValue(
new Error("Invalid time range given - start time must be before end time")
);
await expect(service.getAvailableSlotsWithRouting(baseInputQuery)).rejects.toThrow(BadRequestException);
await expect(service.getAvailableSlotsWithRouting(baseInputQuery)).rejects.toThrow(
"Invalid time range given - check the 'start' and 'end' query parameters."
);
});
it("should re-throw non-time-range errors without modification", async () => {
const genericError = new Error("Database connection failed");
const transformedQuery = {
isTeamEvent: false,
startTime: "2024-01-15T00:00:00.000Z",
endTime: "2024-01-16T23:59:59.000Z",
eventTypeId: 123,
eventTypeSlug: "test-event",
usernameList: [],
timeZone: "America/New_York",
orgSlug: null,
rescheduleUid: null,
routedTeamMemberIds: null,
skipContactOwner: false,
teamMemberEmail: null,
routingFormResponseId: undefined,
};
(slotsInputService.transformRoutingGetSlotsQuery as jest.Mock).mockResolvedValue(transformedQuery);
(availableSlotsService.getAvailableSlots as jest.Mock).mockRejectedValue(genericError);
await expect(service.getAvailableSlotsWithRouting(baseInputQuery)).rejects.toThrow(genericError);
});
it("should handle non-Error objects thrown by dependencies", async () => {
const transformedQuery = {
isTeamEvent: false,
startTime: "2024-01-15T00:00:00.000Z",
endTime: "2024-01-16T23:59:59.000Z",
eventTypeId: 123,
eventTypeSlug: "test-event",
usernameList: [],
timeZone: "America/New_York",
orgSlug: null,
rescheduleUid: null,
routedTeamMemberIds: null,
skipContactOwner: false,
teamMemberEmail: null,
routingFormResponseId: undefined,
};
(slotsInputService.transformRoutingGetSlotsQuery as jest.Mock).mockResolvedValue(transformedQuery);
const nonErrorObject = { message: "Something went wrong", code: "UNKNOWN_ERROR" };
(availableSlotsService.getAvailableSlots as jest.Mock).mockRejectedValue(nonErrorObject);
await expect(service.getAvailableSlotsWithRouting(baseInputQuery)).rejects.toEqual(nonErrorObject);
});
});
describe("getAvailableSlotsWithRouting - Edge Cases", () => {
it("should handle null and undefined routing parameters", async () => {
const input = {
type: "byEventTypeId" as const,
eventTypeId: 123,
start: "2024-01-15T00:00:00.000Z",
end: "2024-01-16T00:00:00.000Z",
timeZone: "America/New_York",
teamMemberEmail: undefined,
routedTeamMemberIds: undefined,
skipContactOwner: undefined,
routingFormResponseId: undefined,
};
const transformedQuery = {
isTeamEvent: false,
startTime: "2024-01-15T00:00:00.000Z",
endTime: "2024-01-16T23:59:59.000Z",
eventTypeId: 123,
eventTypeSlug: "test-event",
usernameList: [],
timeZone: "America/New_York",
orgSlug: null,
rescheduleUid: null,
teamMemberEmail: null,
routedTeamMemberIds: null,
skipContactOwner: false,
routingFormResponseId: undefined,
};
(slotsInputService.transformRoutingGetSlotsQuery as jest.Mock).mockResolvedValue(transformedQuery);
(availableSlotsService.getAvailableSlots as jest.Mock).mockResolvedValue({ slots: {} });
await service.getAvailableSlotsWithRouting(input);
expect(availableSlotsService.getAvailableSlots).toHaveBeenCalledWith({
input: expect.objectContaining({
teamMemberEmail: null,
routedTeamMemberIds: null,
skipContactOwner: false,
routingFormResponseId: undefined,
}),
ctx: {},
});
});
it("should handle empty routedTeamMemberIds array", async () => {
const input = {
type: "byEventTypeId" as const,
eventTypeId: 123,
start: "2024-01-15T00:00:00.000Z",
end: "2024-01-16T00:00:00.000Z",
timeZone: "America/New_York",
routedTeamMemberIds: [],
};
const transformedQuery = {
isTeamEvent: false,
startTime: "2024-01-15T00:00:00.000Z",
endTime: "2024-01-16T23:59:59.000Z",
eventTypeId: 123,
eventTypeSlug: "test-event",
usernameList: [],
timeZone: "America/New_York",
orgSlug: null,
rescheduleUid: null,
routedTeamMemberIds: [],
skipContactOwner: false,
teamMemberEmail: null,
routingFormResponseId: undefined,
};
(slotsInputService.transformRoutingGetSlotsQuery as jest.Mock).mockResolvedValue(transformedQuery);
(availableSlotsService.getAvailableSlots as jest.Mock).mockResolvedValue({ slots: {} });
await service.getAvailableSlotsWithRouting(input);
expect(availableSlotsService.getAvailableSlots).toHaveBeenCalledWith({
input: expect.objectContaining({
routedTeamMemberIds: [],
}),
ctx: {},
});
});
it("should handle all routing parameters being provided", async () => {
const input = {
type: "byEventTypeId" as const,
eventTypeId: 123,
start: "2024-01-15T00:00:00.000Z",
end: "2024-01-16T00:00:00.000Z",
timeZone: "America/New_York",
routedTeamMemberIds: [1, 2, 3],
skipContactOwner: true,
teamMemberEmail: "team@example.com",
routingFormResponseId: 999,
};
const transformedQuery = {
isTeamEvent: false,
startTime: "2024-01-15T00:00:00.000Z",
endTime: "2024-01-16T23:59:59.000Z",
eventTypeId: 123,
eventTypeSlug: "test-event",
usernameList: [],
timeZone: "America/New_York",
orgSlug: null,
rescheduleUid: null,
routedTeamMemberIds: [1, 2, 3],
skipContactOwner: true,
teamMemberEmail: "team@example.com",
routingFormResponseId: 999,
};
(slotsInputService.transformRoutingGetSlotsQuery as jest.Mock).mockResolvedValue(transformedQuery);
(availableSlotsService.getAvailableSlots as jest.Mock).mockResolvedValue({ slots: {} });
await service.getAvailableSlotsWithRouting(input);
expect(availableSlotsService.getAvailableSlots).toHaveBeenCalledWith({
input: expect.objectContaining({
routedTeamMemberIds: [1, 2, 3],
skipContactOwner: true,
teamMemberEmail: "team@example.com",
routingFormResponseId: 999,
}),
ctx: {},
});
});
});
});
@@ -3,7 +3,11 @@ import { AvailableSlotsService } from "@/lib/services/available-slots.service";
import { MembershipsRepository } from "@/modules/memberships/memberships.repository";
import { MembershipsService } from "@/modules/memberships/services/memberships.service";
import { TimeSlots } from "@/modules/slots/slots-2024-04-15/services/slots-output.service";
import { SlotsInputService_2024_09_04 } from "@/modules/slots/slots-2024-09-04/services/slots-input.service";
import {
SlotsInputService_2024_09_04,
InternalGetSlotsQuery,
InternalGetSlotsQueryWithRouting,
} from "@/modules/slots/slots-2024-09-04/services/slots-input.service";
import { SlotsOutputService_2024_09_04 } from "@/modules/slots/slots-2024-09-04/services/slots-output.service";
import { SlotsRepository_2024_09_04 } from "@/modules/slots/slots-2024-09-04/slots.repository";
import { TeamsRepository } from "@/modules/teams/teams/teams.repository";
@@ -18,8 +22,13 @@ import {
import { DateTime } from "luxon";
import { z } from "zod";
import { GetSlotsInput_2024_09_04, ReserveSlotInput_2024_09_04 } from "@calcom/platform-types";
import { Booking, EventType } from "@calcom/prisma/client";
import { SlotFormat } from "@calcom/platform-enums";
import {
GetSlotsInput_2024_09_04,
GetSlotsInputWithRouting_2024_09_04,
ReserveSlotInput_2024_09_04,
} from "@calcom/platform-types";
import { EventType } from "@calcom/prisma/client";
const eventTypeMetadataSchema = z
.object({
@@ -29,6 +38,7 @@ const eventTypeMetadataSchema = z
const DEFAULT_RESERVATION_DURATION = 5;
type InternalSlotsQuery = InternalGetSlotsQuery | InternalGetSlotsQueryWithRouting;
@Injectable()
export class SlotsService_2024_09_04 {
constructor(
@@ -42,21 +52,18 @@ export class SlotsService_2024_09_04 {
private readonly availableSlotsService: AvailableSlotsService
) {}
async getAvailableSlots(query: GetSlotsInput_2024_09_04) {
private async fetchAndFormatSlots(queryTransformed: InternalSlotsQuery, format?: SlotFormat) {
try {
const queryTransformed = await this.slotsInputService.transformGetSlotsQuery(query);
const availableSlots: TimeSlots = await this.availableSlotsService.getAvailableSlots({
input: {
...queryTransformed,
routingFormResponseId: queryTransformed.routingFormResponseId ?? undefined,
},
input: queryTransformed,
ctx: {},
});
const formatted = await this.slotsOutputService.getAvailableSlots(
availableSlots,
queryTransformed.eventTypeId,
queryTransformed.duration,
query.format,
format,
queryTransformed.timeZone
);
@@ -73,6 +80,16 @@ export class SlotsService_2024_09_04 {
}
}
async getAvailableSlots(query: GetSlotsInput_2024_09_04) {
const queryTransformed = await this.slotsInputService.transformGetSlotsQuery(query);
return this.fetchAndFormatSlots(queryTransformed, query.format);
}
async getAvailableSlotsWithRouting(query: GetSlotsInputWithRouting_2024_09_04) {
const queryTransformed = await this.slotsInputService.transformRoutingGetSlotsQuery(query);
return this.fetchAndFormatSlots(queryTransformed, query.format);
}
async reserveSlot(input: ReserveSlotInput_2024_09_04, authUserId?: number) {
if (input.reservationDuration && !authUserId) {
throw new UnauthorizedException(
+1 -1
View File
@@ -25010,7 +25010,7 @@
"example": 123
},
"routing": {
"description": "The routing information.",
"description": "The routing information that could be passed as is to the booking API.",
"example": {
"eventTypeId": 123,
"routing": {
+1 -1
View File
@@ -25010,7 +25010,7 @@
"example": 123
},
"routing": {
"description": "The routing information.",
"description": "The routing information that could be passed as is to the booking API.",
"example": {
"eventTypeId": 123,
"routing": {
@@ -17,6 +17,13 @@ export type GetSlotsInput_2024_09_04 =
| ByTeamSlugAndEventTypeSlug_2024_09_04
| ByUsernames_2024_09_04;
export type GetSlotsInputWithRouting_2024_09_04 = GetSlotsInput_2024_09_04 & {
teamMemberEmail?: string;
routingFormResponseId?: number;
routedTeamMemberIds?: number[];
skipContactOwner?: boolean;
};
@Injectable()
export class GetSlotsInputPipe implements PipeTransform {
// note(Lauris): we need empty constructor otherwise v2 can't be started due to error:
@@ -1,4 +1,4 @@
import { ApiProperty, ApiPropertyOptional, ApiHideProperty } from "@nestjs/swagger";
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { Transform } from "class-transformer";
import {
IsDateString,
@@ -9,7 +9,6 @@ import {
IsArray,
ArrayMinSize,
IsEnum,
IsBoolean,
} from "class-validator";
import { SlotFormat } from "@calcom/platform-enums";
@@ -89,26 +88,6 @@ export class GetAvailableSlotsInput_2024_09_04 {
example: "abc123def456",
})
bookingUidToReschedule?: string;
@IsString()
@IsOptional()
@ApiHideProperty()
teamMemberEmail?: string;
@IsNumber()
@IsOptional()
@ApiHideProperty()
routingFormResponseId?: number;
@IsArray()
@IsOptional()
@ApiHideProperty()
routedTeamMemberIds?: number[];
@IsBoolean()
@IsOptional()
@ApiHideProperty()
skipContactOwner?: boolean;
}
export const ById_2024_09_04_type = "byEventTypeId";