يمكن ربط Balloons وMario بهذه المجموعة تحديدًا.
Checkout بسيط للعميل، لكن قوي جدًا في الخلفية.
المستخدم يرى رحلة هادئة وواضحة. خلفها توجد Delivery Groups، slot capacity، Character capacity، temporary holds، wallet/coupon validation، payment state machine، وserver-side recalculation قبل إنشاء الطلب.
المسار الموحد من السلة حتى النتيجة النهائية
كل خطوة تبني context للخطوة التالية. لا نطلب Character قبل موعد التوصيل، ولا نثق في browser return كدليل نجاح الدفع.
الـMixed Cart يُشرح قبل أن يفاجئ العميل
إذا اختلفت readiness بين المنتجات، يتحول الطلب إلى أكثر من Delivery Group. كل مجموعة لها موعدها ورسومها وخدماتها؛ ثم يتم جمعها في Order واحد.
له موعد ورسوم وسعة منفصلة، لكن يبقى ضمن نفس الطلب.
Slot وCharacter نظامان مستقلان — جرّب السعة بنفسك
قد تكون فترة التوصيل متاحة بينما Mario ممتلئ، أو العكس. الـCheckout يربط النظامين فقط عندما يطلب العميل الخدمة.
effective capacity − (confirmed + valid holds). الـholds المنتهية لا تُحسب حتى لو لم يحذف worker الصف بعد.
عميلان يشاهدان آخر سعة في نفس اللحظة
الواجهة قد تعرض “1 متبقي” لكليهما. الصحيح أن transaction واحدة فقط تنجح، والثانية تعيد حساب السعة وتعرض recovery مفهومًا.
Mario · 1 left
جاهز لإرسال reservation request.
Mario · 1 left
جاهز لإرسال reservation request.
لم تبدأ المحاكاة.
لم تبدأ المحاكاة.
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”، كل خطأ حرِج يعبّر عن سبب تجاري حقيقي ويمكن للواجهة التعامل معه بوضوح.