إجابة مختصرة: كيف يُمنع التسجيل المزدوج؟
امنح كل عمل فحص هوية مصدر ثابتة؛ وشغّل النقل إلى ERP بهذه الهوية بصورة idempotent، وفرض التفرد في قاعدة البيانات، ولا تربط بالمحاسبة إلا المستند الهدف المتحقق منه.
لا يكفي أن يعمل التكامل في المسار الطبيعي فقط. فعند ضياع استجابة الشبكة، أو تكرار رسالة قائمة الانتظار، أو أخذ عاملَي معالجة العمل نفسه، يجب أن تبقى النتيجة عميلًا واحدًا وطلبًا واحدًا وارتباط فوترة واحدًا.
لماذا ينشأ التسجيل المزدوج؟
إجابة مختصرة: معظم حالات الازدواج لا تنشأ لأن المستخدم ضغط الزر مرتين؛ بل بسبب إعادة محاولة غير مضبوطة في اللحظة الغامضة التي نجح فيها الطلب الأول وضاعت استجابته.
يرسل نظام الفحص إلى ERP طلب فتح طلب شراء. فينشئ ERP السجل، لكن الاتصال ينقطع ولا تصل استجابة التكامل. فإذا أرسل عامل المعالجة الطلب نفسه مجددًا كعملية جديدة، فقد يُفتح طلب ثانٍ. ويظهر الخطر نفسه في نمط التسليم مرة واحدة على الأقل في قوائم الانتظار، وتوازي عوامل المعالجة، والإعادة اليدوية بعد انتهاء المهلة، والمزامنة الدفعية.
يعرّف المعيار IETF RFC 9110 العملية الـ idempotent بأنها العملية التي يكون لتطبيق الطلب نفسه عدة مرات فيها الأثر المقصود نفسه كتطبيقه مرة واحدة. وينطبق ذلك على PUT؛ أما إنشاء مورد جديد عبر POST فيحتاج حماية إضافية. ويجب ألا يفترض التصميم التقني أن الشبكة تسلّم مرة واحدة بالضبط.

أي هوية ينبغي أن تكون مالكة السجل؟
عمل الفحص، وطلب ERP، والقيد المحاسبي، والمستند الإلكتروني ليست الهوية نفسها. ففي بداية السلسلة يجب وجود UUID لعمل المصدر ثابت؛ وتُخزَّن الهويات التي تولّدها الأنظمة الأخرى في حقول منفصلة بوصفها مقابلات له.
| الهوية | المالك | متى تنشأ؟ | الاستخدام |
|---|---|---|---|
| UUID لعمل المصدر | نظام الفحص | عند فتح العمل أول مرة | المفتاح الثابت للعمل لجميع عمليات النقل وإعادة المحاولة |
| UUID للحدث | نظام الفحص | عند نشوء الإصدار الجاهز للفوترة | رسالة قائمة الانتظار وفحص الحدث المعالَج |
| معرف العميل/الطلب في ERP | ERP | عند قبول السجل الهدف | التحديثات اللاحقة والاستعلام عن الحالة |
| معرف المستند المحاسبي | النظام المحاسبي | عند نشوء مسودة/سجل المستند | دورة الحياة المالية |
| UUID/رقم المستند الإلكتروني | عملية المستندات الإلكترونية | عند تحرير المستند | الهوية التقنية للمستند نفسه |
يحدد معيار OASIS UBL 2.4 Invoice حقول مرجعية بين الفاتورة والطلب والمستندات الأخرى. كما يشير دليل GİB لبوابة e-Fatura إلى أن الفواتير ذات UUID ورقم الفاتورة نفسيهما لا يمكن تحميلها مرة أخرى. والنتيجة التطبيقية المستخلصة ليست استبدال هوية الفحص المصدر برقم المستند الإلكتروني؛ بل الاحتفاظ بالهويات منفصلة في جدول ربط ثنائي الاتجاه.
كيف ينبغي توليد مفتاح الـ idempotency؟
يجب ألا يعاد توليد المفتاح عشوائيًا مع كل إعادة محاولة؛ بل يبقى نفسه في جميع محاولات الأثر التجاري نفسه. ويمكن اشتقاق نطاق مثال من التوليف القانوني للأجزاء التالية:
tenant + hedef_sistem + işlem_türü + kaynak_iş_uuid + kaynak_sürümü
إصدار المصدر مهم. فإعادة إرسال إصدار التقرير نفسه يجب أن تعيد النتيجة القائمة؛ وإذا كانت المراجعة المخوَّلة ستُنشئ أثرًا تجاريًا جديدًا فينبغي أن تكون حدثًا منفصلًا بقاعدة عمل معلنة. ويجب أن يحتفظ سجل الـ idempotency، إلى جانب المفتاح، بملخص الحمولة (payload)، ووقت الظهور الأول، والحالة، وهوية الاستجابة الهدف.
توثق مراجع Stripe الحالية لواجهة برمجة التطبيقات إمكانية إعادة طلب الإنشاء/التحديث بأمان بعد فشل الاتصال باستخدام مفتاح idempotency نفسه، ورفض الطلب إذا تغيرت المعاملات مع بقاء المفتاح نفسه. وهذا السلوك الخاص بمزوّد الخدمة مثال تعاقدي مفيد أيضًا لمحوّل ERP الداخلي: إذا جاء المفتاح نفسه مع عميل أو مبلغ أو مطابقة ضريبية مختلفة فلا تكتب فوقه بصمت؛ بل أدر التعارض للفحص.
لماذا لا يكفي الضبط على مستوى التطبيق وحده؟
في نهج «استعلام أولًا عن الوجود ثم أضف إن لم يوجد» قد يرى عاملا معالجة معًا نتيجة عدم الوجود. لذا يجب فرض التفرد في قاعدة البيانات أيضًا.
في جدول ربط التكامل tenant_id + target_system + document_type + source_job_uuid أنشئ قيدًا فريدًا مركبًا. وتوثق مستندات PostgreSQL الحالية لأمر INSERT أن مع القيد الفريد ON CONFLICT يشرح أن الاستخدام في ظل التزامن (race condition) يمكن أن يحقق نتيجة insert/update ذرّية. إذا كانت قاعدة العمل لا تسمح بالتحديث، فأعِد المعرّف الهدف الحالي عند التعارض؛ وإذا كانت البيانات مختلفة فافتح سجل فحص بالوضع الآمن المُغلق (fail-closed).
UNIQUE (tenant_id, target_system, document_type, source_job_uuid)
aynı anahtar + aynı payload özeti -> mevcut sonucu döndür
aynı anahtar + farklı payload -> çakışma, otomatik belge açmaكيف يجب إعداد تدفق الـOutbox وقائمة الانتظار؟
اعتبار تقرير الفحص «جاهزًا للفوترة» وكتابة رسالة الـERP كلٌّ على حدة قد يولّد حالة ناقصة. يجب اعتماد حالة العمل وحدث التكامل ضمن المعاملة المحلية (transaction) نفسها.
- يُقرّ المستخدم المخوّل إصدار التقرير ونطاق الفوترة.
- يحدّث التطبيق حالة العمل ويضيف صفًّا في الـOutbox بمعرّف الحدث (UUID) ضمن المعاملة نفسها.
- يرسل الـWorker حدث الـOutbox إلى المحوّل الهدف باستخدام مفتاح idempotency ثابت.
- عند الاستجابة الناجحة يُحفظ المعرّف الهدف في الـERP وملخص الاستجابة في جدول الربط.
- إذا فُقد إشعار ACK يصل الحدث نفسه مجددًا؛ فيرى المستهلك معرّف الحدث (UUID) ورابط العمل ويعيد النتيجة الحالية.
- لا تُدرَج أخطاء البيانات الدائمة في حلقة إعادة المحاولة؛ بل تُحوَّل إلى قائمة الفحص/الرسائل الميتة (dead-letter).
توصي أدلة Microsoft الخاصة بنمط Transactional Outbox بتخزين كائن العمل والحدث في المعاملة نفسها؛ بينما يوصي دليل Service Bus بأن يكون المستهلك idempotent بالاعتماد على MessageId أو الهوية التجارية بسبب فقدان ACK وإعادة التسليم. إنّ اكتشاف التكرار لدى المرسل لا يغني عن فحص التفرد لدى المستقبل.
كيف تُنفَّذ مطابقة العملاء والخدمات والضرائب بأمان؟
تجنّب السجلات المزدوجة ليس مشكلة تقنية تخص إعادة المحاولة فحسب. ففتح العميل نفسه مرة أخرى بصيغة عنوان مختلفة أو فوترة الخدمة نفسها برمز مختلف يولّد أيضًا تضاعفًا تشغيليًا.
- العميل: طابِق عبر VKN/TCKN مُتحقَّق منه ضمن نطاق المستأجر (tenant) أو عبر المفتاح الرئيس للمؤسسة؛ ولا تجعل العنوان وحده مفتاحًا.
- الخدمة: اربط طريقة الفحص بجدول رموز المخزون/الخدمات المعتمد في الـERP؛ ولا تفتح الرموز غير المتطابقة تلقائيًا كنص حر.
- الضريبة والعملة: طبّق مطابقة خاضعة لإدارة الإصدارات على قائمة الرموز في النظام الهدف؛ وأوقف إنتاج المستند عند المطابقة الناقصة أو غير الصالحة.
- المبلغ: ثبّت البنود المحسوبة والخصومات والضريبة مع ملخص الإصدار المصدر؛ وأدخِل أي تغيير بعد الموافقة في مسار مراجعة جديدة.
- الصلاحيات: أدر أدوار إنشاء العملاء وتغيير المطابقة وإنتاج المستندات المالية بآثار تدقيق منفصلة لكل منها.
يجب ألا تختار المطابقة الغامضة «أقرب نتيجة». ينبغي أن ينتظر النقل حتى يكتمل الفحص البشري؛ وأن يُسجَّل للقرار المُتخذ مَن اتخذه ووقته والقيمة السابقة/الجديدة ومبرره.
كيف تُتابَع حالة النقل؟
إنّ حقلًا واحدًا «ناجح/فاشل» يخفي الغموض. يجب أن تُظهر آلة الحالة أي خطوة قابلة للتكرار.
| الحالة | المعنى | العملية المسموح بها |
|---|---|---|
| قيد التحضير | جارٍ التحقق من المطابقة والحمولة (payload) | تصحيح النواقص |
| جاهز للإرسال | الهوية والإصدار وملخص الحمولة مثبّتة | الإدخال في الـOutbox |
| غير محسوم | انقضت المهلة، وقد توجد نتيجة لدى الهدف | الاستعلام/إعادة المحاولة بالمفتاح نفسه |
| تم النقل | حُفظ المعرّف الهدف وإثبات الاستجابة | استعلام الحالة، وعدم إنشاء نسخة |
| يلزم فحص | تعارض مفاتيح أو خطأ في مطابقة البيانات | انتظار قرار المستخدم المخوّل |
| بانتظار الإلغاء/القيد العكسي | يلزم تصحيح مالي | معالجة منفصلة وفق قاعدة النظام الهدف |
حذف سجل النقل الناجح وإعادة إرساله ليس أسلوب تصحيح. فإذا تكوّن مستند مالي، فيجب تنفيذ الإلغاء أو الاسترداد أو القيد العكسي بهويته ومسار موافقته الخاص.
ما الفحوصات التي يجب أن يجريها التسوية (Mutabakat)؟
ينبغي أن تقارن التسوية اليومية سجلات المصدر والهدف على مستوى الهوية، لا أن تكتفي بعدّ سجل الأخطاء.
- الأعمال الجاهزة للفوترة التي لا ارتباط لها في النظام الهدف.
- أكثر من مستند هدف مرتبط بمعرّف العمل المصدر نفسه (UUID).
- المستندات الموجودة في الهدف دون مقابل لها في جدول الربط المصدر.
- السجلات التي لا يتطابق فيها ملخص الحمولة المُرسلة مع إصدار المصدر.
- المحاولات الباقية في حالة غير محسومة مدةً أطول من المهلة المحددة.
- نواقص الموافقة/الإثبات في المطابقات اليدوية والإلغاءات والقيود العكسية.
يجب ألا تُجري نتيجة التسوية حذفًا تلقائيًا أو دمجًا جماعيًا. بل تعرض على المستخدم المخوّل السجلات المشبوهة بهويتها في النظامين والإجراء الآمن المقترح.
كيف يُجَرَّب تكامل VizyonTech تجريبيًا؟
Vizyon Periyodik في الانتقال من مسارات الفحص مثل هذه إلى الـERP، جرّب سيناريوهات الفشل قبل السيناريو الطبيعي. يجب اختبار النقر المزدوج على العمل نفسه، وإنشاء الـERP للسجل دون إرسال استجابة، ووصول رسالة قائمة الانتظار نفسها إلى worker اثنين، والمفتاح نفسه بحمولة مختلفة، ومطابقة عميل غير صالحة، ومراجعة التقرير.
ليس معيار نجاح التجربة أن «التكامل اشتغل». بل يجب إثبات عدد السجلات المتكوّنة لدى الهدف في كل سيناريو، ومدى إنشاء رابط المصدر-الهدف، وأن إعادة المحاولة تعيد النتيجة نفسها، وأن الغموض يبقى ظاهرًا، وأن العملية المالية غير المصرّح بها ممنوعة. وللحفاظ على سلسلة القرار في تقرير الفحص دليل سير عمل التوقيع الإلكتروني يمكن أيضًا تقييمه معًا.
المراجع
- IETF — RFC 9110، دلالات HTTP: الأساليب متطابقة الأثر عند التكرار (يونيو 2022؛ اطلاع بتاريخ 21 يوليو 2026).
- Stripe — الطلبات متطابقة الأثر عند التكرار، مرجع API (وثائق إلكترونية محدّثة؛ اطلاع بتاريخ 21 يوليو 2026).
- Microsoft Learn — منع فقدان الرسائل والمعالجة المكررة في Azure Service Bus (تحديث 29 يونيو 2026).
- Microsoft Learn — تطبيق نمط صندوق الصادر للمعاملات (2026؛ اطلاع بتاريخ 21 يوليو 2026).
- PostgreSQL — INSERT وON CONFLICT، الوثائق المحدّثة (اطلاع بتاريخ 21 يوليو 2026).
- OASIS — ملخص نموذج الفاتورة UBL 2.4 (2024).
- رئاسة إدارة الإيرادات — دليل استخدام بوابة e-Fatura الإصدار 1.5 (نوفمبر 2013؛ لمعرّف تقني وقاعدة إعادة التحميل، اطلاع بتاريخ 21 يوليو 2026).
يجب أيضًا التحقق من قواعد الرموز والحقول في الـERP والمحاسبة والـe-Belge عبر الوثائق التقنية المحدّثة للمزوّد المستخدم وعبر العمليات المالية للمؤسسة.