---
name: hr-management
description: >
  نظام إدارة الموارد البشرية الحكومية الشامل.
  استخدم هذا الـ skill عند: إدارة بيانات الموظفين، الإجازات، الحضور والانصراف،
  الرواتب، التقييم الوظيفي، التدريب، التوظيف، الترقيات، النقل، الإنهاء،
  الهيكل التنظيمي، السلم الوظيفي، أو أي مهمة تتعلق بشؤون الموظفين.
  يشمل التكامل مع نظام مدد ونظام التأمينات الاجتماعية ومنصة مسار.
---

# HR Management System
# نظام إدارة الموارد البشرية

## Domain Model

```csharp
// === الموظف ===
public class Employee : BaseAuditableEntity
{
    public int Id { get; set; }
    public string EmployeeNumber { get; set; } = string.Empty;  // الرقم الوظيفي
    public string NationalId { get; set; } = string.Empty;       // رقم الهوية
    public string NameAr { get; set; } = string.Empty;
    public string? NameEn { get; set; }
    public string? Email { get; set; }
    public string? Phone { get; set; }
    public DateTime DateOfBirth { get; set; }
    public Gender Gender { get; set; }
    public MaritalStatus MaritalStatus { get; set; }
    public string? NafathId { get; set; }

    // الوظيفة
    public int PositionId { get; set; }
    public int DepartmentId { get; set; }
    public int? DirectManagerId { get; set; }
    public int JobGradeId { get; set; }
    public int JobTitleId { get; set; }
    public EmploymentType EmploymentType { get; set; }
    public DateTime HireDate { get; set; }
    public DateTime? ContractEndDate { get; set; }
    public EmployeeStatus Status { get; set; } = EmployeeStatus.Active;

    // العلاقات
    public Position Position { get; set; } = null!;
    public Department Department { get; set; } = null!;
    public Employee? DirectManager { get; set; }
    public JobGrade JobGrade { get; set; } = null!;
    public List<EmployeeDocument> Documents { get; set; } = new();
    public List<LeaveRequest> LeaveRequests { get; set; } = new();
    public List<Attendance> AttendanceRecords { get; set; } = new();
    public List<PerformanceReview> PerformanceReviews { get; set; } = new();
    public List<TrainingRecord> TrainingRecords { get; set; } = new();
    public SalaryInfo Salary { get; set; } = null!;
}

public enum EmployeeStatus
{
    Active,             // على رأس العمل
    OnLeave,            // في إجازة
    Suspended,          // موقوف
    Transferred,        // منقول
    Resigned,           // مستقيل
    Retired,            // متقاعد
    Terminated          // مفصول
}

public enum EmploymentType
{
    Permanent,          // دائم
    Contract,           // عقد
    PartTime,           // دوام جزئي
    Probation,          // تحت التجربة
    Secondment          // منتدب
}

// === الهيكل التنظيمي ===
public class Department
{
    public int Id { get; set; }
    public string NameAr { get; set; } = string.Empty;
    public string? NameEn { get; set; }
    public string Code { get; set; } = string.Empty;
    public int? ParentDepartmentId { get; set; }
    public int? ManagerEmployeeId { get; set; }
    public int Level { get; set; }  // 1=وزارة, 2=إدارة عامة, 3=إدارة, 4=قسم, 5=وحدة
    public bool IsActive { get; set; } = true;
    public Department? ParentDepartment { get; set; }
    public List<Department> SubDepartments { get; set; } = new();
}

public class JobGrade
{
    public int Id { get; set; }
    public string NameAr { get; set; } = string.Empty;
    public int GradeNumber { get; set; }       // المرتبة
    public int Step { get; set; }              // الدرجة
    public decimal BasicSalary { get; set; }
    public decimal TransportAllowance { get; set; }
    public decimal HousingAllowance { get; set; }
}

// === الإجازات ===
public class LeaveRequest : BaseAuditableEntity
{
    public int Id { get; set; }
    public string RequestNumber { get; set; } = string.Empty;
    public int EmployeeId { get; set; }
    public LeaveType LeaveType { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public int TotalDays { get; set; }
    public string? Reason { get; set; }
    public string? AttachmentPath { get; set; }
    public LeaveStatus Status { get; set; } = LeaveStatus.Pending;
    public int? SubstituteEmployeeId { get; set; }  // البديل
    public int? ApprovalWorkflowId { get; set; }
}

public enum LeaveType
{
    Annual,             // سنوية
    Sick,               // مرضية
    Emergency,          // اضطرارية
    Maternity,          // أمومة
    Paternity,          // أبوة
    Hajj,               // حج
    Marriage,           // زواج
    Bereavement,        // وفاة
    Study,              // دراسية
    Unpaid,             // بدون راتب
    Compensatory        // تعويضية
}

// === الحضور والانصراف ===
public class Attendance
{
    public int Id { get; set; }
    public int EmployeeId { get; set; }
    public DateTime Date { get; set; }
    public TimeSpan? CheckInTime { get; set; }
    public TimeSpan? CheckOutTime { get; set; }
    public AttendanceSource Source { get; set; }
    public double? WorkHours { get; set; }
    public bool IsLate { get; set; }
    public bool IsEarlyLeave { get; set; }
    public AttendanceStatus Status { get; set; }
    public string? Notes { get; set; }
    public double? Latitude { get; set; }
    public double? Longitude { get; set; }
}

public enum AttendanceSource
{
    Fingerprint,        // بصمة
    FaceRecognition,    // تعرف على الوجه
    Card,               // بطاقة
    Mobile,             // جوال (GPS)
    Manual              // يدوي
}

// === الرواتب ===
public class SalaryInfo
{
    public int Id { get; set; }
    public int EmployeeId { get; set; }
    public decimal BasicSalary { get; set; }        // الراتب الأساسي
    public decimal HousingAllowance { get; set; }   // بدل سكن
    public decimal TransportAllowance { get; set; }  // بدل نقل
    public decimal OtherAllowances { get; set; }     // بدلات أخرى
    public decimal TotalSalary { get; set; }         // إجمالي الراتب
    public decimal GosiDeduction { get; set; }       // خصم التأمينات
    public decimal OtherDeductions { get; set; }     // خصومات أخرى
    public decimal NetSalary { get; set; }           // صافي الراتب
    public string? BankName { get; set; }
    public string? IBAN { get; set; }
}

public class Payroll
{
    public int Id { get; set; }
    public int Month { get; set; }
    public int Year { get; set; }
    public PayrollStatus Status { get; set; }
    public decimal TotalBasicSalaries { get; set; }
    public decimal TotalAllowances { get; set; }
    public decimal TotalDeductions { get; set; }
    public decimal TotalNetSalaries { get; set; }
    public int EmployeeCount { get; set; }
    public DateTime? ApprovedAt { get; set; }
    public int? ApprovedBy { get; set; }
    public List<PayrollDetail> Details { get; set; } = new();
}

// === تقييم الأداء ===
public class PerformanceReview
{
    public int Id { get; set; }
    public int EmployeeId { get; set; }
    public int ReviewerEmployeeId { get; set; }
    public int ReviewPeriodYear { get; set; }
    public ReviewPeriodType PeriodType { get; set; }
    public decimal OverallScore { get; set; }        // من 5
    public string PerformanceRating { get; set; } = string.Empty;  // ممتاز/جيد جداً/جيد/مقبول/ضعيف
    public string? Strengths { get; set; }
    public string? AreasForImprovement { get; set; }
    public string? Goals { get; set; }
    public ReviewStatus Status { get; set; }
    public List<PerformanceKPI> KPIs { get; set; } = new();
}

public class PerformanceKPI
{
    public int Id { get; set; }
    public int PerformanceReviewId { get; set; }
    public string NameAr { get; set; } = string.Empty;
    public decimal Weight { get; set; }          // الوزن النسبي %
    public decimal TargetValue { get; set; }     // المستهدف
    public decimal ActualValue { get; set; }     // المتحقق
    public decimal Score { get; set; }           // الدرجة
}

// === التدريب ===
public class TrainingRecord
{
    public int Id { get; set; }
    public int EmployeeId { get; set; }
    public string CourseName { get; set; } = string.Empty;
    public string? Provider { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public int DurationHours { get; set; }
    public decimal? Cost { get; set; }
    public string? CertificatePath { get; set; }
    public TrainingStatus Status { get; set; }
}
```

## Leave Balance Calculation

```csharp
public class LeaveBalanceService
{
    // Saudi Labor Law leave entitlements
    private static readonly Dictionary<LeaveType, int> AnnualEntitlements = new()
    {
        { LeaveType.Annual, 30 },        // 30 يوم سنوية (بعد 5 سنوات: 36)
        { LeaveType.Sick, 120 },          // 120 يوم (30 كامل + 60 ثلاثة أرباع + 30 بدون)
        { LeaveType.Emergency, 5 },       // 5 أيام
        { LeaveType.Maternity, 70 },      // 70 يوم
        { LeaveType.Paternity, 3 },       // 3 أيام
        { LeaveType.Hajj, 15 },           // 15 يوم (مرة واحدة)
        { LeaveType.Marriage, 5 },        // 5 أيام
        { LeaveType.Bereavement, 5 },     // 5 أيام
    };

    public async Task<LeaveBalance> CalculateBalanceAsync(int employeeId, LeaveType type, int year)
    {
        var employee = await _context.Employees.FindAsync(employeeId);
        var yearsOfService = (DateTime.Now - employee!.HireDate).Days / 365.25;

        var entitlement = type == LeaveType.Annual && yearsOfService >= 5 ? 36 : 
            AnnualEntitlements.GetValueOrDefault(type, 0);

        var used = await _context.LeaveRequests
            .Where(l => l.EmployeeId == employeeId 
                && l.LeaveType == type 
                && l.StartDate.Year == year
                && l.Status == LeaveStatus.Approved)
            .SumAsync(l => l.TotalDays);

        return new LeaveBalance
        {
            EmployeeId = employeeId,
            LeaveType = type,
            Year = year,
            Entitlement = entitlement,
            Used = used,
            Remaining = entitlement - used,
            CarriedOver = await GetCarriedOverAsync(employeeId, type, year)
        };
    }
}
```

## SQL Schema

```sql
CREATE SCHEMA [HR];

CREATE TABLE [HR].[Employees] (
    [Id] INT IDENTITY(1,1) PRIMARY KEY,
    [EmployeeNumber] NVARCHAR(20) NOT NULL UNIQUE,
    [NationalId] NVARCHAR(10) NOT NULL UNIQUE,
    [NameAr] NVARCHAR(200) NOT NULL,
    [NameEn] NVARCHAR(200) NULL,
    [Email] NVARCHAR(200) NULL,
    [Phone] NVARCHAR(20) NULL,
    [DateOfBirth] DATE NOT NULL,
    [Gender] NVARCHAR(10) NOT NULL,
    [HireDate] DATE NOT NULL,
    [DepartmentId] INT NOT NULL,
    [PositionId] INT NOT NULL,
    [DirectManagerId] INT NULL FOREIGN KEY REFERENCES [HR].[Employees]([Id]),
    [JobGradeId] INT NOT NULL,
    [Status] NVARCHAR(20) NOT NULL DEFAULT 'Active',
    [CreatedAt] DATETIME2 NOT NULL DEFAULT GETUTCDATE()
);

CREATE TABLE [HR].[Departments] (
    [Id] INT IDENTITY(1,1) PRIMARY KEY,
    [NameAr] NVARCHAR(200) NOT NULL,
    [Code] NVARCHAR(20) NOT NULL UNIQUE,
    [ParentDepartmentId] INT NULL FOREIGN KEY REFERENCES [HR].[Departments]([Id]),
    [ManagerEmployeeId] INT NULL,
    [Level] INT NOT NULL DEFAULT 1,
    [IsActive] BIT NOT NULL DEFAULT 1
);

CREATE TABLE [HR].[LeaveRequests] (
    [Id] INT IDENTITY(1,1) PRIMARY KEY,
    [RequestNumber] NVARCHAR(50) NOT NULL UNIQUE,
    [EmployeeId] INT NOT NULL FOREIGN KEY REFERENCES [HR].[Employees]([Id]),
    [LeaveType] NVARCHAR(50) NOT NULL,
    [StartDate] DATE NOT NULL,
    [EndDate] DATE NOT NULL,
    [TotalDays] INT NOT NULL,
    [Reason] NVARCHAR(500) NULL,
    [Status] NVARCHAR(20) NOT NULL DEFAULT 'Pending',
    [SubstituteEmployeeId] INT NULL,
    [ApprovalWorkflowId] INT NULL,
    [CreatedAt] DATETIME2 NOT NULL DEFAULT GETUTCDATE()
);

CREATE TABLE [HR].[Attendance] (
    [Id] INT IDENTITY(1,1) PRIMARY KEY,
    [EmployeeId] INT NOT NULL FOREIGN KEY REFERENCES [HR].[Employees]([Id]),
    [Date] DATE NOT NULL,
    [CheckInTime] TIME NULL,
    [CheckOutTime] TIME NULL,
    [Source] NVARCHAR(50) NOT NULL,
    [WorkHours] FLOAT NULL,
    [IsLate] BIT NOT NULL DEFAULT 0,
    [Status] NVARCHAR(20) NOT NULL,
    UNIQUE([EmployeeId], [Date])
);

CREATE TABLE [HR].[Payroll] (
    [Id] INT IDENTITY(1,1) PRIMARY KEY,
    [Month] INT NOT NULL,
    [Year] INT NOT NULL,
    [Status] NVARCHAR(20) NOT NULL DEFAULT 'Draft',
    [TotalNetSalaries] DECIMAL(18,2) NOT NULL,
    [EmployeeCount] INT NOT NULL,
    [ApprovedAt] DATETIME2 NULL,
    UNIQUE([Month], [Year])
);

CREATE TABLE [HR].[PerformanceReviews] (
    [Id] INT IDENTITY(1,1) PRIMARY KEY,
    [EmployeeId] INT NOT NULL FOREIGN KEY REFERENCES [HR].[Employees]([Id]),
    [ReviewerEmployeeId] INT NOT NULL,
    [ReviewPeriodYear] INT NOT NULL,
    [OverallScore] DECIMAL(3,2) NOT NULL,
    [PerformanceRating] NVARCHAR(50) NOT NULL,
    [Status] NVARCHAR(20) NOT NULL DEFAULT 'Draft'
);
```

## External Integrations

| النظام | التكامل | الوصف |
|--------|---------|--------|
| مُدد (Mudad) | حماية الأجور | رفع ملفات الرواتب الشهرية |
| التأمينات الاجتماعية (GOSI) | اشتراكات | تسجيل/إلغاء موظفين + خصم اشتراكات |
| مسار | الخدمة المدنية | بيانات وظيفية للقطاع الحكومي |
| نفاذ (Nafath) | التحقق | مصادقة هوية الموظف |
| أبشر | بيانات | التحقق من صلاحية الإقامة |
| مقيم | عمالة | إدارة تأشيرات العمالة |

## Reports

| التقرير | الوصف |
|---------|--------|
| كشف الرواتب | تفصيلي شهري لكل موظف |
| تقرير الحضور | إحصائيات التأخر والغياب |
| رصيد الإجازات | الرصيد المتبقي لكل نوع |
| تقييم الأداء | نتائج التقييم ومقارنات |
| الهيكل التنظيمي | شجرة الأقسام والموظفين |
| إحصائيات القوى العاملة | توزيع حسب الجنس/العمر/المرتبة |
| تقرير دوران العمالة | معدل الاستقالات والتعيينات |
| تقرير التدريب | ساعات ونفقات التدريب |
