feat(bookings): session-to-session move for class bookings

Class customers can move a booking to another future session of the
same template from the manage page. Full target sessions place the
booking on the waitlist; freeing a confirmed seat drains the old
session's queue via the existing promotion path. Reminders re-arm
for the new time.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-18 15:42:04 +02:00
1 parent 6c3b2bf6bf
commit e5cb9bd543
10 files changed
+927 -10

No files matched your search

+171
View File
@@ -740,6 +740,26 @@ export interface paths {
patch?: never;
trace?: never;
};
"/v1/public/bookings/{reference}/move": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* Move a class booking to another session of the same template
* @description Retargets the booking to the target session. Confirmed bookings free their old seat (draining its waitlist); waitlisted bookings release their queue position. The booking is confirmed when the target has a free seat, otherwise it joins the target's waitlist.
*/
post: operations["moveBookingToSession"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/v1/public/bookings/{reference}/reschedule": {
parameters: {
query?: never;
@@ -756,6 +776,26 @@ export interface paths {
patch?: never;
trace?: never;
};
"/v1/public/bookings/{reference}/sessions": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Upcoming sessions a class booking can move to
* @description Class bookings cannot reschedule to arbitrary windows — they move between sessions of the same template. Returns upcoming same-template sessions with live capacity info.
*/
get: operations["listSessionMoveTargets"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/v1/public/calendar/{token}": {
parameters: {
query?: never;
@@ -1374,6 +1414,21 @@ export interface components {
/** Format: uuid */
tenantId: string;
};
SessionMoveTarget: {
capacity?: number;
confirmedCount?: number;
/** Format: date-time */
endsAt?: string;
location?: string;
/** @description Free confirmed seats; 0 or negative means the move lands on the waitlist */
remaining?: number;
/** Format: uuid */
sessionId?: string;
/** Format: date-time */
startsAt?: string;
title?: string;
waitlistCount?: number;
};
SessionRoster: {
capacity: number;
confirmed: components["schemas"]["SessionRosterEntry"][];
@@ -3412,6 +3467,68 @@ export interface operations {
};
};
};
moveBookingToSession: {
parameters: {
query: {
token: string;
};
header?: never;
path: {
reference: string;
};
cookie?: never;
};
requestBody: {
content: {
"application/json": {
/** Format: uuid */
classSessionId: string;
};
};
};
responses: {
/** @description Booking moved; status is the resulting booking state */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
/** @enum {string} */
status?: "confirmed" | "waitlisted";
};
};
};
/** @description Not a live class booking, or target is not an upcoming same-template session */
400: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Invalid manage token */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Booking not found */
404: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Booking already cancelled */
409: {
headers: {
[name: string]: unknown;
};
content?: never;
};
};
};
rescheduleBooking: {
parameters: {
query: {
@@ -3466,6 +3583,60 @@ export interface operations {
};
};
};
listSessionMoveTargets: {
parameters: {
query: {
token: string;
};
header?: never;
path: {
reference: string;
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description Move targets with capacity info */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": {
sessions?: components["schemas"]["SessionMoveTarget"][];
};
};
};
/** @description Not a live class booking */
400: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Invalid manage token */
403: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Booking not found */
404: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description Booking already cancelled */
409: {
headers: {
[name: string]: unknown;
};
content?: never;
};
};
};
getCalendarFeed: {
parameters: {
query?: never;