feat: add rrHostSubsetIds to reschedule booking endpoint (#27135)

* feat: add rrHostSubsetIds to reschedule booking endpoint

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* test: add e2e test for reschedule with rrHostSubsetIds

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* chore: update openapi.json

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Morgan
2026-01-22 17:44:26 +02:00
committed by GitHub
co-authored by morgan@cal.com Devin AI
parent e056274983
commit 51976b1eab
5 changed files with 1067 additions and 4145 deletions
@@ -951,6 +951,75 @@ describe("Bookings Endpoints 2024-08-13", () => {
}
});
});
it("should reschedule a team RR booking and use rrHostSubsetIds to force teamUser2 as host", async () => {
const createBody: CreateBookingInput_2024_08_13 = {
start: new Date(Date.UTC(2030, 0, 10, 10, 0, 0)).toISOString(),
eventTypeId: team2RREventTypeId,
attendee: {
name: "reschedule-test",
email: "reschedule-test@gmail.com",
timeZone: "Europe/Rome",
language: "it",
},
meetingUrl: "https://meet.google.com/abc-def-ghi",
rrHostSubsetIds: [teamUser.id],
};
const createResponse = await request(app.getHttpServer())
.post("/v2/bookings")
.send(createBody)
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
.expect(201);
const createResponseBody: CreateBookingOutput_2024_08_13 = createResponse.body;
expect(responseDataIsBooking(createResponseBody.data)).toBe(true);
if (!responseDataIsBooking(createResponseBody.data)) {
throw new Error("Invalid response data - expected booking");
}
const createdBooking: BookingOutput_2024_08_13 = createResponseBody.data;
expect(createdBooking.hosts[0].id).toEqual(teamUser.id);
const rescheduleBody: RescheduleBookingInput_2024_08_13 = {
start: new Date(Date.UTC(2030, 0, 10, 12, 0, 0)).toISOString(),
reschedulingReason: "Need to change host",
rrHostSubsetIds: [teamUser2.id],
};
return request(app.getHttpServer())
.post(`/v2/bookings/${createdBooking.uid}/reschedule`)
.send(rescheduleBody)
.set(CAL_API_VERSION_HEADER, VERSION_2024_08_13)
.expect(201)
.then(async (response) => {
const responseBody: RescheduleBookingOutput_2024_08_13 = response.body;
expect(responseBody.status).toEqual(SUCCESS_STATUS);
expect(responseBody.data).toBeDefined();
expect(responseDataIsBooking(responseBody.data)).toBe(true);
if (responseDataIsBooking(responseBody.data)) {
const data: BookingOutput_2024_08_13 = responseBody.data;
expect(data.id).toBeDefined();
expect(data.uid).toBeDefined();
expect(data.hosts.length).toEqual(1);
expect(data.hosts[0].id).toEqual(teamUser2.id);
expect(data.status).toEqual("accepted");
expect(data.start).toEqual(rescheduleBody.start);
expect(data.end).toEqual(new Date(Date.UTC(2030, 0, 10, 13, 0, 0)).toISOString());
expect(data.duration).toEqual(60);
expect(data.eventTypeId).toEqual(team2RREventTypeId);
expect(data.attendees.length).toEqual(1);
expect(data.attendees[0].email).toEqual(createBody.attendee.email);
expect(data.absentHost).toEqual(false);
} else {
throw new Error(
"Invalid response data - expected booking but received array of possibly recurring bookings"
);
}
});
});
});
describe("book using teamSlug, eventTypeSlug and organizationSlug", () => {
@@ -799,6 +799,7 @@ export class InputBookingsService_2024_08_13 {
},
rescheduleUid: bookingUid,
verificationCode: inputBooking.emailVerificationCode,
rrHostSubsetIds: inputBooking.rrHostSubsetIds,
};
}
+2 -6
View File
@@ -65,7 +65,8 @@
"!!packages/lib/raqb/resolveQueryValue.test.ts",
"!!packages/ui/components/editor/plugins/ToolbarPlugin.tsx",
"!!packages/embeds/embed-core/src/lib/domUtils.ts"
]
],
"maxSize": 2097152
},
"javascript": {
"parser": {
@@ -93,11 +94,6 @@
}
},
"overrides": [
{
"includes": ["docs/api-reference/v2/openapi.json"],
"linter": { "enabled": false },
"formatter": { "enabled": false }
},
{
"includes": ["**/*.tsx"],
"javascript": {
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsDateString, IsOptional, IsString, Validate, isEmail } from "class-validator";
import { ApiHideProperty, ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsArray, IsDateString, IsInt, IsOptional, IsString, isEmail, Validate } from "class-validator";
export const RESCHEDULED_BY_DOCS = `Email of the person who is rescheduling the booking - only needed when rescheduling a booking that requires a confirmation.
If event type owner email is provided then rescheduled booking will be automatically confirmed. If attendee email or no email is passed then the event type
@@ -36,6 +36,12 @@ export class RescheduleBookingInput_2024_08_13 {
example: "123456",
})
emailVerificationCode?: string;
@ApiHideProperty()
@IsOptional()
@IsArray()
@IsInt({ each: true })
rrHostSubsetIds?: number[];
}
export class RescheduleSeatedBookingInput_2024_08_13 {