Cross-Context Event Contracts: Backoffice → Commerce, Operations
Formal event contracts for events emitted by the Backoffice bounded context. For the pricing-specific events (
PriceMatrixPublished,BookingConfirmed), see event-contracts-pricing.md. For the broader domain events catalog, see domain-driven-design.md §4.
Event Catalog
| Event | Emitter | Consumer(s) | Purpose |
|---|---|---|---|
TripPublished | Backoffice (TourDeparture.status → PUBLISHED) | Commerce (TourOffering creation, boarding points + ancillaries sync), Operations (ServiceLeg creation) | Signals a departure is ready for sale and dispatch |
TripCancelled | Backoffice (TourDeparture.status → CANCELLED) | Commerce (TourOffering.status → CANCELLED) | Stops sales immediately |
Payload Schemas
TripPublished
The most cross-cutting Backoffice event. Each consumer reads the fields it needs; the payload carries the full departure context to avoid follow-up queries.
| Field | Type | Description |
|---|---|---|
event_id | UUID | Idempotency key |
tenant_id | UUID | Owning operator |
tour_departure_id | UUID | The published departure |
tour_template_id | UUID | Source template |
start_date | DATE | Departure date |
end_date | DATE | Return date |
capacity | INT | Max passengers (from capacity_rules) |
max_door_pickups | INT | Door pickup limit (from tour_templates.max_door_pickups) |
deposit_config | JSONB | Resolved deposit config (template override or tenant default) |
cancellation_policy | JSONB | Resolved cancellation policy |
boarding_points | TripPublishedBoardingPoint[] | Resolved boarding point catalog (library defaults + template overrides + is_origin surcharge zeroing). See boarding-points.md §Commerce Projection. |
ancillaries | TripPublishedAncillary[] | Resolved ancillary catalog (catalog defaults + template overrides). See ancillary-catalog.md §Commerce Projection. |
legs | TripLegDefinition[] | Itinerary structure for ServiceLeg creation. See schema-operations.md §service_legs for the Operations consumer handler. |
published_at | TIMESTAMPTZ | Publication timestamp |
TripPublishedBoardingPoint fields: boarding_point_id, name, address, geo_coordinates, zone_label, surcharge, is_origin, door_pickup_available, door_pickup_surcharge, door_pickup_radius_km, passenger_instructions, display_order.
TripPublishedAncillary fields: catalog_item_id, type, label, description, cover_image_key, price, currency, is_per_passenger, max_quantity, included_by_default, sort_order.
TripLegDefinition fields: sequence_order, leg_type, scheduled_start, scheduled_end, waypoints[] (each: geo_coordinates, sequence_order, label, waypoint_type).
Consumer handler logic:
- Commerce: Creates/updates
tour_offeringsrow. Denormalizesboarding_points→available_boarding_pointsJSONB,ancillaries→available_ancillariesJSONB,max_door_pickups,deposit_config,cancellation_policy. Idempotent on re-publish (upsert ontour_departure_id). - Operations: Creates
service_legs+route_waypointsfromlegs[]. UsesUPSERT ON CONFLICT (tour_departure_id, sequence_order). Skips legs inACTIVE/COMPLETED/CANCELLEDstatus. See schema-operations.md §service_legs for the full handler contract.
TripCancelled
| Field | Type | Description |
|---|---|---|
event_id | UUID | Idempotency key |
tenant_id | UUID | Owning operator |
tour_departure_id | UUID | The cancelled departure |
tour_template_id | UUID | Source template |
cancelled_at | TIMESTAMPTZ | Cancellation timestamp |
Consumer handler logic:
- Commerce: Sets
tour_offerings.status → CANCELLEDfor the matchingtour_departure_id. The booking widget immediately stops selling this departure. Existing bookings are unaffected (operator contacts passengers manually at V0.1; automated notifications via Communications arrive at[v0.2]).
Delivery Contracts
| Event | Mechanism | Trigger | Idempotency |
|---|---|---|---|
TripPublished | Hasura Event Trigger (async, post-commit) | backoffice.tour_departures.status → PUBLISHED | event_id (UUID). Commerce: upsert on tour_departure_id. Operations: upsert on (tour_departure_id, sequence_order). |
TripCancelled | Hasura Event Trigger (async, post-commit) | backoffice.tour_departures.status → CANCELLED | event_id (UUID). Commerce: idempotent status set (already CANCELLED = no-op). |
All consumers implement at-least-once processing with event_id-based deduplication.