1 اللي طلبته (تأكيد الفهم)
- كل عملية تتسجل على فرع اليوزر الافتراضي (الفرع الأساسي بتاعه).
- إعداد في الإعدادات يُظهر الفرع في كل الشاشات (الريكوست، إلخ)، واليوزر يقدر يفلتر بالفرع.
- افتراضيًا كل يوزر يشوف فرعه بس — الأدمن يشوف كل حاجة.
- الفرع الرئيسي (المركزي) عنده كل الأجهزة؛ الفروع تعمل تحاليل محدودة (مثلاً البراز/CBC بس)، وباقي التحاليل تتحوّل للفرع المركزي اللي يحللها وترجع النتيجة.
- كل ده يتعمل من جوّه موديول المعمل — من غير الدخول للموديول الرئيسي.
2 المعامل الكبرى بتعمل ايه؟ (Hub & Spoke — نموذج المعمل المرجعي)
ده بالظبط اللي إنت بتوصفه — المعيار العالمي للسلاسل والمعامل متعددة الفروع:
🏪 الفرع (Spoke)
تجميع + تحاليل بسيطة→ يحوّل ←
🏛️ المركزي (Hub)
كل التحاليل المعقّدة→ النتيجة ترجع ←
🏪 الفرع يشوف النتيجة + يطبع
| المبدأ | إزاي بيشتغل في المعامل الكبرى |
| الفرع = موقع تجميع + منيو محدود | يسجّل المريض، يجمع العينة، يحلل منيو صغير محليًا (CBC, بول, براز, سكر) بأجهزة صغيرة. |
| المركزي = المعمل المرجعي | يحلل المنيو الكامل (كيمياء، هرمونات، باثولوجي…) لكل الفروع. |
| توجيه العينات (Routing) | التحاليل اللي الفرع ما يقدرش يعملها تتحوّل للمركزي مع مانيفست/سلسلة عهدة وتتبّع الحالة (بالفرع → في الطريق → وصل المركزي → اتحلّل). |
| مستودع نتائج مركزي | النتيجة تظهر في الفرع الأصلي ومركزيًا. التقرير يوضّح فرع السحب + الفرع المُنفّذ (مطلوب اعتماديًا). |
| وورك-ليست لكل فرع | كل فرع يشوف شغله المعلّق؛ المركزي يشوف الطابور المجمّع. |
| تشغيل لكل فرع | مخزون/كواشف، خزنة/كاش، QC، وصلاحيات لكل فرع على حدة. |
الخلاصة: رؤيتك مطابقة 100% لنموذج Hub & Spoke. وعندنا بالفعل بنية الـ الإحالات (Referrals) اللي نقدر نوسّعها لتكون إحالة داخلية للفرع المركزي بدل معمل خارجي.
3 اللي موجود فعلًا في النظام (الأساس)
| العنصر | الحالة | التفاصيل |
| موديل الفرع | موجود | is_main (الفرع المركزي)، is_active. لكنه مسطّح (مفيش parent/هرمية). |
| ربط اليوزر بالفروع | موجود | Many-to-many branch_user + is_primary → user->primaryBranch(). |
| branch_id على الكيانات | جزئي | موجود على: الريكوست، العينة (بتتختم تلقائي ✓)، الزيارة، الفاتورة. ناقص: المدفوعات، النتيجة. |
| الأدمن = يشوف الكل | موجود (FE) | سوبر أدمن = أدوار وصلاحيات فاضية. permissionService.isSuperAdmin(). |
| نمط فلتر الفرع (FE) | موجود | BranchContextService + نمط مجرّب في الخزن/الأصول (dropdown مفلتر بفروع اليوزر). |
| نمط الإعدادات | موجود | صفحة «إعدادات المعمل» التبويبية — نضيف تبويب/سويتش بسهولة. |
4 الفجوات (الناقص)
1) مفيش فلترة تلقائية بالفرع: كل اليوزرز بيشوفوا كل الفروع (الفلترة بالشركة بس). مفيش «اليوزر يشوف فرعه».
2) branch_id مش بيتختم في كل مكان: الريكوست/المدفوعات/النتيجة مش بتتختم بفرع اليوزر تلقائيًا (العينة بس).
3) مفيش منيو فرع (قدرات): مفيش تعريف «الفرع ده يعمل أنهي تحاليل». مفيش ربط جهاز↔فرع ولا تحليل↔فرع.
4) مفيش توجيه داخلي بين الفروع: الإحالات الموجودة للمعامل الخارجية بس — مفيش «حوّل للفرع المركزي» داخليًا.
5) مفيش فلتر فرع في شاشات المعمل ولا selector في الهيدر، ومفيش صلاحية «شوف كل الفروع».
5 التصميم المقترح — ركيزتان، كله جوّه المعمل
الركيزة (أ): نطاق ورؤية الفروع — Branch Scoping
- ختم تلقائي: أي عملية جديدة (ريكوست، عينة، مدفوعة، نتيجة) تتختم بفرع اليوزر الأساسي. (نضيف
branch_id للمدفوعات والنتيجة.)
- الرؤية الافتراضية: اليوزر العادي يشوف فرعه بس (مفروض من السيرفر — مايقدرش يشوف غيره). الأدمن (أو صلاحية
lis.view-all-branches) يشوف الكل + يقدر يفلتر.
- فلتر فرع في كل شاشة: selector في هيدر المعمل + باراميتر
?branch_id= على كل قوائم الـ LIS (الريكوست، العينات، الكانبان، النتائج، المدفوعات، الفواتير).
- سويتش «إظهار الفروع»: في إعدادات المعمل (يتفعّل تلقائي لو الشركة فيها أكتر من فرع) — فالمعمل بفرع واحد ما يشوفش أي تعقيد.
الركيزة (ب): منيو الفرع + التوجيه الداخلي — Hub & Spoke
- المركزي (
is_main) يعمل كل حاجة افتراضيًا.
- منيو الفرع (قدرات): لكل فرع فرعي قائمة بالتحاليل اللي يعملها محليًا (مثلاً: براز + بول). يُدار من جوّه المعمل (شاشة «فروع المعمل / منيو الفرع»).
- عند التجميع في فرع: التحاليل اللي ضمن منيو الفرع → تفضل في وورك-ليست الفرع. التحاليل اللي مش ضمنه → تتحوّل تلقائيًا «إحالة داخلية» للفرع المركزي (نفس آلية الإحالة الخارجية لكن داخل الشركة، من غير فاتورة خارجية).
- الحالة والتتبّع: بالفرع → في الطريق → وصل المركزي → اتحلّل → النتيجة رجعت. الفرع الأصلي يشوف النتيجة ويطبعها. التقرير يوضّح فرع السحب + الفرع المُنفّذ.
Order @ Branch "Maadi" → tests: [Stool, CBC, TSH]
Stool → in Maadi worklist (branch can do it)
CBC → INTERNAL REFERRAL → Hub (not in Maadi menu)
TSH → INTERNAL REFERRAL → Hub
─────────────────────────────────────────────
Hub resolves CBC, TSH → results flow back to Maadi
Report: Collected at Maadi · Performed at Central Lab
فين بيتعمل ده؟ (كله جوّه المعمل)
- منيو الفرع + سويتش الفروع: شاشة/تبويب جديد جوّه المعمل («فروع المعمل»).
- فلتر الفرع: selector في هيدر واجهة المعمل + على كل قائمة.
- التوجيه الداخلي: يعيد استخدام آلية الإحالة + الكانبان الموجودة.
- تعيين اليوزرز للفروع أصله في الموديول الرئيسي — هنوفّر اختصار/عرض جوّه المعمل، لكن البيانات نفسها مشتركة فمفيش ازدواج.
6 الصلاحيات ومجموعات الموظفين — من جوّه المعمل
إنت عايز تظبط صلاحيات المعمل من جوّه المعمل: تعمل مجموعات موظفين (أدوار) كل واحدة بخواصها، وكل زرّ/فنكشن في كل شاشة بصلاحية، وكل دور له نطاق بيانات وصفحة رئيسية.
الأدوار اللي إنت ذكرتها
الاستقبال (Reception)
فني التجميع (Collector)
الكيميائي / منفّذ التحليل
فني المعمل
مدير المعمل
كل فنكشن في كل شاشة = صلاحية (مصفوفة الصلاحيات)
| الشاشة | الفنكشنات (كل واحدة صلاحية مستقلة) |
| الطلبات (Requests) | عرض · إضافة · تعديل · حذف · طباعة · إلغاء |
| التجميع (Collection) | تجميع · طباعة باركود · تأجيل |
| الاستلام (Receiving) | استلام · رفض |
| الورك-ليست (Worklist) | إدخال نتيجة · ري-رن · طباعة |
| الفاليديشن (Validation) | اعتماد (Validate) · إطلاق (Release) · طباعة |
| عام | كل شاشة view مستقل + الأزرار محكومة بالصلاحية (تختفي/تتعطّل لو ملوش صلاحية) |
نطاق البيانات لكل دور (Data Scope) — مرتبط بالفروع 👇
ده بالظبط نفس محور الفروع —
نطاق واحد موحّد لكل دور:
| النطاق | يشوف ايه |
own — بياناته بس | اللي هو أنشأه فقط (مثلاً ريسبشن يشوف طلباته هو). |
branch — بيانات الفرع | كل بيانات اليوزرز جوّه فرعه. |
all — كل الفروع | المدير/الأدمن — كل حاجة + فلتر بالفرع. |
يعني سؤالك «يتحكم في بياناته هو بس ولا كل بيانات الفرع» = خاصية
data_scope على الدور، وهي نفسها اللي بتحدد رؤية الفروع.
صفحة رئيسية لكل دور (Home Page)
كل دور يختار صفحته الرئيسية من الشاشات الموجودة — أول ما اليوزر يفتح يروح عليها. مثلاً فني التجميع → صفحة «التجميع» تفتح أول.
اللي موجود مقابل الناقص
| العنصر | الحالة | التفاصيل |
| أدوار وصلاحيات (Spatie) | موجود | نظام أدوar/صلاحيات كامل + شاشة Roles في الموديول الرئيسي. |
| صلاحيات LIS | موجود (139) | 139 صلاحية lis.* متفصّلة (طلبات، عينات، نتائج، كانبان…). معظم فنكشناتك موجودة (collect/receive/reject/enter/validate/release). |
| شاشة أدوار جوّه المعمل | ناقص | محتاجين نسخة LIS-only تعرض صلاحيات lis.* بس، مجمّعة حسب الشاشة. |
| نطاق البيانات (own/branch/all) | ناقص | مفهوم جديد على الدور — data_scope (موحّد مع الفروع). |
| صفحة رئيسية للدور | ناقص | حقل home_page جديد على الدور + توجيه عند الدخول. |
| بعض الفنكشنات الدقيقة | جزئي | زي طباعة/تأجيل/ري-رن/طباعة-باركود — نضيف اللي ناقص لإكمال المصفوفة. |
ليه مع الفروع؟ النطاق (own/branch/all) هو نفسه محور رؤية الفروع — فالأدوار والفروع بيشتركوا في نفس الآلية: الدور بيحدد الصلاحيات + النطاق، والفرع بيحدد الـ branch_id. عشان كده بنعملهم مع بعض.
7 خطة على مراحل
المرحلة 1 — النطاق + الصلاحيات (تسلّم الرؤية بالفرع + أدوار المعمل):
- ختم
branch_id في كل العمليات + إضافته للمدفوعات/النتيجة.
data_scope على الدور (own/branch/all) + فلترة سيرفر.
- شاشة أدوار المعمل (مصفوفة صلاحيات
lis.* حسب الشاشة) + home_page.
- الأزرار في كل شاشة محكومة بالصلاحية (تختفي/تتعطّل) + selector الفرع.
المرحلة 2 — Hub & Spoke (براز هنا، CBC للمركزي):
- منيو الفرع (قدرات التحاليل لكل فرع).
- زر «حوّل للمركزي» (يدوي) + رجوع النتيجة.
- تقرير «سُحب في / نُفّذ في».
8 القرارات المؤكَّدة ✓
| القرار | المؤكَّد |
| رؤية الفروع | قابلة للتحكم لكل دور عبر data_scope (own / branch / all) — مش binary صارم. الأدمن: all. |
| منيو الفرع | منيو لكل فرع — كل فرع يختار تحاليله؛ المركزي يعمل الكل افتراضيًا. |
| التوجيه الداخلي | يدوي — زر «حوّل للمركزي» (مش تلقائي). |
| إظهار الفروع | تلقائي حسب عدد الفروع + إمكانية override. |
| الصلاحيات | شاشة أدوار جوّه المعمل، مصفوفة lis.* حسب الشاشة/الفنكشن، + data_scope + home_page لكل دور. |