Implements the facility-classes-booking-dashboard plan (backend):
- Facility.BookingMode (single Scheduled/AdHoc choice) replaced with
independent SupportsClasses/SupportsBooking flags, so one facility
can run a class and accept walk-in bookings; a running class now
blocks walk-in booking for its window on both create and reschedule.
- CustomerPlan.GrantsGymAccess + CustomerPlanClass join table let a
customer hold one gym-access plan plus any number of class-only
plans. Replaced the old single-subscription resolution
(GetActiveSubscriptionByCustomerId/HasAnyActiveSubscriptionAsync)
with gym-access-aware and class-aware resolvers across booking
creation/cancellation, plan assignment, and customer self-service.
Fixed ChangeMembershipPlan/renewal plan-changes, which resolved "the
subscription to replace" by most-recent-created and would have
deactivated a member's class subscription instead of their gym one.
- New FacilityClass model: recurring class definitions (Daily/Weekly/
Monthly/Custom) with lazy occurrence generation (8-week horizon,
race-safe via a unique index) and proper unlimited-capacity handling.
"Mark not held" replaces the old bare-cancel: cascades to cancel and
refund every confirmed booking on the occurrence through the same
core CancelBooking uses, and frees the slot for walk-in booking.
Scheduling conflicts (a walk-in booking now overlapping a class) are
surfaced for staff to resolve via the existing Reschedule flow.
- Renamed the pre-existing "AdHoc" booking-mode terminology to
"WalkIn" throughout (routes, methods, DTOs, the stored BookingMode
value) for a clearer, simpler name.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>