refactor: GetAvailableSlotsService (#22321)

* refactor: GetAvailableSlotsService

* chore: add todo comments where DI is needed

* chore: bump platform libs
This commit is contained in:
Morgan
2025-07-08 16:54:45 -04:00
committed by GitHub
parent 0c182e2813
commit c3dab3e4f8
18 changed files with 1337 additions and 1277 deletions
+6 -2
View File
@@ -8,7 +8,7 @@ import { HttpError } from "@calcom/lib/http-error";
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
import { createContext } from "@calcom/trpc/server/createContext";
import { getScheduleSchema } from "@calcom/trpc/server/routers/viewer/slots/types";
import { getAvailableSlots } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { TRPCError } from "@trpc/server";
import { getHTTPStatusCodeFromError } from "@trpc/server/http";
@@ -27,7 +27,11 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}
const input = getScheduleSchema.parse({ usernameList: slugs, isTeamEvent: parsedIsTeamEvent, ...rest });
const timeZoneSupported = input.timeZone ? isSupportedTimeZone(input.timeZone) : false;
const availableSlots = await getAvailableSlots({ ctx: await createContext({ req, res }), input });
const availableSlotsService = new AvailableSlotsService();
const availableSlots = await availableSlotsService.getAvailableSlots({
ctx: await createContext({ req, res }),
input,
});
const slotsInProvidedTimeZone = timeZoneSupported
? Object.keys(availableSlots.slots).reduce(
(acc: Record<string, { time: string; attendees?: number; bookingUid?: string }[]>, date) => {
+1 -1
View File
@@ -38,7 +38,7 @@
"@axiomhq/winston": "^1.2.0",
"@calcom/platform-constants": "*",
"@calcom/platform-enums": "*",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.241",
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.243",
"@calcom/platform-types": "*",
"@calcom/platform-utils": "*",
"@calcom/prisma": "*",
@@ -17,7 +17,7 @@ import {
VERSION_2024_08_13,
} from "@calcom/platform-constants";
import { TRPCError } from "@calcom/platform-libraries";
import { getAvailableSlots } from "@calcom/platform-libraries/slots";
import { AvailableSlotsService } from "@calcom/platform-libraries/slots";
import { RemoveSelectedSlotInput_2024_04_15, ReserveSlotInput_2024_04_15 } from "@calcom/platform-types";
import { ApiResponse, GetAvailableSlotsInput_2024_04_15 } from "@calcom/platform-types";
@@ -170,8 +170,10 @@ export class SlotsController_2024_04_15 {
: query.isTeamEvent;
// Do not use workers in E2E, not supported by TS-JEST
const availableSlots = this.config.get<boolean>("e2e")
? await getAvailableSlots({
const availableSlotsService = this.config.get<boolean>("e2e") ? new AvailableSlotsService() : null;
const availableSlots = availableSlotsService
? await availableSlotsService.getAvailableSlots({
input: {
...query,
isTeamEvent,
@@ -1,11 +1,13 @@
import { parentPort } from "worker_threads";
import { getAvailableSlots } from "@calcom/platform-libraries/slots";
import { AvailableSlotsService } from "@calcom/platform-libraries/slots";
parentPort?.on("message", async (data) => {
try {
const { input, ctx } = data;
const result = await getAvailableSlots({ input, ctx });
const availableSlotsService = new AvailableSlotsService();
const result = await availableSlotsService.getAvailableSlots({ input, ctx });
parentPort?.postMessage({ success: true, data: result });
} catch (error) {
parentPort?.postMessage({
@@ -17,7 +17,7 @@ import {
import { DateTime } from "luxon";
import { z } from "zod";
import { getAvailableSlots } from "@calcom/platform-libraries/slots";
import { AvailableSlotsService } from "@calcom/platform-libraries/slots";
import { GetSlotsInput_2024_09_04, ReserveSlotInput_2024_09_04 } from "@calcom/platform-types";
import { Booking, EventType } from "@calcom/prisma/client";
@@ -31,6 +31,8 @@ const DEFAULT_RESERVATION_DURATION = 5;
@Injectable()
export class SlotsService_2024_09_04 {
private readonly availableSlotsService: AvailableSlotsService;
constructor(
private readonly eventTypeRepository: EventTypesRepository_2024_06_14,
private readonly slotsRepository: SlotsRepository_2024_09_04,
@@ -39,12 +41,14 @@ export class SlotsService_2024_09_04 {
private readonly membershipsService: MembershipsService,
private readonly membershipsRepository: MembershipsRepository,
private readonly teamsRepository: TeamsRepository
) {}
) {
this.availableSlotsService = new AvailableSlotsService();
}
async getAvailableSlots(query: GetSlotsInput_2024_09_04) {
try {
const queryTransformed = await this.slotsInputService.transformGetSlotsQuery(query);
const availableSlots: TimeSlots = await getAvailableSlots({
const availableSlots: TimeSlots = await this.availableSlotsService.getAvailableSlots({
input: {
...queryTransformed,
routingFormResponseId: queryTransformed.routingFormResponseId ?? undefined,
@@ -8,7 +8,7 @@ import type { TGetRetellLLMSchema } from "@calcom/features/ee/cal-ai-phone/zod-u
import { fetcher } from "@calcom/lib/retellAIFetcher";
import { defaultHandler } from "@calcom/lib/server/defaultHandler";
import prisma from "@calcom/prisma";
import { getAvailableSlots } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
dayjs.extend(advancedFormat);
@@ -86,8 +86,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
const startTime = now.startOf("month").toISOString();
const endTime = now.add(2, "month").endOf("month").toISOString();
const orgSlug = eventType?.team?.parent?.slug ?? null;
const availableSlotsService = new AvailableSlotsService();
const availableSlots = await getAvailableSlots({
const availableSlots = await availableSlotsService.getAvailableSlots({
input: {
startTime,
endTime,
+95 -90
View File
@@ -17,7 +17,7 @@ import { describe, vi, test } from "vitest";
import dayjs from "@calcom/dayjs";
import { SchedulingType, type BookingStatus } from "@calcom/prisma/enums";
import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expect, expectedSlotsForSchedule } from "./getSchedule/expects";
import { setupAndTeardown } from "./getSchedule/setupAndTeardown";
@@ -31,6 +31,7 @@ vi.mock("@calcom/lib/constants", () => ({
}));
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
setupAndTeardown();
// TODO: Move these inside describe('Team Event')
@@ -113,7 +114,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleWithLeadSkip = await getSchedule({
const scheduleWithLeadSkip = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -134,7 +135,7 @@ describe("getSchedule", () => {
}
);
const scheduleWithoutLeadSkip = await getSchedule({
const scheduleWithoutLeadSkip = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -262,7 +263,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleFixedHostLead = await getSchedule({
const scheduleFixedHostLead = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -291,7 +292,7 @@ describe("getSchedule", () => {
}
);
const scheduleRRHostLead = await getSchedule({
const scheduleRRHostLead = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -392,7 +393,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleWithLeadSkip = await getSchedule({
const scheduleWithLeadSkip = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -526,7 +527,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleWithLeadSkip = await getSchedule({
const scheduleWithLeadSkip = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -623,7 +624,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleWithLeadSkip = await getSchedule({
const scheduleWithLeadSkip = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -732,7 +733,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleWithLeadSkip = await getSchedule({
const scheduleWithLeadSkip = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -829,7 +830,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleWithLeadSkip = await getSchedule({
const scheduleWithLeadSkip = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -926,7 +927,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleWhenContactOwnerIsSkipped = await getSchedule({
const scheduleWhenContactOwnerIsSkipped = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1030,7 +1031,7 @@ describe("getSchedule", () => {
});
// Day Plus 2 is completely free - It only has non accepted bookings
const scheduleOnCompletelyFreeDay = await getSchedule({
const scheduleOnCompletelyFreeDay = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
// EventTypeSlug doesn't matter for non-dynamic events
@@ -1064,7 +1065,7 @@ describe("getSchedule", () => {
);
// Day plus 3
const scheduleForDayWithOneBooking = await getSchedule({
const scheduleForDayWithOneBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1130,7 +1131,7 @@ describe("getSchedule", () => {
});
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
const scheduleForEventWith30Length = await getSchedule({
const scheduleForEventWith30Length = await availableSlotsService.getAvailableSlots({
input: {
orgSlug: null,
eventTypeId: 1,
@@ -1167,17 +1168,18 @@ describe("getSchedule", () => {
}
);
const scheduleForEventWith30minsLengthAndSlotInterval2hrs = await getSchedule({
input: {
orgSlug: null,
eventTypeId: 2,
eventTypeSlug: "",
startTime: `${plus1DateString}T18:30:00.000Z`,
endTime: `${plus2DateString}T18:29:59.999Z`,
timeZone: Timezones["+5:30"],
isTeamEvent: false,
},
});
const scheduleForEventWith30minsLengthAndSlotInterval2hrs =
await availableSlotsService.getAvailableSlots({
input: {
orgSlug: null,
eventTypeId: 2,
eventTypeSlug: "",
startTime: `${plus1DateString}T18:30:00.000Z`,
endTime: `${plus2DateString}T18:29:59.999Z`,
timeZone: Timezones["+5:30"],
isTeamEvent: false,
},
});
// `slotInterval` takes precedence over `length`
// 4:30 is utc so it is 10:00 in IST
expect(scheduleForEventWith30minsLengthAndSlotInterval2hrs).toHaveTimeSlots(
@@ -1227,7 +1229,7 @@ describe("getSchedule", () => {
// Time Travel to the beginning of today after getting all the dates correctly.
timeTravelToTheBeginningOfToday({ utcOffsetInHours: 5.5 });
const scheduleForEventWithBookingNotice13Hrs = await getSchedule({
const scheduleForEventWithBookingNotice13Hrs = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1251,7 +1253,7 @@ describe("getSchedule", () => {
}
);
const scheduleForEventWithBookingNotice10Hrs = await getSchedule({
const scheduleForEventWithBookingNotice10Hrs = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 2,
eventTypeSlug: "",
@@ -1314,7 +1316,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEventOnADayWithNonCalBooking = await getSchedule({
const scheduleForEventOnADayWithNonCalBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1389,7 +1391,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEventOnADayWithCalBooking = await getSchedule({
const scheduleForEventOnADayWithCalBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1448,7 +1450,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const schedule = await getSchedule({
const schedule = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1513,7 +1515,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEventOnADayWithDateOverride = await getSchedule({
const scheduleForEventOnADayWithDateOverride = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1592,7 +1594,7 @@ describe("getSchedule", () => {
// Requesting this user's availability for their
// individual Event Type
const thisUserAvailability = await getSchedule({
const thisUserAvailability = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 2,
eventTypeSlug: "",
@@ -1705,7 +1707,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const thisUserAvailabilityBookingLimitOne = await getSchedule({
const thisUserAvailabilityBookingLimitOne = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1717,7 +1719,7 @@ describe("getSchedule", () => {
},
});
const thisUserAvailabilityBookingLimitTwo = await getSchedule({
const thisUserAvailabilityBookingLimitTwo = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 2,
eventTypeSlug: "",
@@ -1833,7 +1835,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const thisUserAvailabilityDurationLimitReached = await getSchedule({
const thisUserAvailabilityDurationLimitReached = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1845,7 +1847,7 @@ describe("getSchedule", () => {
},
});
const thisUserAvailabilityDurationLimitNotReached = await getSchedule({
const thisUserAvailabilityDurationLimitNotReached = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 2,
eventTypeSlug: "",
@@ -1943,7 +1945,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const thisUserAvailabilityDurationLimit = await getSchedule({
const thisUserAvailabilityDurationLimit = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -2039,7 +2041,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const weeklyAvailability = await getSchedule({
const weeklyAvailability = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -2169,7 +2171,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const availabilityEventTypeOne = await getSchedule({
const availabilityEventTypeOne = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -2190,7 +2192,7 @@ describe("getSchedule", () => {
expect(availableSlotsInTz.filter((slot) => slot.format().startsWith(plus2DateString)).length).toBe(0);
const availabilityEventTypeTwo = await getSchedule({
const availabilityEventTypeTwo = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 2,
eventTypeSlug: "",
@@ -2211,7 +2213,7 @@ describe("getSchedule", () => {
expect(availableSlotsInTz2.filter((slot) => slot.format().startsWith(plus2DateString)).length).toBe(0);
const availabilityUserEventType = await getSchedule({
const availabilityUserEventType = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 3,
eventTypeSlug: "",
@@ -2327,7 +2329,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const eventType1Availability = await getSchedule({
const eventType1Availability = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -2339,7 +2341,7 @@ describe("getSchedule", () => {
},
});
const eventType2Availability = await getSchedule({
const eventType2Availability = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 2,
eventTypeSlug: "",
@@ -2387,7 +2389,7 @@ describe("getSchedule", () => {
],
});
const eventType2AvailabilityUpdated = await getSchedule({
const eventType2AvailabilityUpdated = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 2,
eventTypeSlug: "",
@@ -2468,7 +2470,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const thisUserAvailabilityBookingLimit = await getSchedule({
const thisUserAvailabilityBookingLimit = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -2583,7 +2585,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const availabilityEventTypeOne = await getSchedule({
const availabilityEventTypeOne = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -2604,7 +2606,7 @@ describe("getSchedule", () => {
expect(availableSlotsInTz.filter((slot) => slot.format().startsWith(plus2DateString)).length).toBe(0); // 1 booking per day as limit
const availabilityEventTypeTwo = await getSchedule({
const availabilityEventTypeTwo = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 2,
eventTypeSlug: "",
@@ -2624,7 +2626,7 @@ describe("getSchedule", () => {
expect(availableSlotsInTz.filter((slot) => slot.format().startsWith(plus2DateString)).length).toBe(0); // 1 booking per day as limit
const availabilityUserEventType = await getSchedule({
const availabilityUserEventType = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 3,
eventTypeSlug: "",
@@ -2708,7 +2710,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const thisUserAvailabilityBookingLimit = await getSchedule({
const thisUserAvailabilityBookingLimit = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -2791,7 +2793,7 @@ describe("getSchedule", () => {
// Requesting this user's availability for their
// individual Event Type
const thisUserAvailability = await getSchedule({
const thisUserAvailability = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 2,
eventTypeSlug: "",
@@ -2862,7 +2864,7 @@ describe("getSchedule", () => {
],
});
const schedule = await getSchedule({
const schedule = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -2961,7 +2963,7 @@ describe("getSchedule", () => {
],
});
const scheduleForTeamEventOnADayWithNoBooking = await getSchedule({
const scheduleForTeamEventOnADayWithNoBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -2992,17 +2994,18 @@ describe("getSchedule", () => {
}
);
const scheduleForTeamEventOnADayWithOneBookingForEachUser = await getSchedule({
input: {
eventTypeId: 1,
eventTypeSlug: "",
startTime: `${plus1DateString}T18:30:00.000Z`,
endTime: `${plus2DateString}T18:29:59.999Z`,
timeZone: Timezones["+5:30"],
isTeamEvent: true,
orgSlug: null,
},
});
const scheduleForTeamEventOnADayWithOneBookingForEachUser =
await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
startTime: `${plus1DateString}T18:30:00.000Z`,
endTime: `${plus2DateString}T18:29:59.999Z`,
timeZone: Timezones["+5:30"],
isTeamEvent: true,
orgSlug: null,
},
});
// A user with blocked time in another event, still affects Team Event availability
// It's a collective availability, so both user 101 and 102 are considered for timeslots
@@ -3101,17 +3104,18 @@ describe("getSchedule", () => {
},
],
});
const scheduleForTeamEventOnADayWithOneBookingForEachUserButOnDifferentTimeslots = await getSchedule({
input: {
eventTypeId: 1,
eventTypeSlug: "",
startTime: `${plus1DateString}T18:30:00.000Z`,
endTime: `${plus2DateString}T18:29:59.999Z`,
timeZone: Timezones["+5:30"],
isTeamEvent: true,
orgSlug: null,
},
});
const scheduleForTeamEventOnADayWithOneBookingForEachUserButOnDifferentTimeslots =
await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
startTime: `${plus1DateString}T18:30:00.000Z`,
endTime: `${plus2DateString}T18:29:59.999Z`,
timeZone: Timezones["+5:30"],
isTeamEvent: true,
orgSlug: null,
},
});
// A user with blocked time in another event, still affects Team Event availability
expect(scheduleForTeamEventOnADayWithOneBookingForEachUserButOnDifferentTimeslots).toHaveTimeSlots(
[
@@ -3130,17 +3134,18 @@ describe("getSchedule", () => {
{ dateString: plus2DateString }
);
const scheduleForTeamEventOnADayWithOneBookingForEachUserOnSameTimeSlot = await getSchedule({
input: {
eventTypeId: 1,
eventTypeSlug: "",
startTime: `${plus2DateString}T18:30:00.000Z`,
endTime: `${plus3DateString}T18:29:59.999Z`,
timeZone: Timezones["+5:30"],
isTeamEvent: true,
orgSlug: null,
},
});
const scheduleForTeamEventOnADayWithOneBookingForEachUserOnSameTimeSlot =
await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
startTime: `${plus2DateString}T18:30:00.000Z`,
endTime: `${plus3DateString}T18:29:59.999Z`,
timeZone: Timezones["+5:30"],
isTeamEvent: true,
orgSlug: null,
},
});
// A user with blocked time in another event, still affects Team Event availability
expect(scheduleForTeamEventOnADayWithOneBookingForEachUserOnSameTimeSlot).toHaveTimeSlots(
[
@@ -3195,7 +3200,7 @@ describe("getSchedule", () => {
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
const { dateString: plus2DateString } = getDate({ dateIncrement: 2 });
const getScheduleRes = await getSchedule({
const getScheduleRes = await availableSlotsService.getAvailableSlots({
input: {
eventTypeSlug: scenario.eventTypes[0]?.slug,
startTime: `${plus1DateString}T18:30:00.000Z`,
@@ -3275,7 +3280,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleWithHostChoosenSch = await getSchedule({
const scheduleWithHostChoosenSch = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -3341,7 +3346,7 @@ describe("getSchedule", () => {
bookings: [],
});
const scheduleWithEventCommonSch = await getSchedule({
const scheduleWithEventCommonSch = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -3422,7 +3427,7 @@ describe("getSchedule", () => {
],
});
const schedule = await getSchedule({
const schedule = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -3503,7 +3508,7 @@ describe("getSchedule", () => {
],
});
const schedule = await getSchedule({
const schedule = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -9,12 +9,13 @@ import {
import { describe, test } from "vitest";
import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expect, expectedSlotsForSchedule } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
setupAndTeardown();
describe("Calendar event", () => {
test("correctly identifies unavailable slots from selected calendars at user level", async () => {
@@ -63,7 +64,7 @@ describe("getSchedule", () => {
// An event with one accepted booking
await createBookingScenario(scenarioData);
const scheduleForDayWithAGoogleCalendarBooking = await getSchedule({
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -133,7 +134,7 @@ describe("getSchedule", () => {
// An event with one accepted booking
await createBookingScenario(scenarioData);
const scheduleForDayWithAGoogleCalendarBooking = await getSchedule({
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId,
eventTypeSlug: "",
@@ -202,7 +203,7 @@ describe("getSchedule", () => {
// An event with one accepted booking
await createBookingScenario(scenarioData);
const scheduleForDayWithAGoogleCalendarBooking = await getSchedule({
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId,
eventTypeSlug: "",
@@ -275,7 +276,7 @@ describe("getSchedule", () => {
// An event with one accepted booking
await createBookingScenario(scenarioData);
const scheduleForDayWithAGoogleCalendarBooking = await getSchedule({
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId,
eventTypeSlug: "",
@@ -13,13 +13,14 @@ import { expectNoAttemptToGetAvailability } from "../../utils/bookingScenario/ex
import { describe, test } from "vitest";
import { MembershipRole } from "@calcom/prisma/enums";
import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expect, expectedSlotsForSchedule } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
describe("getSchedule", () => {
setupAndTeardown();
describe("Delegation Credential", () => {
test("correctly identifies unavailable slots using DelegationCredential credentials", async () => {
const { dateString: plus1DateString } = getDate({ dateIncrement: 1 });
@@ -89,8 +90,8 @@ describe("getSchedule", () => {
};
await createBookingScenario(scenarioData);
const scheduleForDayWithAGoogleCalendarBooking = await getSchedule({
const availableSlotsService = new AvailableSlotsService();
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -181,8 +182,8 @@ describe("getSchedule", () => {
};
await createBookingScenario(scenarioData);
const scheduleForDayWithAGoogleCalendarBooking = await getSchedule({
const availableSlotsService = new AvailableSlotsService();
const scheduleForDayWithAGoogleCalendarBooking = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -9,7 +9,7 @@ import type { ScenarioData } from "../../utils/bookingScenario/bookingScenario";
import { describe, expect, vi, test } from "vitest";
import { PeriodType } from "@calcom/prisma/enums";
import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expectedSlotsForSchedule } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
@@ -70,6 +70,7 @@ vi.mock("@calcom/lib/constants", () => ({
}));
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
setupAndTeardown();
describe("Future Limits", () => {
describe("PeriodType=ROLLING", () => {
@@ -112,7 +113,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -200,7 +201,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -284,7 +285,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -379,7 +380,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -483,7 +484,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -573,7 +574,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -657,7 +658,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -780,7 +781,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -878,7 +879,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -979,7 +980,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1087,7 +1088,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1207,7 +1208,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1304,7 +1305,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1413,7 +1414,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1515,7 +1516,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEvent = await getSchedule({
const scheduleForEvent = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -1601,7 +1602,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const scheduleForEventForPagoTz = await getSchedule({
const scheduleForEventForPagoTz = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -11,7 +11,7 @@ import { describe, test, vi } from "vitest";
import type { z } from "zod";
import type { getScheduleSchema } from "@calcom/trpc/server/routers/viewer/slots/types";
import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expect } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
@@ -89,6 +89,7 @@ async function setupTeamAndFeatures() {
}
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
setupAndTeardown();
describe("Restriction Schedule", () => {
@@ -156,7 +157,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const result = await getSchedule({
const result = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -252,7 +253,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const result = await getSchedule({
const result = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -353,7 +354,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const result = await getSchedule({
const result = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -438,7 +439,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const result = await getSchedule({
const result = await availableSlotsService.getAvailableSlots({
input: {
eventTypeId: 1,
eventTypeSlug: "",
@@ -12,7 +12,7 @@ import type { z } from "zod";
import { prisma } from "@calcom/prisma";
import type { getScheduleSchema, GetScheduleOptions } from "@calcom/trpc/server/routers/viewer/slots/types";
import { getAvailableSlots as getSchedule } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
import { expect } from "./expects";
import { setupAndTeardown } from "./setupAndTeardown";
@@ -62,6 +62,7 @@ const getBaseScenarioData = (): ScheduleScenario => ({
});
describe("getSchedule", () => {
const availableSlotsService = new AvailableSlotsService();
setupAndTeardown();
describe("Reserved Slots", () => {
@@ -93,7 +94,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const schedule = await getSchedule({
const schedule = await availableSlotsService.getAvailableSlots({
input: getTestScheduleInput({ yesterdayDateString, plus5DateString }),
});
@@ -128,7 +129,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const schedule = await getSchedule({
const schedule = await availableSlotsService.getAvailableSlots({
input: getTestScheduleInput({ yesterdayDateString, plus5DateString }),
ctx: {
req: {
@@ -183,7 +184,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const schedule = await getSchedule({
const schedule = await availableSlotsService.getAvailableSlots({
input: getTestScheduleInput({ yesterdayDateString, plus5DateString }),
});
@@ -238,7 +239,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const schedule = await getSchedule({
const schedule = await availableSlotsService.getAvailableSlots({
input: getTestScheduleInput({ yesterdayDateString, plus5DateString }),
});
@@ -287,7 +288,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
const schedule = await getSchedule({
const schedule = await availableSlotsService.getAvailableSlots({
input: getTestScheduleInput({ yesterdayDateString, plus5DateString }),
});
@@ -366,7 +367,7 @@ describe("getSchedule", () => {
await createBookingScenario(scenarioData);
await getSchedule({
await availableSlotsService.getAvailableSlots({
input: getTestScheduleInput({ yesterdayDateString, plus5DateString }),
ctx: {
req: {
+1
View File
@@ -116,6 +116,7 @@
},
"dependencies": {
"@daily-co/daily-js": "^0.76.0",
"@evyweb/ioctopus": "^1.2.0",
"@next/third-parties": "^14.2.5",
"@vercel/functions": "^1.4.0",
"city-timezones": "^1.2.1",
+2 -2
View File
@@ -1,3 +1,3 @@
import { getAvailableSlots } from "@calcom/trpc/server/routers/viewer/slots/util";
import { AvailableSlotsService } from "@calcom/trpc/server/routers/viewer/slots/util";
export { getAvailableSlots };
export { AvailableSlotsService };
@@ -1,6 +1,6 @@
import type { IncomingMessage } from "http";
import { getAvailableSlots } from "../slots/util";
import { AvailableSlotsService } from "../slots/util";
import type { TGetTeamScheduleInputSchema } from "./getTeamSchedule.schema";
export type GetTeamScheduleOptions = {
@@ -13,5 +13,6 @@ interface ContextForGetSchedule extends Record<string, unknown> {
}
export const getTeamScheduleHandler = async ({ ctx, input }: GetTeamScheduleOptions) => {
return await getAvailableSlots({ ctx, input });
const availableSlotsService = new AvailableSlotsService();
return await availableSlotsService.getAvailableSlots({ ctx, input });
};
@@ -1,6 +1,7 @@
import type { GetScheduleOptions } from "./types";
import { getAvailableSlots } from "./util";
import { AvailableSlotsService } from "./util";
export const getScheduleHandler = async ({ ctx, input }: GetScheduleOptions) => {
return await getAvailableSlots({ ctx, input });
const availableSlotsService = new AvailableSlotsService();
return await availableSlotsService.getAvailableSlots({ ctx, input });
};
File diff suppressed because it is too large Load Diff
+13 -5
View File
@@ -2519,7 +2519,7 @@ __metadata:
"@axiomhq/winston": ^1.2.0
"@calcom/platform-constants": "*"
"@calcom/platform-enums": "*"
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.241"
"@calcom/platform-libraries": "npm:@calcom/platform-libraries@0.0.243"
"@calcom/platform-types": "*"
"@calcom/platform-utils": "*"
"@calcom/prisma": "*"
@@ -3565,13 +3565,13 @@ __metadata:
languageName: unknown
linkType: soft
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.241":
version: 0.0.241
resolution: "@calcom/platform-libraries@npm:0.0.241"
"@calcom/platform-libraries@npm:@calcom/platform-libraries@0.0.243":
version: 0.0.243
resolution: "@calcom/platform-libraries@npm:0.0.243"
dependencies:
"@calcom/features": "*"
"@calcom/lib": "*"
checksum: 1eec9dce749b6678427e00d0f2d2f383d798066f2f7ef7aca1ce90d5c649ed41d2fc1496be93c7448e7c22d2e015e333c8fe0b81b7c3b04b9637f6ea1910a898
checksum: ce0a4778857a62a6df46b1c0b419fbaad1d874d7b0da92d43589348f6e07a7de912703692c9fbc1e21fb2e0bf4d323bcd7eae96b5198376216216c872374cc09
languageName: node
linkType: hard
@@ -5816,6 +5816,13 @@ __metadata:
languageName: node
linkType: hard
"@evyweb/ioctopus@npm:^1.2.0":
version: 1.2.0
resolution: "@evyweb/ioctopus@npm:1.2.0"
checksum: f48382e2dfab9b48b59d02a0718ddbb8e9d81cbb6d214eb42b5378c2b9d9f9f8decb5b13019600972252e5b6c204901ebfbc36000a4a8ea0f69d6fd8b3417458
languageName: node
linkType: hard
"@ewsjs/ntlm-client@npm:^3.0.1":
version: 3.0.1
resolution: "@ewsjs/ntlm-client@npm:3.0.1"
@@ -21766,6 +21773,7 @@ __metadata:
"@changesets/changelog-github": ^0.5.1
"@changesets/cli": 2.29.4
"@daily-co/daily-js": ^0.76.0
"@evyweb/ioctopus": ^1.2.0
"@jetstreamapp/soql-parser-js": ^6.1.0
"@next/third-parties": ^14.2.5
"@playwright/test": ^1.45.3