クーポン発行機能
概要
店舗事業者がクーポンを作成・配布し、ユーザーが提示・消費する機能。 クーポンは消費されるまでユーザー間で受け渡しができる。
登場人物
| 役割 | できること |
|---|---|
| 店舗事業者(org:owner) | クーポン作成・ユーザーへの配布 |
| ユーザー | クーポンの受け取り・提示・受け渡し |
| 主催者 または 事業者 | クーポンの消費確認(OK 操作) |
クーポンの種類
| 種別 | 説明 | 例 |
|---|---|---|
discount_percentage | 割引率 | 10% OFF |
discount_amount | 固定割引額 | 500円引き |
free_item | 無料アイテム | ドリンク1杯無料 |
フロー
1. 作成(事業者)
- 事業者がクーポンを作成する
- 特定イベントに紐づけることができる(任意)
- 紐づけたイベントのイベント画面に「利用可能クーポン」として表示される
2. 配布(事業者 → ユーザー)
- 事業者が配布したいユーザーを画面から選択して送信する
- 受け取ったユーザーの所持クーポン一覧に表示される
3. 受け渡し(ユーザー → ユーザー)
- 所持クーポン画面から渡したい相手のユーザーを選択して確定する
- 確定と同時に
current_holder_idが変わる - 受け取り側への通知あり。拒否機能は初期実装では持たない
4. 提示・消費
- ユーザーが所持クーポン画面を相手(主催者 or 事業者)に見せる
- 相手が確認して「OK」操作をする →
status: 'used'に変わる - 消費後は受け渡し・再利用不可
表示ルール
| 画面 | 表示内容 |
|---|---|
| 所持クーポン一覧 | current_holder_id = 自分 かつ status: 'active' のクーポン |
| イベント画面 | event_id = そのイベント かつ自分が所持している active なクーポン |
データ設計
coupons(クーポン定義)
| カラム | 型 | 備考 |
|---|---|---|
org_id | 必須(将来 nullable) | 作成した店舗。イベンター対応時に nullable 化 |
created_by | users.id | 作成したユーザー |
event_id | 任意 | 紐づけるイベント |
type | enum | discount_percentage / discount_amount / free_item |
value | number | 割引率・割引額・無料アイテム数 |
description | text | 例: ドリンク1杯無料 |
max_issuance | 任意 | 発行上限枚数。未設定は上限なし |
expires_at | 必須 | 有効期限 |
user_coupons(クーポン所持)
| カラム | 型 | 備考 |
|---|---|---|
coupon_id | coupons.id | |
issued_to_id | users.id | 最初の受取人(変わらない) |
current_holder_id | users.id | 現在の所持者(受け渡しで変わる) |
token | UUID | QR コード対応用。encode するだけで QR 化できる |
status | enum | active / used / expired |
used_at | 任意 | 消費日時 |
used_by_id | 任意 | 消費を確認したユーザー(主催者 or 事業者) |
ビジネスルール
status: 'used'または'expired'のクーポンは受け渡し・消費不可- 有効期限(
expires_at)を過ぎたクーポンは表示時にexpiredとして扱う(cron 不要・時刻導出) - 消費操作は主催者または事業者のみ実行可能
- クーポンの消費は
audit_logsに記録する issued_to_idは変更不可(誰に最初に配布されたかの履歴)
将来対応
| 対応 | 必要な変更 |
|---|---|
| QR コードで提示・受け渡し | token を QR encode するだけ(スキーマ変更なし) |
| イベンターもクーポン作成可能 | org_id を nullable に変更 + event_id を活用 |
| 受け渡し時の受諾確認 | user_coupons に status: 'pending_transfer' を追加 |
クリップボードコピー
- 所持クーポン画面で、クーポンの説明・利用条件をクリップボードにコピーできる(相手に内容を伝えやすくする用途)
TBD
- なし