# Holiday data model (HR-11)

This document describes the holiday/leave data model used by the IGF HR app. It supports employee requests, manager approval, and display on the calendar.

---

## Overview

There are **three** related concepts:

| Concept | Purpose | Collection |
|--------|---------|------------|
| **Holiday** (leave request) | Employee requests time off; manager approves/rejects | `holidays` |
| **HolidayAllowance** | Annual allowance (days per year per employee) | `holiday_allowances` |
| **PublicHoliday** | Company-wide non-working days (e.g. bank holidays) | `public_holidays` |

---

## 1. Holiday (leave request)

**Model:** `models/Holiday.js`  
**Collection:** `holidays`

Represents a single leave request from an employee.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `adminId` | ObjectId (ref: Admin) | Yes | Employee who requested the leave |
| `startDate` | Date | Yes | First day of leave |
| `endDate` | Date | Yes | Last day of leave |
| `comment` | String | No | Optional note from employee (default `''`) |
| `status` | String | Yes | `pending` \| `approved` \| `rejected` (default `pending`) |
| `rejectedReason` | String | No | Set when status is `rejected` (default `null`) |
| `approvedBy` | ObjectId (ref: Admin) | No | Manager who approved/rejected (default `null`) |
| `createdAt` | Date | Yes | Set on create (default `Date.now`) |
| `updatedAt` | Date | Yes | Set on create and on any update |

**Lifecycle:**

- Employee creates request → `status: 'pending'`.
- Manager approves → `status: 'approved'`, `approvedBy` set, `rejectedReason` cleared.
- Manager rejects → `status: 'rejected'`, `approvedBy` set, `rejectedReason` required.
- Only **pending** requests can be edited or deleted by the employee.

**API (existing):** `routes/holidayRoutes.js`

- `GET /api/holidays?adminId=&status=` – list (employee: own; manager: any by adminId)
- `GET /api/holidays/:id` – get one
- `POST /api/holidays` – create request (body: `startDate`, `endDate`, `comment`)
- `PUT /api/holidays/:id` – update (employee: pending only; manager: approve/reject via `status`, `rejectedReason`)
- `DELETE /api/holidays/:id` – delete (pending only, own)

---

## 2. HolidayAllowance

**Model:** `models/HolidayAllowance.js`  
**Collection:** `holiday_allowances`

Annual allowance (number of days) per employee per year. Used to compute *used* and *remaining* days from approved holidays (computed, not stored).

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `adminId` | ObjectId (ref: Admin) | Yes | Employee |
| `year` | Number | Yes | Year (e.g. 2026) |
| `allowanceDays` | Number | Yes | Total days allowed for that year |
| `createdAt` | Date | Yes | |
| `updatedAt` | Date | Yes | |

**Index:** `{ adminId: 1, year: 1 }` unique (one allowance per employee per year).

**Usage:** “My allowance” / “Allowance used” is derived by summing **approved** holiday request days in that year for that employee, then `remaining = allowanceDays - usedDays`.

---

## 3. PublicHoliday

**Model:** `models/PublicHoliday.js`  
**Collection:** `public_holidays`

Company-wide non-working days (e.g. bank holidays). Can be used to grey out or mark days on the calendar and optionally exclude from allowance.

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | String | Yes | e.g. "Christmas Day" |
| `nameFr` | String | No | French name, e.g. "Noël" |
| `date` | Date | Yes | Single date |

No unique constraint; multiple entries can exist (e.g. different years). For “display on calendar” (HR-15), the frontend can query by date range and show these alongside approved `Holiday` requests.

---

## How this maps to your JIRA tickets

| Ticket | What it needs | Covered by |
|--------|----------------|------------|
| **HR-11** Design holiday data model | Clear schema and lifecycle | This doc + `Holiday`, `HolidayAllowance`, `PublicHoliday` |
| **HR-12** Create holiday request form | Create a leave request | `POST /api/holidays` + body `startDate`, `endDate`, `comment` |
| **HR-13** Manager holiday approval interface | List pending, approve/reject | `GET /api/holidays?status=pending` (manager), `PUT /api/holidays/:id` with `status`, `rejectedReason` |
| **HR-14** Implement holiday status update logic | Status transitions and validation | Already in `holidayRoutes.js` PUT (manager path + pending-only edit) |
| **HR-15** Display approved holidays on calendar | Data to show approved leave | `GET /api/holidays?status=approved` (and optionally by date range); use `startDate`/`endDate` to render on calendar |

---

## Optional future extensions

- **Request type:** e.g. `type: 'annual' | 'sick' | 'unpaid'` if you need to distinguish.
- **Half-day:** e.g. `isHalfDay: Boolean` or `startDate`/`endDate` same day + `halfDay: 'am'|'pm'`.
- **Date-range query:** e.g. `GET /api/holidays?startDate=&endDate=&status=approved` for the calendar view (could be added in holidayRoutes).
- **Public holidays:** Implemented – CRUD at `/api/public-holidays`, Manager "Public holidays" tab, optional seed `scripts/seed-public-holidays-2026.js`.

The current model is enough to implement HR-12 through HR-15; the above are only if product requirements grow.
