Scheduling
Status: v1 primary
Packages: packages/domain/scheduling, packages/application/scheduling
Purpose
The Scheduling context manages the allocation of aircraft and instructors over time. It is responsible for all booking creation, conflict detection, and grounded-aircraft enforcement. It coordinates across People and Aircraft without owning their data — it references them by identifier only.
Entities
Booking (aggregate root)
A scheduled allocation of an aircraft for a member, covering a defined time range.
Key attributes:
id— unique identifiermemberId— the member who owns the booking (MemberId)aircraftId— the aircraft allocated (AircraftId)instructorId— optional instructor assigned (MemberId | null)timeRange— start and end time of the bookingstatus—confirmed|cancelledcreatedAt— creation timestampcancelledAt— timestamp if cancelled; null otherwise
Value objects
- BookingId — typed identifier wrapping a UUID.
- TimeRange — start and end
Datepair; validated so end > start; used for all overlap calculations.
Domain rules
- A Booking cannot be created for an aircraft that is
grounded. The aircraft status must be checked before the Booking is accepted. - A Booking cannot overlap with another confirmed Booking for the same aircraft. Overlap is detected on
TimeRange. - If an instructor is assigned, the instructor cannot already have a confirmed booking in the same time range.
- The booking owner (
memberId) must be an active Member. - A Booking with
status: cancelledcannot be modified or reassigned. - Bookings cannot be backdated beyond a configurable threshold.
Key use cases
createBooking— validate availability, detect conflicts, persist a new confirmed Booking.cancelBooking— transition a confirmed Booking to cancelled.updateBooking— amend time range or instructor assignment (subject to re-validation of all rules).listBookings— return Bookings filterable by aircraft, member, instructor, and date range.getBooking— return a single Booking by ID.checkAvailability— query whether an aircraft (and optional instructor) is free in a given time range.
Conflict detection
Conflict detection is a first-class domain rule, not an infrastructure concern. The domain checks for overlapping TimeRange values across confirmed bookings before accepting a new one. The check must cover:
- Aircraft conflicts: same
aircraftId, overlappingtimeRange. - Instructor conflicts: same
instructorId, overlappingtimeRange.
An overlap exists when newBooking.start < existing.end AND newBooking.end > existing.start.
Cross-context relationships
| Context | Usage |
|---|---|
| People | Reads active Member status and Instructor role via port before allowing a booking |
| Aircraft | Reads aircraft status (grounded/available) via port before allowing a booking |
| Training | A Lesson may reference a BookingId (Scheduling does not know about Training) |
| Billing | A Charge Item may reference a BookingId (Scheduling does not know about Billing) |
| Notifications | Booking confirmation and cancellation events trigger Notifications |
Scheduling depends on People and Aircraft by port — it calls repository interfaces that return minimal read-models, not full domain objects.