不要把訂閱做成一種特殊的訂單,讓它去「生」訂單。
做定期購的時候,第一個要決定的是:訂閱資料要放哪裡?
最直覺的做法是在 orders 加幾個欄位——is_subscription、cycle_days、next_billing_date——然後讓這張訂單一直重複出貨。
這條路很快就會撞牆。訂單是「一次交易的歷史紀錄」,它的金額、狀態、發票、物流編號都只對應一次出貨。你讓它重複,就得開始問:這張單的 payment_status 是第幾期的?客戶第三期退貨,要改哪裡?
subscriptions 一份持續產生未來訂單的契約
orders 每一期實際發生的那次交易
subscriptions 存的是「規則」:買什麼、多久一次、寄到哪、用哪張卡、下次什麼時候扣。
每到扣款日,系統依照這份契約建立一張全新的訂單:
$order = $subscription->createDraftOrder($cycle);
訂單上有一個 subscription_cycle 欄位,記錄這是第幾期。
這是整個設計最大的收穫。
第 3 期的訂單,跟一般客戶自己下的訂單,在資料結構上完全一樣。所以:
你不需要為訂閱做第二套後台。訂閱只多了一張表跟一支排程,其餘全部沿用。
反過來說,如果訂閱訂單是另一種資料結構,上面每一條都要做第二次。
訂閱有自己的狀態,跟訂單的狀態完全不同:
draft 建立中,還沒完成首次扣款
active 生效中,排程會依 next_billing_date 續扣
paused 顧客暫停
past_due 續扣失敗,待處理
canceled 已取消
這五個狀態在講「這份契約還活著嗎」,而訂單的狀態在講「這一次交易走到哪了」。
契約被暫停,不影響前三期已經出貨的訂單。第四期扣款失敗,不會讓契約消失,只是變成 past_due。 兩者各自演進,互不干擾。
訂閱不是一種訂單,訂閱是一台生產訂單的機器。
想清楚這件事,後面所有設計都會順。