دورة الإجازات الكاملة — Moon HR

من تعريف أنواع الإجازات لحد خصم الرصيد — شرح كامل للوجيك

1

تعريف أنواع الإجازات (Leave Types)

المكان: /hr/leave-types — أول حاجة لازم تتعمل

كل نوع إجازة ليه قواعد مختلفة. مثال:

النوعالكودأيام/سنةمدفوعةترحيلحد الترحيلجنسحد خدمة
إجازة سنويةAL30نعم ✅نعم ✅5 أيامالكل0 شهر
إجازة مرضيةSL15نعم ✅لا ❌0الكل0 شهر
إجازة أمومةML70نعم ✅لا ❌0أنثى فقط0 شهر
إجازة أبوةPL10نعم ✅لا ❌0ذكر فقط0 شهر
إجازة بدون راتبUL30لا ❌لا ❌0الكل3 شهور

شرح الحقول:

  • أيام/سنة (max_days_per_year): الحد الأقصى اللي الموظف يقدر ياخده في السنة
  • مدفوعة (is_paid): هل الإجازة براتب ولا بدون — تأثر على حساب الرواتب
  • ترحيل (is_carry_over_allowed): هل الرصيد المتبقي بيترحل للسنة الجاية
  • حد الترحيل (max_carry_over_days): أقصى عدد أيام يترحلوا (5 يعني لو فاضل 10 أيام بيترحل 5 بس)
  • جنس (gender): لو محددة = ذكر أو أنثى فقط. لو فاضية = الكل
  • حد خدمة (min_service_months): الموظف لازم يكون شغال X شهر على الأقل عشان يستحق النوع ده
2

تهيئة الأرصدة (Initialize Balances)

المكان: /hr/leave-balances ← زر "تهيئة السنة"

في بداية كل سنة مالية، لازم تهيئ الأرصدة لكل الموظفين.

إيه اللي بيحصل لما تضغط "تهيئة السنة 2026"؟

  1. النظام بيجيب كل الموظفين النشطين (Active)
  2. ولكل نوع إجازة فعّال
  3. يتحقق:
    • لو الموظف عنده رصيد للنوع ده في السنة دي بالفعل ← يتخطى (مش يكرر)
    • لو النوع ليه حد خدمة (مثلاً 3 شهور) والموظف لسه جديد ← يتخطى
    • لو النوع مخصص لجنس (أنثى) والموظف ذكر ← يتخطى
  4. لو كل الشروط متحققة ← يعمل رصيد جديد

الرصيد المبدئي:

total_days = max_days_per_year (من نوع الإجازة)
used_days = 0
carried_over_days = 0 (لسه مفيش ترحيل — السنة لسه بدأت)
adjusted_days = 0
remaining_days = total_days + carried_over_days + adjusted_days - used_days = 30
💡 التهيئة آمنة — لو عملتها مرتين، مش هتكرر الأرصدة. النظام بيتحقق قبل الإنشاء.

مثال عملي:

عملت تهيئة لسنة 2026 وعندك 20 موظف نشط و 2 نوع إجازة:

20 موظف × 2 نوع = 40 رصيد تم إنشاؤه
Response: "Initialized 40 leave balances for fiscal year 2026."
3

تقديم طلب إجازة (Submit Request)

المكان: /hr/leave-requests ← زر "طلب جديد"

الحقول المطلوبة:

  • الموظف * — من هو
  • نوع الإجازة * — سنوية/مرضية/إلخ
  • من تاريخ * / إلى تاريخ * — فترة الإجازة
  • السبب — اختياري

إيه اللي بيحصل لما يتقدم الطلب؟

  1. حساب أيام العمل: النظام بيحسب الأيام بين التاريخين بدون أيام الويكند
    مثال: من 15 أبريل (أربعاء) لـ 20 أبريل (اثنين)
    الأيام: أربعاء 15, خميس 16, ❌ جمعة 17, ❌ سبت 18, أحد 19, اثنين 20
    total_days = 4 أيام عمل (بدون الجمعة والسبت)
  2. إنشاء مستويات الموافقة:
    • المستوى 1: المدير المباشر (لو الموظف عنده manager_id)
    • المستوى 2: HR (أي شخص عنده صلاحية hrm.leave-requests.approve)
    • لو الموظف مفيش عنده مدير ← مستوى واحد بس (HR)
  3. الحالة تبقى: معلق (pending)
عرض الرصيد: لما تختار الموظف ونوع الإجازة في الفورم، النظام بيعرض الرصيد المتاح فوراً (أخضر = كافي، برتقالي = قليل).
4

الموافقة والرفض (Approve / Reject)

مسار الموافقة (Multi-Level Approval):

معلق
pending
موافقة المدير
manager_approved
معتمد
approved

تفاصيل كل مرحلة:

المرحلةمين بيوافقإيه اللي بيحصل
معلق المدير المباشر المدير يضغط ✅ موافقة ← الحالة تتغير لـ "موافقة المدير" ← تروح للمستوى التاني
موافقة المدير HR (أي شخص بالصلاحية) HR يضغط ✅ موافقة ← الحالة تتغير لـ "معتمد"الرصيد يتخصم تلقائي
أو في أي مرحلة:
مرفوض المدير أو HR يضغط ❌ رفض + يكتب السبب ← الطلب يترفض ← مفيش خصم من الرصيد
⚠️ الخصم من الرصيد بيحصل بس لما كل المستويات توافق (الحالة تبقى "معتمد"). لو المدير وافق بس HR لسه ← مفيش خصم لسه.
5

خصم الرصيد (Balance Deduction)

إيه اللي بيحصل لما الطلب يتعتمد؟

  1. النظام بيدور على رصيد الموظف لنفس نوع الإجازة في نفس السنة المالية
  2. بيزود used_days بعدد أيام الطلب
قبل: total=30, used=0, remaining=30
طلب 4 أيام → اعتماد
بعد: total=30, used=4, remaining=26

معادلة الرصيد المتبقي:

remaining_days = total_days + carried_over_days + adjusted_days - used_days

مثال: 30 + 5 (ترحيل) + 2 (تعديل يدوي) - 10 (مستخدم) = 27 يوم متبقي
6

إلغاء الطلب (Cancel)

إيه اللي بيحصل لما يتلغي طلب معتمد؟

  1. النظام بيتحقق: هل الطلب كان معتمد (يعني الرصيد اتخصم)؟
  2. لو أيوه ← بيرجّع الأيام للرصيد (decrement used_days)
  3. لو الطلب كان لسه معلق أو مرفوض ← مفيش تغيير في الرصيد
  4. كل الموافقات المعلقة بتتحول لـ "ملغية"
قبل الإلغاء: used=10, remaining=20
إلغاء طلب 4 أيام (كان معتمد)
بعد الإلغاء: used=6, remaining=24 ← الأيام رجعت!
✅ الإلغاء آمن — لو الطلب كان معلق (مش معتمد)، الإلغاء مش بيأثر على الرصيد لأن الرصيد ما اتخصمش أصلاً.
7

تعديل الرصيد يدوياً (Adjust Balance)

المكان: /hr/leave-balances ← زر "تعديل" على كل صف

إمتى تحتاج تعديل يدوي؟

  • منح أيام إضافية (مكافأة أو تعويض)
  • خصم أيام (جزاء إداري)
  • تصحيح خطأ في الرصيد
  • ترحيل أيام من سنة سابقة يدوياً

الحقول:

  • الأيام — رقم (موجب = إضافة، سالب = خصم). مثلاً: +3 أو -2
  • السبب * — إجباري (مثل: "مكافأة أداء" أو "جزاء تأخير")
قبل: adjusted_days = 0
تعديل: +3 أيام
بعد: adjusted_days = 3

تعديل آخر: -1 يوم
بعد: adjusted_days = 2 (تراكمي)
8

ترحيل الرصيد (Carry Over) — نهاية السنة

ملاحظة: الترحيل حالياً يدوي — النظام مش بيعمله تلقائي.

الخطوات:

  1. في نهاية السنة (مثلاً ديسمبر 2026)، شوف رصيد كل موظف
  2. لو نوع الإجازة بيسمح بترحيل (is_carry_over_allowed = true)
  3. احسب: الأيام المترحلة = min(remaining_days, max_carry_over_days)
  4. هيّئ أرصدة السنة الجديدة (2027) عن طريق "تهيئة السنة"
  5. عدّل الرصيد الجديد يدوياً: أضف الأيام المترحلة عن طريق "تعديل"
مثال:
نهاية 2026: رصيد أحمد = 8 أيام متبقية
نوع الإجازة: ترحيل مسموح، حد أقصى 5 أيام
المترحل = min(8, 5) = 5 أيام

بداية 2027: هيّئ الأرصدة ← أحمد يحصل على 30 يوم
عدّل الرصيد: +5 أيام ← remaining = 35 يوم
💡 مقترح للمستقبل: إضافة زر "ترحيل تلقائي" يعمل كل الحسابات دي دفعة واحدة لكل الموظفين.

ملخص الدورة الكاملة

1. تعريف أنواع الإجازات مرة واحدة في الإعداد
2. تهيئة الأرصدة للسنة مرة كل سنة مالية
3. تقديم طلب إجازة الموظف أو HR
4. موافقة المدير المستوى الأول
5. اعتماد HR → خصم الرصيد تلقائي المستوى الثاني
6. نهاية السنة → ترحيل الرصيد (يدوي) مرة كل سنة
💰

تأثير الإجازات على الرواتب

نوع الإجازةالتأثير على الراتب
إجازة مدفوعة (is_paid = true)الموظف ياخد راتبه كامل — مفيش خصم
إجازة بدون راتب (is_paid = false)بيتخصم من الراتب حسب عدد الأيام — خصم = (راتب يومي × أيام الإجازة)
إجازة بدون رصيد (تجاوز الحد)حسب سياسة الشركة — ممكن يتحول لإجازة بدون راتب

في الرواتب (Payroll):

لما تعمل حساب الرواتب لشهر معين، النظام بيحسب:

أيام الغياب = الأيام اللي الموظف كان فيها في إجازة بدون راتب
خصم الغياب = (الراتب الأساسي ÷ 30) × أيام الغياب
صافي الراتب = إجمالي المكاسب - إجمالي الخصومات - خصم الغياب
📋

تأثير الإجازات على نهاية الخدمة (EOS)

لما موظف يستقيل أو يُنهى خدمته:

  • الرصيد المتبقي من الإجازات السنوية بيتحول لبدل نقدي
  • البدل = رصيد الأيام المتبقية × الراتب اليومي
  • يتضاف على مكافأة نهاية الخدمة كـ "رصيد إجازات مستحق"
مثال: رصيد 15 يوم × (8000 ÷ 30) = 15 × 266.67 = 4,000 ريال بدل إجازات