StageFlow — منصة إدارة دورة حياة التدريب

LaravelPHPMySQLBladeTailwind CSS· دقيقتان قراءة

منصة تتعامل مع التدريب باعتباره دورة حياة واحدة لا كومة من الأوراق: تنشر الشركة عرضًا، ويترشح الطالب، ويرفع الوثائق المطلوبة، وينتهي المسار بمناقشة مجدولة تحمل لجنة تحكيم ونقطة — كل ذلك كسجلات مترابطة لا كملفات متناثرة.

المشكلة والقيود

تعيش إدارة التدريبات عادةً في ثلاثة أماكن في آنٍ واحد: جدول بيانات يبيّن من ترشّح وأين، وصندوق بريد مليء بالتقارير المرفقة، وتقويم منفصل لمواعيد المناقشات. لا شيء يوفّق بينها، فتصبح الحالة الحقيقية لملف الطالب هي ما يتذكره آخر من تعامل معه. كان القيد هو تمثيل المسار كاملًا في مخطط واحد، حيث تكون كل مرحلة سجلًا قابلًا للاستعلام لا سلسلة رسائل بريدية.

النهج

  • خمس كيانات مترابطة تحمل مجال العمل: الشركات تملك التدريبات، والتدريبات تستقبل الترشيحات، والترشيحات تؤدي إلى المناقشات، والوثائق ترتبط بالمستخدم الذي رفعها.
  • تحمل الترشيحات حقل status صريحًا (pending / accepted / rejected) بدلًا من حالة مستنتجة، فيكون لسؤال «أين وصل هذا الملف» جواب واحد في قاعدة البيانات دائمًا.
  • يُختار الدور ويُتحقق منه عند التسجيل (student / professor / admin)، ما يتيح للمسارات نفسها تقديم واجهات مختلفة دون نظام حسابات منفصل لكل فئة.
  • متحكمات موارد لما يُتصفَّح (التدريبات، الشركات)، ونقاط دخول مخصّصة لانتقالات الحالة (/apply و/upload و/defense/schedule) — فالقراءة والتقدّم في الدورة لهما شكلان مختلفان عن قصد.
1..n1..n1..n0..1companiesusersrole: student,professor, admininternshipsdocumentsPOST /uploadowner: userapplicationsPOST /applystatus: pending,accepted, rejecteddefensesPOST /defense/schedulejury, grade

الوصف الكامل:

  1. companies → internships (1..n)
  2. users — role: student, — professor, admin → documents — POST /upload — owner: user (1..n)
  3. internships → applications — POST /apply — status: pending, — accepted, rejected (1..n)
  4. applications — POST /apply — status: pending, — accepted, rejected → defenses — POST /defense/schedule — jury, grade (0..1)
السجلات الخمسة المترابطة، والنقاط النهائية التي تُحرّك الملف بينها. الكاردينالية مكتوبة على الأسهم، والمسار الذي يُنشئ السجل مكتوب داخله.

المفاضلات

Decision

المناقشة كجدول مستقل مرتبط بالترشيح بدلًا من أعمدة داخل الترشيح: يُبقي الموعد ولجنة التحكيم والنقطة خارج سطر الترشيح، ويسمح للملف بأن يوجد بشكل مشروع دون مناقشة بعد، مقابل ربط إضافي في الواجهات التي تعرض ملفًا كاملًا.

Decision

الدور كحقل مُتحقَّق منه على المستخدم بدلًا من حزمة صلاحيات: أسرع طريق صادق إلى ثلاث فئات مفصولة بوضوح، مع تقبّل أن أي حاجة أدق من «طالب / أستاذ / مشرف» ستتطلب إعادة البناء فوق طبقة تفويض حقيقية.

النتائج

مسار عملي من عرض التدريب المنشور وصولًا إلى المناقشة المنقّطة، حيث تكون كل مرحلة سجلًا محفوظًا له مالك — فيتحول سؤال «أي الطلبة لم يسلّموا وثائقهم بعد» إلى استعلام بدل تدقيق صندوق بريد.

ما كنت سأفعله بشكل مختلف

تخزين أعضاء لجنة التحكيم كعلاقة حقيقية بدل سلسلة نصية مفصولة بفواصل في عمود واحد — فالشكل الحالي لا يمكنه الإجابة عن «في أي لجان يجلس هذا الأستاذ» دون مطابقة نصوص. وكنت سأتحقق أيضًا من الوثائق المرفوعة عبر نوع MIME لا عبر الحجم فقط، فحدّ 2 ميغابايت لا يقول شيئًا عمّا يحتويه الملف فعلًا.