fix: pass seatUid when rescheduling seated booking from booking limit error (#26389)
* fix: pass seatUid when rescheduling seated booking from booking limit error Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * test: add test case for seatUid in booking limit reschedule error for seated events Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
3 files changed
+130
-2
No files matched your search
@@ -399,12 +399,12 @@ export const useBookings = ({ event, hashedLink, bookingForm, metadata, isBookin
|
||||
}
|
||||
|
||||
const error = err as Error & {
|
||||
data: { rescheduleUid: string; startTime: string; attendees: string[] };
|
||||
data: { rescheduleUid: string; startTime: string; attendees: string[]; seatUid?: string };
|
||||
traceId?: string;
|
||||
};
|
||||
|
||||
if (error.message === ErrorCode.BookerLimitExceededReschedule && error.data?.rescheduleUid) {
|
||||
setRescheduleUid(error.data?.rescheduleUid);
|
||||
setRescheduleUid(error.data?.seatUid ?? error.data?.rescheduleUid);
|
||||
setBookingData({
|
||||
uid: error.data?.rescheduleUid,
|
||||
startTime: error.data?.startTime,
|
||||
|
||||
@@ -102,12 +102,22 @@ const checkActiveBookingsLimitAndOfferReschedule = async ({
|
||||
select: {
|
||||
name: true,
|
||||
email: true,
|
||||
bookingSeat: {
|
||||
select: {
|
||||
referenceUid: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
email: bookerEmail,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const lastBooking = bookingsCount[bookingsCount.length - 1];
|
||||
// Get the seatUid for the booker's seat in this booking (if it's a seated event)
|
||||
const seatUid = lastBooking?.attendees[0]?.bookingSeat?.referenceUid;
|
||||
|
||||
if (bookingsCount.length >= maxActiveBookingsPerBooker) {
|
||||
log.warn(`Maximum booking limit reached for ${bookerEmail} for event type ${eventTypeId}`);
|
||||
@@ -118,6 +128,7 @@ const checkActiveBookingsLimitAndOfferReschedule = async ({
|
||||
rescheduleUid: lastBooking.uid,
|
||||
startTime: lastBooking.startTime,
|
||||
attendees: lastBooking.attendees,
|
||||
seatUid,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
getScenarioData,
|
||||
getGoogleCalendarCredential,
|
||||
mockCalendarToHaveNoBusySlots,
|
||||
getMockBookingAttendee,
|
||||
} from "@calcom/testing/lib/bookingScenario/bookingScenario";
|
||||
import { getMockRequestDataForBooking } from "@calcom/testing/lib/bookingScenario/getMockRequestDataForBooking";
|
||||
import { setupAndTeardown } from "@calcom/testing/lib/bookingScenario/setupAndTeardown";
|
||||
@@ -402,6 +403,122 @@ describe("Booking Validation Specifications", () => {
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("includes seatUid in reschedule error for seated events", async () => {
|
||||
vi.setSystemTime(new Date("2025-01-01"));
|
||||
const plus1DateString = "2025-01-02";
|
||||
const plus2DateString = "2025-01-03";
|
||||
|
||||
const handleNewBooking = getNewBookingHandler();
|
||||
|
||||
const bookerA = getBooker({
|
||||
email: "bookerA@example.com",
|
||||
name: "Booker A",
|
||||
});
|
||||
|
||||
const bookerB = getBooker({
|
||||
email: "bookerB@example.com",
|
||||
name: "Booker B",
|
||||
});
|
||||
|
||||
const organizer = getOrganizer({
|
||||
name: "Organizer",
|
||||
email: "organizer@example.com",
|
||||
id: 101,
|
||||
schedules: [TestData.schedules.IstWorkHours],
|
||||
credentials: [getGoogleCalendarCredential()],
|
||||
selectedCalendars: [TestData.selectedCalendars.google],
|
||||
});
|
||||
|
||||
const seatReferenceUidA = "seat-reference-uid-a";
|
||||
|
||||
await createBookingScenario(
|
||||
getScenarioData({
|
||||
eventTypes: [
|
||||
{
|
||||
id: 1,
|
||||
slotInterval: 30,
|
||||
length: 30,
|
||||
maxActiveBookingsPerBooker: 1,
|
||||
maxActiveBookingPerBookerOfferReschedule: true,
|
||||
seatsPerTimeSlot: 3,
|
||||
users: [
|
||||
{
|
||||
id: 101,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
organizer,
|
||||
apps: [TestData.apps["google-calendar"]],
|
||||
bookings: [
|
||||
{
|
||||
uid: "existing-booking-1",
|
||||
eventTypeId: 1,
|
||||
userId: organizer.id,
|
||||
startTime: `${plus1DateString}T10:00:00.000Z`,
|
||||
endTime: `${plus1DateString}T10:30:00.000Z`,
|
||||
title: "Existing Booking",
|
||||
status: BookingStatus.ACCEPTED,
|
||||
attendees: [
|
||||
getMockBookingAttendee({
|
||||
id: 1,
|
||||
name: bookerA.name,
|
||||
email: bookerA.email,
|
||||
locale: "en",
|
||||
timeZone: "America/Toronto",
|
||||
bookingSeat: {
|
||||
referenceUid: seatReferenceUidA,
|
||||
data: {},
|
||||
},
|
||||
}),
|
||||
getMockBookingAttendee({
|
||||
id: 2,
|
||||
name: bookerB.name,
|
||||
email: bookerB.email,
|
||||
locale: "en",
|
||||
timeZone: "America/Toronto",
|
||||
bookingSeat: {
|
||||
referenceUid: "seat-reference-uid-b",
|
||||
data: {},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
await mockCalendarToHaveNoBusySlots("googlecalendar", {});
|
||||
|
||||
const mockBookingData = getMockRequestDataForBooking({
|
||||
data: {
|
||||
eventTypeId: 1,
|
||||
start: `${plus2DateString}T10:00:00.000Z`,
|
||||
end: `${plus2DateString}T10:30:00.000Z`,
|
||||
responses: {
|
||||
email: bookerA.email,
|
||||
name: bookerA.name,
|
||||
location: { optionValue: "", value: "New York" },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
await handleNewBooking({
|
||||
bookingData: mockBookingData,
|
||||
});
|
||||
expect.fail("Expected booking to throw booker_limit_exceeded_error_reschedule");
|
||||
} catch (error) {
|
||||
expect(error.message).toEqual("booker_limit_exceeded_error_reschedule");
|
||||
expect(error.data).toEqual(
|
||||
expect.objectContaining({
|
||||
rescheduleUid: "existing-booking-1",
|
||||
seatUid: seatReferenceUidA,
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("User Email Verification Setting", () => {
|
||||
|
||||
Reference in new issue
Block a user