Commerce & Checkout

Checkout بسيط للعميل، لكن قوي جدًا في الخلفية.

المستخدم يرى رحلة هادئة وواضحة. خلفها توجد Delivery Groups، slot capacity، Character capacity، temporary holds، wallet/coupon validation، payment state machine، وserver-side recalculation قبل إنشاء الطلب.

Server authoritative
Race-safe reservations

المسار الموحد من السلة حتى النتيجة النهائية

كل خطوة تبني context للخطوة التالية. لا نطلب Character قبل موعد التوصيل، ولا نثق في browser return كدليل نجاح الدفع.

01Cart
02Identity
03Recipient / Address
04Delivery Groups
05Dates / Slots
06Gift Services
07Quote + Wallet
08Payment
09Authoritative Result

الـMixed Cart يُشرح قبل أن يفاجئ العميل

إذا اختلفت readiness بين المنتجات، يتحول الطلب إلى أكثر من Delivery Group. كل مجموعة لها موعدها ورسومها وخدماتها؛ ثم يتم جمعها في Order واحد.

Delivery Group A
متاح أسرع
Toy Aجاهز اليوم
Toy Bجاهز اليوم
6–9
Tuesday · 6–9 PM

يمكن ربط Balloons وMario بهذه المجموعة تحديدًا.

Delivery Group B
يحتاج تجهيزًا
Special itemجاهز غدًا
3–6
Wednesday · 3–6 PM

له موعد ورسوم وسعة منفصلة، لكن يبقى ضمن نفس الطلب.

Slot وCharacter نظامان مستقلان — جرّب السعة بنفسك

قد تكون فترة التوصيل متاحة بينما Mario ممتلئ، أو العكس. الـCheckout يربط النظامين فقط عندما يطلب العميل الخدمة.

Delivery Slot4 متبقٍ
Mario Capacity1 متبقٍ
يمكن اختيار الموعد وMarioكلا مصدري السعة متاحان في هذا السياق.
Character availability

effective capacity − (confirmed + valid holds). الـholds المنتهية لا تُحسب حتى لو لم يحذف worker الصف بعد.

عميلان يشاهدان آخر سعة في نفس اللحظة

الواجهة قد تعرض “1 متبقي” لكليهما. الصحيح أن transaction واحدة فقط تنجح، والثانية تعيد حساب السعة وتعرض recovery مفهومًا.

Customer A

Mario · 1 left

جاهز لإرسال reservation request.

VS
Customer B

Mario · 1 left

جاهز لإرسال reservation request.

A

لم تبدأ المحاكاة.

B

لم تبدأ المحاكاة.

Browser return ≠ Payment success

الـbackend يملك الحالة النهائية. Provider webhook وعودة العميل يمكن أن يصلا في أي ترتيب، لذلك نحتاج idempotency وdeduplication وlegal state transitions.

PENDING attempt

قبل فتح provider session، ينشأ payment attempt بمرجع فريد مرتبط بالـcheckout/order context.

Webhook + callback

كلاهما يسأل/يبلغ الـbackend، لكن لا يوجد مسار يعلّم الطلب paid مرتين.

Commit once

بعد التحقق: mark paid مرة واحدة، commit reservations، ثم emit notifications/analytics downstream.

الأخطاء المتوقعة لها أسماء وتجارب Recovery واضحة

بدل generic “Something went wrong”، كل خطأ حرِج يعبّر عن سبب تجاري حقيقي ويمكن للواجهة التعامل معه بوضوح.