一句話:
trips是行程產品定義(目錄/行銷/MDX 內容),departures是該行程的可賣梯次(日期區間 + 席次容量 = 旅遊團的售賣單位)。本檔是行程實體的單一入口。欄位以 code 為準(packages/core/src/schema/business.ts、packages/core/src/catalog/*),畫面以 wireframe 為準(§6)。定位:domain/core spec。功能切片(定價 / 內容 / 團號 / 配套住宿 / 分房 / 登山難度)在各自 spec,§5 索引串接。訂房不走此模型(旅宿走房型每晚庫存,見 lodging-inventory)。狀態見 roadmap。
trips(行程定義):slug(unique)、title、summary、content_mdx、cover_image_url、price_from_twd(起價,展示用)、duration_days、destination、status(draft…)、模組旗標 is_climbing / is_overseas(行程層 gate,見 modules)、三條硬規則 config(見 §3.1)、created_at/updated_at。trip_images:trip_id(cascade)、url、caption、display_order。departures(可賣梯次 = 售賣單位):trip_id(cascade)、departure_date、return_date、price_twd(梯次價)、capacity、booked_count、status(selling…)、notes。CHECK:capacity > 0、booked_count <= capacity。與訂單的接點:
order_lines→tour_booking_lines.departure_id→departures.id。一張 tour 訂單的party_size由 tour line 承載(見 orders)。
trips.status:draft → 上架(published)等。departures.status:selling → 關閉/額滿/取消等(updateDepartureStatus)。
確切值集以 code 為準(
catalog/trips-repo.ts);本檔描述語意,不鎖列舉。
GS 國內高山團的三條硬規則扶正為 trips 上的可設定欄(已落地 packages/core/src/schema/business.ts)。本批僅落「設定欄」;實際 gating / 抽籤 / 候補遞補的 enforcement 邏輯隨 lottery-integration / climbing-screening epic。
| 欄位 | 型別 | 語意 |
|---|---|---|
confirm_group_multiple | integer nullable | 成團倍數(GS 國內高山團 = 7 的倍數)。NULL = 不限倍數。成團 / 派車 / 人力(每 8 人一組)算法的基準。 |
restricted_quota_enabled | boolean default false | 人頭使用次數限制開關(奇萊南華 / 嘉明湖 / 北大武等以身分證計次的國家公園 permit 配額)。 |
quota_per_person_limit | integer nullable | 每人(每身分證)使用次數上限。NULL = 不限。 |
quota_window | text nullable | 計次窗口(如 'annual')。NULL = 不限窗口。 |
waitlist_enabled | boolean default false | 候補開關(玉山搶候補 / 候補遞補)。本批僅旗標,遞補邏輯隨 lottery epic。 |
三者皆 nullable 或有預設,不破既有列。人頭使用次數限制屬登山專屬規則(permit 配額),enforcement 檢查層會比對旅客身分證的歷史使用次數(見 lottery-integration 的人頭限制檢查層註記)。
UPDATE departures SET booked_count = booked_count + N WHERE booked_count + N <= capacity + DB CHECK booked_count <= capacity,不靠讀後寫(catalog/seat-reservation.ts,由 orders createOrderWithReservation 呼叫)。control_db.tenant.module_*)且 行程層旗標(trips.is_climbing / is_overseas)皆開才生效(modules)。resolveDeparturePrice(catalog/pricing.ts,fallback 鏈 promo→梯次價→行程起價),歸 trip-pricing,不另寫第二份。packages/core/src/catalog/trips-repo.ts(first arg db: ScopedDb):
listPublishedTrips(目錄卡)、getTripBySlug(行程頁)。listAdminTrips、getTripById、createTrip、updateTrip、createDeparture、updateDepartureStatus。catalog/seat-reservation.ts。價格:catalog/pricing.ts(resolveDeparturePrice,trip-pricing)。| Spec | 擴充什麼 |
|---|---|
| trip-pricing | 直客/同業價欄、訂金/尾款、resolveDeparturePrice、包團(charter) |
| content-authoring | MDX 行程內容 / 圖片 / journal 撰寫 |
| group-code | 梯次團號(region/airline code + 產生/搜尋) |
| climbing-screening | 行程難度欄(grade_score 等)+ is_climbing,下單資格審核 |
| lodging-tour-package | departure_lodging 配套住宿(扣旅宿庫存、派生 departure_rooms) |
| room-assignment | departure_rooms 分房配置 |
| modules | is_climbing / is_overseas 兩層 gate |
| departure-prep | 出團 deadline 警戒 / 許可證文件 |
| lottery-integration | 成團倍數 / 人頭使用次數限制 / 候補(§2.1 config 的 enforcement) |
../apps/wireframes/app/admin/trips/| 版本 | 日期 | 變更 | Commit |
|---|---|---|---|
| 1 | 2026-06-01 | 初版:行程/梯次實體核心 spec(模型/狀態/race-safe 席次/兩層 gate/契約/擴充索引/wireframe) | — |
| 2 | 2026-06-23 | §2.1 補三條硬規則 trip 層 config(已落地 schema):confirm_group_multiple(成團倍數)/ restricted_quota_enabled + quota_per_person_limit + quota_window(人頭使用次數限制)/ waitlist_enabled(候補);本批僅設定欄,enforcement 隨 lottery / climbing epic(§5 索引加 lottery-integration)。 | — |
| 3 | 2026-07-01 | §6 wireframe 連結由過時 legacy .html 更新為現行 apps/wireframes/app/admin/trips/(Next.js static export React app)。 | — |