Skip to content

Parallel Booking

Complete guide to configuring and using parallel booking functionality for group services and classes.

📘 For API Testing: See the Parallel Booking Testing Guide for step-by-step end-to-end testing instructions with complete API examples.


Overview

Parallel Booking allows multiple customers to book the same staff member for the same service at the same time slot - up to a configurable capacity limit. This feature is essential for businesses offering group classes, workshops, and events.

Key Benefits:

  • Group Classes - Support fitness studios, yoga classes, boot camps
  • Workshops - Enable cooking classes, art workshops, educational sessions
  • Events - Manage wine tastings, tours, group therapy sessions
  • Flexible Capacity - Configure limits from 1-100+ participants per service
  • Real-time Tracking - Display available spots (e.g., "7/10 spots left")
  • Backward Compatible - Single-booking services work exactly as before

Key Concepts:

  • Single Booking = One customer per staff member per time slot (legacy behavior)
  • Parallel Booking = Multiple customers per staff member per time slot (new feature)
  • Capacity Limit = Maximum number of simultaneous bookings allowed
  • Service Isolation = Staff can teach multiple services with different capacity rules

Business Use Cases

Group Services (Parallel Booking Enabled)

Business Type Service Example Typical Capacity
Fitness Studio Group Yoga Class 10-30 people
Personal Training Boot Camp Session 5-15 people
Education Cooking Class 8-12 students
Workshops Art Workshop 6-10 participants
Events Wine Tasting 15-20 guests
Tours City Walking Tour 10-25 tourists
Group Therapy Support Group Session 5-8 clients

Single-Client Services (Parallel Booking Disabled)

Business Type Service Example Capacity
Salon Haircut 1 client
Spa Massage Therapy 1 client
Medical Consultation 1 patient
Beauty Facial Treatment 1 client
One-on-One Coaching Personal Training 1 client

Service Configuration

Enable Parallel Booking

Configure parallel booking settings when creating or updating a service.

Service Model Fields

{
  "name": "Group Yoga Class",
  "duration": 60,
  "price": 150000,

  # Parallel booking configuration
  "allow_parallel_bookings": true,      # Enable parallel bookings
  "max_parallel_bookings": 10,          # Maximum capacity (1-100)

  # Other service fields...
}

Field Descriptions:

  • allow_parallel_bookings (boolean, default=false)

  • false = Single booking only (legacy behavior)

  • true = Enable parallel booking with capacity limit

  • max_parallel_bookings (integer, default=1, range=1-100)

  • Maximum simultaneous bookings allowed for this service

  • Only applies when allow_parallel_bookings=true

Configuration Examples

Example 1: Group Yoga Class (Parallel Enabled)

{
  "name": "Group Yoga Class",
  "slug": "group-yoga-class",
  "category": "FITNESS",
  "duration": 60,
  "pricing": {
    "type": "FIXED",
    "base_price": 150000,
    "currency": "IDR"
  },
  "allow_parallel_bookings": true,
  "max_parallel_bookings": 10
}

Behavior:

  • ✅ Customers 1-9: Accepted (capacity available)
  • ✅ Customer 10: Accepted (capacity full - last slot)
  • ❌ Customer 11: Rejected (capacity exceeded)

Example 2: Haircut (Single Booking)

{
  "name": "Haircut",
  "slug": "haircut",
  "category": "SALON",
  "duration": 45,
  "pricing": {
    "type": "FIXED",
    "base_price": 75000,
    "currency": "IDR"
  },
  "allow_parallel_bookings": false,
  "max_parallel_bookings": 1
}

Behavior:

  • ✅ Customer 1: Accepted
  • ❌ Customer 2: Rejected (single booking only)

API Endpoints

Get Availability Grid

Retrieve available time slots with capacity information for parallel booking services.

Endpoint

GET /api/v1/availability/availability-grid

Authentication: Required (JWT token)

Query Parameters

  • outlet_id (required) - Outlet ID
  • service_id (required) - Service ID
  • start_date (required) - Start date (YYYY-MM-DD)
  • end_date (required) - End date (YYYY-MM-DD)
  • staff_id (optional) - Filter by specific staff member

Response

{
  "2025-10-26": [
    {
      "start_time": "10:00:00",
      "end_time": "11:00:00",
      "staff_id": "507f1f77bcf86cd799439011",
      "staff_name": "John Smith",
      "is_available": true,

      // NEW: Parallel booking capacity info
      "allows_parallel_bookings": true,
      "available_capacity": 7,
      "max_capacity": 10
    },
    {
      "start_time": "11:00:00",
      "end_time": "12:00:00",
      "staff_id": "507f1f77bcf86cd799439011",
      "staff_name": "John Smith",
      "is_available": true,

      "allows_parallel_bookings": true,
      "available_capacity": 1,
      "max_capacity": 10
    },
    {
      "start_time": "14:00:00",
      "end_time": "15:00:00",
      "staff_id": "507f1f77bcf86cd799439011",
      "staff_name": "John Smith",
      "is_available": false,

      "allows_parallel_bookings": true,
      "available_capacity": 0,
      "max_capacity": 10
    }
  ]
}

Field Descriptions:

  • allows_parallel_bookings - Whether service supports multiple simultaneous bookings
  • available_capacity - Remaining slots (null for single-booking services)
  • max_capacity - Total capacity (null for single-booking services)

Frontend Display Examples:

Single Booking Service (Haircut):
  ✅ 14:00 - 15:00 (Available)

Parallel Booking Service (Group Yoga):
  ✅ 10:00 - 11:00 (7/10 spots left)
  ⚠️  11:00 - 12:00 (1/10 spots left - Almost Full!)
  ❌ 14:00 - 15:00 (Full)

Create Appointment

Create a new appointment with automatic capacity checking.

Endpoint

POST /api/v1/appointments

Authentication: Required (JWT token)

Request Body

{
  "outlet_id": "507f1f77bcf86cd799439010",
  "customer_id": "507f1f77bcf86cd799439020",
  "appointment_date": "2025-10-26",
  "start_time": "10:00:00",
  "services": [
    {
      "service_id": "507f1f77bcf86cd799439030",
      "staff_id": "507f1f77bcf86cd799439011"
    }
  ]
}

Response (Success)

{
  "id": "507f1f77bcf86cd799439040",
  "status": "confirmed",
  "appointment_date": "2025-10-26",
  "start_time": "10:00:00",
  "end_time": "11:00:00",
  "services": [
    {
      "service_id": "507f1f77bcf86cd799439030",
      "service_name": "Group Yoga Class",
      "staff_id": "507f1f77bcf86cd799439011",
      "staff_name": "John Smith"
    }
  ]
}

Response (Capacity Exceeded)

{
  "detail": "Time slot conflicts with existing appointments or capacity limit reached"
}

HTTP Status: 409 Conflict


Booking Behavior

Single Booking Service (Legacy)

Staff: John (Yoga Instructor)
Service: Personal Training (allow_parallel_bookings: false)
Capacity: 1 client

Booking Flow:
  ✅ Customer 1 books → 10:00-11:00 with John ✅ SUCCESS
  ❌ Customer 2 books → 10:00-11:00 with John ❌ BLOCKED
  ❌ Customer 3 books → 10:00-11:00 with John ❌ BLOCKED

Parallel Booking Service

Staff: John (Yoga Instructor)
Service: Group Yoga Class (allow_parallel_bookings: true, max_capacity: 10)

Booking Flow:
  ✅ Customer 1 books → 10:00-11:00 with John (1/10 slots)
  ✅ Customer 2 books → 10:00-11:00 with John (2/10 slots)
  ✅ Customer 3 books → 10:00-11:00 with John (3/10 slots)
  ...
  ✅ Customer 10 books → 10:00-11:00 with John (10/10 slots - FULL)
  ❌ Customer 11 books → 10:00-11:00 with John ❌ CAPACITY REACHED

Mixed Services on Same Staff

Staff: John teaches both Yoga (parallel) and Personal Training (single)

Service 1: Group Yoga Class

  - allow_parallel_bookings: true
  - max_parallel_bookings: 10

Service 2: Personal Training

  - allow_parallel_bookings: false
  - max_parallel_bookings: 1

Booking Flow:
  ✅ 10 customers book Yoga at 10:00 (10/10 capacity - FULL)
  ❌ 11th customer cannot book Yoga at 10:00 (capacity exceeded)

  ✅ 1 customer books Personal Training at 14:00 (1/1 capacity - FULL)
  ❌ 2nd customer cannot book Personal Training at 14:00 (single booking only)

Key Point: Capacity is tracked per service, not per staff member.

Rescheduling with Capacity

Reschedule Appointment

Rescheduling respects capacity limits and automatically updates availability.

Endpoint

PUT /api/v1/appointments/{appointment_id}/reschedule

Authentication: Required (JWT token)

Request Body

{
  "new_date": "2025-10-27",
  "new_start_time": "14:00:00"
}

Behavior

Scenario: Customer reschedules from 10:00 to 14:00

Before Reschedule:

  • 10:00 slot: 5/10 capacity (Customer A, B, C, D, E)
  • 14:00 slot: 3/10 capacity (Customer F, G, H)

After Reschedule (Customer C moves to 14:00):

  • 10:00 slot: 4/10 capacity (Customer A, B, D, E) ← Freed 1 slot
  • 14:00 slot: 4/10 capacity (Customer F, G, H, C) ← Filled 1 slot

Important: The system uses exclude_appointment_id parameter to prevent counting the current appointment when checking destination slot capacity.

Response (Success)

{
  "id": "507f1f77bcf86cd799439040",
  "status": "confirmed",
  "appointment_date": "2025-10-27",
  "start_time": "14:00:00",
  "end_time": "15:00:00"
}

Response (Destination Slot Full)

{
  "detail": "Time slot conflicts with existing appointments or capacity limit reached"
}

HTTP Status: 409 Conflict


Cancellations and Capacity

Cancellation Impact

Cancelled appointments immediately free capacity for new bookings.

Endpoint

PUT /api/v1/appointments/{appointment_id}/cancel

Authentication: Required (JWT token)

Behavior

Before Cancellation:

  • Group Yoga at 10:00: 10/10 capacity (FULL)
  • New booking attempts: ❌ REJECTED

After Cancellation (Customer 5 cancels):

  • Group Yoga at 10:00: 9/10 capacity (AVAILABLE)
  • New booking attempts: ✅ ACCEPTED

Status Filtering:

Capacity calculation only counts appointments with status:

  • confirmed - Counted toward capacity
  • pending - Counted toward capacity
  • cancelled - NOT counted (frees capacity)
  • no_show - NOT counted (frees capacity)
  • rescheduled - NOT counted (frees capacity)

Response

{
  "id": "507f1f77bcf86cd799439040",
  "status": "cancelled",
  "cancelled_at": "2025-10-26T15:30:00Z"
}

Testing Scenarios

Test Case 1: Single Booking Legacy Behavior

Objective: Verify backward compatibility with single-booking services

Setup:

Service: Personal Training
  - allow_parallel_bookings: False
  - max_parallel_bookings: 1

Staff: John Smith
Time Slot: 10:00-11:00

Test Scenarios:

Scenario 1. First booking succeeds

  • Customer 1 books 10:00-11:00 with John
  • Expected: ✅ Booking confirmed

Scenario 2. Second booking blocked

  • Customer 2 books 10:00-11:00 with John (same time)
  • Expected: ❌ 409 Conflict - "Time slot conflicts with existing appointments"

Scenario 3. Different staff available

  • Customer 2 books 10:00-11:00 with Sarah (different staff)
  • Expected: ✅ Booking confirmed

Scenario 4. Same staff different time

  • Customer 2 books 14:00-15:00 with John (different time)
  • Expected: ✅ Booking confirmed

Scenario 5. Cancellation frees slot

  • Customer 1 cancels 10:00-11:00 booking
  • Customer 3 books 10:00-11:00 with John
  • Expected: ✅ Booking confirmed (slot freed)

Test Case 2: Parallel Booking Within Capacity

Objective: Verify parallel booking allows multiple bookings up to capacity

Setup:

Service: Group Yoga Class
  - allow_parallel_bookings: True
  - max_parallel_bookings: 5

Staff: John Smith
Time Slot: 10:00-11:00

Test Scenarios:

Scenario 1. Capacity tracking as bookings increase

  • Customer 1 books → Capacity: 1/5 used, 4/5 available
  • Customer 2 books → Capacity: 2/5 used, 3/5 available
  • Customer 3 books → Capacity: 3/5 used, 2/5 available
  • Customer 4 books → Capacity: 4/5 used, 1/5 available
  • Customer 5 books → Capacity: 5/5 used, 0/5 available (FULL)
  • Expected: All ✅ Bookings confirmed

Scenario 2. Slot shows as full when at capacity

  • Get availability grid for 10:00-11:00
  • Expected: is_available: false, available_capacity: 0, max_capacity: 5

Scenario 3. Same customer different service

  • Customer 1 books Personal Training at 10:00-11:00 (different service)
  • Expected: ✅ Booking confirmed (service isolation)

Scenario 4. Database verification

  • Query appointments for John at 10:00-11:00 for Yoga service
  • Expected: 5 confirmed appointments returned

Test Case 3: Capacity Exceeded

Objective: Verify bookings are blocked when capacity limit is reached

Setup:

Service: Boot Camp
  - allow_parallel_bookings: True
  - max_parallel_bookings: 3

Staff: John Smith
Time Slot: 10:00-11:00

Test Scenarios:

Scenario 1. Fill to capacity

  • Customer 1, 2, 3 book 10:00-11:00
  • Expected: All ✅ Bookings confirmed (3/3 capacity)

Scenario 2. System detects capacity reached

  • Check logs for "parallel_booking_capacity_check"
  • Expected: Log shows current_bookings: 3, max_capacity: 3, capacity_reached: True

Step 3. Fourth booking blocked

  • Customer 4 attempts to book 10:00-11:00
  • Expected: ❌ 409 Conflict - "capacity limit reached"

Scenario 4. Boundary conditions

  • Verify exactly 3/3 capacity (not 2/3 or 4/3)
  • Expected: available_capacity: 0, difference = 0

Scenario 5. Capacity tracked per time slot

  • Customer 4 books Boot Camp at 14:00-15:00 (different time)
  • Expected: ✅ Booking confirmed (different slot has separate capacity)

Scenario 6. Multiple exceed attempts blocked

  • Customer 4, 5, 6 all attempt to book 10:00-11:00
  • Expected: All ❌ 409 Conflict (capacity enforcement consistent)

Test Case 4: Availability Grid Capacity Display

Objective: Verify capacity information appears in availability grid API responses

Setup:

Service: Cooking Class
  - allow_parallel_bookings: True
  - max_parallel_bookings: 8

Staff: Chef Marie
Time Slots: Multiple throughout the day

Test Scenarios:

Scenario 1. Empty capacity display

  • Get availability grid (no bookings)
  • Expected: allows_parallel_bookings: true, available_capacity: 8, max_capacity: 8

Scenario 2. Partial capacity display

  • Create 3 bookings for 10:00-11:00
  • Get availability grid
  • Expected: available_capacity: 5 (8 - 3 = 5 remaining)

Scenario 3. Almost full display

  • Create 7 bookings for 14:00-15:00
  • Get availability grid
  • Expected: available_capacity: 1, is_available: true (still shows as available)

Scenario 4. Full capacity display

  • Create 8 bookings for 18:00-19:00
  • Get availability grid
  • Expected: available_capacity: 0, is_available: false (shows as FULL)

Scenario 5. API response serialization

  • Verify AvailabilitySlot fields are JSON serializable
  • Expected: All capacity fields present in response without errors

Test Case 5: Mixed Services on Same Staff

Objective: Verify staff can handle both parallel and single-booking services correctly

Setup:

Service 1: Group Yoga Class
  - allow_parallel_bookings: True
  - max_parallel_bookings: 10

Service 2: Personal Training
  - allow_parallel_bookings: False
  - max_parallel_bookings: 1

Staff: John Smith

Test Scenarios:

Scenario 1. Parallel service allows multiple bookings

  • Book 10 customers to Yoga at 10:00-11:00
  • Expected: All ✅ Bookings confirmed (10/10 capacity)

Scenario 2. Single-booking service blocks second booking

  • Book Customer A to Personal Training at 14:00-15:00
  • Book Customer B to Personal Training at 14:00-15:00
  • Expected: ✅ Customer A confirmed, ❌ Customer B rejected

Scenario 3. Service isolation

  • Yoga has 10/10 bookings
  • Personal Training has 1/1 booking
  • Expected: Both services track capacity independently

Scenario 4. Same staff different times

  • Yoga at 10:00 (10 bookings)
  • Personal Training at 14:00 (1 booking)
  • Expected: Both work correctly (time slot isolation)

Scenario 5. Capacity per service not per staff

  • Total bookings for John: 11 (10 Yoga + 1 Training)
  • Expected: Both services function correctly despite 11 total bookings

Scenario 6. Overlapping services prevented

  • Yoga class at 10:00-11:00 (parallel, 10 people)
  • Attempt to book Personal Training at 10:30-11:30 (overlaps)
  • Expected: ❌ Rejected (staff cannot be in two places)

Test Case 6: Rescheduling with Capacity

Objective: Verify rescheduling respects capacity limits and updates availability

Setup:

Service: Wine Tasting
  - allow_parallel_bookings: True
  - max_parallel_bookings: 4

Staff: Sommelier Lisa
Initial State:
  - 15:00 slot: 3/4 capacity
  - 18:00 slot: 2/4 capacity
  - 21:00 slot: 4/4 capacity (FULL)

Test Scenarios:

Scenario 1. Setup initial bookings

  • Create 3 bookings at 15:00
  • Create 2 bookings at 18:00
  • Create 4 bookings at 21:00
  • Expected: All ✅ Bookings confirmed

Scenario 2. Reschedule within capacity

  • Reschedule Customer C from 15:00 to 18:00
  • Expected: ✅ Reschedule confirmed
  • Verify: 15:00 now 2/4, 18:00 now 3/4

Scenario 3. Reschedule to full slot blocked

  • Attempt to reschedule Customer A from 15:00 to 21:00 (full)
  • Expected: ❌ 409 Conflict - "capacity limit reached"

Scenario 4. Exclude current appointment works

  • Check capacity calculation when rescheduling
  • Expected: exclude_appointment_id parameter reduces count (3/4 → 2/4 when excluding self)

Scenario 5. Multiple sequential reschedules

  • Reschedule Customer D: 10:00 → 14:00
  • Reschedule Customer D again: 14:00 → 18:00
  • Expected: Both ✅ Reschedules confirmed, capacity updated correctly

Scenario 6. Capacity freed after reschedule

  • Original 15:00 slot had 3/4
  • After Customer C reschedules out: 2/4
  • New customer books 15:00
  • Expected: ✅ Booking confirmed (slot was freed)

Test Case 7: Cancellation Impact

Objective: Verify cancellations correctly free capacity and allow new bookings

Setup:

Service: Art Workshop
  - allow_parallel_bookings: True
  - max_parallel_bookings: 6

Staff: Artist Emma
Time Slot: 14:00-16:00 (2 hours)

Test Scenarios:

Scenario 1. Fill to capacity

  • Book 6 students to 14:00-16:00
  • Expected: All ✅ Bookings confirmed (6/6 capacity)

Scenario 2. Capacity full before cancellation

  • Get availability grid
  • Expected: available_capacity: 0, is_available: false

Scenario 3. Single cancellation impact

  • Cancel Student 3's booking
  • Get availability grid
  • Expected: available_capacity: 1, is_available: true (5/6 capacity)

Scenario 4. Multiple cancellations impact

  • Cancel Student 2 and Student 5
  • Get availability grid
  • Expected: available_capacity: 3, is_available: true (3/6 capacity)

Scenario 5. New booking after cancellation

  • New Student 7 books 14:00-16:00 (after 3 cancellations)
  • Expected: ✅ Booking confirmed (4/6 capacity)

Scenario 6. Cancelled status excluded from capacity

  • Query all appointments (including cancelled)
  • Expected: 7 total (4 active + 3 cancelled), capacity shows 4/6

Scenario 7. No-show status impact

  • Mark Student 4 as no-show
  • Get availability grid
  • Expected: available_capacity: 4 (3/6 active, no-show excluded like cancellation)

Scenario 8. Refill after cancellations

  • Book 2 new students (Students 8, 9)
  • Expected: Both ✅ Bookings confirmed (6/6 capacity again - FULL)

Edge Cases

Edge Case 1: Staff with Overlapping Different Services

Scenario: Staff teaches Yoga (parallel) at 10:00 AND has Personal Training (single) at 10:30

Question: Should we allow this overlap?

Answer:NO - Staff cannot physically be in two places

Behavior:

  • Step 1: Check for overlapping appointments with DIFFERENT services
  • If different service conflict exists → Return conflict error
  • Step 2: Only check capacity for SAME service bookings

Example:

Staff: John
10:00-11:00: Group Yoga Class (10 people)
10:30-11:30: Personal Training (attempt)

Result: ❌ Personal Training booking REJECTED (staff busy with Yoga)

Edge Case 2: Service Capacity Change

Scenario: Admin changes max_parallel_bookings from 10 to 8, but 9 people already booked

Options:

  1. ❌ Strict: Reject capacity reduction if over-booked
  2. ✅ Grandfathered: Allow existing bookings, block new ones
  3. ⚠️ Warning: Show warning but allow change

Recommended Behavior: Grandfathered

  • Existing 9 bookings remain valid
  • New bookings blocked if capacity exceeded
  • Show warning: "Note: 9 bookings exist but capacity is now 8"

Edge Case 3: Concurrent Booking Requests

Scenario: Two customers simultaneously book the last available slot (e.g., 9/10 → 10/10)

Potential Issue: Race condition - both might see 9/10 and attempt to book

Mitigation:

  • Use MongoDB atomic operations with transactions
  • Lock-free optimistic concurrency control
  • Retry logic with capacity recheck

Future Enhancement: Implement database transactions for capacity checks


Best Practices

For Service Configuration

DO:

  • Set realistic capacity limits based on physical space/equipment
  • Use allow_parallel_bookings=false for one-on-one services
  • Configure max_parallel_bookings to match actual class size
  • Test capacity changes in staging before production

DON'T:

  • Set capacity higher than physical space allows
  • Enable parallel booking for services requiring individual attention
  • Change capacity drastically without checking existing bookings
  • Forget to communicate capacity changes to customers

For Booking Operations

DO:

  • Display real-time capacity information ("7/10 spots left")
  • Show "Almost Full" warnings when capacity > 80%
  • Allow early booking for popular group classes
  • Send capacity-related notifications (e.g., "Last 2 spots!")

DON'T:

  • Allow overbooking beyond capacity
  • Hide capacity information from customers
  • Process bookings without checking capacity
  • Ignore cancelled bookings (they free capacity)

For Rescheduling

DO:

  • Check destination slot capacity before allowing reschedule
  • Use exclude_appointment_id to prevent false "full" detection
  • Update capacity information immediately after reschedule
  • Log all reschedule operations for audit trail

DON'T:

  • Allow reschedule to full slots
  • Count current appointment twice (in both source and destination)
  • Process reschedules without capacity validation
  • Forget to free capacity in original slot

Performance Considerations

Database Indexing

Required Index:

db.appointments.createIndex({
  "tenant_id": 1,
  "services.staff_id": 1,
  "services.service_id": 1,
  "appointment_date": 1,
  "status": 1
})

Index Name: idx_appointment_parallel_booking_capacity

Purpose: Efficient service-specific capacity checks

Performance Characteristics:

  • Query execution time: < 10ms
  • Data transfer reduction: 30-70% for multi-service staff
  • Scalability: Supports 15+ slots/day with fast response

Query Optimization

Before Optimization:

  • Fetch ALL overlapping appointments
  • Filter in Python by service_id
  • Higher data transfer and processing time

After Optimization:

  • MongoDB filters by service_id at database level
  • Return only relevant appointments
  • 30-70% reduction in data transfer

Migration Script

Create the index on existing databases:

python scripts/create_parallel_booking_indexes.py [database_name]

Expected Output:

Creating parallel booking index...
Index created successfully in 0.12 seconds
Total appointment indexes: 8


Troubleshooting

Issue 1: Capacity Not Updating After Cancellation

Symptoms: Customer cancels but availability grid still shows full capacity

Checks:

  1. Verify appointment status changed to cancelled
  2. Check that capacity query filters exclude cancelled status
  3. Review database for stuck appointments

Fix:

# Ensure status filter excludes cancelled appointments
filter_dict["status"] = {"$nin": ["cancelled", "no_show", "rescheduled"]}

Issue 2: Overbooking Occurs

Symptoms: More bookings exist than max_parallel_bookings allows

Checks:

  1. Check for race conditions (concurrent booking requests)
  2. Verify capacity checking logic is enabled
  3. Review service configuration (is parallel booking enabled?)

Fix:

  • Implement database transactions for capacity checks
  • Add retry logic with capacity recheck
  • Validate service configuration

Issue 3: Wrong Capacity Count

Symptoms: Availability grid shows incorrect available capacity

Checks:

  1. Verify service_id filtering is working (app/crud/appointment.py)
  2. Check that only confirmed/pending appointments are counted
  3. Ensure exclude_appointment_id is used during reschedules

Fix:

# Correct capacity calculation
current_bookings = await count_parallel_bookings(...)
available_capacity = max_capacity - current_bookings

Issue 4: Performance Degradation

Symptoms: Slow availability grid queries (> 100ms)

Checks:

  1. Verify parallel booking index exists: db.appointments.getIndexes()
  2. Check query execution plan: db.appointments.explain()
  3. Monitor slow query log

Fix:

# Create missing index
python scripts/create_parallel_booking_indexes.py


API Reference Summary

Endpoint Method Purpose Key Response Fields
/availability/availability-grid GET Get available slots with capacity allows_parallel_bookings, available_capacity, max_capacity
/appointments POST Create appointment with capacity check status, appointment_date, services
/appointments/{id}/reschedule PUT Reschedule with capacity validation appointment_date, start_time
/appointments/{id}/cancel PUT Cancel and free capacity status: "cancelled", cancelled_at

Backward Compatibility

Compatibility Matrix

Scenario Service Setting Behavior Impact
Existing Services allow_parallel_bookings not set Defaults to False ✅ No change - single booking
Single Booking allow_parallel_bookings=False Legacy conflict detection ✅ No change
New Parallel allow_parallel_bookings=True, max_capacity=10 Capacity-based detection ✅ New feature enabled

Migration: No database migration required - new fields default to single-booking mode.



Next Steps:

  1. Review service configuration for group classes
  2. Enable parallel booking for appropriate services
  3. Follow the API Testing Guide to test with real-world capacity scenarios
  4. Monitor performance metrics and capacity tracking
  5. Gather feedback from users on capacity display