Middleware متعدد الفروع والأجهزة — التحليل المعماري

المركز فيه فروع كتير، وكل محطة عليها نسخة من الـmiddleware. الكلود فيه كل الأجهزة، وكل محطة تفعّل اللي متوصّل عندها بس. ده التحليل الكامل للموديل قبل التنفيذ.

1 الصورة الكاملة (Topology)

┌─────────────────────────────┐ │ Moon ERP (السحابة) │ │ سجل واحد لكل الأجهزة │ │ ┌─────────────────────┐ │ │ │ DH36-A (id 3) │ │ │ │ DH36-B (id 7) │ │ ← كل الأجهزة (كل الفروع) │ │ Maglumi (id 2) │ │ code فريد لكل واحد │ │ CBC-Lab2 (id 9) ... │ │ │ └─────────────────────┘ │ └───────┬───────────┬─────────┘ مزامنة (كل الأجهزة)│ │(كل الأجهزة) ┌────────────────────┘ └────────────────────┐ ┌────────▼─────────┐ ┌─────────────▼────────┐ │ فرع 1 — محطة A │ │ فرع 2 — محطة B │ │ Middleware #1 │ │ Middleware #2 │ │ يشوف الكل، يفعّل: │ │ يشوف الكل، يفعّل: │ │ ✅ DH36-A :5600 │ │ ✅ CBC-Lab2 :5600 │ │ ⬜ DH36-B │ │ ✅ DH36-B :5601 │ │ ⬜ Maglumi ... │ │ ⬜ الباقي ... │ └────────┬─────────┘ └──────────┬───────────┘ │ TCP/HL7 │ TCP/HL7 ┌─────▼─────┐ ┌─────▼─────┐ │ جهاز DH36-A│ │ جهازين │ └───────────┘ └───────────┘

القاعدة الأساسية

الكلود = سجل واحد لكل الأجهزة (كل الفروع). كل محطة middleware بتسحب القائمة كاملة، لكن بتفعّل محلياً الجهاز/الاتنين المتوصّلين عندها فقط. قرار «التفعيل» قرار محلي لكل محطة — مش في الكلود.

2 الهوية الفريدة لكل جهاز

ممكن يكون في أكتر من جهاز من نفس الموديل (٢ × DH36)، وفرع واحد فيه أكتر من جهاز. فلازم كل جهاز يتميّز بهوية فريدة:

الحقلالدورالحالة
id (machine_id)المعرّف الرقمي الفريد — يتبعت مع كل نتيجةموجود
codeكود فريد للجهاز (UNIQUE في DB) — مثلاً DH36-A، DH36-Bموجود + UNIQUE
nameاسم مقروء يميّز الجهاز للمستخدمموجود
branch_idالفرع التابع له الجهازغير موجود — يُضاف

توصية: نضيف branch_id للأجهزة

دلوقتي الأجهزة مربوطة بالشركة بس (company_id) من غير فرع. عشان تعرف كل جهاز في أي فرع (وتفلتر المزامنة لاحقاً)، نضيف branch_id على الجهاز في الكلود. مش شرط للـMVP لكنه الأنضف للتوسّع.

3 منطق التفعيل: «محلي» مش «تلقائي»

⚠️ تصحيح للمنطق اللي بنيته أول

النسخة الأولى من المزامنة كانت بتفعّل أي جهاز active — ده غلط هنا، لأن كل الأجهزة active في الكلود، فكل محطة كانت هتحاول تفعّل الكل → تعارض بورتات + استقبال غلط.

المنطق الصحيح

4 إدارة البورتات

كل جهاز مُفعّل على محطة لازم يكون له بورت فريد على المحطة دي. بما إن المحطة بتفعّل ١–٢ بس، التفرّد مطلوب بين المُفعّلين عندها فقط.

5 هوية المحطة (Workstation)

عشان نعرف أي محطة شغّالة وأي أجهزة عليها، كل نسخة middleware ليها اسم محطة:

6 تدفق المزامنة (المصحّح)

#الخطوة
1المحطة تنادي GET /lis/machines → كل أجهزة الشركة.
2تفلتر: interface ∈ {tcp, hl7} + connection_settings.port موجود.
3لكل جهاز (بالـmachine_id): تحدّث الاسم/البورت/الدرايفر من الكلود، وتحافظ على enabled المحلي.
4الأجهزة الجديدة → enabled = false (المستخدم يفعّلها).
5تحفظ config.json وتعيد تشغيل المستمعين للأجهزة المُفعّلة فقط.
6الواجهة تعرض: كل الأجهزة (الكل)، مع توجل تفعيل + الحالة الحية لكل واحد.

7 اللي اتعمل واللي ناقص

العنصرالحالة
تثبيت Python على المحطة + الـmiddleware شغّالتم
واجهة ويب (config + حالة حية + log)تم
اتصال الكلود (login admin@moonerp.com) + رفع النتائجتم ومُختبر
سحب الأجهزة من الكلود (sync) + connection_settingsمبني — يحتاج تصحيح التفعيل
تفعيل محلي (preserve enabled، جديد=OFF)يُعدّل
اسم المحطة + إرساله في heartbeatيُضاف
كشف تعارض البورت في الواجهةيُحسّن
branch_id على الجهاز (كلود + فورم LIS Machines)قرار

8 قرارات محتاجينها

  1. التفعيل التلقائي: نكتفي بالتفعيل اليدوي على كل محطة (MVP بسيط)، ولا نضيف workstation_key على الجهاز في الكلود عشان كل محطة تفعّل أجهزتها أوتوماتيك؟
  2. الفروع: نضيف branch_id للأجهزة دلوقتي (وفورم LIS Machines يبقى فيه اختيار الفرع)، ولا نأجّله؟
  3. فورم الأجهزة في الكلود: نظبّط فورم LIS Machines يبقى فيه حقول الربط (port / driver / barcode fields) بشكل واضح بدل JSON خام في connection_settings؟
  4. الدرايفرات: دلوقتي عندنا dymind_hl7 بس. الأجهزة التانية (Maglumi…) محتاجة درايفرات — نبنيها دلوقتي ولا نركّز على الـCBC أول؟