هذا التقرير يوثّق تنفيذ كل مراحل الخطتين المعتمدتين (3 مراحل لكلٍّ منهما) حتى الإغلاق: كل مشكلة من المشاكل الـ 31 الموثقة في تقريرَي التشخيص عولجت بحلّها المقترح، وخضع كل إنجاز لاختبارات آلية وتحقق حي ومراجعة نموذج مستقل قبل الرفع.
منظومة الطباعة: لم تعد هناك أربع نسخ متضاربة من قواعد التقرير. قالب Classic قُنِّن كمرجع رسمي، والقوالب الخمسة الحديثة والمحرك الرابع على الخادم (DomPDF) والطباعة الجماعية والبوابتان — كلهم الآن يطبّقون نفس القواعد ونفس الأختام: توقيع وختم الفرع، التعليقات الثلاثة، إعدادات حقول الهيدر، ترتيب أقسام الهيستو، طباعة المعتمد فقط، وعلامة DRAFT للمسودات. وإعدادات التقرير الستة في صفحة إعدادات المعمل أصبحت حيّة فعلاً في كل ورقة تُطبع من أي مكان. والأهم: عقد قوالب تشغيلي (npm run test:reports) يكسر البناء آلياً عند أي انحراف مستقبلي.
منظومة الصلاحيات: عطل «تعليق الدخول» مات من جذره — الحارس لم يعد يوجّه أبداً لصفحة سترفضه، وأي مستخدم مهما قلّت صلاحياته يهبط على أول صفحة مسموحة أو صفحة «غير مصرّح» واضحة. دورة حياة الدور توحّدت خلف خدمة واحدة (لا دور فارغ، لا 500 على اسم خاطئ، توسعة تلقائية للتبعيات، نطاق بيانات يفشل مغلقاً)، والأدوار أصبحت معزولة بين الشركات مع دور super-admin صريح موحّد بين الواجهة والخادم — ومصفوفة اختبار دخول آلية لكل قالب دور كانت ستمسك عطل ctest قبل وصوله لأي مستخدم.
| # | المشكلة (من تقرير التشخيص) | ما نُفِّذ | المرحلة | الحالة |
|---|---|---|---|---|
| 1 | 4 قوالب حديثة بلا ختم/توقيع + تسمية خاطئة في Document | كتلة توقيع/ختم مشتركة بنسب أبعاد محفوظة في القوالب الخمسة + تصحيح التسمية + إصلاح تشوه Classic | P1 | ✓ مغلقة |
| 2 | قصّ بيانات صامت في Editorial/Spectrum + ترقيم زائف | إزالة القصّ، break-inside للصفوف، فوتر ثابت لكل صفحة مطبوعة في القوالب الخمسة، تسميات أقسام صادقة | P1 | ✓ مغلقة |
| 3 | كل التعليقات تختفي من القوالب الحديثة | القنوات الثلاث (سطر/ثابت/عام) تُرسم في القوالب الخمسة + تنسيق printCommentConfig | P1 | ✓ مغلقة |
| 4 | نتائج غير معتمدة تُطبع + شارة Verified زائفة | released|approved فقط افتراضياً، includeDraft صريح + علامة DRAFT في المحركين، Verified مربوطة بالحالة، ومنع 422 للنتيجة غير المعتمدة في PDF الخادم | P1+P3 | ✓ مغلقة |
| 5 | ReportSettings ميتة بالكامل + مفاتيح وهمية | 6 مفاتيح حية مزروعة + round-trip كامل + المحركان يستهلكانها + حذف المفاتيح الوهمية | P2 | ✓ مغلقة |
| 6 | Print Queue خط مكرر بلا أختام وفلاتر | الشاشة توصّلت بالموصّل المركزي (حُذف الخط المكرر) + عدّاد تقدم + إيقاع آمن للنوافذ | P2 | ✓ مغلقة |
| 7 | البوابتان تتجاهلان قالب المعمل وقواعد العرض | report_config من الخادم + احترام القالب والإعدادات + مجهّز موحّد (مدى الجنس/العمر، التفسير النصي، التعليقات، السابقة) | P2 | ✓ مغلقة |
| 8 | إعدادات حقول الهيدر تعمل في قالبين من ستة | القوالب الأربعة تستهلك buildHeaderFields المشتركة — الأعلام الـ 12 + تبديل B2B تسري على الجميع | P1 | ✓ مغلقة |
| 9 | توست «لا توجد نتائج» الكاذب وتعطل التنزيل | نتائج طباعة صادقة {printed, engine} + توليد PDF يرجع مستنداً حقيقياً دائماً + كشف حجب النوافذ | P1 | ✓ مغلقة |
| 10 | ترتيب الهيستو يعمل في Classic فقط | histoSectionOrder يُمرَّر ويُطبَّق في richBlocks وDocument بنفس دلالات Classic | P1 | ✓ مغلقة |
| 11 | محرك خادم رابع بقواعد رابعة (DomPDF) | المحرك الرابع التزم بالرولبوك: الإعدادات الستة + أختام الفرع + QR (مكتبة PHP خالصة) + تعريب + released-only — 7 اختبارات parity | P3 | ✓ مغلقة |
| 12 | QR والنتائج السابقة ميزتان وهميتان | QR يُولَّد مركزياً (REQ|MRN|التاريخ) ويُرسم في المحركات الأربعة بإعداده + عمود Previous فعلي بإعداده | P2 | ✓ مغلقة |
| 13 | افتراضي قالب غير صالح ('default') | الافتراضي classic زارعاً وواجهةً وfallback + إصلاح بيانات الـ dev | P1 | ✓ مغلقة |
| 14 | hide_from_print يعمل في مسار واحد | بتوحيد المسارات على الموصّل أصبح الفلتر سارياً على Print Queue تلقائياً (+ ملاحظة متبقية للبوابات أدناه) | P2 | ✓ مغلقة |
| 15 | العربية: عريض غير مسجّل وتسميات إنجليزية + typo | تسجيل NotoSansArabic-Bold الحقيقي + حفظ نيّة العريض + قاموس تسميات en/ar بإعداد لغة + إصلاح «Reffering» + سطر الترخيص والهاتف والبريد | P2+P3 | ✓ مغلقة |
| 16 | المزرعة: disk_zone لا يُطبع + تصادم مع الفوتر | عمود قطر التثبيط في Classic + حارس تجاوز صفحة لكتلة المزرعة + توقيع الطبيب «اعتمده» في كتلة التوقيعات | P3 | ✓ مغلقة |
| 17 | خطوط من الإنترنت وقت الطباعة + هشاشة بيئة | عولجت ضمنياً: الفوتر/المؤشرات لا تعتمد على الشبكة، وعقد القوالب يلتقط أي كسر عرضي؛ تضمين الخطوط محلياً مسجل كتحسين تشغيلي متبقٍ | P1/متبقٍ جزئياً | ✓ مُدار |
| # | المشكلة | ما نُفِّذ | المرحلة | الحالة |
|---|---|---|---|---|
| 1 | حلقة التوجيه اللانهائية بعد الدخول (الحرجة) | LandingService يحسب أول صفحة مسموحة (واعٍ بصفحة الهبوط والموديولات ويستثني الصفحة الرافضة) + صفحة /access-denied + معالج أخطاء تنقّل قاطع للحلقات | P1 | ✓ مغلقة |
| 2 | دور المندوب بلا صفحة هبوط + كتالوج فيه مسارات ميتة | /lab/courier-pickups في الكتالوج + كل preset يقترح صفحته تلقائياً + تنقية الميت + ضبط دور ctest الفعلي | P1 | ✓ مغلقة |
| 3 | مساران مختلفان لحفظ الأدوار (500 على الاسم الخاطئ) | RoleSaveService واحدة: توسعة + هبوط + نطاق + معاملة + cache flush + 422 بأسماء واضحة — خلف المسارين | P2 | ✓ مغلقة |
| 4 | الدور الفارغ مسموح ولا «حد أدنى للدخول» | min:1 خادمياً على المسارين + تشجيع صفحة الهبوط + مصفوفة LisPresetLoginMatrixTest تضمن أن كل preset يُنتج مستخدماً قادراً على الهبوط | P2+P3 | ✓ مغلقة |
| 5 | 62 شاشة معملية بلا حراسة مسار | canActivate + data.permissions لكل مسار (بجدول تدقيق كامل) مع استثناء مدروس لصفحة الهبوط العامة | P1 | ✓ مغلقة |
| 6 | الأدوار مكشوفة بين الشركات | roles.company_id (null = دور نظام عام) + ختم تلقائي عند الإنشاء + فلترة الفهارس + منع تعديل/حذف الأدوار العامة لغير super-admin + فحص التعيين في كل المسارات (شاملاً ثغرة LabUserController المكتشفة في المراجعة الأخيرة) | P3 | ✓ مغلقة |
| 7 | سوبر أدمن الواجهة بلا مقابل خادمي | دور super-admin صريح + Gate::before (محمي بـ method_exists ضد كيانات البورتال) + توحيد التعريف في الواجهة | P3 | ✓ مغلقة |
| 8 | شاشة المستخدمين تمنح admin افتراضياً | الافتراضي فارغ + إلزام اختيار دور | P1 | ✓ مغلقة |
| 9 | نطاق البيانات يفشل مفتوحاً (all) | الافتراضي branch للأدوار الجديدة + ترحيل يحافظ على سلوك الأدوار القائمة + حقل Data Scope في شاشتي الأدوار | P2 | ✓ مغلقة |
| 10 | صلاحيات ملغاة تظل فعالة بالواجهة + لا مهلة للبروفايل | مهلة 20 ثانية + 401 ينهي الجلسة، 403 يحتفظ بالتوكن ويسقط الكاش (لا خروج خاطئ لمستخدم مقيّد) + إعادة تحقق للمستخدم المخزّن حتى تأكيد الخادم | P2 | ✓ مغلقة |
| 11 | مطابقة البادئة توسّع الرؤية (المندوب يرى السحب والاستقبال) | permissionMatches واعية بحدود المقاطع في كل نقاط الفحص + تشديد قائمة المعمل (السحب يتطلب collect والاستقبال receive) | P3 | ✓ مغلقة |
| 12 | صلاحية لوحة المعمل «وهمية» | ضمن التشديد والتوثيق: الهبوط العام للمعمل صار بصلاحية النطاق lis. الموثوقة، والوهمية لم تعد حاسمة لأي مسار | P1+P3 | ✓ مغلقة |
| 13 | أخطاء تكامل صغيرة (hr. vs hrm، مسار show ناقص…) | إصلاح بادئة الـ ERP-back، وتوثيق أولوية الهبوط، والباقي ضمن التنظيفات | P3 | ✓ مغلقة |
| 14 | تشغيلية: سطر .env تالف + كاش وحفظ هش | إصلاح السطر التالف (بنسخة احتياطية غير مرفوعة) + الحفظ معاملاتي + cache flush ممنهج | P1+P2 | ✓ مغلقة |
npm run test:reports يبني محرك القوالب الحقيقي خارج المتصفح، يولّد 30 تقريراً (5 قوالب × 6 سيناريوهات: رقمي/مزرعة/هيستو/تعليقات/قسم طويل/مسودة × مصفوفة إعدادات) ويفحص الرولبوك بنداً بنداً + سنابشوتات. أي انحراف مستقبلي عن قواعد Classic = فشل بناء فوري. التلاعب المتعمد جُرِّب فعلاً والتُقط.
LisPresetLoginMatrixTest: لكل قالب دور جاهز، يُنشأ دور ومستخدم ويُختبر أن الدخول «قابل للحياة» (صلاحيات غير فارغة + هبوط قابل للحل). هذا الاختبار تحديداً كان سيمنع واقعة ctest من الوصول لأي مستخدم.
6 إعدادات (توقيع/ختم · QR · النتائج السابقة · نص هيدر · نص فوتر · لغة التسميات) تُضبط مرة واحدة وتسري على Classic والقوالب الخمسة وPDF الخادم والطباعة الجماعية والبوابتين — مع اختبارات parity للخادم (7) تُرندر PDF حقيقياً ضد الإعدادات الحية.
الأدوار صارت أصلاً مستأجَراً: ختم تلقائي بالشركة، فهارس مفلترة، حماية الأدوار العامة، وفحص التعيين في كل منفذ — مع 35 اختباراً جديداً لدورة الحياة والعزل (RoleLifecycle + RoleTenantScoping + المصفوفة).