- Trip Logic Module (next conversation)
Trip pricing requires: • City selection • Experience selection per city • Duration logic • Group size logic • Seasonal pricing • Differential pricing for private vs group trips • Breakdown into: • accommodation • transport • sessions • logistics • staff • materials • etc.
This module will provide the computeTripPricing() implementation.
You have multiple existing versions: • Google Apps Script • Spreadsheet logic • Nested NextJS FE/BE • NestJS backend modules
We will converge these into a clean modern pricing engine.
⸻
FRONT END
export interface TripDraftDataCommentedPropertiesForReference { /** Local UI id for this draft */ id: string; projectId: number;// This should be passed from the UI or from the context productTypeId: number; /** Human name for the trip (maps loosely to Trip.name) */ title: string;
/**
- UI-level pax. This is the field your document section
- currently uses. When syncing to Prisma Trip, you can map:
- Trip.numPax = pax */
/**
- Optional alias for compatibility with existing Trip entities.
- When you load from a Trip row, you can keep numPax here, and
- normalize it to
paxin your engine / UI. */ numPax?: number;
/*_ Trip date range (can be partial, doc-level draft only) _/ startDate?: string; // ISO endDate?: string; // ISO
/**
- Hotel and room configuration, doc-level.
- These correspond to hotelStandards + room count logic
- in your Apps Script / Nest logic. */ hotelStandard?: "standard" | "comfort" | "premium" | string; numDoubleRooms?: number; numSingleRooms?: number; /**
- Trip style:
-
- "independent": mostly self-guided, occasional support
-
- "guided": guide/assistant expected most of the time
- This can drive defaults for guide-related costs. */ style?: "independent" | "guided";
/**
- High-level toggle for tours inclusion.
- This can be a default for per-city tours options. */ toursIncluded?: boolean; choiceTours?: boolean; /**
- Cities in this trip, in itinerary order.
- These are document-level drafts that can later be persisted
- to TripCity rows. */ cities: TripCityDraft[];
/**
- Optional link to Prisma Trip.id, when this draft is
- actually mirroring a stored Trip. */ linkedTripId?: number;
/**
- Optional pricing preview stored on the doc.
- Shape is intentionally loose to allow different engines
- (mock, local, server-side).
- Typical structure:
- {
- total: number;
- rows: { title, qty, unitPrice, total, meta? }[];
- breakdown?: { ... };
- } */ pricing?: any;
/**
-
For React Suspense pattern:
-
TripBuilderShell can store a Promise resolved by
-
a server action / pricing engine. */ pricingPromise?: Promise<any>;
/** ✨ internal canvas integration signals */
_requestInsertIntoLineItems?: boolean; _requestOverwriteTripLineItems?: boolean; }