Issue #576

商品サブスク機能

主サブスク(ジム会員)とは別に、プロテイン等の商品を月額定期購入できる仕組みを追加する

何が変わるか

現在
1ユーザー = 1サブスク
(ジム会員のみ)
今後
1ユーザー = 主サブスク + 副サブスク(複数可)
(ジム会員 + プロテイン定期購入 etc.)

基本ルール

課金タイミング

主サブスクと同じく毎月20日。PayJP で別の subscription を作成し、決済は独立して行われる。

受け取り

月1回、購入時に指定した店舗で店頭受け取り。管理画面でスタッフが受取確認を行う。

解約ルール

副サブスク単独の解約は可能。主サブスクを解約すると副サブスクも連動して解約される。縛り・申請期限は主サブスクと同じロジック。

実装スコープ

2
新規テーブル
7
新規 API
2
既存 API 改修
3
バッチ処理
NestJS TypeORM PayJP Next.js MySQL

データ構造

users id, name, email... user_memberships 主サブスク product_subscriptions 副サブスク(NEW) status, payjp_subscription_id... product_subscription _deliveries 受け取り管理(NEW) products 商品マスタ studios 連動解約

ステータス遷移

PENDING
ACTIVE
SCHEDULED_CANCEL
CANCELED
ACTIVE ↔ SCHEDULED_CANCEL は解約取り消し(15日まで)で双方向

購入フロー

1

商品選択

ユーザーが商品・受取店舗・支払い方法を選択

2

初回決済

PayJP charge 作成で即時課金

3

定期課金登録

PayJP subscription 作成(20日課金、トライアル期間設定)

4

DB登録

product_subscriptions + 初回 deliveries レコード作成

5

完了通知

購入完了メール送信

API エンドポイント

POST /v2/users/:id/product-subscriptions
副サブスク購入
NEW
GET /v2/users/:id/product-subscriptions
副サブスク一覧取得
NEW
GET /v2/users/:id/product-subscriptions/:id
副サブスク詳細取得
NEW
PUT ...product-subscriptions/:id/cancel
解約申請
NEW
PUT ...product-subscriptions/:id/abort-cancel
解約取り消し
NEW
GET /v2/product-subscription-deliveries
受け取り予定一覧(管理画面用)
NEW
PUT ...deliveries/:id/mark-delivered
受け取り完了マーク(管理画面用)
NEW
PUT /api/users/:id/memberships/:id/cancel
主サブスク解約(連動解約追加)
改修
POST /api/orders/pay-jp/webhooks
Webhook(副サブスク課金対応追加)
改修

バッチ処理

月次ステータス更新

毎日深夜に実行。change_at が過去の SCHEDULED_CANCEL レコードを CANCELED に変更。

PayJP 定期課金キャンセル

毎日深夜に実行。解約予定の subscription を PayJP 側でもキャンセル。

受け取りレコード生成

毎月1日に実行。ACTIVE な副サブスクに対して翌月分の deliveries レコードを自動作成。

設計の方針: 既存の主サブスクロジックへの破壊的変更を避けるため、新規 API は /v2 として実装。既存エンドポイントへの改修は Webhook と主サブスク解約の2箇所のみ。詳細な設計書は Issue #576 のコメント を参照。