/** * Owned-arm booking handler for the `cruises` vertical (Phase F * skeleton). * * Per `docs/architecture/booking-journey-architecture.md` §6 + * §7 (cruise example) + §10 Phase F. * * computeQuote scope: * - Reads cruise content via the caller-supplied loader * (`getCruiseContent`). * - Projects to a `BookingDraftShape` with cabin-category + * occupancy sub-steps via `buildCruiseDraftShape`. * - When a sailing + cabin category + occupancy are picked, * looks up the per-occupancy `cruise_prices` row and returns * pricing as `pricePerPerson × paxCount`. * */ import type { OwnedBookingHandler, OwnedHandlerContext } from "@voyant-travel/catalog/booking-engine"; import type { CruiseContent } from "../content-shape.js"; export interface ResolvedCruisePrice { /** Per-pax price in major units as a numeric string (matches * cruise_prices.pricePerPerson). */ pricePerPerson: string; currency: string; fareCode?: string | null; } /** * Caller-supplied loaders. Templates wire these to * `getCruiseContent` and `pricingService.lowestAvailablePrice` / * a custom per-(category, occupancy) lookup. */ export interface CruiseHandlerLoaders { loadContent: (ctx: OwnedHandlerContext, entityId: string) => Promise; /** * Resolve a price for the chosen sailing + category + occupancy. * Returns null when no available row matches (e.g. cabin * category is sold out at that occupancy). */ loadPrice: (ctx: OwnedHandlerContext, args: { entityId: string; sailingId: string; cabinCategoryId: string; occupancy: number; }) => Promise; } export interface CreateCruiseBookingHandlerOptions extends CruiseHandlerLoaders { /** Force the wizard to render a cabin-number sub-step even when * the supplier doesn't surface a cabin map. Defaults to false. */ forceCabinNumberSubStep?: boolean; /** Pass `true` when the deployment ships an insurance offer. */ includeInsurance?: boolean; } export declare function createCruiseBookingHandler(options: CreateCruiseBookingHandlerOptions): OwnedBookingHandler;