線稿索引所有 spec最後更新 2026-06-20
specs/discount-code.md

折扣碼與分潤快照

一句話:折扣碼是結帳時產生「負應收」的規則;應收真相仍在 order-money-model,本檔只定義折扣碼的適用規則、兌換快照、分潤快照與報表語意。

1. 核心模型

折扣碼資料分三層:

職責
discount_codescode 本體:可用期間、折扣類型、折扣值、使用上限、分潤規則、啟停狀態。
discount_code_trips適用範圍:全站、特定 trip、特定 departure、特定 lodging product 的關聯。
order_discounts訂單成交快照:哪個 code、折多少、誰推薦、分潤快照、當時規則摘要。

折扣實際影響應收時,必須同時寫:

  1. order_discounts:保留兌換與分潤快照;
  2. order_charge_lines(type='discount', amount_twd=-N, source_type='discount_code', source_id=order_discounts.id):讓金流模型扣應收。

order_discounts 是 write-once business snapshot;若折扣套錯,不能改原列,應以反向 charge line / audit 流程修正。

2. 適用規則

折扣碼可限制:

  • 使用期間;
  • 啟用狀態;
  • 最大兌換次數與每客戶次數;
  • 適用產品範圍;
  • 價格通路 / 客戶分類;
  • 最低應收門檻;
  • 是否可與其他折扣併用。

價格通路以成交 line snapshot 為準,不讀取可變的會員分類來重算既有訂單。

3. 金額計算

結帳時計算順序:

  1. trip-pricing 或 lodging pricing 解析商品原始應收;
  2. 寫入商品對應的正向 order_charge_lines
  3. 驗證折扣碼;
  4. 計算折扣金額並 floor 到 0,不允許折扣造成負應收;
  5. 寫入負向 discount charge line;
  6. 產生 payment_schedules,確保 current schedules target 總和等於最新應收。

Tour 與 lodging 都走同一原則:

  • tour:依 order_linestour_booking_lines 的成交快照計算折扣。
  • lodging:逐晚應收先寫 lodging_nightly_snapshotsorder_charge_lines(type='lodging_night'),再寫折扣 line。

4. 分潤

若折扣碼代表 KOL / 合作方推薦,order_discounts 在成交時凍結:

  • profit_share_twd
  • payee snapshot;
  • 計算規則摘要;
  • referral / owner 資訊。

分潤付款本身不由本檔建立。需要付款時,由 control-finance 產生 payables(payee_type='other' 或 staff_commission)payable_items,並保留對應 order_discounts 的來源連結。

5. 報表語意

團控與報表可顯示:

  • 折扣前應收:同訂單所有正向商品 charge line 的聚合;
  • 折扣金額:discount charge line 的絕對值;
  • 折扣後應收:SUM(order_charge_lines.amount_twd)
  • 已收現金:payment_transactions(direction='in'),依報表語意扣除退款或 chargeback;
  • 待分潤:order_discounts.profit_share_twd 中尚未轉 payable 的金額。

tour-centric 報表必須經 order_linestour_booking_lines 篩 departure;跨產品報表不得用 tour-only join。

6. 不變式

  • 折扣碼兌換與 order_charge_lines 寫入必須同一交易。
  • redemption_count 更新要 race-safe,避免超用。
  • 折扣金額不得讓 gross receivable 小於 0。
  • 折扣碼規則改動不回寫既有 order_discounts
  • 使用者可見的訂單金額一律走金流 helper,不在 UI 重算。

7. 實作入口

本檔描述模型與不變式;精確 schema/DTO 看 code。權威入口:

  • Schema:packages/core/src/schema/business.tsdiscount_codes / discount_code_trips / order_discounts
  • 結帳套碼(原子 gate、floor 折抵、round 分潤、race-safe 鎖兌換次數、reason 列舉):resolveAndApplyDiscountInTxpackages/core/src/discount/repo.ts
  • 唯讀預覽(前台結帳「試算」):previewDiscount,同檔
  • 串接點:tour createOrderWithReservationorders/repo.ts)、lodging createLodgingBookinglodging/booking-repo.ts)、房升折扣感知 recalculateOrderRoomUpgraderooms/repo.ts

Changelog

版本日期變更Commit
52026-06-20修正 §7 實作入口:recalculateOrderRoomUpgrade 定義位置由 orders/money.ts 改為 rooms/repo.ts(對齊 code)。
42026-06-10補「實作入口」指標(讓 spec 可對到 discount/repo.tsresolveAndApplyDiscountInTx / previewDiscount),不改模型語意。
32026-06-05改為折扣碼 × 金流分類帳 SSOT;折扣用負 charge line,分潤付款改接 payables。
22026-05-31補 KOL 分潤與團控統計。
12026-05-30初版折扣碼設計。