########################################
# EMPLOYEES & HR MODULE REFACTOR
########################################

We want to extend and organize the Employees and HR modules as follows:

- "الموظفين" (Employees) is a main module with:
  - الأدوار (Roles)
  - الموظفين (Employees)
  - المشرفين (Supervisors)
  - مهام (Employee Tasks)
  - الوظائف (Job Positions)
  - الجنسيات (Nationalities)

- "الموارد البشرية" (HR) is a separate module with:
  - الورديات (Work Shifts)
  - مناوبات الموظفين (Employee Shift Assignments)
  - الحضور (Attendance)
  - سجل الحضور (Attendance Log)
  - الوقت الإضافي (Overtime)
  - الرواتب (Payroll Runs)
  - الرواتب المولدة (Generated Payroll / Payroll Lines)
  - الإجازات (Leaves)

Please implement the following without breaking existing employees/payroll logic. Extend the current models where necessary.


========================================
# 1) SIDEBAR / NAV STRUCTURE
========================================

Update the sidebar navigation as follows:

1) Main group: "الموظفين"
   - "الأدوار"      → roles module/routes
   - "الموظفين"    → employees list
   - "المشرفين"    → supervisors management (new page)
   - "مهام"        → employee tasks
   - "الوظائف"     → job positions management (new page)
   - "الجنسيات"    → nationalities management (new page)

2) Main group: "الموارد البشرية"
   - "الورديات"
   - "مناوبات الموظفين"
   - "الحضور"
   - "سجل الحضور"
   - "الوقت الإضافي"
   - "الرواتب"
   - "الرواتب المولدة"
   - "الإجازات"

Keep RTL layout and do not break existing routes for roles, employees, tasks or payroll.
Create new routes/pages or API endpoints where needed.


========================================
# 2) JOB POSITIONS (الوظائف)
========================================

We already have employees with a "job_title_ar". We now want a proper job positions table and link.

### Table: job_positions
Fields:
- id (integer, primary key, auto increment)
- name_ar (string, not null, unique)      // اسم الوظيفة (مثال: "أخصائية شعر", "مشرفة فرع")
- code (string, nullable, unique)         // كود الوظيفة (اختياري)
- description_ar (string, nullable)
- is_active (boolean, default true)
- created_at (datetime)
- updated_at (datetime)

### Update employees table:
- Add job_position_id (integer, nullable, foreign key to job_positions.id)
- Optionally keep job_title_ar as a free-text field for legacy.

### Job Positions APIs:
- GET /job-positions
- POST /job-positions
- GET /job-positions/:id
- PUT /job-positions/:id
- DELETE /job-positions/:id (soft delete: is_active = false)

Use Arabic error messages such as:
- "اسم الوظيفة مطلوب"
- "اسم الوظيفة مستخدم من قبل"


========================================
# 3) NATIONALITIES (الجنسيات)
========================================

Instead of storing nationality as free-text only, define a nationalities table.

### Table: nationalities
Fields:
- id (integer, primary key, auto increment)
- name_ar (string, not null, unique)   // مثال: "سعودية", "يمنية", "مصرية"
- code (string, nullable, unique)      // ISO code or internal code
- is_active (boolean, default true)
- created_at (datetime)
- updated_at (datetime)

### Update employees table:
- Replace or add nationality_id (integer, foreign key to nationalities.id)
- Keep nationality_name_ar as optional free-text if needed.

### Nationalities APIs:
- GET /nationalities
- POST /nationalities
- GET /nationalities/:id
- PUT /nationalities/:id
- DELETE /nationalities/:id (soft delete)

Validation messages:
- "الجنسية مطلوبة"
- "الجنسية مستخدمة من قبل"


========================================
# 4) SUPERVISORS (المشرفين)
========================================

We need to define which employees are supervisors and which employees report to them.

### Table: employee_supervisors
Fields:
- id (integer, primary key, auto increment)
- supervisor_employee_id (integer, foreign key to employees.id)  // المشرف
- employee_id (integer, foreign key to employees.id)             // الموظف التابع
- created_at (datetime)
- updated_at (datetime)

Rules:
- An employee can have multiple supervisors if needed, but typically one.
- A supervisor is just an employee who has one or more subordinates.

### Supervisors APIs:
- GET /supervisors
  - List all employees who are supervisors, with count of subordinates.
- GET /supervisors/:id/employees
  - List employees assigned to this supervisor.
- POST /supervisors/assign
  - Assign a supervisor to an employee.
  - Request:
    {
      "supervisor_employee_id": 3,
      "employee_id": 7
    }
- DELETE /supervisors/assignments/:id
  - Remove a supervisor–employee assignment.

Arabic errors:
- "المشرف غير موجود"
- "الموظف غير موجود"
- "هذا الربط موجود مسبقاً"


========================================
# 5) WORK SHIFTS (الورديات)
========================================

We need to define shifts (وردية) with start/end times and break, then assign employees to shifts by date range.

### Table: work_shifts (الورديات)
Fields:
- id (integer, primary key, auto increment)
- name_ar (string, not null)                   // اسم الشفت (مثال: "صباحي", "مسائي", "شفت عروس")
- shift_type (string, not null)                // "morning" or "evening" or "custom"
- start_time (time, not null)                  // وقت بداية الشفت (HH:MM)
- end_time (time, not null)                    // وقت نهاية الشفت (HH:MM)
- break_start_time (time, nullable)            // بداية البريك
- break_end_time (time, nullable)              // نهاية البريك
- is_active (boolean, default true)
- created_at (datetime)
- updated_at (datetime)

### Work Shifts APIs:
- GET /hr/work-shifts
- POST /hr/work-shifts
- GET /hr/work-shifts/:id
- PUT /hr/work-shifts/:id
- DELETE /hr/work-shifts/:id (soft delete: is_active = false)

Validation messages:
- "اسم الشفت مطلوب"
- "وقت بداية الشفت مطلوب"
- "وقت نهاية الشفت مطلوب"
- "وقت نهاية الشفت يجب أن يكون بعد بداية الشفت"


========================================
# 6) EMPLOYEE SHIFT ASSIGNMENTS (مناوبات الموظفين)
========================================

After creating shifts, we need to assign employees to shifts for a specific period.

### Table: employee_shift_assignments (مناوبات الموظفين)
Fields:
- id (integer, primary key, auto increment)
- employee_id (integer, foreign key to employees.id)
- work_shift_id (integer, foreign key to work_shifts.id)
- start_date (date, not null)             // تاريخ بداية المناوبة
- end_date (date, not null)               // تاريخ نهاية المناوبة
- created_at (datetime)
- updated_at (datetime)

Behavior:
- This defines the employee's expected working schedule for that period.
- Later, attendance and lateness/overtime will use this shift data.

### APIs:
- GET /hr/shift-assignments
  - Filters:
    - ?employee_id=
    - ?date=YYYY-MM-DD  (return assignments covering that date)
- POST /hr/shift-assignments
  - Request example:
    {
      "employee_id": 7,
      "work_shift_id": 2,
      "start_date": "2025-10-01",
      "end_date": "2025-10-31"
    }
- PUT /hr/shift-assignments/:id
- DELETE /hr/shift-assignments/:id

Validation messages:
- "الموظف غير موجود"
- "الشفت غير موجود"
- "تاريخ البداية مطلوب"
- "تاريخ النهاية مطلوب"
- "تاريخ النهاية يجب أن يكون بعد تاريخ البداية"


========================================
# 7) ATTENDANCE & ATTENDANCE LOG (الحضور + سجل الحضور)
========================================

We assume that fingerprint device data will be imported (by file or integration) and stored as raw logs,
then we compute a daily attendance summary for each employee.

### Table: attendance_raw (optional)
Raw logs imported from fingerprint device.

Fields:
- id (integer, primary key, auto increment)
- employee_id (integer, foreign key to employees.id)
- timestamp (datetime, not null)            // وقت البصمة
- direction (string, nullable)              // "in" or "out" if provided by device
- device_id (string, nullable)
- created_at (datetime)

This table can be used for debugging or detailed history.

### Table: attendance_logs (سجل الحضور اليومي)
Daily summarized record per employee per day.

Fields:
- id (integer, primary key, auto increment)
- employee_id (integer, foreign key to employees.id)
- date (date, not null)
- work_shift_id (integer, nullable, foreign key to work_shifts.id)   // الشفت المتوقع لهذا اليوم
- scheduled_start_time (time, nullable)
- scheduled_end_time (time, nullable)
- actual_check_in (time, nullable)
- actual_check_out (time, nullable)
- late_minutes (integer, not null, default 0)          // دقائق التأخير
- overtime_minutes (integer, not null, default 0)      // دقائق العمل الإضافي
- total_work_minutes (integer, not null, default 0)    // صافي وقت العمل
- status (string, not null)                            // "present", "absent", "late", "on_leave", "off"
- notes (string, nullable)
- created_at (datetime)
- updated_at (datetime)

Behavior:
- Use the assigned shift from employee_shift_assignments for that date to fill scheduled_start_time and scheduled_end_time.
- From attendance_raw (or manual entry), determine:
  - earliest check-in
  - latest check-out
- Compute:
  - late_minutes = max(0, difference between actual_check_in and scheduled_start_time)
  - overtime_minutes = max(0, actual_check_out - scheduled_end_time), considering break if needed.
  - total_work_minutes = actual_check_out - actual_check_in minus break duration.

### Attendance APIs:

1) GET /hr/attendance-logs
   - Filters:
     - ?date=YYYY-MM-DD
     - ?employee_id=
     - ?status=

2) POST /hr/attendance-raw/import
   - Endpoint to import raw logs (receiving an array of logs).
   - For now, just store them and optionally generate or update attendance_logs.

3) POST /hr/attendance-logs/generate
   - For a given date range, generate attendance_logs from:
     - employee_shift_assignments
     - attendance_raw logs.
   - Basic implementation is enough – exact algorithm can be simple.


========================================
# 8) OVERTIME (الوقت الإضافي)
========================================

Sometimes overtime is entered manually by HR/supervisor.

### Table: overtime_entries
Fields:
- id (integer, primary key, auto increment)
- employee_id (integer, foreign key to employees.id)
- date (date, not null)
- start_time (time, not null)
- end_time (time, not null)
- total_minutes (integer, not null)       // computed: end_time - start_time
- reason (string, nullable)
- approved_by_employee_id (integer, nullable)  // المشرف أو المسؤول المعتمد
- created_at (datetime)
- updated_at (datetime)

Behavior:
- These entries can later be used in payroll calculation (overtime_amount).

### APIs:
- GET /hr/overtime
- POST /hr/overtime
- GET /hr/overtime/:id
- PUT /hr/overtime/:id
- DELETE /hr/overtime/:id

Validation:
- "وقت البداية مطلوب"
- "وقت النهاية مطلوب"
- "وقت النهاية يجب أن يكون بعد وقت البداية"


========================================
# 9) LEAVES / VACATIONS (الإجازات)
========================================

We need to manage employee leave requests, either created by admin or by the employee later.

Leave types:
- "annual"      (سنوية)
- "sick"        (مرضية)
- "unpaid"      (غير مدفوعة)
- "public_holiday" (عطلة عامة)
- "paid"        (مدفوعة أخرى)
- "other"       (أخرى)
- "hourly"      (إجازة ساعية)

### Table: leaves
Fields:
- id (integer, primary key, auto increment)
- employee_id (integer, foreign key to employees.id)
- requested_by_employee_id (integer, nullable)  // الموظف أو الأدمن الذي قدّم الطلب
- leave_type (string, not null)                // one of: "annual", "sick", "unpaid", "public_holiday", "paid", "other", "hourly"
- start_date (date, not null)
- end_date (date, not null)
- start_time (time, nullable)                  // for hourly leave
- end_time (time, nullable)                    // for hourly leave
- duration_days (real, not null, default 0)    // عدد الأيام (يمكن حسابه)
- duration_hours (real, not null, default 0)   // للساعية
- status (string, not null)                    // "pending", "approved", "rejected", "canceled"
- attachment_url (string, nullable)            // ملف مرفق (تقرير طبي مثلاً)
- reason (string, nullable)                    // سبب الإجازة / ملاحظات
- created_at (datetime)
- updated_at (datetime)

Behavior:
- If leave_type = "hourly":
  - start_date = end_date (same day)
  - start_time and end_time required
  - duration_hours computed from time difference.
- If leave_type is not "hourly":
  - start_time and end_time can be null.
  - duration_days = number of days between start_date and end_date (inclusive).
- Approved leaves should set attendance_logs.status = "on_leave" for those dates.

### Leaves APIs:

1) GET /hr/leaves
   - Filters:
     - ?employee_id=
     - ?status=
     - ?date=YYYY-MM-DD (leaves covering specific date)

2) POST /hr/leaves
   - Admin-created leave OR later employee self-request.
   - Request example:
   {
     "employee_id": 7,
     "requested_by_employee_id": 3,
     "leave_type": "annual",
     "start_date": "2025-10-10",
     "end_date": "2025-10-15",
     "reason": "إجازة سنوية"
   }

   Or hourly:
   {
     "employee_id": 7,
     "requested_by_employee_id": 7,
     "leave_type": "hourly",
     "start_date": "2025-10-20",
     "end_date": "2025-10-20",
     "start_time": "14:00",
     "end_time": "16:00",
     "reason": "مراجعة مستشفى"
   }

   - By default, status = "pending" (or "approved" if created by admin – you can decide and document in code comments).

3) PUT /hr/leaves/:id
   - Update fields and/or status.
   - If status changes to "approved":
     - Update or create attendance_logs for those dates with status = "on_leave".

4) DELETE /hr/leaves/:id
   - Optional: mark as canceled or physically delete.

Validation messages:
- "الموظف غير موجود"
- "نوع الإجازة غير صحيح"
- "تاريخ البداية مطلوب"
- "تاريخ النهاية مطلوب"
- "تاريخ النهاية يجب أن يكون بعد تاريخ البداية"
- "وقت البداية مطلوب في الإجازة الساعية"
- "وقت النهاية مطلوب في الإجازة الساعية"


========================================
# 10) PAYROLL LINKS (الرواتب والرواتب المولدة)
========================================

We already have:
- salary_profiles
- payroll_runs
- payroll_lines

For now:
- Do NOT change their core structure.
- Later we will integrate:
  - attendance_logs (late_minutes, overtime_minutes)
  - overtime_entries
  - leaves (unpaid days)  
  into payroll calculations.

Just ensure:
- "الرواتب" (payroll_runs) route is listed under "الموارد البشرية"
- "الرواتب المولدة" (payroll_lines per run) is also under "الموارد البشرية".

Keep all existing functionality working.


========================================
# 11) GENERAL NOTES
========================================

- Use Arabic field labels where applicable in JSON.
- Use Arabic error messages for validations.
- Keep the code modular:
  - Put HR-related routes under something like: `src/routes/hr/`
  - Services and controllers under `src/services/hr/`, `src/controllers/hr/`.

- Do NOT remove any existing HR or employees functionality; only extend and reorganize.
