شاشة الصلاحيات: إعادة التصميم + خريطة «كل صلاحية بتتنفّذ فين في الواجهة»
دراسة المرحلة الأولى (بحث فقط — بدون أي كود) · شاشة /core/roles · Moon ERP / moonui2
🎨 إعادة تصميم UX (Fable)🗺️ خريطة تطبيق 996 صلاحيةℹ️ وصف لكل صلاحية⚙️ قاعدة: setting + صلاحيتهالتاريخ: 2026-07-13
١. المشكلة
شاشة الصلاحيات الحالية /core/roles فيها ثلاث مشاكل مترابطة طلب المالك معالجتها كلها كدراسة قبل أي كود:
أ
الشكل والمسمّيات لا تعبّر عن الصلاحية. ~1000 صلاحية تظهر كقائمة مسطّحة (مربع اختيار لكل صلاحية) داخل نافذة 800px، والاسم مركّب آليًّا («الفواتير - اعتماد») بدون أي شرح لما بتعمله الصلاحية فعلًا. المطلوب: تصميم احترافي سريع سهل الاستخدام، وكل صلاحية ليها «info» توضّح وظيفتها.
ب
«صلاحية موجودة لازم تتنفّذ في الواجهة» — وده غير متحقّق. المالك محتاج يعرف كل صلاحية مكانها فين في الـUI (أي زر/شاشة/حركة بتتحكم فيها)، عشان يضمن إنها مطبَّقة في كل مكان — لأن في صلاحيات ممنوحة لكن مالهاش أثر ظاهر في الواجهة.
ج
قاعدة الإعدادات. لما نعدّل أو نضيف أي setting، لازم نفتكر نضيف الـsetting وصلاحيته معه (كل إعداد جديد ياخد صلاحيته الخاصة).
يجلب الكتالوج من GET /core/permissions ويعرضه مجمّعًا بالموديول داخل accordions، مربع اختيار واحد لكل صلاحية (roles.component.html:202-230)، داخل نافذة عرضها 800px.
الاسم يُركّب آليًّا في translatePermission() (roles.component.ts:547-571): ROLES.RESOURCES.<seg> + « - » + ROLES.ACTIONS.<action>. لو الجزء مش مترجَم، يسقط للمفتاح الإنجليزي الخام.
«تحديد الكل» على مستوى الموديول فقط (toggleModuleAll(), ts:350) — مفيش «تحديد المورد كله».
i18n فيه ROLES.RESOURCES (252 عنصر) وROLES.ACTIONS (119) — لكن مفيش أي ROLES.DESCRIPTIONS. مفيش مكان يقول «الصلاحية دي بتعمل إيه».
٢.٢ كيف تُطبَّق الصلاحية في الواجهة (3 طبقات)
كل الطبقات تمرّ عبر permissionMatches(owned, required) (permission.service.ts:18-22) — منطق «حدّ النقطة»:
قاعدة المطابقة الحاسمة: المطابقة إما تطابق تام، أو بادئة تنتهي بنقطة. يعني بوابة sales.invoices تغطّي sales.invoices.delete (بادئة). لكن hrm.trainingلا تطابق hrm.training-programs.view (الحرف بعد training شرطة «-» مش نقطة). الـBE يُطبّق منفصلًا عبر Spatie permission:<الاسم-الدقيق> — تطابق دقيق بلا بوادئ. السوبر-أدمن يتخطّى كل الفحوص (service:113).
٢.٣ النتيجة الكمية — خريطة التغطية (996 صلاحية)
استخرجنا كل سلاسل الكتالوج من RolePermissionSeeder::permissions() (سطور 293–1480) وكل بوابات الواجهة (585 سلسلة: 398 *appCan + 197 بوابة منيو/مسار)، وصنّفنا كل صلاحية:
430
مُطبّقة بدقة (43%) السلسلة الكاملة موجودة كبوابة
422
تغطية خشنة فقط (42%) «الزر لسه بيظهر»
144
بلا أثر في الواجهة (14%) مُطبّقة في الـBE فقط
الموديول
الكتالوج
دقيقة
خشنة فقط
بلا واجهة
الموديول
الكتالوج
دقيقة
خشنة فقط
بلا واجهة
accounting
141
54
87
0
cmms
22
0
13
9
lis
179
46
133
0
crm
21
0
11
10
hrm
112
75
37
0
einvoicing
7
0
0
7
core
78
39
39
0
nphies
8
0
0
8
production
55
32
23
0
qms
22
0
9
13
sales
43
33
10
0
inventory
48
28
18
2
purchases
50
36
14
0
webstore
95
0
0
95
clinic
93
75
18
0
pos / reports
22
12
10
0
الإجمالي
996
430
422
144
٢.٤ الـ144 «بلا واجهة» = 7 موديولات كاملة بلا شاشات Angular
كل الـ144 مُطبَّقة فعلًا في الـBE عبر permission: middleware — بس مفيش لها زر/منيو/مسار في الـSPA. التصنيف الصحيح: «مُطبّقة في الـBE، غير مرئية في الواجهة» — مش «غير مطبّقة».
باگ حقيقي واحد اكتُشف: قائمة «تدريب HR» مبوّبة بـpermissions:['hrm.training'] (nav-items.config.ts:312), لكن الكتالوج فيه بس hrm.training-programs.*/training-sessions.*/training-enrollments.*. بسبب قاعدة «حدّ النقطة» فإن hrm.training لا تطابق أيًّا منها → قائمة تدريب HR تظهر للسوبر-أدمن فقط، ومفيش أي صلاحية مِنح تفتحها. البوابة المعلّقة الوحيدة (1 من 585).
٢.٥ الوصف والإعدادات — الوضع الحالي
مفيش وصف لأي صلاحية. بس سابقتان لوصف ثنائي اللغة موجودتان بالفعل: LisScreenCatalog.php:83-96 (كل صلاحية-في-شاشة معها desc_ar/desc_en/label/kind/danger)، وجدول setting_definitions (به description_ar/description_en لكل إعداد).
الإعداد ↔ الصلاحية: لا رابط. جدول setting_definitions ليس به عمود permission. الإعدادات مبوّبة خشنًا لكل موديول: كتابة تتطلب core.settings.manage (SettingController.php:65-72). و*.settings.manage موجودة في 7 موديولات (core, cmms, hrm, lis, purchases, qms, sales) وغائبة في 8 (accounting, inventory, crm, nphies, einvoicing, pos, production, clinic) — دي تسقط على core.settings.manage. مفيش عُرف بأن الإعداد الجديد ياخد صلاحيته الخاصة.
٣. المطلوب
إعادة تصميم شاشة /core/roles احترافية سريعة: مسمّيات معبّرة + info لكل صلاحية يوضّح وظيفتها، وتصفّح سريع لـ1000 صلاحية.
سدّ فجوة التطبيق: كل صلاحية مؤثّرة يبقى ليها بوابة دقيقة في الواجهة (مش «الزر لسه بيظهر»)، مع معرفة «مكان كل صلاحية».
مصدر موحّد للوصف (كتالوج أو i18n).
قاعدة: كل setting جديد ياخد صلاحيته.
٤. الفجوة (GAP)
المحور
موجود اليوم
المطلوب
ما يجب تغييره
وصف الصلاحية
لا شيء — اسم مركّب آليًّا فقط
info/شرح لكل صلاحية
كتالوج BE للصلاحيات (label/desc/danger/kind) يعمّم LisScreenCatalog، تستهلكه الشاشة
عرض الشاشة
قائمة مسطّحة، مربع/صلاحية، نافذة 800px
احترافي سريع، تصفّح 1000 صلاحية بسهولة
مصفوفة «مورد × إجراء» + شريط وحدات + بحث ذكي + قوالب + وضع «حسب الشاشة»
إعادة تصميم الشاشة (FE): مصفوفة مورد×إجراء + شريط الوحدات + بحث/فلاتر + قوالب + info popover + coverage lint + وضع «حسب الشاشة». تستهلك كتالوج WP1، وfallback للاسم المركّب.
FE
WP1
ng build؛ اختبار يدوي للمالك على /app
WP4
تصليب التطبيق: إنزال البوابات الخشنة لمستوى الإجراء عبر *appCan — بالأولوية: الخطير/المالي أولًا (حذف، اعتماد، ترحيل، تحويل — ومنها أزرار التحويل من تحليل convert-buttons). مرحلي لكل موديول.
FE
WP1
ng build؛ دور نموذجي/موديول؛ لوج ما لم يُغطَّ
WP5
قاعدة «إعداد ⇒ صلاحيته»: عمود permission على setting_definitions + فحص لكل إعداد في مسار الكتابة، + توثيق العُرف في KB/CLAUDE.
BE
WP2
Pest: كتابة إعداد بلا الصلاحية → 403
ملاحظة: WP4 هو الجزء الأكبر (420 بوابة). لا يُنفَّذ دفعة واحدة — يُرتّب بالمخاطر، ويُسجَّل ما لم يُغطَّ بعد (log) بدل الادّعاء بالاكتمال.
٨. قرارات تحتاج المالك
1
مصدر الوصف: كتالوج BE أم i18n؟
التوصية: كتالوج BE (يعمّم LisScreenCatalog/setting_definitions). السبب: 1000 مفتاح في i18n هتنفصل فورًا عن الـmiddleware الحقيقي ولا شيء يختبرها؛ الكتالوج بجانب الصلاحيات نفسها، مصدر واحد، وهو ما يشغّل coverage lint. مع fallback للـi18n ثم للاسم المركّب.
2
نطاق تصليب التطبيق (WP4): كل الـ420 البوابة الخشنة، أم بالأولوية؟
التوصية: بالأولوية — الخطير/المالي أولًا (حذف/اعتماد/ترحيل/تحويل)، ثم الباقي مرحليًّا. تغطية الـ420 دفعة واحدة مخاطرة عالية وبطيئة الاختبار.
3
الـ144 «بلا واجهة»: نسيبها في الشاشة أم نخفيها؟
التوصية: تظل قابلة للمنح بشارة «API فقط — لا شاشة بعد» (لأنها مُطبّقة فعلًا في الـBE)، بدل إخفائها فتبان الصلاحية «مش موجودة».
4
قاعدة الإعدادات: عمود permission على setting_definitions (قوي) أم عُرف + بوابة موديول (أخف)؟
التوصية: العمود — هو التنفيذ المباشر لطلبك «كل إعداد ياخد صلاحيته»، ويُفحَص لكل إعداد. مع سدّ فجوة الـ*.settings.manage الثمانية كحدّ أدنى فوري.
5
طرح المصفوفة: تستبدل النافذة الحالية كليًّا، أم خلف مفتاح تبديل مؤقّت؟
التوصية: استبدال كامل (النمط أثبت نفسه في LIS)، مع الحفاظ على كل الموجود (القوالب، الاسم/النطاق/الصفحة الرئيسية، تبويب المنيوهات).
٩. معاينة الواجهة المتوقّعة (قبل / بعد)
تصميم من وكيل Fable. الفكرة الجوهرية: نتوقّف عن عرض الصلاحيات كقائمة سلاسل، ونعرضها كـمصفوفة «مورد × إجراء» — صف واحد = مورد («فواتير المبيعات»)، أعمدة = الإجراءات (عرض/إنشاء/تعديل/حذف/اعتماد/ترحيل) + خلية «أخرى» للذيل الطويل. sales.invoices.* (8 صلاحيات) ينكمش من 8 سطور إلى سطر واحد. المبيعات: 50 سطر → 9. الكتالوج كله: ~1000 → ~180 سطر. مع info لكل صلاحية، شريط وحدات، قوالب جاهزة، وشريط تحذير تغطية حيّ.
ملاحظة قراءة: المعاينة أدناه mockup تقريبي بـHTML/CSS (بيانات نموذجية) — الغرض اعتماد «شكل الشاشة» قبل كتابة أي كود واجهة. الأرقام (22/50 إلخ) توضيحية.
قبل الشاشة الحالية — قائمة مسطّحة
تعديل دور — مسؤول مبيعات
💰 المبيعات 12 / 50
… وهكذا حتى ~1000 صلاحية في نافذة 800px
لا يوجد أي شرح: «الفواتير - اعتماد» — اعتماد إيه بالظبط؟ وماذا يترتب عليه؟
سطر لكل صلاحية: مورد واحد (أذون التسليم) = 8 سطور متطابقة الشكل؛ الوحدة كلها = 50 سطر تمرير.
لا يوجد «تحديد المورد كله» — فقط تحديد الوحدة بالكامل (50 صلاحية دفعة واحدة).
الحذف بجانب العرض بنفس الشكل — لا تمييز للصلاحيات الخطيرة.
لا تحذير تغطية: دور «يشوف الفواتير» بدون «عرض الفروع» = شاشة بيضاء، ولا أحد يعرف السبب.
بعد محرّر الصلاحيات الجديد — مصفوفة المورد × الإجراء + شرح لكل صلاحية
🔍 اعتماد14 نتيجة
الكلالمحدّدة 34الخطيرة
🗂 المصفوفة🖥 حسب الشاشة
قوالب جاهزة:👁 مُشاهد فقط✏️ مدخل بيانات✅ مشرف اعتماد💼 محاسب فرع
💰 المبيعات 22/50
🚚 المشتريات 12/56
📦 المخزون 0/38
📊 المحاسبة 0/152
🧪 المختبر 0/121
👥 الموارد البشرية 0/74
🛒 نقاط البيع 0/30
⚙️ النظام الأساسي 0/82
+ 7 وحدات أخرى…
المورد / الشاشة
عرضتحديد العمود
إنشاءتحديد العمود
تعديل
حذف
اعتماد
ترحيل / تأكيد
إجراءات أخرى
💰 المبيعات
22 / 50تحديد الكل ▾
عروض الأسعارi
—
—
+4 · إرسال، قبول، رفض، نسخ
أوامر البيعi
—
+3 · إلغاء، إقفال، نسخ
أوامر البيع sales.orders
أمر البيع هو تأكيد طلب العميل قبل التسليم والفوترة — تُبنى عليه أذون التسليم والفواتير.
عرضيشاهد قائمة أوامر البيع وتفاصيلها دون أي تعديل.
تأكيديحوّل الأمر من مسودة إلى أمر مؤكد يُسمح ببدء التسليم بناءً عليه.
حذف خطيرحذف نهائي للأمر — لا يمكن التراجع عنه.
عرض العملاء ⚠ لازمةصلاحية مشتركة من النظام الأساسي — بدونها لا تُفتح شاشة إنشاء الأمر.
أذون التسليمi
—
+3 · شحن، تسليم، إلغاء
فواتير المبيعاتi
+2 · إلغاء، نسخ
مقبوضات العملاءi
—
+1 · إلغاء
مرتجعات المبيعاتi
+1 · إلغاء
🚚 المشتريات
12 / 56تحديد الكل ▾
طلبات الشراءi
—
+3 · تحويل لأمر، رفض، إلغاء
أوامر الشراءi
+3 · إدارة، إقفال، إلغاء
إذن الاستلام (GRN)i
—
+2 · فحص جودة، إلغاء
فواتير الموردينi
+1 · إلغاء
أسعار الموردينi
—
—
—
⚠️ شاشة أوامر الشراء هتفشل — الدور معه «اعتماد أمر الشراء» لكن ناقصه «عرض الموردين» (النظام الأساسي). أضِفها
34 صلاحية محددة · وحدتان
وضع «حسب الشاشة» (المفتاح أعلى اليسار) يعرض نفس الدور مجمّعًا بشاشات النظام كما في محرّر أدوار المختبر: كل شاشة ببند أساسي + متطلباتها الخفية ⚠ + إجراءاتها، مع وصف لكل بند.
الخلاصة
~1000 صلاحية: 430 مُطبّقة بدقة، 422 تغطية خشنة (فئة «الزر لسه بيظهر»، ~420 منها على مستوى الإجراء — أغلبها LIS/محاسبة/core/HR)، 144 بلا واجهة (7 موديولات كاملة مُطبّقة في الـBE بلا شاشات). + بوابة معلّقة واحدة (hrm.training) يشوفها السوبر-أدمن فقط، ولا وصف لأي صلاحية. الحل: كتالوج صلاحيات BE (يعمّم LisScreenCatalog) + إعادة تصميم الشاشة لمصفوفة بـinfo وcoverage lint + تصليب تطبيق بالأولوية + ربط الإعداد بصلاحيته. هذا تحليل — بانتظار موافقتك قبل أي كود.