Busflow Docs

Internal documentation portal

Skip to content

ADR-014: Ticket Issuance Trigger Strategy — Operator-Configurable

Status: ✅ Approved — 2026-04-12 Impacts: schema-commerce.md (tickets.status field), PRODUCT_domain-model.md (Ticket entity), event-catalog.md (BookingConfirmed side effects) Origin: Booking Lifecycle Protocol


Context

User Journey 1 Step 3 describes "instant" Apple Wallet pass delivery upon deposit payment — implying ticket issuance at DEPOSIT_PAID. However, many DACH bus operators prefer to issue tickets only after FULLY_PAID to prevent passengers from boarding without completing the final payment. The boarding gateway difference is significant:

  • Early issuance (DEPOSIT_PAID): Better UX (instant fulfillment), but risk of unpaid travelers holding valid tickets. Requires a voiding mechanism when the final payment is overdue.
  • Late issuance (FULLY_PAID): Safe (no ticket without full payment), but worse UX — passengers receive only a booking confirmation at deposit, not the boarding-valid wallet pass.

The Ticket entity now carries a status field (ACTIVE, VOIDED) per the L2-2.1 review, which enables the voiding mechanism required for early issuance.

Decision

Operator-configurable. The ticket issuance trigger is set per Operator (default) or overridden per TourTemplate. Default: DEPOSIT_PAID (matching the user journey's "instant fulfillment" intent).

Configuration field: ticket_issuance_trigger: 'DEPOSIT_PAID' | 'FULLY_PAID' on backoffice.operators (global default) and optionally on backoffice.tour_templates (per-product override, nullable — falls back to operator default if null).

Consequences

Positive:

  • Operators choose the strategy that fits their business model
  • DEPOSIT_PAID default matches the product vision (instant digital fulfillment)
  • Ticket.status = VOIDED provides the safety net for early issuance — if final payment is overdue, a Hasura Scheduled Trigger voids the ticket

Neutral:

  • Checkout flow must conditionally check the issuance trigger before calling ticket generation
  • BookingConfirmed event consumers must be aware that ticket issuance is conditional — some bookings at DEPOSIT_PAID will have tickets, others won't (depending on the operator's config)

Implementation notes:

  • If DEPOSIT_PAID mode: the system issues the ticket during BookingConfirmed event handling. If final payment does not arrive by departure_date - 7 days, a Scheduled Trigger voids the ticket.
  • If FULLY_PAID mode: the system issues the ticket during BookingFullyPaid event handling. No voiding logic needed.
  • Schema addition: backoffice.operators.ticket_issuance_trigger VARCHAR DEFAULT 'DEPOSIT_PAID' and backoffice.tour_templates.ticket_issuance_trigger VARCHAR (nullable).

Internal documentation — Busflow