Architecture¶
Booking is a headless, API-first core with a family of optional
submodules. The core ships only entities, the BookingManager service,
events and plugin types - no UI, no payment, no contrib dependencies.
Layers¶
flowchart TB
subgraph presentation["Presentation / consumers (submodules & 3rd party)"]
UI[yoyaku_ui<br/>admin]
CAL[yoyaku_calendar<br/>public picker]
WFE[booking_webform<br/>element]
ORCH[booking_orchestra<br/>workflow tasks]
PAY[yoyaku_payment<br/>deposit / Commerce]
API[booking_api<br/>remote HTTP client]
end
subgraph core["booking (core, headless)"]
BM[BookingManager service]
EV[Lifecycle events]
CON[BookingConstraint plugins]
QW[yoyaku_expire_holds<br/>queue worker + cron]
end
subgraph data["Entities"]
R[Resource] --> S[Slot] --> C[Category] --> B[Booking]
end
presentation --> BM
BM --> CON
BM --> data
BM --> EV
EV --> presentation
QW --> BM
The dependency direction is strict: consumers depend on the core; the core depends on nothing but Drupal. The engine never knows about webforms, payments, nodes or workflows - they react through the events and drive it through the API.
The booking on a resource page with a calendar is one surface, not the model. For the full space of booking use cases (search, appointments, events, carts, API), the seams that absorb each one, and the rule that the core never assumes a surface, see Use cases and surfaces.
Module map¶
| Module | Role | Status |
|---|---|---|
booking |
Core: entities, BookingManager, events, constraint plugin type, hold-expiry worker, multi-tenancy. |
Done |
booking_node |
Bind a resource to a node + per-user resource management. | Planned |
yoyaku_ui |
Availability/calendar admin + booking dashboards. | Planned |
yoyaku_calendar |
Public JS slot-picker (block / field formatter) over an availability endpoint. | Planned |
booking_webform |
Webform element wrapping the slot-picker. | Planned |
booking_orchestra |
Orchestra task types: hold / confirm / release in a workflow. | Planned |
yoyaku_payment |
Deposit/price config on the category + "confirm on payment" contract. | Planned |
booking_recur |
Recurrence rules that materialise slots. | Planned |
booking_views |
Views integration. | Planned |
booking_api |
Remote HTTP client API (REST/JSON:API + OAuth + OpenAPI). | Planned |
Services¶
| Service id | Class | Purpose |
|---|---|---|
booking.booking_manager |
BookingManager |
The capacity engine and lifecycle API. |
booking.yoyaku_constraint_manager |
BookingConstraintManager |
Discovers/runs constraint plugins. |
booking.tenant_context |
TenantContext |
Resolves the active tenant. |
logger.channel.booking |
- | The module's log channel. |
The BookingManager is injected with the entity type manager, the database
connection (for transactions + row locks), the event dispatcher, the time
service, and the constraint manager.
Design rules¶
- OOP
#[Hook]only - no.modulefile (D11.3+, D12-ready), matching the Orchestra house style. - Attribute-based entities (
#[ContentEntityType],#[ConfigEntityType]),finalclasses,declare(strict_types=1). - Capacity is the lock target - see Capacity and holds.
- Money and presentation stay out of the core.