H1🧠 Trip & Booking Domain Model — Molino + Legacy Reference
last_updated: 2026-04-30
H2📦 Current Commercial Lanes in Molino
| Lane | Status | Description |
|---|---|---|
| Tours/Experiences | ✅ Working | FareHarbor Lightframe modal, booking buttons on trips/cities/experiences |
| Trip Join | ✅ Wired | createTripJoin → creates TripJoin record with recalculated pricing |
| Featured Trips | ✅ Done | Fixed FH price, no recalculation |
| Private Trips | ⚡ In Progress | Join → recalculate via tripEngine, booking pending |
| Hotels | ⏳ Planned | Separate lane: estimate OR FH OR external links |
| Bookings Export | ✅ PDF wired | /trips/[tripId]/export/pdf |
H2🏗️ Trip Domain — Current State
H3Entities (Prisma)
| Entity | Role | Status |
|---|---|---|
Trip | Core trip with cities, dates, pax | ✅ |
TripCity | City in trip with nights, guide, tours | ✅ |
TripJoin | Participant join record | ✅ |
TripJoinQuote | Quote snapshot | ✅ |
Pricing | Computed via tripEngine | ✅ |
H3Trip Pricing Engine
tripEngine(input: TripInput) → TripPricingOutput
- totalBase (raw)
- totalWithMarkup (margin)
- lineItems[]
H3Join Flow (Wired This Session)
User clicks "Join this trip"
↓
TripJoinPanel → createTripJoin({ tripId, pax, rooms, hotelStandard })
↓
createTripJoin action:
- Loads Trip + Cities from Prisma
- Maps to TripInput
- Calls tripEngine({ ...input, numPax, numDoubleRooms, numSingleRooms })
- Creates TripJoin with pricingSnapshot
- Returns joinId
H2🏗️ Legacy NestJS Backend Reference
Located: legacy-version-reference/
H3Endpoint Surface (what legacy calls)
GET /trips → list trips
POST /trips → create trip
GET /trips/:id → get trip detail
PATCH /trips/:id → update trip
GET /cities → list cities
GET /plans → list city plans (experiences)
GET /trip-cities → trip city relations
POST /trip-city-plan → bind plan to trip city
GET /bookings → list bookings
POST /bookings → create booking
H3Legacy Service Layer
| Service | Molino Equivalent |
|---|---|
trips.ts | trip-engine/ + trips.read.actions.ts |
cities.ts | cities seed + Prisma City |
plans.ts | getFeaturedExperiences → Experience |
tripCities.ts | TripCity (via cities relation) |
tripCityPlans.ts | Binding Experience to TripCity |
bookings.ts | TripJoin + BookingBundle (planned) |
H2🎯 Optimization Targets — Ordered by Priority
H3P0 — Must Ship
-
Trip Booking Flow
- TripJoin created ✅
- Confirm/Pay step (link to FH or manual)
- Confirmation email
-
Hotels Lane
- Decision: estimate OR FH OR external
- UI: show/hide based on hotel policy
H3P1 — Should Ship
-
Trip Sharing
- Share private trip via email
- Invitee sees trip with join option
- Invite accepted → recalculates
-
TripCity Plans Binding
- UI to bind Experiences (plans) to TripCity
- Maps to
city.toursin Prisma
H3P2 — Can Wait
-
Booking Export
-
/trips/[tripId]/export/email— email template -
/trips/[tripId]/export/calendar— .ics
-
-
TripCity Updates
- Sync TripCity when Experience content changes
H2🔌 Mapping Legacy → Molino
| Legacy API | Molino Action/Route |
|---|---|
GET /trips | getTrips (read actions) |
POST /trips | createTrip (create action) |
GET /trips/:id | getTripById (read actions) |
PATCH /trips/:id | updateTrip (update action) |
GET /plans | getFeaturedExperiences |
POST /trip-city-plan | Bind Experience via updateTripCity |
GET /bookings | TripJoin list (future) |
POST /bookings | createTripJoin → BookingBundle |
H2📝 Notes
- Hotels remain separate commercial lane
- TripJoin ≠ BookingBundle (TripJoin is intent, BookingBundle is execution)
- FH for experiences only; trip pricing managed internally
- Legacy NestJS backend provides patterns to migrate later if needed
Reference files:
- Legacy actions:
legacy-version-reference/actions/*.ts - Legacy frontend shell:
legacy-version-reference/legacy-trips-frontend-shell.md - Current engine:
app/trips/actions/trip-engine/