۵. پردازش سفارش (Order Processing)

۵.۱ چرا این بخش حیاتی است؟

این بخش دقیقاً مشخص می‌کند POS شما بعد از دریافت سفارش چه کارهایی باید انجام دهد و با چه ترتیب و زمان‌بندی‌ای. بخش «پردازش سفارش» مستقیم روی تجربه مشتری، نرخ NFC و تماس‌های مرکز تماس اثر می‌گذارد.

نقطه شکست رایج: اگر POS بعد از Ack، تصمیم‌گیری (تأیید یا نیاز به تماس) را با تأخیر انجام دهد، سفارش از مسیر خودکار خارج شده و برای بررسی به مرکز تماس ارجاع می‌شود.

۵.۲ مرور چرخه عمر سفارش (State Machine)

سفارش بعد از ثبت/ویرایش با وضعیت‌های مشخص به فروشگاه ارسال می‌شود و تا زمانی که فروشگاه پاسخ ندهد ممکن است مجدداً ارسال شود. سپس با انجام اکشن‌های فروشگاه، وضعیت سفارش در پلتفرم تغییر می‌کند:

56 / 714 (New / Re-send)  →  ACK (204)  →  61
                                ↓
                              PICK (204) → 713
                                ↓
                        تصمیم نهایی: ACCEPT یا REJECT(Need Call)
طبق داک: سفارش ابتدا با کد ۵۶ ارسال می‌شود، ممکن است مجدد با کد ۷۱۴ تکرار شود، پس از Ack وضعیت به ۶۱ و پس از Pick به ۷۱۳ تغییر می‌کند.

۵.۳ SLA و پنجره‌های زمانی (برای جلوگیری از Call Center)

بعد از دریافت سفارش، دو کار باید خیلی سریع انجام شود:

قانون مهم داک: اگر سفارش در پنجره زمانی ۵ دقیقه پس از Ack به «تأیید یا نیاز به تماس» نرسد، برای بررسی به مرکز تماس ارجاع داده می‌شود.

۵.۴ آدرس پایه Order API

تمام اندپوینت‌های پردازش سفارش زیر این Base قرار دارند:

https://api-proxy.snapp.express/va/v1/order

۵.۵ ACK – تأیید دریافت سفارش

بلافاصله بعد از دریافت سفارش (Webhook یا MQTT)، POS باید Ack ارسال کند. Ack یعنی «سفارش به دست من رسید و در سیستم ثبت شد».

Endpoint

POST https://api-proxy.snapp.express/va/v1/order/{orderCode}/ack
Authorization: Bearer <access_token>

نمونه

curl --location --request POST \
'https://api-proxy.snapp.express/va/v1/order/8549yn4g/ack' \
--header 'Authorization: Bearer some_token_string'
Response: در موفقیت 204 No Content و بدنه خالی.
خطای رایج: 1023 یعنی orderCode پیدا نشد (معمولاً orderCode اشتباه یا سفارش منقضی/لغو شده).

الزام پیاده‌سازی در POS

۵.۶ PICK – «باز کردن سفارش توسط اپراتور»

Pick به معنی این است که اپراتور فروشگاه سفارش را باز کرده و وارد فاز آماده‌سازی شده است. این مرحله معمولاً بعد از Ack و قبل از تصمیم نهایی انجام می‌شود.

Endpoint

POST https://api-proxy.snapp.express/va/v1/order/{orderCode}/pick
Authorization: Bearer <access_token>

نمونه

curl --location --request POST \
'https://api-proxy.snapp.express/va/v1/order/8549yn4g/pick' \
--header 'Authorization: Bearer some_token_string'
Response: در موفقیت 204 No Content.
خطاهای مهم Pick:
  • 1023 سفارش یافت نشد
  • 1068 قبلاً Pick شده
  • 1059 قبلاً تایید شده
  • 1060 قبلاً Need Call / Reject شده
توصیه اجرایی: Pick را به «باز شدن صفحه سفارش در UI» گره بزنید، نه به «پایان آماده‌سازی». (پایان آماده‌سازی در این داک با Accept/Need Call مدیریت می‌شود.)

۵.۷ ACCEPT – تأیید سفارش

وقتی فروشگاه مطمئن است سفارش قابل انجام است، باید Accept ارسال کند. این مرحله سفارش را «تأیید» می‌کند.

Endpoint

POST https://api-proxy.snapp.express/va/v1/order/{orderCode}/accept
Authorization: Bearer <access_token>
Content-Type: application/json

Body (طبق داک)

{
  "packingPrice": 0,
  "delta": 0,
  "deliveryTime": 0,
  "riderPickupTime": 0
}
معنی فیلدها:
  • packingPrice همیشه ۰ است.
  • delta میزان اختلاف قیمت (به تومان) بین POS و سفارش است.
  • deliveryTime فقط در حالت Own Delivery، «زمان تحویل به مشتری» است؛ در غیر این صورت ۰.
  • riderPickupTime زمان جمع‌آوری و بسته‌بندی در فروشگاه است (مبنای زمان رسیدن پیک).
خطاهای مهم Accept:
  • 2110 زمان دلیوری غیرمجاز
  • 503 خطای دسترسی (موقت)
  • 1059 قبلاً تایید شده
  • 1060 قبلاً Need Call شده

الزام‌های پیاده‌سازی (برای کاهش NFC/Call)

۵.۸ Need Call (Reject) – ارسال به مرکز تماس با دلیل + توضیح + جایگزین

در این داک، Reject یعنی بردن سفارش به وضعیت «نیاز به تماس». هدف این است که با ارسال اطلاعات دقیق در همان درخواست، تعداد تماس‌های مرکز تماس با فروشگاه کم شود و تصمیم نهایی سریع‌تر گرفته شود.

قدم ۱: دریافت لیست دلیل‌ها (Decline Reasons)

GET https://api-proxy.snapp.express/va/v1/order/decline-reason/
Authorization: Bearer <access_token>

قدم ۲: ارسال Need Call (Reject)

POST https://api-proxy.snapp.express/va/v1/order/{orderCode}/reject
Authorization: Bearer <access_token>
Content-Type: application/json

Body استاندارد (پیشنهادی و Vendor-friendly)

{
  "reasonId": 177,
  "comment": "شیر این برند موجود نیست. امکان ارسال برند X یا Y هست.",
  "nonExistentProducts": [
    {
      "barcode": "34144555",
      "suggestedProductBarcodes": ["53535222", "4568745451"]
    }
  ]
}
محدودیت مهم: اگر بیش از ۱ ساعت از زمان تأیید گذشته باشد، ممکن است خطای 1059 دریافت کنید.
بهترین‌عمل برای کاهش تماس:
  • حتماً comment را دقیق و عملیاتی بنویسید.
  • اگر فقط چند قلم مشکل دارند، برای همان‌ها nonExistentProducts و جایگزین پیشنهاد دهید.
  • اگر مشکل «قیمت/دلتا» است، مقدار delta را در Accept درست کنید یا Need Call را با توضیح شفاف بفرستید.

۵.۹ جدول وضعیت‌ها (StatusCode) برای پیاده‌سازی درست در POS

در دیتای دریافتی (Webhook/MQTT) فیلد statusCode می‌آید. پیشنهاد می‌شود POS بر اساس آن رفتار کند:

statusCode معنی اقدام پیشنهادی POS
56سفارش ثبت یا ویرایش شدهثبت/آپدیت در DB → Ack
714ارسال مجدد سفارشIdempotent upsert → اگر Ack نشده: Ack
61Ack شدهورود به فاز عملیاتی → Pick/Decision
713Pick شدهاپراتور در جریان است → Decision سریع
42تایید شده / ویرایش تایید شدهثبت در DB و ادامه عملیات
51Need Call / رد شده و در صف مرکز تماسثبت، جلوگیری از عملیات تکراری
54لغو شدهبستن سفارش در POS
71نیازمند پرداخت اضافهنمایش به اپراتور (بدون تغییر خودسرانه)

۵.۱۰ سناریوهای اجرایی (برای جلوگیری از NFC / False-Flow)

سناریو A: سفارش جدید (Happy Path)

  1. Webhook رسید (56/714) → سفارش را Idempotent در DB ذخیره کن
  2. فوراً Ack بزن
  3. اپراتور سفارش را باز کرد → Pick
  4. همه اقلام OK → Accept (داخل پنجره ۵ دقیقه بعد از Ack)

سناریو B: چند قلم موجود نیست ولی جایگزین دارید

  1. Ack سریع
  2. Pick
  3. Reject(Need Call) با reasonId + comment دقیق + suggestedProductBarcodes
  4. همزمان در POS، موجودی SKUهای مشکل‌دار را اصلاح کنید و در فلو سینک به‌روز کنید (برای کاهش تکرار NFC)

سناریو C: سفارش تکراری/ارسال مجدد (714)

۵.۱۱ Error Handling و Retry (اصولی و امن)

Log پیشنهادی: (orderCode, statusCode_in, action, sent_at, http_status, error_code, latency_ms)

۵.۱۲ ادامه مسیر

در بخش بعدی، ساختار خطاها، پیام‌های استاندارد و سیاست Retry را دقیق‌تر و با مثال‌های بیشتر بررسی می‌کنیم.

رفتن به بخش ۶: ارور هندلینگ