Booking Module
Purpose
codex_django.booking is the Django adapter layer for the resource-slot booking engine that lives in codex-services.
Its job is not to reimplement scheduling logic.
Its job is to bridge Django project models and transaction semantics to the engine's provider-oriented interface.
This module gives a Django project three things at once:
- reusable abstract models for booking-related entities
- ORM-based adapters that convert project data into engine input
- selector functions that expose booking operations in a view-friendly form
So booking is best understood as an integration layer between Django domain data and resource-slot scheduling intelligence in codex-services.
Architectural Boundary
The core booking algorithm is delegated to ChainFinder and related DTOs from codex-services.
codex_django.booking focuses on the Django-specific concerns around that engine:
- how resources/executors, services, schedules, and appointments are modeled
- how ORM data is converted into
BookingEngineRequestandMasterAvailability - how row locking and transaction boundaries are handled during booking creation
- how busy-slot caching is invalidated safely
This separation is important because it keeps scheduling rules reusable across frameworks while still giving Django projects a practical integration path.
Main Building Blocks
Composable Booking Models
The mixins package defines abstract model mixins for the core booking entities:
AbstractBookableMasterAbstractBookableServiceAbstractBookableAppointmentAbstractWorkingDayMasterDayOffMixinAbstractBookingSettings
These are not final project models. They are scaffolding primitives that let each project keep its own foreign keys, categories, statuses, and business details while still matching the expectations of the adapter layer.
The design choice here is composability over hardcoded schema.
Availability Adapter
DjangoAvailabilityAdapter is the center of the module.
It translates Django ORM state into the provider data structures expected by the booking engine.
It is responsible for:
- building engine requests from service ids and resource selections
- resolving which resources can perform which services
- collecting working hours, breaks, days off, and busy intervals
- constructing availability DTOs consumed by the engine (
MasterAvailabilityclass name in currentcodex-services) - locking resource rows during booking creation
In effect, this adapter is the contract translator between Django models and ChainFinder.
High-Level Selectors
booking.selectors contains pure-function entry points used by views and generated feature code:
get_available_slots()get_nearest_slots()get_calendar_data()create_booking()
These functions keep orchestration outside of model methods. That makes them easier to reuse from views, APIs, commands, and future generated code.
Cache Adapter
BookingCacheAdapter is a thin bridge over the Redis booking cache manager from core.
The module's caching strategy is intentionally narrow:
- cache busy intervals per resource per date
- compute free windows dynamically from those intervals
- invalidate only the affected resource/date entries after a successful booking change
This keeps cache invalidation surgical and avoids storing derived slot maps as the primary source of truth.
Booking Settings Sync
AbstractBookingSettings provides configurable booking defaults such as:
- slot step size
- default buffer between appointments
- advance booking limits
- fallback working hours for all 7 weekdays
The booking adapter reads fallback hours only from booking settings.
It does not depend on site settings.
Timezone handling defaults to UTC unless a project passes a different
runtime timezone into the adapter or exposes a per-resource timezone field.
Its save hook synchronizes settings to Redis, following the same general pattern used elsewhere in the repository for runtime-accessed administrative state.
Concurrency Model
The most important architectural concern in this module is not slot computation itself, but safe booking creation under concurrency.
create_booking() follows a defensive flow:
- enter a transaction
- lock the relevant resource rows
- recompute availability under lock
- verify the requested start time still exists
- persist the appointment or the multi-service chain
- invalidate cache only after transaction commit
This design avoids the classic problem where a slot appears free during initial display but is taken before final confirmation.
For multi-service booking, the module introduces a BookingPersistenceHook protocol.
That keeps the persistence of complex booking chains project-specific while preserving the shared locking and revalidation logic.
Naming And Compatibility Policy
Starting from 0.3.0, the public booking API uses neutral naming:
resource_idinstead ofmaster_idresource_selectionsinstead ofmaster_selectionslock_resources()instead oflock_masters()
This change is intentionally immediate-break for runtime surfaces in codex_django.booking.
Some model mixin names remain historical (AbstractBookableMaster, MasterDayOffMixin) for schema compatibility in existing projects.
Runtime Flow
flowchart TD
A["Django view or API"] --> B["booking selectors"]
B --> C["DjangoAvailabilityAdapter"]
C --> D["Project ORM models"]
C --> E["BookingCacheAdapter"]
C --> F["codex-services ChainFinder"]
B --> F
G["create_booking transaction"] --> H["lock resources"]
H --> I["recompute availability"]
I --> J["persist appointment or chain"]
J --> K["invalidate cache on commit"]
Role In The Repository
booking is the domain adapter layer for appointment scheduling.
It is where the repository turns generic booking engine capabilities into Django-usable building blocks.
That makes it different from:
core, which provides shared infrastructure primitivessystem, which provides project-state models and admin workflowsnotifications, which handles message dispatch around domain events
booking sits closer to business behavior than those modules, but it still remains an adapter library rather than a full concrete booking application.
See Also
notificationsfor confirmation and reminder workflows built on top of booking eventssystemfor site-facing project state that remains outside booking runtime mathcodex-servicesfor the actual slot-finding and chain-solving engine this module integrates with