Skip to content

クーポンの仕様

申込時に使えるクーポンの種類・割引計算・利用制限・確定/取消の挙動をまとめます。実装 (apps/apidiscounts/coupon-service) に基づく現状仕様です。

1. 基本方針

  • クーポンは 運営が発行します(主催者側からは発行しません)。
  • 利用者は申込フォームで クーポンコードを入力して適用します。
  • 1 申込につき クーポンは 1 枚。タイムセール・ポイントとは併用できます(後述の順序で計算)。

2. クーポンの属性

項目内容
code利用者が入力するコード
label明細・履歴に出る表示名
discountKind割引の種類。amount(円の固定額)/ rate(%, 0〜100)
value割引値。amount なら円、rate なら%
scope適用範囲。global(全大会)/ tournament(特定大会)/ organizer(特定主催者)/ venue(特定施設)
scopeRefIdscope が tournament / organizer / venue のときの対象 ID
validFrom / validUntil有効期間(任意。未設定なら期間制限なし)
usageLimit全体の利用上限回数(任意)
perUserLimit1 ユーザあたりの利用上限回数(任意)

3. 適用可否の検証

申込(hold)時に、以下を順にチェックします。1 つでも外れると適用不可(エラーコードを返す)。

チェック不可のときのコード
コードが存在するかCOUPON_NOT_FOUND
validFrom <= 今 <= validUntil(有効期間内か)COUPON_OUT_OF_PERIOD
scope=tournament: 対象大会と一致するかCOUPON_SCOPE_MISMATCH
scope=organizer: 対象主催者と一致するかCOUPON_SCOPE_MISMATCH
scope=venue: 対象施設(大会の会場)と一致するかCOUPON_SCOPE_MISMATCH
全体利用上限(usageLimit)に達していないかCOUPON_USAGE_LIMIT
ユーザ別利用上限(perUserLimit)に達していないかCOUPON_PER_USER_LIMIT

利用回数は 確定済みの利用記録(coupon_redemptions) を数えます。キャンセル/返金で取り消した 分は再びカウント対象から外れ、再利用できるようになります(第 6 節)。

4. 割引の計算

基礎額(プラン価格 + 当日現金加算)から、次の 順序で引いていきます。

基礎額 = プラン価格 + 当日現金加算

   ├─ ① タイムセール    (クーポンより先に引く)
   ├─ ② クーポン        (タイムセール後の残額に対して計算)
   └─ ③ ポイント利用    (最後に残額から引く)

合計(0 円が下限)

ルール:

  • rate(%): 残額 × %切り捨て。残額を超えない。
  • amount(円): 固定額。残額を超えない(残額が割引額より小さければ残額まで)。
  • ポイント: 利用者の希望使用量を [0, 保有残高, 残額] の範囲にクランプ。
  • 0 円下限: どの割引も合計をマイナスにしません(合計 = max(0, …))。

プラン 3,000 円・タイムセール −500 円の場合、20% クーポンは残額 2,500 円に対して 計算され −500 円(合計 2,000 円)。「3,000 円の 20%」ではない点に注意。

5. 合計が 0 円になったとき

クーポン(やポイント)で 合計が 0 円になった申込は、Stripe 決済を介さずその場で confirmed(確定)になります。「決済待ち(holding)」を経由しません。

詳細は 申込状態の表示ルール を参照。

6. 利用の確定とロールバック

タイミング動作
申込確定(hold)coupon_redemptions に利用記録を追加し、適用額(amountApplied)を申込に凍結保存
決済成功(webhook)同上を冪等に確定(二重記録は無害化)
キャンセル / 返金coupon_redemptions削除して再利用可能に戻す
  • 申込に凍結した クーポンスナップショットapplied_coupon_snapshot: コード・割引種別・値・ 適用額)は、キャンセル後も履歴として残します(経理・監査用)。利用上限の集計から外すために 削除するのは利用記録(coupon_redemptions)の方だけです。