diff --git a/apps/web/test/lib/getSchedule.test.ts b/apps/web/test/lib/getSchedule.test.ts index fa3df7711c..1778819241 100644 --- a/apps/web/test/lib/getSchedule.test.ts +++ b/apps/web/test/lib/getSchedule.test.ts @@ -630,8 +630,7 @@ describe("getSchedule", () => { ...TestData.users.example, id: 101, schedules: [TestData.schedules.IstWorkHours], - credentials: [getGoogleCalendarCredential()], - selectedCalendars: [TestData.selectedCalendars.google], + credentials: [], }, ], bookings: [ @@ -643,7 +642,7 @@ describe("getSchedule", () => { status: "ACCEPTED" as BookingStatus, }, ], - apps: [TestData.apps.googleCalendar], + // apps: [TestData.apps.googleCalendar], }; await createBookingScenario(scenarioData); diff --git a/packages/core/getBusyTimes.ts b/packages/core/getBusyTimes.ts index c239a7c1b5..fa36a336e9 100644 --- a/packages/core/getBusyTimes.ts +++ b/packages/core/getBusyTimes.ts @@ -144,43 +144,50 @@ export async function getBusyTimes(params: { }); const bookingSeatCountMap: { [x: string]: number } = {}; - const busyTimes = bookings.reduce( - (aggregate: EventBusyDetails[], { id, startTime, endTime, eventType, title, ...rest }) => { - if (rest._count?.seatsReferences) { - const bookedAt = `${dayjs(startTime).utc().format()}<>${dayjs(endTime).utc().format()}`; - bookingSeatCountMap[bookedAt] = bookingSeatCountMap[bookedAt] || 0; - bookingSeatCountMap[bookedAt]++; - // Seat references on the current event are non-blocking until the event is fully booked. - if ( - // there are still seats available. - bookingSeatCountMap[bookedAt] < (eventType?.seatsPerTimeSlot || 1) && - // and this is the seated event, other event types should be blocked. - eventTypeId === eventType?.id - ) { - // then we do not add the booking to the busyTimes. - return aggregate; - } - // if it does get blocked at this point; we remove the bookingSeatCountMap entry - // doing this allows using the map later to remove the ranges from calendar busy times. - delete bookingSeatCountMap[bookedAt]; - } - if (rest.uid === rescheduleUid) { - return aggregate; - } - aggregate.push({ - start: dayjs(startTime) - .subtract((eventType?.beforeEventBuffer || 0) + (afterEventBuffer || 0), "minute") - .toDate(), - end: dayjs(endTime) - .add((eventType?.afterEventBuffer || 0) + (beforeEventBuffer || 0), "minute") - .toDate(), - title, - source: `eventType-${eventType?.id}-booking-${id}`, - }); - return aggregate; - }, - [] - ); + // Only take bookings as source of truth when there are no connected calendars + // this is because cancellations downstream aren't reflected in our Booking database. + // TODO: Reflect downstream cancellations in our Booking database and use Booking as + // source of truth. + const busyTimes = + credentials?.length > 0 + ? [] + : bookings.reduce( + (aggregate: EventBusyDetails[], { id, startTime, endTime, eventType, title, ...rest }) => { + if (rest._count?.seatsReferences) { + const bookedAt = `${dayjs(startTime).utc().format()}<>${dayjs(endTime).utc().format()}`; + bookingSeatCountMap[bookedAt] = bookingSeatCountMap[bookedAt] || 0; + bookingSeatCountMap[bookedAt]++; + // Seat references on the current event are non-blocking until the event is fully booked. + if ( + // there are still seats available. + bookingSeatCountMap[bookedAt] < (eventType?.seatsPerTimeSlot || 1) && + // and this is the seated event, other event types should be blocked. + eventTypeId === eventType?.id + ) { + // then we do not add the booking to the busyTimes. + return aggregate; + } + // if it does get blocked at this point; we remove the bookingSeatCountMap entry + // doing this allows using the map later to remove the ranges from calendar busy times. + delete bookingSeatCountMap[bookedAt]; + } + if (rest.uid === rescheduleUid) { + return aggregate; + } + aggregate.push({ + start: dayjs(startTime) + .subtract((eventType?.beforeEventBuffer || 0) + (afterEventBuffer || 0), "minute") + .toDate(), + end: dayjs(endTime) + .add((eventType?.afterEventBuffer || 0) + (beforeEventBuffer || 0), "minute") + .toDate(), + title, + source: `eventType-${eventType?.id}-booking-${id}`, + }); + return aggregate; + }, + [] + ); logger.debug( `Busy Time from Cal Bookings ${JSON.stringify({ diff --git a/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts b/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts index faba12aa50..8857811a4e 100644 --- a/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts +++ b/packages/features/bookings/lib/handleNewBooking/test/fresh-booking.test.ts @@ -2433,13 +2433,7 @@ describe("handleNewBooking", () => { email: "organizer@example.com", id: 101, schedules: [TestData.schedules.IstWorkHours], - credentials: [getGoogleCalendarCredential()], - selectedCalendars: [TestData.selectedCalendars.google], - destinationCalendar: { - integration: "google_calendar", - externalId: "organizer@google-calendar.com", - primaryEmail: organizerOtherEmail, - }, + credentials: [], }); await createBookingScenario( @@ -2455,15 +2449,10 @@ describe("handleNewBooking", () => { id: 101, }, ], - destinationCalendar: { - integration: "google_calendar", - externalId: "event-type-1@google-calendar.com", - primaryEmail: organizerDestinationCalendarEmailOnEventType, - }, }, ], organizer, - apps: [TestData.apps["google-calendar"], TestData.apps["daily-video"]], + apps: [TestData.apps["daily-video"]], }) ); @@ -2524,36 +2513,10 @@ describe("handleNewBooking", () => { meetingPassword: "MOCK_PASS", meetingUrl: "http://mock-dailyvideo.example.com/meeting-1", }, - { - type: appStoreMetadata.googlecalendar.type, - uid: "MOCKED_GOOGLE_CALENDAR_EVENT_ID", - meetingId: "MOCKED_GOOGLE_CALENDAR_EVENT_ID", - meetingPassword: "MOCK_PASSWORD", - meetingUrl: "https://UNUSED_URL", - }, ], iCalUID: createdBooking.iCalUID, }); - expectSuccessfulCalendarEventCreationInCalendar(calendarMock, { - calendarId: "event-type-1@google-calendar.com", - videoCallUrl: "http://mock-dailyvideo.example.com/meeting-1", - }); - - const iCalUID = expectICalUIDAsString(createdBooking.iCalUID); - - expectSuccessfulBookingCreationEmails({ - booking: { - uid: createdBooking.uid!, - urlOrigin: WEBSITE_URL, - }, - booker, - organizer, - emails, - iCalUID, - destinationEmail: organizerDestinationCalendarEmailOnEventType, - }); - await expect(async () => await handleNewBooking(req)).rejects.toThrowError( ErrorCode.NoAvailableUsersFound ); diff --git a/packages/features/bookings/lib/handleNewBooking/test/recurring-event.test.ts b/packages/features/bookings/lib/handleNewBooking/test/recurring-event.test.ts index 8587acaaa6..a5ef6a4a54 100644 --- a/packages/features/bookings/lib/handleNewBooking/test/recurring-event.test.ts +++ b/packages/features/bookings/lib/handleNewBooking/test/recurring-event.test.ts @@ -266,12 +266,8 @@ describe("handleNewBooking", () => { email: "organizer@example.com", id: 101, schedules: [TestData.schedules.IstWorkHours], - credentials: [getGoogleCalendarCredential()], - selectedCalendars: [TestData.selectedCalendars.google], - destinationCalendar: { - integration: "google_calendar", - externalId: "organizer@google-calendar.com", - }, + credentials: [], + selectedCalendars: [], }); const recurrence = getRecurrence({ @@ -303,10 +299,6 @@ describe("handleNewBooking", () => { id: 101, }, ], - destinationCalendar: { - integration: "google_calendar", - externalId: "event-type-1@google-calendar.com", - }, }, ], bookings: [ @@ -320,7 +312,7 @@ describe("handleNewBooking", () => { }, ], organizer, - apps: [TestData.apps["google-calendar"], TestData.apps["daily-video"]], + apps: [TestData.apps["daily-video"]], }) ); @@ -837,12 +829,7 @@ describe("handleNewBooking", () => { ], // Has morning shift with some overlap with morning shift schedules: [TestData.schedules.IstMorningShift], - credentials: [getGoogleCalendarCredential()], - selectedCalendars: [TestData.selectedCalendars.google], - destinationCalendar: { - integration: TestData.apps["google-calendar"].type, - externalId: "organizer@google-calendar.com", - }, + credentials: [], }); const otherTeamMembers = [ @@ -856,12 +843,7 @@ describe("handleNewBooking", () => { id: 102, // Has Evening shift schedules: [TestData.schedules.IstMorningShift], - credentials: [getGoogleCalendarCredential()], - selectedCalendars: [TestData.selectedCalendars.google], - destinationCalendar: { - integration: TestData.apps["google-calendar"].type, - externalId: "other-team-member-1@google-calendar.com", - }, + credentials: [], }, ]; @@ -901,10 +883,6 @@ describe("handleNewBooking", () => { isFixed: true, }, ], - destinationCalendar: { - integration: "google_calendar", - externalId: "event-type-1@google-calendar.com", - }, }, ], bookings: [ @@ -923,7 +901,7 @@ describe("handleNewBooking", () => { ], organizer, usersApartFromOrganizer: otherTeamMembers, - apps: [TestData.apps["google-calendar"], TestData.apps["daily-video"]], + apps: [TestData.apps["daily-video"]], }) ); @@ -936,13 +914,6 @@ describe("handleNewBooking", () => { }, }); - const calendarMock = mockCalendarToHaveNoBusySlots("googlecalendar", { - create: { - id: "MOCKED_GOOGLE_CALENDAR_EVENT_ID", - iCalUID: "MOCKED_GOOGLE_CALENDAR_ICS_ID", - }, - }); - const recurringCountInRequest = 4; const mockBookingData1 = getMockRequestDataForBooking({ data: {