Scheduling & Bookings — Code Map
API
Module — class sessions (apps/api/src/class-sessions/)
| File | Purpose |
|---|---|
class-sessions.module.ts | Wires controller, service, R2 (logo presign), and dependencies (Memberships, Users, Email, DailyProgramming, Subscriptions, PaymentProviderConfig, Workouts). |
class-sessions.controller.ts | All routes under organizations/:orgId/sessions. |
class-sessions.service.ts | CRUD + bulk + check-in + eligibility (~2300 lines). |
dto/create-class-session.dto.ts | classTypeId, locationId?, coachMembershipId?, title?, startsAt, endsAt, capacity?, waitlistCapacity?, notes?, status? (‘draft’|‘published’). |
dto/update-class-session.dto.ts | PartialType(OmitType(CreateClassSessionDto, ['classTypeId'])) — class type immutable post-create. |
dto/set-session-workouts.dto.ts | workouts: [{ workoutId, sortOrder }]. |
dto/inline-workout.dto.ts | programId?, title?, description?, scoring?, timeCap?. |
dto/self-checkin.dto.ts | method: 'qr'|'gps', token?, expiresAt?, latitude?, longitude?. |
dto/bulk-filter.dto.ts | programId?, classTypeId?, dateFrom?, dateTo?, daysOfWeek?, startTimes? (HH:mm in org TZ), status?, includeBooked?. |
utils/checkin.utils.ts | generateQrToken, verifyQrToken, generateDisplaySignature, verifyDisplaySignature, haversineMeters, isWithinCheckinWindow, GPS_MAX_METERS. |
Routes (prefix organizations/:orgId/sessions)
| Method | Path | Handler |
|---|---|---|
| POST | / | create |
| GET | / | list (by week, optional programId) |
| GET | /upcoming-today | upcomingToday (owner/admin dashboard) |
| GET | /today-workouts | todayWorkouts |
| GET | /:id | getById |
| PATCH | /:id | update |
| PUT | /:id/workouts | setWorkouts |
| POST | /:id/workouts/inline | createInlineWorkout |
| POST | /:id/publish | publish |
| POST | /:id/unpublish | unpublish |
| POST | /:id/cancel | cancel |
| POST | /bulk-preview | bulkPreview |
| POST | /bulk-delete | bulkDelete |
| POST | /bulk-publish | bulkPublish |
| GET | /:id/bookings | getBookings (roster, staff only) |
| POST | /:id/check-in/:bookingId | checkIn |
| DELETE | /:id/check-in/:bookingId | undoCheckIn |
| GET | /:id/qr-token | getQrToken (staff, returns {token, expiresAt, checkinUrl}) |
| POST | /:id/display-url | getDisplayUrl (staff, signed URL) |
| GET | /:id/display-data | getDisplayData (@Public, sig+exp validated) |
| POST | /:id/self-checkin | selfCheckin |
| GET | /attendance/:membershipId | getAttendanceHistory |
Module — bookings (apps/api/src/bookings/)
| File | Purpose |
|---|---|
bookings.module.ts | Imports MembershipsModule, UsersModule, SubscriptionsModule, NotificationsModule, PushNotificationsModule. |
bookings.controller.ts | Mixed routes (org-scoped and bookings/my). |
bookings.service.ts | book, cancel, adminCancel, waitlist promotion, credit accounting, analytics (getAttendanceSummary/Daily/Trend), getMyBookings. |
dto/book-session.dto.ts | subscriptionId? (UUID) — opt-in explicit plan selection. |
Routes
| Method | Path | Handler |
|---|---|---|
| POST | /organizations/:orgId/sessions/:sessionId/book | book |
| DELETE | /organizations/:orgId/sessions/:sessionId/book | cancel (self) |
| DELETE | /organizations/:orgId/sessions/:sessionId/bookings/:bookingId | adminCancel |
| POST | /organizations/:orgId/members/:membershipId/refund-credit | refundCredit |
| GET | /organizations/:orgId/bookings/attendance-trend | attendanceTrend |
| GET | /organizations/:orgId/analytics/attendance/summary | attendanceSummary |
| GET | /organizations/:orgId/analytics/attendance/daily | attendanceDaily |
| GET | /bookings/my | myBookings |
Web
Routes
| Route | Description |
|---|---|
apps/web/src/app/[lang]/(protected)/dashboard/schedule/page.tsx | Weekly calendar for staff. |
apps/web/src/app/[lang]/(protected)/dashboard/schedule/sessions/[sessionId]/page.tsx | Session detail (roster, workouts, check-in display). |
apps/web/src/app/[lang]/(protected)/dashboard/schedule/sessions/[sessionId]/builder/page.tsx | Inline workout builder for a session. |
apps/web/src/app/[lang]/(protected)/(member)/schedule/page.tsx | Member weekly view. |
apps/web/src/app/[lang]/(protected)/(member)/checkin/page.tsx | QR/GPS check-in landing. |
apps/web/src/app/[lang]/checkin-display/ | Public signed-URL display screen. |
Hooks / API helpers
useApi(client) andserverFetch(server) — Clerk bearer attached automatically. Seeapps/web/src/hooks/use-api.ts,apps/web/src/lib/api.ts.apps/web/src/components/dashboard/schedule/*— calendar grid, session sheet, bulk-ops dialog (TODO: verify exact paths).
DB tables involved
| Table | Role |
|---|---|
class_sessions | The session row itself. |
class_session_workouts | Join with sort order, cascade-delete on session/workout drop. |
bookings | The booking row + check-in metadata. |
class_types | Parent of session (mandatory FK). |
programs | Parent of class_type; carries organizationId (the org-scoping anchor). |
locations | Optional location on session; lat/lng powers GPS check-in. |
memberships | coachMembershipId and bookings.membershipId. |
organizations | cancellationWindowHours, allowLateCancellation, timezone. |
subscriptions | bookings.subscriptionId (nullable for staff). |
audit_logs | One row per bulk-delete / bulk-publish batch with payload. |
Shared schemas
libs/shared/src/lib/schemas/scheduling.schema.ts— Zod schemas for session response, booking response, bulk filter, eligibility (BookingEligibility,BookingPlanEntry,BookingBlockReason).libs/shared/src/lib/schemas/day-of-week.ts—dayOfWeekValuesarray used by bulk filter.isStaffRolehelper in@fitkit/shared— single source of truth for staff vs member.
Tests
| File | What it covers |
|---|---|
apps/api/src/class-sessions/class-sessions.service.unit.spec.ts | CRUD, publish/unpublish guards, cancel side effects. |
apps/api/src/class-sessions/class-sessions.bulk.unit.spec.ts | Bulk preview/delete/publish, filter resolution, audit logging. |
apps/api/src/bookings/bookings.service.unit.spec.ts | Booking transaction, capacity, waitlist, quotas, cancel + refund + promotion. |
apps/web/e2e/specs/schedule*.spec.ts | Playwright flows (TODO: verify by ls apps/web/e2e/specs). |