Saudi commerce · Salla · Booking architecture

حجوزات طلبات Salla: امنع الحجز المزدوج بين الأنظمة

دليل إنتاج للتعامل مع حجوزات Salla كقراءات، وكشف تعارض الفترات والسعة، والحفاظ على Calendar وERP كـProjections قابلة للتعافي.

المسار المرتبطهندسة التجارة الإلكترونية
مركز خدمة حجوزات محوسب حقيقي يضم موظفين وشاشات، يوضح مطابقة الحجوزات التشغيلية.
e

تعرض Salla Order Reservations API قراءة فقط للحجوزات الحالية للطلبات ضمن نافذة تواريخ. وهذا يجعلها مفيدة لمطابقة التقويم وERP والتشغيل، لكنها ليست محرك Availability ولا تمنع بمفردها نظامين من بيع المقعد أوالفترة الزمنية نفسها. النمط الآمن هو إدخال الحجوزات في Local Projection مطبّعة، وكشف تعارض الفترات والسعة، وإرسال التغييرات إلى الأنظمة الأخرى عبر Idempotent Outbox، ثم مطابقة Projection دوريًا مع Salla.

هذا شرح هندسي عملي قائم على الوثائق، وليس إعلان منتج أوخبرًا. الـEndpoint والـScope وحقول الاستجابة أدناه حقائق موثقة في صفحات Salla Merchant API الرسمية، وتم التحقق منها في 29 أكتوبر 2026. أما نموذج التطبيع وقواعد التعارض والـOutbox وخطة Reconciliation فهي توصيات هندسية، وليست ادعاءات عن سلوك غير موثق في Salla.

الخلاصة أولًا

استخدم GET /admin/v2/reservations مع نافذة محدودة من start وend وToken يملك orders.read. احفظ كل Reservation بهوية مركبة من Merchant وReservation ID، وطبّع الفترة الزمنية وفق Time Zone الموثقة للمتجر، واحتفظ بـtype وseats_count ورابط الطلب وSource Timestamps. أرسل تغييرات Calendar أوERP عبر Outbox، ثم أعد قراءة النافذة نفسها لاكتشاف Drift.

لا تعامل List Endpoint كـCommand API. العملية الموثقة تسترجع الحجوزات الحالية؛ ولا توثق إنشاء Reservation أوقفل Capacity أوحل التنافس. يجب أن يكون للـAvailability مصدر سلطة واحد صريح، وتصبح بقية الأنظمة Projections عنه.

المجالالسلطة المقترحةالدليل المحفوظ
مراقبة الحجزSalla Order Reservations read endpointReservation ID والنوع والبداية والنهاية والمقاعد ووقت القراءة
السعة القابلة للبيعنظام المنتج أوالحجز الذي يملك AvailabilityCapacity Version وقرار قبول الحجز
عرض التقويمExternal Projection قابلة للتكرار بأمانProvider Event ID وSource Reservation ID وآخر Digest
سير عمل ERPProjection للطلب أوالمهمةExternal Document ID ومرجع الطلب
إصلاح DriftSalla Reconciliation مجدولةWindow Cursor والمعرفات المرئية وحد الغياب والنتيجة

ابدأ من العقد الموثق

توثق Salla المسار GET https://api.salla.dev/admin/v2/reservations باسم List Order Reservations. وتقول الصفحة إن Endpoint تسترجع حجوزات الطلبات الحالية، وتتطلب Scope باسم orders.read، وتعرض مثالًا لمعاملَي التاريخ start وend. تشمل أمثلة الاستجابة الموثقة:

  • id: هوية الحجز؛
  • title: عنوانًا للعرض؛
  • type: وتعرض الأمثلة day وtime؛
  • start وend: فترة الحجز؛
  • seats_count: عدد المقاعد في الحجز؛
  • url: رابط Dashboard للطلب في المثال؛
  • created_at: وقت الإنشاء لدى المصدر.

تذكر الصفحة أنها عُدلت في 7 سبتمبر 2026. ويذكر Changelog لدى Salla بشكل منفصل أن Order Details وكل Order Webhooks تدعم product_reservations. يفيد ذلك للاكتشاف المعتمد على الأحداث، لكنه لا يجعل Webhook Delivery سجلًا تاريخيًا كاملًا. استخدم Events لتقليل Latency، واستخدم Reservations Endpoint لمطابقة الحقيقة ضمن نافذة محدودة.

لا تنص الوثائق العامة التي تمت مراجعتها على أن Endpoint:

  • تكتب الحجوزات أوتلغيها؛
  • تضمن Resource-capacity Lock؛
  • تعيد Resource ID مناسبًا لتجميع التعارض؛
  • تحدد ما إذا كانت حدود الفترة Inclusive أوExclusive؛
  • تعرّف Time-zone Offset لكل Timestamp؛
  • تضمن أن كل Webhook Delivery تساوي Business Transition واحدة.

تعامل مع هذه النقاط كقرارات تكامل أومعلومات مجهولة. تحقق من إعداد المتجر والمنتج في بيئة منضبطة قبل السماح بإجراءات Downstream مؤتمتة.

افصل Observation عن Availability

من الأخطاء الشائعة أن تعتقد ثلاثة أنظمة أنها تملك الجدول. يقبل Storefront الحجز، ويعدّل الموظف Shared Calendar يدويًا، وينشئ ERP أمر عمل. ثم تنحرف الحالات مع الوقت.

استخدم ثلاث طبقات صريحة:

  1. Availability Authority: النظام الذي يقرر هل يمكن بيع مقعد أوفني أوغرفة أوTime Slot.
  2. Reservation Observation: السجل المطبّع المقروء من Salla والمرتبط بسياق الطلب.
  3. Operational Projections: Calendar Events ومهام ERP والتنبيهات واللوحات المشتقة من Observation.

لا تجعل Calendar سلطة ضمنية لأن الموظفين يستطيعون سحب Event. إذا كانت Manual Calendar Edits مهمة، فمررها عبر Command Path مراجعة تحدّث مالك Availability الفعلي. وإلا فاكتب Projection الصحيحة من جديد أوارفع Drift للمراجعة.

مخطط هندسي أصلي: تتدفق قراءات Salla وWebhooks عبر Durable Inbox وProjection مطبّعة للفترات وفحوص السعة وOutbox مع مطابقة محدودة. صورة الغلاف للمصور SeekerAlamahgem بترخيص CC0 1.0 عبر Wikimedia Commons؛ قد تُغيّر أبعادها للعرض المتجاوب.
مخطط هندسي أصلي: تتدفق قراءات Salla وWebhooks عبر Durable Inbox وProjection مطبّعة للفترات وفحوص السعة وOutbox مع مطابقة محدودة. صورة الغلاف للمصور SeekerAlamahgem بترخيص CC0 1.0 عبر Wikimedia Commons؛ قد تُغيّر أبعادها للعرض المتجاوب. اضغط لعرض أكبر

ابن Projection ثابتة للحجز

افصل Source Data عن Derived Data. يمكن أن يبدو السجل المحايد عن Provider هكذا:

{
  "tenant_key": "merchant-42",
  "provider": "salla",
  "reservation_id": "1473353380",
  "reservation_type": "time",
  "title": "Service appointment",
  "start_local": "2026-11-03T10:00:00",
  "end_local": "2026-11-03T10:30:00",
  "source_timezone": "Asia/Riyadh",
  "start_utc": "2026-11-03T07:00:00Z",
  "end_utc": "2026-11-03T07:30:00Z",
  "seats": 1,
  "source_order_url": "redacted-or-access-controlled",
  "source_created_at": "2026-10-29T13:48:33+03:00",
  "observed_at": "2026-10-29T17:05:12Z",
  "source_digest": "sha256:..."
}

هذا مثال تصميم للتطبيق وليس Salla Payload. احفظ Time Zone الخاصة بالمتجر من Authoritative Configuration، وارفض Local Times الملتبسة بدل التخمين. حوّل إلى UTC للمقارنة، لكن احتفظ بالقيم المحلية الأصلية للتدقيق والعرض للعميل.

استخدم Compound Uniqueness Key مثل (tenant_key, provider, reservation_id). لا تسمح بتصادم Reservation IDs بين المتاجر. واحسب Digest من Source Fields المطبّعة فقط حتى تصبح القراءة المكررة No-op.

عرّف قواعد تعارض الفترة والسعة

طبّع Time Reservations إلى Half-open Intervals: [start, end). تتداخل فترتان عندما:

a.start < b.end AND b.start < a.end

تسمح Half-open Boundaries بأن ينتهي حجز في اللحظة التي يبدأ فيها التالي. هذه قاعدة مقارنة محلية، وليست ادعاءً عن Boundary Semantics غير الموثقة في Salla.

يحتاج Conflict Grouping إلى Resource Key: منتج أوخدمة أوغرفة أوموظف أوCapacity Pool. لا يعرض مثال List هذا المفتاح، لذلك اشتقه فقط من Mapping موثقة للطلب أوالمنتج أومن Configuration صريحة. لا تجمع الحجوزات عبر Title Text.

في Capacity Pool، اجمع المقاعد في كل الحجوزات النشطة المتداخلة وقارن أعلى Concurrent Total بالسعة المضبوطة. تستهلك seats_count=2 وحدتين وليس Event واحدة. عند فقد Capacity أوResource Identity، علّم السجل unclassified وأوقف القبول أوالإلغاء الآلي.

تحتاج Day Reservations إلى سياسة منفصلة. وسّعها إلى Business-day Interval في Time Zone المتجر، لاTime Zone خادم التكامل. عالج Daylight-saving Transitions للمتاجر خارج السعودية، ولا تفترض أن كل Local Day مدته 24 ساعة UTC.

اجمع Webhooks وReconciliation

Webhooks إشارة سريعة وليست آلية التعافي الوحيدة. تقول وثائق Salla Webhooks إن Receiver يجب أن يستجيب خلال 30 ثانية، وتصف Retries عند فشل Delivery. لذلك يجب أن يصادق Receiver الطلب، ويحفظ Raw Event بشكل دائم، ويرد بسرعة، ثم يعالج Asynchronously.

Workflow مقترحة:

  1. تحقق من Webhook وفق Security Guidance الحالية لدى Salla.
  2. احفظ Immutable Inbox Record تحوي Tenant وEvent Type وSource IDs وPayload Digest.
  3. نفذ Deduplication بمفتاح Delivery أوBusiness Key ثابت متاح في Event Model.
  4. أرسل Narrow Refresh للطلب أوReservation Window المتأثرة.
  5. نفذ Upsert للـNormalized Reservation Projection.
  6. أنشئ Outbox Rows لمستهلكي Calendar وERP والتنبيهات.
  7. علّم Inbox Item مكتملة فقط بعد Durable Commit.

يمكن لأحداث الطلب التي تشمل product_reservations تحديد التغييرات المحتملة. ومع ذلك جدول List Reads دورية، لأن Events قد تتأخر أوتتكرر أوتغيب أثناء الصيانة أوتكون قد فاتت قبل تثبيت التكامل.

طابق نوافذ تواريخ محدودة

لا تشغّل Job غير محدودة لقراءة كل شيء. قسّم حسب Merchant وDate Window واحفظ Checkpoints:

window = [today - lookback, today + horizon]
GET reservations?start=window.start&end=window.end
normalize every returned record
upsert by merchant + reservation_id
mark each returned ID as seen in this run
compare local active records inside the same window
quarantine missing records before declaring deletion
emit outbox changes
advance checkpoint only after commit

تغطي Lookback التغييرات المتأخرة، وتغطي Future Horizon العمل القادم. اخترهما من Business Lead Times لاConstant عامة اعتباطية. واستخدم Grace Rule قبل اعتبار Missing Item محذوفة؛ فلا يجب أن يحذف API Failure مؤقت أوتغير في Filter Semantics أوصفحة غير مكتملة Calendar Events فورًا.

سجل Request Window وHTTP Status وعدد النتائج وRun ID وCompletion Time. إذا انتهت مهلة Endpoint، فإن Read قابلة للتكرار، لكن Job المحيطة يجب أن تبقى Idempotent حتى لا تكرر Downstream Events.

أرسل إلى Calendar وERP بأمان

أنشئ Outbox Row واحدة لكل Destination وReservation Digest. يجعل Idempotency Key مثل tenant:reservation:destination:source_digest التوصيل المكرر آمنًا. احفظ Event أوDocument ID لدى الوجهة بعد النجاح.

إذا انتهت مهلة Calendar Request فنتيجتها Unknown. اقرأ بالمفتاح الخارجي الثابت قبل إنشاء Event أخرى، ولا تفترض فشل الطلب الأول. وفي Updates قارن Last Applied Digest وعدّل الحقول المتغيرة فقط. وعند الإزالة انتقل إلى Cancelled أوTentative State قابلة للعكس قبل Hard Delete إن كانت الوجهة تدعم ذلك.

احفظ Order Dashboard URLs في سجلات محكومة الوصول. لا تضعها في Public Calendar Descriptions أوAnalytics Labels أوError Messages. أرسل أقل بيانات عميل لازمة للـDownstream Workflow.

جدول القرار

الحالةالإجراء الآمنالاختصار غير الآمن
نفس Reservation ID وDigestNo-opإعادة كتابة كل الوجهات
نفس ID مع تغير الفترة أوالمقاعدتحديث Projection وOutboxإنشاء Calendar Event ثانية
حجز متداخل جديد دون تجاوز السعةProject طبيعيًا وسجل Utilizationاعتبار كل Overlap خطأ
المقاعد المتزامنة تتجاوز السعةأوقف التأكيد الآلي ونبه المالكإلغاء طلب من Local Inference فقط
Reservation غائبة من قراءة واحدةQuarantine وتحقق بقراءة لاحقة أوOrder Detailالحذف فورًا
انتهت مهلة Calendar Writeاقرأ بالمفتاح الخارجي ثم قررإعادة Create عمياء
Time Zone أوResource مجهولةعلّمها Unclassified وأوقف Automationالتخمين من خادم التكامل

أفضل الممارسات

  • امنح Reservation Reader نطاق orders.read فقط.
  • ضع Tenant Identity في كل Key وLog وCheckpoint.
  • احتفظ بـLocal Timestamps الأصلية وحوّل باستخدام IANA Time Zone صريحة.
  • استخدم Half-open Intervals باستمرار في Local Conflict Engine.
  • احسب seats_count مقابل السعة بدل عد الصفوف.
  • عالج Webhooks عبر Durable Idempotent Inbox.
  • انشر تغييرات Calendar وERP عبر Outbox مع Read-after-timeout.
  • طابق Bounded Windows واعزل Missing Records قبل الإزالة.
  • اختبر Day وTime والحدود والسعة وحالات Time Zone.
  • اعرض Metrics لعمر Reconciliation والسجلات غير المصنفة وتعارض السعة وOutbox Lag.

Anti-patterns والقيود

  • معاملة List Endpoint كقفل حجز أوWrite API.
  • استخدام Calendar كسلطة Availability ثانية.
  • تجميع Resources بواسطة Title Text مترجم.
  • افتراض أن كل Reservation تستهلك مقعدًا واحدًا.
  • مقارنة Naive Timestamps في Local Zone الخاصة بالخادم.
  • إلغاء طلب تلقائيًا لأن Reconciliation Read واحدة أغفلته.
  • إعادة Calendar Create انتهت مهلتها دون البحث عن Event الأولى.
  • تسجيل Bearer Tokens أوCustomer Data أوDashboard URLs.

لا يستطيع هذا التصميم اختراع حقول لا يعرضها Provider. إذا لم يتمكن Integration من ربط Reservation بـAuthoritative Capacity Pool، فيمكنه Mirror الحجز ومطابقته، لكنه لا يستطيع إثبات أن الحجز خالٍ من التعارض بصدق.

Checklist التنفيذ

  1. أكد Authoritative Time Zone للمتجر ومالك Availability.
  2. اطلب orders.read فقط للـReservation Reader.
  3. اقرأ Date Window صغيرة وتحقق من أشكال الحقول الموثقة.
  4. ابن Tenant-scoped Normalized Projection وSource Digest.
  5. عرّف Resource Mappings وHalf-open Intervals وقواعد Capacity.
  6. أضف Durable Webhook Inbox وNarrow Refresh Jobs.
  7. أضف Idempotent Outbox لوجهات Calendar وERP.
  8. طابق Bounded Lookback وFuture Windows.
  9. اعزل Missing وUnclassified Records للمراجعة.
  10. اختبر Retries وDuplicates وUnknown Writes والحدود الزمنية وMulti-seat Overlaps.

اقرأ أيضًا: State Machines لحالات طلبات Salla وZid، وBackfills المتسلسلة لطلبات Salla، وتبديل Salla Webhook Endpoint، ومركز هندسة التجارة الإلكترونية.

المراجع الأساسية

إعداد: Noor Yasser

المراجع الرسمية

تدعم هذه المراجع سلوك الأدوات المذكورة. الأمثلة وقرارات التصميم توضيحية، ويجب تكييفها مع متطلبات المشروع وإصداراته.

إعداد: Noor Yasser

من القرار إلى التنفيذ

تعمل على تحدٍ تقني مشابه؟

أساعد الفرق على تحويل القرار المعماري إلى نطاق واضح وتنفيذ يمكن تشغيله ومراجعته بثقة.

احجز لقاءً لمدة ٣٠ دقيقةالخدمة المرتبطةهندسة الأنظمة الخلفية وتكاملات APIمشروع من الأعمالمنصة اللوجستيات