۰۶ — چرخه سفارش (Order Lifecycle)
۱. فلو اصلی (پیادهسازی شده)
┌─────────────────┐
│ Browse & reserve│ مشتری باکس سرپرایز را انتخاب میکند
└────────┬────────┘
▼
┌─────────────────┐
│ Pay │ درگاه آنلاین یا «پرداخت در محل»
└────────┬────────┘
▼
┌─────────────────────────┐
│ awaiting_vendor │ وندور باید تأیید کند قبل از اطلاعرسانی مشتری
│ SMS → وندور │
└────────┬────────────────┘
▼
┌─────────────────┐
│ confirmed │ کد pickup فعال، SMS → مشتری
└────────┬────────┘
▼
┌─────────────────┐
│ Pickup window │ مشتری مراجعه میکند، کد نشان میدهد
└────────┬────────┘
▼
┌─────────────────┐
│ picked_up │ وندور کد را تأیید کرد — موفق
└─────────────────┘۲. State machine — order_status (پیادهسازی واقعی)
┌──────────┐
│ pending │ سفارش ایجاد شد، منتظر پرداخت
└────┬─────┘
│ payment OK (gateway callback) OR pay_at_pickup
▼
┌─────────────────┐
│ awaiting_vendor │ پرداخت دریافت شد
│ SMS → وندور │ وندور باید تأیید کند
└────────┬────────┘
│ POST /api/vendor/orders/[id]/confirm
▼
┌──────────┐
│confirmed │ SMS → مشتری؛ کد pickup فعال
└────┬─────┘
│ vendor confirm-pickup
▼
┌──────────┐
│picked_up │ SUCCESS — terminal
└──────────┘
لغو (cancel):
pending → cancelled (مشتری یا سیستم)
awaiting_vendor → cancelled (مشتری یا وندور — **تنها قبل از تأیید وندور**)
confirmed → ❌ نمیتوان لغو کرد
no_show (cron):
confirmed → no_show (بعد از pickup_end بدون تأیید)تعاریف
| Status | معنی |
|---|---|
pending | سفارش ثبت؛ منتظر پرداخت یا تایید pay-at-pickup |
awaiting_vendor | پرداخت OK. وندور SMS دریافت کرده. باید تأیید کند قبل از اطلاعرسانی مشتری |
confirmed | وندور تأیید کرد. مشتری SMS دریافت کرده. Pickup code فعال |
picked_up | وندور کد را verify کرد — terminal success |
cancelled | لغو شده — فقط وقتی هنوز awaiting_vendor یا pending است |
no_show | مشتری نیامد — cron بعد از pickup_end set میکند |
۳. State machine — payment_status
| Status | معنی |
|---|---|
pending | pay-at-pickup یا منتظر callback درگاه |
paid | پول دریافت/تایید شد |
failed | درگاه fail |
refunded | برگشت وجه |
ترکیبهای مجاز MVP
| payment_method | flow |
|---|---|
gateway | pending → (Zarinpal callback) paid → order awaiting_vendor |
pay_at_pickup | payment pending + order awaiting_vendor → vendor confirms → confirmed → vendor marks paid at pickup |
۴. State machine — SurpriseBox.status
| Status | معنی |
|---|---|
draft | وندور ساخته، publish نکرده |
active | قابل رزرو |
sold_out | quantity_remaining = 0 |
expired | بعد از pickup_end |
cancelled | وندور/ادمین لغو کرد |
۵. سیاست لغو (Cancel Policy)
مشتری میتواند لغو کند وقتی:
order_status=pendingیاawaiting_vendor
مشتری نمیتواند لغو کند وقتی:
order_status=confirmed,picked_up,no_show,cancelled
وندور میتواند لغو کند:
POST /api/vendor/orders/[id]/cancel— در هر مرحلهای قبل ازpicked_up
UI: دکمه لغو فقط اگر polling نشان دهد status هنوز pending یا awaiting_vendor است نمایش داده میشود.
۶. Inventory rules
- Decrement فقط وقتی order →
awaiting_vendor(بعد از پرداخت) - Race condition: transaction/lock روی
quantity_remaining - اگر دو کاربر همزمان — یکی success، یکی «آخرین باکس رزرو شد»
- Cancel → increment (اگر قبل از
picked_up)
۷. Pickup code
| مورد | پیشنهاد MVP |
|---|---|
| Format | ۶ رقم numeric |
| Uniqueness | per order |
| Display | فقط وقتی order_status = confirmed |
| Expiry | معتبر تا pickup_end |
| Abuse | rate-limit verify attempts |
۸. Timeline events (برای SMS/log)
| Event | Trigger | SMS |
|---|---|---|
order.created | POST /orders | — |
payment.completed | gateway callback | وندور: «سفارش جدید» |
order.awaiting_vendor | payment OK | وندور SMS |
order.confirmed | vendor confirms | مشتری: «آماده تحویل» |
pickup.reminder | cron: 30 min before pickup_end | مشتری |
pickup.completed | vendor confirm-pickup | — |
order.no_show | cron after pickup_end | — |
order.cancelled | cancel API | مشتری |
payment.refunded | admin/refund job | مشتری |
→ قالب SMS: 10-sms-notifications.md
۹. Vendor confirm flow (پیادهسازی شده)
- Gateway callback →
awaiting_vendor→ SMS به وندور - وندور پنل را باز میکند (polling 5 ثانیه)
- وندور «تأیید سفارش» میزند →
POST /api/vendor/orders/[id]/confirm - API:
order.status = confirmed، SMS به مشتری - مشتری در صفحه order/[id] (polling 5 ثانیه) میبیند که کد تحویل ظاهر شده
۱۰. Vendor pickup flow
- مشتری کد ۶ رقمی را نشان میدهد
- وندور کد را در
confirm-pickupوارد میکند - API:
POST /api/vendor/orders/confirm-pickupبا{ pickupCode } - اگر
pay_at_pickup→ همزمانpayment_status = paid - order →
picked_up
۱۱. No-show policy
| قانون | پیشنهاد MVP |
|---|---|
| Trigger | now > pickup_end AND status = confirmed |
| Action | status → no_show (cron job) |
| Payment gateway | no refund |
| Payment pay_at_pickup | no charge |
| Inventory | باکس «سوخت» — دیگر برنمیگردد |
→ تصمیم نهایی: 11-open-decisions.md
۱۲. Mermaid
mermaid
stateDiagram-v2
[*] --> pending: reserve
pending --> awaiting_vendor: payment OK
pending --> cancelled: timeout/fail
awaiting_vendor --> confirmed: vendor confirms
awaiting_vendor --> cancelled: cancel (before confirm)
confirmed --> picked_up: vendor confirm-pickup
confirmed --> no_show: past pickup_end
picked_up --> [*]
no_show --> [*]
cancelled --> [*]