- مقدمة
- العرض
- MVP
- خارطة الطريق
- متطلبات المنتج
- ابدأ الآن
- البيئة المحلية
- البنية المعمارية
- الهيكل
- الأنماط
- الحزمة التقنية
- قاعدة البيانات
- تعدّد المستأجرين
- الفهرس (Catalog)
- العمل دون اتصال
- المصادقة
- التهيئة (Onboarding)
- تدفق التكامل (Integration Flow)
- التهيئة (Provision)
- القبول
- الحضور
- الامتثال التنظيمي
- الملف الشخصي
- الاجتماعات
- إدارة الرسوم
- الفاتورة
- التدويل
- الترجمة
- دليل الترجمة
- أمان قاعدة البيانات
- المساهمة
- هَوْغوارتس
- عرض حي
- الإلهام
تتبّع وحدة الحضور حضور الطلاب عبر طرق التقاط متعدّدة، مع وصول مبني على الأدوار، إشعارات للأهل، مستويات خطر وفق US DoE، تتبّع للتدخّلات، وتصدير CSV / Excel / PDF. المعلمون يرون فصولهم المسندة فقط؛ الطلاب وأولياء الأمور يرون سجلاتهم فقط.
متتبّع الإصدار: databayt/hogwarts#1 — متتبّع رئيسي موحّد للحضور والامتثال. راجع كذلك Aldar Epic 01.
الحالة
| الميزة | الحالة | ملاحظات |
|---|---|---|
| التحضير السريع (واجهة المعلم) + ساعة الدوام للمعلمين والموظفين | Production | تحضير موجه للغياب بلمسة واحدة؛ تسجيل الحضور/الانصراف يغذي كشوف الدوام |
| يدوي / حصة / QR / باركود / رفع جماعي | Production | طرق التقاط متعدّدة (راجع جدول طرق الالتقاط) |
| إشعارات الأهل + تقديم الأعذار | Production | داخل التطبيق + SMS + بريد؛ يراجعها الكادر |
| الإنذار المبكّر | Production | مستويات خطر US DoE، تتبّع التدخّلات |
| تصدير التقارير | Production | CSV، Excel (5 أوراق)، PDF (بهوية المدرسة) |
| الحذف الناعم + الاستعادة | Production | deletedAt |
| العذر التلقائي | Production | AbsenceIntention معتمَد → EXCUSED |
| أسماء حسّاسة للّغة | Production | getText() يترجم عند الطلب |
| Geofence / Master gate / محرّك السياسات / تقارير الامتثال | موصول | يعمل، الواجهة لا تزال تنضج |
| الإعدادات | Production | تُحفظ في سجل AttendancePolicy على مستوى المدرسة |
| توقّعات AI / Gamification / Hall pass / Kiosk / خطابات الامتثال | Production | لها صفحات؛ تظهر عبر شبكة الوصول السريع في النظرة العامة |
| نوايا الغياب / واجهة Geofence | موصول | روابط مباشرة فقط حتى تُعرَّب واجهاتها الداخلية |
| إرسال يومي لـ ADEK eSIS | Production | موصّل عام في /compliance، الوضع الافتراضي DRY_RUN |
| كرون تواصل ولي الأمر خلال ساعتين | Production | /api/cron/absence-followup، كل 30 دقيقة، UTC |
المسارات
صفحة الحضور الرئيسية حسب الدور: المعلم يصل إلى التحضير السريع (موجه للجوال والغياب — الجميع حاضر افتراضيًا، واللمسات تتنقل غائب ← متأخر ← حاضر، وحفظ واحد يرسل الكشف كاملًا ويُشعر أولياء أمور الغائبين)، والمشرف/الموظف إلى النظرة العامة، والطالب/ولي الأمر إلى سجله الذاتي. كلها تحت src/app/[lang]/s/[subdomain]/(school-dashboard)/attendance/. التبويبات: /, /manual, /qr-code, /records, /excuses, /early-warning, /interventions, /analytics, /reports, /settings. شبكة الوصول السريع في النظرة العامة تربط /recent, /bulk-upload, /barcode, /hall-pass, /interventions/tiers, /gamification, /ai (+ /kiosk, /letters للمشرفين). روابط مباشرة فقط: /geo, /intentions, /bulk. /analysis يعيد التوجيه نهائيًا إلى /analytics؛ /parent/attendance يعيد التوجيه إلى /attendance/records. راجع جدول طرق الالتقاط أدناه لغرض كل route؛ راجع RBAC للوصول حسب الدور.
RBAC
| الإجراء | DEVELOPER | ADMIN | TEACHER (فصوله) | STAFF | STUDENT | GUARDIAN (أبناؤه) |
|---|---|---|---|---|---|---|
| تسجيل الحضور | Y | Y | Y | Y | — | — |
| قراءة سجلاته | Y | Y | — | — | Y | Y |
| قراءة سجلات الفصل | Y | Y | Y | — | — | — |
| قراءة على مستوى المدرسة | Y | Y | — | Y | — | — |
| حذف | Y | Y | Y | Y | — | — |
| استعادة | Y | Y | — | — | — | — |
| رفع جماعي | Y | Y | Y | — | — | — |
| تصدير | Y | Y | Y | Y | — | — |
| تحليلات | Y | Y | Y | Y | — | — |
| امتثال / إعدادات | Y | Y | — | — | — | — |
| مراجعة الأعذار | Y | Y | Y | Y | — | — |
| تقديم الأعذار | Y | Y | — | — | — | Y |
getTeacherClassIds() (actions/helpers.ts) يجمع المعلم الأساسي + أدوار ClassTeacher المشاركة.
فلتر الصف: الـactions تقبل gradeId للفلترة عبر Class.gradeId → AcademicGrade (helper getClassIdsByGrade()).
الحضور اليدوي
شريط أدوات مسطّح inline (PlatformToolbar): محدّد الفصل، منتقي التاريخ، أزرار حالة جماعية، Save. getCurrentPeriod() يختار تلقائياً الفصل المطابق لحصة الجدول الحالية؛ الأسماء تُترجَم عند الطلب عبر getText(). لوحة المفاتيح: P / A / L لحاضر / غائب / متأخر، Cmd/Ctrl+S للحفظ. أولياء الأمور للطلاب الغائبين يُخطَرون تلقائياً عند الحفظ؛ AbsenceIntention معتمَد يحوّل ABSENT → EXCUSED.
طرق الالتقاط
| الطريقة | المسار | ملاحظات |
|---|---|---|
| Manual | /manual | قائمة منسدلة لكل طالب + أزرار جماعية |
| Period | /manual (بحسب الحصة) | getCurrentPeriod()، تحليلات الحصة |
| QR | /qr-code | صلاحية افتراضية 30 دقيقة؛ التحقّق من التسجيل، إزالة التكرار |
| Barcode | /barcode | يبحث في StudentIdentifier |
| Bulk upload | /bulk-upload | CSV: studentId, date, status, checkInTime, checkOutTime, notes |
| Geofence | /geo | متتبّع موقع (للطلاب)، مناطق (للمشرفين) |
| Master gate | server actions | recordMasterAttendance(), getPrefillFromMaster() |
إشراك الأهل
triggerAbsenceNotification() يُطلَق عند الغياب: داخل التطبيق (أولوية عالية)، SMS عبر Twilio (إن كان مهيّأً)، بريد. يستخدم preferredLanguage للمدرسة.
أسباب العذر: طبّي، طارئ عائلي، ديني، نشاط مدرسي، نقل، طقس، أخرى. معتمَد → EXCUSED؛ مرفوض → غير معذور.
عرض الطالب / ولي الأمر: نسبة + اتجاه، تقويم تاريخي، تفصيل الحالات، تقديم عذر للغيابات غير المعذورة.
الإنذار المبكّر
مستويات خطر US DoE:
| الخطر | معدّل الحضور | معدّل الغياب |
|---|---|---|
| مُرضٍ | ≥95% | <5% |
| في خطر | 90 – 94.9% | 5 – 9.9% |
| مزمن متوسّط | 80 – 89.9% | 10 – 19.9% |
| مزمن حادّ | <80% | ≥20% |
تتبّع التدخّلات في /attendance/interventions — 14 نوع تدخّل (تواصل مع ولي الأمر، زيارة منزلية، إحالة لمرشد / أخصائي اجتماعي / إداري، عقد حضور، إحالة تغيّب، مورد مجتمعي، دعم أكاديمي، إرشاد، تحفيز، أخرى) مع حالات Scheduled → In Progress → Completed / Cancelled / Escalated. محرّك السياسات في actions/policy.ts يقيّم المُحفّزات ويدير الاستثناءات.
التحليلات والتقارير
تحليلات بـ7 تبويبات في /analytics: Summary، Calendar، Trends، Patterns، Methods، Classes، At Risk.
التقارير في /reports: فلترة بالفصل، الطالب، الحالة، نطاق التاريخ، الحصة. تصدير: CSV، Excel (5 أوراق — summary، detailed، by status، by class، by date)، PDF (بهوية المدرسة).
الامتثال: getComplianceDashboard(), getComplianceReport(), getScheduledReports().
Server actions
الـactions مقسّمة عبر وحدات حسب المعنى تحت src/components/.../attendance/actions/.
| الوحدة | الملف | السطح |
|---|---|---|
| Core | core.ts | تسجيل، قائمة، تسجيل سريع، تسجيل خروج، حذف + استعادة جماعية |
| Analytics | analytics.ts | إحصاءات، اتجاهات، استخدام الطرق، تقويم، مقارنة فصول، في خطر، نشاط حديث |
| Periods | periods.ts | تسجيل لكل حصة، اكتشاف الحصة الحالية، تحليلات الحصة |
| QR | qr.ts | توليد جلسة، مسح، جلسات نشطة |
| Identifiers | identifiers.ts | CRUD باركود الطالب / معرّف البطاقة + بحث |
| Excuses | excuses.ts | تقديم، مراجعة، قائمة المعلَّق / غير المعذور |
| Interventions | interventions.ts | إنشاء، تحديث، تصعيد، قائمة، إحصاءات، مكلَّفون |
| Bulk | bulk.ts | رفع CSV / Excel، مولِّد التقارير، تصدير CSV، عمليات الرفع الأخيرة |
| Dashboard | dashboard.ts | نظرة اليوم، حسب الخطر، إنذار مبكّر، فصول غير مسجَّلة، ملخّص ولي الأمر |
| Policy | policy.ts | تقييم السياسات، المحفّزات، الاستثناءات، الإلغاءات |
| Master | master.ts | دخول / خروج بوّابة المدرسة، prefill من master |
| Compliance | compliance.ts | لوحة الامتثال + التقارير المجدولة |
| Records | records.ts | الطالب لذاته + أبناء ولي الأمر |
توقيعات نموذجية:
markAttendance(input: {
classId: string
date: string
records: Array<{ studentId: string; status: 'present' | 'absent' | 'late' }>
})
markPeriodAttendance(input: {
classId: string
date: string
periodId: string
records: Array<{ studentId: string; status: 'PRESENT' | 'ABSENT' | 'LATE'; notes?: string }>
})
getAttendanceList({ classId, date, lang? }) // lang يُطلق الترجمة
deleteAttendance(id: string) // حذف ناعم
restoreAttendance(id: string)Schema
model Attendance {
id String @id @default(cuid())
schoolId String
studentId String
classId String
date DateTime @db.Date
status AttendanceStatus
method AttendanceMethod @default(MANUAL)
checkInTime DateTime?
checkOutTime DateTime?
notes String?
markedBy String?
markedAt DateTime @default(now())
deletedAt DateTime?
periodId String?
timetableId String?
periodName String?
@@unique([schoolId, studentId, classId, date, periodId])
@@index([schoolId, date, periodId])
}دلالات الحذف الناعم. الحقل deletedAt علامة حذف (tombstone) وليس حذفًا نهائيًا. يُستبعَد السجل المحذوف من كل قراءات التحليلات ولوحة المعلومات والتصدير والامتثال التنظيمي، ومن عروض الطالب وولي الأمر على الجوال — مع الاحتفاظ بالصف للتدقيق وإمكانية استعادته من قِبل المسؤول (restoreAttendance). وبما أن قيد @@unique لا يزال يحجز مفتاح الصف المحذوف، فإن إعادة تسجيل الطالب لنفس اليوم/الحصة تُحيي السجل الأصلي (تمسح deletedAt) بدلًا من إنشاء نسخة مكررة — وينطبق ذلك على التسجيل اليدوي والحصص ورمز QR والباركود والسياج الجغرافي والكشك.
نماذج داعمة: AttendanceExcuse, AttendanceIntervention, QRCodeSession, StudentIdentifier, AbsenceIntention, PolicyTrigger, PolicyExemption, MasterAttendance, HallPass, KioskLog, AttendanceReward, StudentBadge, AttendanceStreak.
Seed
pnpm db:seed:single attendanceالامتثال للجهات التنظيمية (ADEK eSIS — الإمارات)
يمكن لمدارس الإمارات (School.country === "AE") تفعيل رفع يومي لملف CSV
إلى بوابة ADEK eSIS على esis.adek.gov.ae بالإضافة إلى التواصل مع ولي
الأمر خلال ساعتين من الغياب غير المُبلَّغ (متطلب ADEK). الإطار العام —
إضافة جهة تنظيمية جديدة (هيئة التعليم السعودية، وزارة التعليم القطرية،
وزارة التعليم السودانية) تتطلب فقط إضافة قيمة إلى enum
ComplianceProvider ودليل تحت src/lib/compliance/providers/<authority>/.
| القطعة | المسار | الغرض |
|---|---|---|
| واجهة الإعدادات | /{lang}/compliance | تفعيل، الوضع، المهلة، وقت الإرسال اليومي، قائمة الإرسالات |
| إدارة عبر المستأجرين | /{lang}/(saas-dashboard)/compliance (DEVELOPER) | مجموعات بيانات الاعتماد المشتركة لنمط Aldar |
| كرون يومي | /api/cron/esis-submit (0 10 * * *) | إدخال طوابير + توزيع على المدارس |
| كرون متابعة | /api/cron/absence-followup (*/30 * * * *) | سجل امتثال ساعتين |
| Webhook | /api/webhooks/adek | استلام ACCEPTED/REJECTED غير متزامن |
| Worker (خارج المستودع) | tools/adek-rpa-worker/ (Fly.io) | Playwright عند عدم توفر API |
أوضاع الموصّل — قابلة للضبط لكل مدرسة × مزوّد:
| الوضع | الوظيفة |
|---|---|
DRY_RUN | إنشاء CSV، حفظه للتدقيق، يرفعه المسجّل يدوياً إلى eSIS |
PIGGYBACK | الإرسال عبر بيانات اعتماد مجموعة مشتركة (نمط الدار، صف اعتماد واحد × N مدارس، قاطع دائرة عند التدفقات الفاشلة) |
OFFICIAL_API | واجهة برمجية موثّقة من المزوّد (بانتظار وصول مطوّرين من ADEK) |
RPA | يلتقط عامل Playwright خارجي الصفوف QUEUED ويرفع عبر بوابة eSIS |
DISABLED | تخطّي في الكرون |
مهلة التواصل مع ولي الأمر — ساعتين
عند تفعيل SchoolComplianceConfig.enabled = true، فإن
triggerAbsenceNotification يُرسل عبر قنوات in_app + email + whatsapp
(بدلاً من in_app فقط) لكي تستهلك كرونات البريد و WhatsApp الصف. كل
30 دقيقة، يبحث كرون absence-followup عن صفوف ABSENT التي:
markedAt < now() - parentContactSlaMinutes(افتراضي 120، محسوب بـ UTC)- لا يوجد لها
AttendanceExcuse - لا يوجد لها
AbsenceIntentionمعتمَد يغطّي اليوم - لا يوجد لها
AttendanceInterventionمن نوعPARENT_PHONE_CALL/PARENT_EMAILخلال آخر 24 ساعة
يُرسل إشعار absence_unreported_followup لكل ولي أمر، ثم يكتب صفّ
AttendanceIntervention (PARENT_EMAIL, parentNotified=true,
contactMethod=in_app+email+whatsapp). هذا الصفّ هو سجل التدقيق الموجّه
للجهة التنظيمية — يستعلم getParentContactSlaReport() عنه لتقديم
عدّ "تواصل ضمن المهلة" لتدقيقات ADEK.
النموذج البياني (جانب الامتثال)
خمسة كيانات جديدة في prisma/models/compliance.prisma — ليس أيٌّ منها
خاصّاً بـ ADEK:
ComplianceProviderenum (حالياًADEK_ESIS،CUSTOM)ConnectorModeenumComplianceSubmissionStatusenum +CircuitBreakerStateenumSchoolComplianceConfig— صفّ واحد لكل مدرسة × مزوّد (تفعيل اختياري)SharedComplianceCredentialGroup— بيانات اعتماد مشتركة لمجموعة (نمط الدار)SchoolComplianceCredential— بيانات اعتماد لكل مدرسة (وضع OFFICIAL_API)ComplianceSubmission— صفّ لكل محاولة، مفهرس بـ(schoolId, provider, submissionDate, attemptNumber). تتسلسل المحاولات عبرsupersededBy. يُحفظ CSV داخلcsvArtifactContentويُنزَّل عبر/api/compliance/artifact/[submissionId](S3 URL موقّع قيد التخطيط).
تمّ توسيع AuditLog.userId ليقبل null في نفس الإصدار لكي يُسجَّل كرون /
عامل / webhook كأحداث نظام — تمرير userId: null في المكالمات.
أُضيف نوع NotificationType.absence_unreported_followup لمسار المهلة.
انظر أيضاً
- تعدد المستأجرين — RBAC + نطاق المستأجر
- الإشعارات — إرسال الغياب
- الجدول — اكتشاف الحصة تلقائياً
- الامتثال — إطار الإرسال للجهات التنظيمية (ADEK + جهات مستقبلية)