既存スキーマとの整合性、要件充足、レビュー指摘を一覧で確認
ユーザーごとの副サブスク契約状態を管理する。既存の user_memberships(主サブスク)と対になるテーブル。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id | bigint | PK, AUTO_INCREMENT | |
user_id | varchar(36) | NOT NULL, FK→users(id) CASCADE | 既存 users.id に合わせ varchar(36) |
user_membership_id | bigint | NOT NULL, FK→user_memberships(id) CASCADE | 主サブスクとの紐付け(連動解約用) |
product_id | bigint | NOT NULL, FK→products(id) | |
studio_id | bigint | FK→studios(id) | 要検討: 権利タイプ商品では不要の可能性。nullable にすべきか |
payjp_subscription_id | varchar(255) | NOT NULL, UNIQUE | PayJP の定期課金ID |
status | varchar(30) | NOT NULL | PENDING/ACTIVE/SCHEDULED_CANCEL/CANCELED/PAUSED |
term_from | date | NOT NULL | 要検討: 既存 user_memberships は datetime |
term_to | date | NOT NULL | 同上 |
change_at | date | NULLABLE | 同上。解約予定日 |
canceled_at | timestamp | NULLABLE | レビューで追加提案。実際に CANCELED になった日時 |
created_at | timestamp | DEFAULT CURRENT_TIMESTAMP | |
updated_at | timestamp | DEFAULT CURRENT_TIMESTAMP ON UPDATE |
| 種別 | カラム | 備考 |
|---|---|---|
| 単体 | user_id | |
| 単体 | user_membership_id | |
| 単体 | status | |
| 単体 | change_at | |
| UNIQUE | payjp_subscription_id | Webhook解決の一意性担保 |
| 複合 | (user_id, status, term_to) | レビューで追加。有効サブスク検索用 |
月次の商品受け取り状況を管理する。物品タイプの商品のみレコードが作られる(権利タイプは0件)。
| カラム | 型 | 制約 | 説明 |
|---|---|---|---|
id | bigint | PK, AUTO_INCREMENT | |
product_subscription_id | bigint | NOT NULL, FK→product_subscriptions(id) CASCADE | |
delivery_month | date | NOT NULL | 月初固定 (YYYY-MM-01)。元設計は varchar(YYYY-MM) → date に変更 |
studio_id | bigint | NOT NULL, FK→studios(id) | 受け取り店舗 |
is_delivered | boolean | DEFAULT FALSE | delivery_status ENUM 化を検討中 |
delivered_at | timestamp | NULLABLE | |
delivered_by | varchar(36) | NULLABLE, FK→users(id) SET NULL | 元設計は bigint → varchar(36) に修正 |
note | text | NULLABLE | 備考 |
created_at | timestamp | DEFAULT CURRENT_TIMESTAMP | |
updated_at | timestamp | DEFAULT CURRENT_TIMESTAMP ON UPDATE |
| 種別 | カラム | 備考 |
|---|---|---|
| 単体 | product_subscription_id | |
| 単体 | delivery_month | |
| 単体 | studio_id | |
| 単体 | is_delivered | |
| UNIQUE | (product_subscription_id, delivery_month) | 1サブスク×1ヶ月で1レコード |
| 複合 | (studio_id, delivery_month, is_delivered) | レビューで追加。店舗の月次一覧用 |
id は varchar(36)(UUID)。新規テーブルの user_id, delivered_by はこれに合わせる。
主サブスクの契約状態を管理。id は bigint。product_subscriptions.user_membership_id から参照。プラン変更時は既存レコードを更新する設計(新レコード作成ではない)のため、FK が古い値を指し続ける問題は起きない。
type カラムに 'RECURRING_GOODS' を追加する方針。attr_id で商品種別ごとの属性テーブルを参照する構造のため、recurring_goods_attrs テーブルも新規作成が必要。
id は bigint。product_subscriptions.studio_id と deliveries.studio_id から参照。
user_memberships(主)と product_subscriptions(副)が別テーブルなので独立管理可能。user_membership_id FK で紐付け。
product_subscriptions.status を単独で SCHEDULED_CANCEL にできる。users.withdrawal_date には触れない設計。
user_membership_id で紐づく product_subscriptions を検索し、一括で SCHEDULED_CANCEL にする。
payjp_subscription_id を独立して持つため、PayJP 上で別 subscription として管理される。UNIQUE 制約で Webhook の振り分けも安全。
既存の products + products_studios(多対多)で店舗ごとの商品紐付けが可能。新規テーブルの追加は不要。
product_subscription_deliveries で月ごとの受取状況を記録。ユニーク制約 (subscription_id, delivery_month) で重複防止。
product_subscriptions に user_payment_method_id を持たない設計。主サブスクの支払い方法を共用。テーブル設計上は不要なカラムを入れていないので正しい。
deliveries テーブルにレコードが0件になるケースが正当。テーブル設計自体は問題ないが、fulfillment_type(PICKUP_GOODS / IN_STORE_EQUIPMENT_RIGHT 等)を商品マスタ側(products or recurring_goods_attrs)に持たせて、購入時の delivery 作成を分岐する必要がある。
product_subscriptions テーブルには該当カラムがない。これは商品マスタ側(recurring_goods_attrs)に first_billing_type 等として持たせるべき。product_subscriptions 自体の設計は問題なし。
delivery_month のユニーク制約があるため、1サブスク×1ヶ月で1レコード。繰越を表現するなら delivery_status の ENUM 化(PENDING/DELIVERED/SKIPPED/CARRIED_OVER 等)が必要。ルール自体は未確定。
user_membership_id が NOT NULL FK なので、主サブスクなしでは作成不可。CASCADE で主サブスク削除時に副サブスクも削除される。
bc-master-dev 経由で届いたレビュー全14項目を、対応方針ごとに分類。
新規テーブルの設計を既存テーブル(develop ブランチ)と照合した結果、判断が必要な点が4つあります。
term_from datetimeterm_to datetimechange_at datetime
term_from dateterm_to datechange_at date
プロジェクト内で型が混在すると、サービス層で dayjs の扱いがぶれる。既存に合わせて datetime にするか、date で良い明確な理由があるか判断が必要。副サブスクは時刻精度が不要(日単位で十分)なら date でも合理的だが、コードの一貫性を優先するなら datetime。
status varchar(30)
status ENUM(...)
bc-master-dev の更新済み ER 図では varchar に修正済み。既存に合わせて varchar(30) で統一が妥当。ENUM にするとステータス追加時にマイグレーションが必要になるデメリットもある。
studio_id bigint, NULLABLEstudio_id bigint, NOT NULL権利タイプ商品(ピラティスマシン等)では受取店舗の概念がないため、studio_id に値を入れる意味がない。「契約した店舗」として必ず入れるか、nullable にして権利タイプでは NULL を許容するか。既存 user_memberships も nullable なので、揃えて nullable にしておく方が自然。
fulfillment_type を追加fulfillment_type を追加「プロテインは物品」「ピラティスマシンは権利」という性質は商品ごとに固定なので、商品マスタ側(案A)が妥当。recurring_goods_attrs に fulfillment_type カラムを持たせ、購入時に delivery レコード作成を分岐する。