Appearance
クーポンの仕様
申込時に使えるクーポンの種類・割引計算・利用制限・確定/取消の挙動をまとめます。実装 (apps/api の discounts/ と coupon-service) に基づく現状仕様です。
1. 基本方針
- クーポンは 運営が発行します(主催者側からは発行しません)。
- 利用者は申込フォームで クーポンコードを入力して適用します。
- 1 申込につき クーポンは 1 枚。タイムセール・ポイントとは併用できます(後述の順序で計算)。
2. クーポンの属性
| 項目 | 内容 |
|---|---|
code | 利用者が入力するコード |
label | 明細・履歴に出る表示名 |
discountKind | 割引の種類。amount(円の固定額)/ rate(%, 0〜100) |
value | 割引値。amount なら円、rate なら% |
scope | 適用範囲。global(全大会)/ tournament(特定大会)/ organizer(特定主催者)/ venue(特定施設) |
scopeRefId | scope が tournament / organizer / venue のときの対象 ID |
validFrom / validUntil | 有効期間(任意。未設定なら期間制限なし) |
usageLimit | 全体の利用上限回数(任意) |
perUserLimit | 1 ユーザあたりの利用上限回数(任意) |
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)の方だけです。