diff --git a/apps/web/test/lib/getSchedule.test.ts b/apps/web/test/lib/getSchedule.test.ts index 9229c8bbe5..d6c8ebcb7f 100644 --- a/apps/web/test/lib/getSchedule.test.ts +++ b/apps/web/test/lib/getSchedule.test.ts @@ -2735,6 +2735,103 @@ describe("getSchedule", () => { expect(availableSlotsInTz.filter((slot) => slot.format().startsWith(plus2DateString)).length).toBe(0); // 1 booking per day as limit }); + test("booking limits use schedule timezone when set, falling back to user timezone", async () => { + const { dateString: plus1DateString } = getDate({ dateIncrement: 1 }); + const { dateString: plus2DateString } = getDate({ dateIncrement: 2 }); + const { dateString: plus3DateString } = getDate({ dateIncrement: 3 }); + + const scenarioData = { + eventTypes: [ + { + id: 1, + length: 60, + beforeEventBuffer: 0, + afterEventBuffer: 0, + bookingLimits: { + PER_DAY: 1, + }, + schedule: { + id: 1, + name: "Schedule with timezone", + availability: [ + { + userId: null, + eventTypeId: null, + days: [0, 1, 2, 3, 4, 5, 6], + startTime: new Date("1970-01-01T00:00:00.000Z"), + endTime: new Date("1970-01-01T23:59:59.999Z"), + date: null, + }, + ], + timeZone: Timezones["+5:30"], + }, + users: [ + { + id: 101, + }, + ], + }, + ], + users: [ + { + ...TestData.users.example, + id: 101, + schedules: [ + { + id: 2, + name: "User schedule", + availability: [ + { + userId: null, + eventTypeId: null, + days: [0, 1, 2, 3, 4, 5, 6], + startTime: new Date("1970-01-01T00:00:00.000Z"), + endTime: new Date("1970-01-01T23:59:59.999Z"), + date: null, + }, + ], + timeZone: Timezones["+6:00"], + }, + ], + }, + ], + bookings: [ + { + userId: 101, + eventTypeId: 1, + startTime: `${plus2DateString}T08:00:00.000Z`, + endTime: `${plus2DateString}T09:00:00.000Z`, + status: "ACCEPTED" as BookingStatus, + }, + ], + }; + + await createBookingScenario(scenarioData); + + const availability = await availableSlotsService.getAvailableSlots({ + input: { + eventTypeId: 1, + eventTypeSlug: "", + startTime: `${plus1DateString}T00:00:00.000Z`, + endTime: `${plus3DateString}T23:59:59.999Z`, + timeZone: Timezones["+5:30"], + isTeamEvent: false, + orgSlug: null, + }, + }); + + const availableSlotsInScheduleTz: dayjs.Dayjs[] = []; + for (const date in availability.slots) { + availability.slots[date].forEach((timeObj) => { + availableSlotsInScheduleTz.push(dayjs(timeObj.time).tz(Timezones["+5:30"])); + }); + } + + expect(availableSlotsInScheduleTz.filter((slot) => slot.format().startsWith(plus2DateString)).length).toBe( + 0 + ); + }); + test("a slot counts as being busy when the eventType is requiresConfirmation and requiresConfirmationWillBlockSlot", async () => { const { dateString: plus1DateString } = getDate({ dateIncrement: 1 }); const { dateString: plus2DateString } = getDate({ dateIncrement: 2 }); diff --git a/packages/trpc/server/routers/viewer/slots/util.ts b/packages/trpc/server/routers/viewer/slots/util.ts index f77035a9c0..8d688bdc83 100644 --- a/packages/trpc/server/routers/viewer/slots/util.ts +++ b/packages/trpc/server/routers/viewer/slots/util.ts @@ -823,6 +823,7 @@ export class AvailableSlotsService { let busyTimesFromLimitsMap: Map | undefined = undefined; if (eventType && (bookingLimits || durationLimits)) { const usersForLimits = usersWithCredentials.map((user) => ({ id: user.id, email: user.email })); + const eventTimeZone = eventType.schedule?.timeZone ?? usersWithCredentials[0]?.timeZone ?? "UTC"; busyTimesFromLimitsMap = await this.getBusyTimesFromLimitsForUsers( usersForLimits, bookingLimits, @@ -831,7 +832,7 @@ export class AvailableSlotsService { endTime, typeof input.duration === "number" ? input.duration : undefined, eventType, - usersWithCredentials[0]?.timeZone || "UTC", + eventTimeZone, input.rescheduleUid || undefined ); } @@ -845,6 +846,7 @@ export class AvailableSlotsService { let teamBookingLimitsMap: Map | undefined = undefined; if (teamForBookingLimits && teamBookingLimits) { const usersForTeamLimits = usersWithCredentials.map((user) => ({ id: user.id, email: user.email })); + const eventTimeZone = eventType.schedule?.timeZone ?? usersWithCredentials[0]?.timeZone ?? "UTC"; teamBookingLimitsMap = await this.getBusyTimesFromTeamLimitsForUsers( usersForTeamLimits, teamBookingLimits, @@ -852,7 +854,7 @@ export class AvailableSlotsService { endTime, teamForBookingLimits.id, teamForBookingLimits.includeManagedEventsInLimits, - usersWithCredentials[0]?.timeZone || "UTC", + eventTimeZone, input.rescheduleUid || undefined ); }