Saudi commerce · Salla · Shipping operations

وقت استلام شحنة سلة: اجعل تسليمها للناقل قابلًا للتدقيق

دليل عملي يحول وقت الاستلام الفعلي في سلة إلى دليل قابل للتدقيق على تسليم الشحنة للناقل بدل تحديث حالة هش.

المسار المرتبطهندسة التجارة الإلكترونية
رافعة شوكية تحمّل شحنة على طبالي داخل حاوية في مستودع، في توضيح للتسليم الفعلي للناقل خلف وقت Pickup.
h

أضافت سلة في 14 أكتوبر 2026 الحقل النصي actual_picked_up_at إلى Update Shipment Details، ليصبح للتكاملات مسار موثق لتسجيل الوقت الفعلي الذي استلم فيه الناقل الشحنة. يبدو التغيير صغيرًا، لكنه يسد فجوة تشغيلية مهمة: «جاهزة للاستلام» و«تم تعيين الناقل» و«استلمها الناقل فعليًا» حقائق مختلفة. يحتاج التاجر والمستودع والناقل وخدمة العملاء إلى الحقيقة الأخيرة لقياس تأخر التسليم للناقل والتحقيق في الطرود المفقودة.

هذا شرح عملي للتوثيق، وليس ادعاءً بأن سلة أطلقت منتجًا كبيرًا اليوم. الحقل وعقد Endpoint مستندان إلى Changelog وتوثيق الشحنات الرسميين لدى سلة، وتم التحقق منهما في 25 أكتوبر 2026. أما Event Ledger وقواعد التحقق ومسار المطابقة أدناه فهي توصيات هندسية.

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

تعامل مع actual_picked_up_at كحدث أعمال شاهده الناقل، لا كوقت إرسال Worker لطلب API. احفظ ملاحظة الاستلام قبل استدعاء سلة، ووحّد منطقتها الزمنية، وأرسلها مع status المطلوب، ثم اقرأ الشحنة مجددًا قبل اعتبار المزامنة مكتملة. لا تصنع الوقت من إنشاء البوليصة أو موعد الاستلام المخطط أو انتقال حالة محلي.

الوقتما يجب أن يعنيهما يجب ألا يعنيه
label_created_atإنشاء Label أوAWBمغادرة الطرد للمستودع
pickup_scheduled_atالتخطيط لزيارة الناقلوصول الناقل أوقبوله العهدة
actual_picked_up_atرصد استلام الناقل الفعلينجاح Sync Job فقط
actual_delivered_atرصد التسليم الفعليمجرد تحويل الطلب إلى مكتمل

يتضمن مثال Update Shipment Details في توثيق سلة كلا من actual_picked_up_at وactual_delivered_at. كما يوثق أن status مطلوب وأن Scope هو shipping.read_write. هذه حقائق من المورد؛ أما جمع الدليل ومنع الكتابات المتعارضة فمسؤولية التكامل.

مكان الحقل في التصميم

قسّم الشحنة إلى ثلاث طبقات:

  1. Observations: حقائق ثابتة تصل من Webhook للناقل أومسح المستودع أوتطبيق السائق أوإجراء Operator معتمد.
  2. Projection: أفضل حالة حالية مشتقة من Observations المقبولة.
  3. Commands: محاولات تحديث سلة أوأي نظام بعيد.

وقت الاستلام يدخل أولًا في Observation. إذا أفاد Webhook للناقل أن الاستلام حدث 14:08، فاحفظ الحدث الخام ومعرف شحنة المزود ووقت الحدوث ووقت الاستلام والمصدر وPayload Hash ونتيجة التحقق. بعد ذلك اشتق Projection محلية وضع تحديث سلة في Queue. يبقى الدليل محفوظًا لو انتهت مهلة الاتصال بالنظام البعيد أوتكرر الطلب.

يمكن أن يبدو السجل الأدنى هكذا:

create table shipment_observations (
  merchant_id bigint not null,
  shipment_id bigint not null,
  source text not null,
  source_event_id text not null,
  event_type text not null,
  occurred_at timestamptz not null,
  received_at timestamptz not null default now(),
  payload_hash text not null,
  verification_state text not null,
  primary key (merchant_id, source, source_event_id)
);

يجب أن يكون Unique Boundary مرتبطًا بالتاجر والمصدر؛ فقد يكون معرف حدث الناقل فريدًا داخل حساب ناقل واحد فقط. إن لم يقدم المزود Event ID ثابتًا، فأنشئ Fingerprint مدروسًا من التاجر ومعرف شحنة المزود ونوع الحدث ووقت الحدوث الموحد وPayload Hash، واحتفظ بالملاحظة الخام للتدقيق.

حدد ترتيب مصادر الحقيقة

ليست كل الأوقات متساوية في الثقة. استخدم سياسة أولوية صريحة:

المصدرالدليل المعتادالثقة الافتراضية
Carrier Webhook موقّع أوAPIProvider Event ID ووقت الناقلأعلى دليل آلي
مسح المستودعDevice وOperator وDock ومسح الطرددليل عهدة قوي عند ضبط العملية
تطبيق السائقهوية السائق والمسار ووقت الجهازمفيد مع فحص الساعة والتعيين
إجراء التاجر يدويًاالمستخدم والسبب وAudit Trailاستثناء مسموح لا Overwrite صامت
ساعة Integration Jobوقت المعالجة فقطليست حقيقة استلام أبدًا

إذا تعارض مصدران مقبولان، فلا تحتفظ بالأحدث بصمت. سجل Conflict يضم الملاحظتين وسبب الحل. قد يصل حدث متأخر ليصف استلامًا أقدم؛ Arrival Order ليس Business Order.

مخطط هندسي أصلي: ارصد دليل الاستلام واحفظه وحدّث سلة ثم اقرأ وطابق. الصورة للمصور Goterrestrial بترخيص CC BY 4.0 عبر Wikimedia Commons؛ قد تُغيّر أبعادها للعرض المتجاوب.
مخطط هندسي أصلي: ارصد دليل الاستلام واحفظه وحدّث سلة ثم اقرأ وطابق. الصورة للمصور Goterrestrial بترخيص CC BY 4.0 عبر Wikimedia Commons؛ قد تُغيّر أبعادها للعرض المتجاوب. اضغط لعرض أكبر

وحّد الوقت قبل الكتابة

توثق سلة الحقل كـString وتعرض مثالًا بشكل تاريخ ووقت. لا تنص الصفحة على وجود Timezone Offset داخل قيمة الطلب. لذلك احتفظ داخليًا بالقيمة الموثوقة كـtimestamptz أوUTC Instant مكافئ مع التمثيل الأصلي للمزود. نسّق القيمة المرسلة تمامًا كما يقبل عقد سلة الحالي ومتجر الاختبار الذي تحققت منه؛ لا تفترض تعاملًا غير موثق مع Offset.

طبّق هذه القواعد قبل Dispatch:

  • ألا يكون وقت الاستلام بعد وقت تسليم مؤكد؛
  • ألا يسبق إنشاء الشحنة بشكل غير منطقي؛
  • عزل قيمة مستقبلية تتجاوز هامش Clock Skew صغيرًا؛
  • تطابق هوية الناقل أوالمستودع مع Mapping الشحنة؛
  • عدم استبدال مصدر أعلى ثقة بمصدر أدنى دون مراجعة؛
  • بقاء المنطقة الزمنية الأصلية والقيمة الخام متاحتين للتحقيق.

تؤثر Daylight Saving والغموض المحلي مع النواقل العابرة للحدود. السعودية UTC+3 طوال العام، لكن نظام المزود الذي أصدر الحدث قد لا يكون كذلك. وحّد الوقت من Timezone المعلن للمصدر، لا من Timezone المتجر افتراضًا.

استخدم Update Command آمنة عند التكرار

أنشئ Command Record قبل PUT /shipments/{shipment_id}. يمكن أن يتكون Business Key من التاجر ومعرف شحنة سلة ونوع العملية ومعرف Pickup Observation المقبولة. تنتقل Command عبر pending وdispatching وobserved_succeeded وobserved_failed وoutcome_unknown.

Pickup Observation موثقة
  -> اشتق Shipment Projection
  -> أنشئ Update Command واحدة
  -> PUT مع status المطلوب + actual_picked_up_at
  -> اقرأ Shipment Details
  -> أغلق Command بعد تطابق مرصود فقط

حتى لو أعاد PUT نجاحًا موثقًا، احتفظ بـCommand وResponse Correlation. وإذا انقطع الاتصال بعد إرسال الطلب، فلا تنشئ عملية أعمال ثانية فورًا. اقرأ Shipment Details أولًا. أعد محاولة Command نفسها فقط عندما تثبت الحالة البعيدة أن القيمة المطلوبة لم تقبل، ويسمح عقد API بالتكرار.

يتطلب Endpoint قيمة status. لا تدع مزامنة Pickup Timestamp تخترع حالة الشحنة أوتعيدها للخلف. ابن Request من Shipment Projection حديثة ومصرح بها وانتقال مسموح. وإذا كان التكامل لا يملك الحالة، فحدد الملكية صراحة بدل نسخ قيمة قديمة من Cache.

افصل الاستلام عن التجهيز ووعد العميل

يجيب دليل الاستلام عن «متى انتقلت العهدة إلى الناقل؟». لكنه لا يثبت:

  • دخول الطرد أول Hub للناقل؛
  • توافر Tracking عامًا؛
  • الالتزام بموعد Checkout؛
  • تحصيل Cash on Delivery؛
  • اكتمال مطابقة المخزون أوالمحاسبة.

استخدم الوقت لقياس تسليم المستودع للناقل وبدء المؤقتات التشغيلية الصحيحة. مثال: أرسل تنبيهًا عندما تبقى الشحنة Ready دون Pickup Observation موثقة بعد سياسة التاجر. وبعد الاستلام استخدم Tracking وحالة الشحنة لمراقبة In Transit. لا ترسل «تم شحن طلبك» لمجرد إنشاء Label.

Reconciliation تكتشف الأحداث المفقودة

قد تتأخر Webhooks والمسحات أوتتكرر أوتغيب. شغّل Reconciliation محدودة تقارن:

  • Pickup Observations المحلية المقبولة؛
  • Commands المحلية والنتائج المجهولة؛
  • Shipment Details في سلة للشحنة المطابقة؛
  • دليل Tracking أوPickup لدى الناقل؛
  • Warehouse Dispatch Ledger.

صنّف الاختلاف بدل الكتابة فوقه:

الاختلافالتصرف الآمن
Pickup محلية وسلة بلا قيمةاقرأ ثم أعد Command نفسها إن كان ذلك آمنًا
سلة تحتوي Pickup والمحلي يفتقدهااستوردها كـExternal Observation وحقق في الملكية
القيمتان متطابقتانعلّمها Converged
القيمتان مختلفتاناعزلها لمراجعة الأولوية والدليل
Delivery موجود وPickup مفقودBackfill من دليل حقيقي فقط، ولا تصنع وقتًا

تؤثر Pagination وRate Limits وعدالة المستأجرين عند مطابقة متاجر كثيرة. أعط كل تاجر Budget محدودًا، واحفظ Checkpoint للتقدم، وقدّم Unknown Outcomes القديمة على الشحنات الحديثة السليمة.

Observability تفيد المشغل

اعرض Shipment ID وOrder Reference وCarrier Reference وSource Event ID وPickup Instant وSource Timezone وحالة Command وعدد المحاولات وآخر Read-back. راقب:

  • عمر Ready-to-pickup؛
  • تأخر Pickup الموثقة عن وقت جاهزية المستودع؛
  • تحديثات Pickup التي تنتظر Read-back؛
  • النتائج البعيدة المجهولة؛
  • تعارضات الوقت حسب المصدر؛
  • شحنات Delivered بلا Pickup Evidence؛
  • عمر Reconciliation Backlog.

لا تسجل أرقام هواتف العملاء أوالعناوين الكاملة أوBearer Tokens أوLabels أوPayloads الخام في Logs مفتوحة. اربط المشغل بدليل محمي بالصلاحيات.

أفضل الممارسات وAnti-patterns

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

  • التقط الاستلام عند حد العهدة الفعلي بين المستودع والناقل.
  • احتفظ بالحدث الأصلي وTimezone ونتيجة التحقق.
  • استخدم Durable Command واحدة لكل Pickup Observation مقبولة.
  • أرسل status من انتقال حديث تملكه الخدمة.
  • اقرأ الشحنة بعد الكتابات وبعد Unknown Outcomes.
  • طابق أدلة سلة والناقل والمستودع دوريًا.
  • سجل التصحيحات اليدوية مع Actor والسبب والقيمة السابقة.

Anti-patterns

  • وضع now() كوقت استلام عند تشغيل Sync Job.
  • اعتبار إنشاء Label أوموعد الاستلام عهدة فعلية.
  • جعل Webhook مكرر ينشئ Remote Mutation جديدة.
  • استبدال وقت ناقل موثوق بوقت يدوي أحدث.
  • إعادة PUT انتهت مهلته بشكل أعمى.
  • افتراض أن كل Datetime String تحمل Offset دون نص في العقد.
  • استخدام Pickup كدليل تسليم أوSettlement أوإكمال مخزون.

خلاصة التنفيذ

  1. أضف نوع Pickup Observation ثابتًا وسياسة أولوية للمصادر.
  2. وحّد وقت المزود إلى UTC مع الاحتفاظ بالقيمة الخام والمنطقة الزمنية.
  3. تحقق من Mapping الشحنة وTemporal Invariants.
  4. أنشئ Salla Update Command آمنة عند التكرار.
  5. أرسل actual_picked_up_at مع status المطلوب تحت shipping.read_write.
  6. اقرأ Shipment Details ولا تغلق إلا بعد تطابق مرصود.
  7. طابق النتائج المفقودة والمتعارضة والمجهولة.
  8. راقب Handoff Lag دون كشف بيانات العميل أوالاعتماد.

اقرأ أيضًا: State Machine قابلة للتعافي لشحنات سلة، ووعود توصيل سلة الموثوقة، واستعادة Webhooks في سلة وزد، ومركز هندسة التجارة الإلكترونية.

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

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

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

إعداد: Noor Yasser

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

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

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

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