# Leave Classification API — Frontend Reference

Base: `/api/v1`

---

## Response Envelope

**Success (single):**
```json
{ "success": true, "data": { ... }, "message": "..." }
```

**Success (paginated):**
```json
{ "success": true, "data": [...], "current_page": 1, "last_page": 3, "per_page": 15, "total": 42, "meta": { "current_page": 1, "last_page": 3, "per_page": 15, "total": 42 }, "message": "..." }
```

**Error:**
```json
{ "success": false, "message": "...", "error_code": 422 }
```

---

## 1. Leave Classifications CRUD

### `GET /api/v1/settings/leave_classifications`

Query params: `?status=Active&name=Vacation&per_page=15&page=1`

```json
{
  "data": [{
    "id": 1,
    "name": "Vacation Leave",
    "code": "VL",
    "leave_per_year": 15,
    "description_for_approver": "...",
    "description_for_employee": "...",
    "leave_classification_is": "1",
    "is_paid": true,
    "applicable_gender": null,
    "applicable_employment_statuses": null,
    "others": false,
    "specify": null,
    "remarks": null,
    "status": "Active",
    "created_at": "...",
    "updated_at": "...",
    "employees": [{ "id": 1, "pivot": { "status": "Active" } }]
  }]
}
```

| Field | Type | Values |
|-------|------|--------|
| `leave_classification_is` | enum string | `"1"` = by employee schedule, `"2"` = by calendar days |
| `is_paid` | boolean | `true` = Paid, `false` = Unpaid |
| `applicable_gender` | string\|null | `"male"`, `"female"`, or `null` (all) |
| `applicable_employment_statuses` | array\|null | Array of employment status IDs, or `null` (all) |
| `status` | string | `"Active"`, or any custom value |

### `GET /api/v1/settings/leave_classifications/{id}`

Same shape as a single item in the list above.

### `POST /api/v1/settings/leave_classifications`

```json
{
  "name": "Sick Leave",
  "code": "SL",
  "leave_per_year": 15,
  "description_for_approver": "For approver reference",
  "description_for_employee": "Shown to employee",
  "leave_classification_is": "1",
  "is_paid": true,
  "applicable_gender": null,
  "applicable_employment_statuses": null,
  "others": false,
  "specify": null,
  "remarks": null,
  "status": "Active"
}
```

### `PUT /api/v1/settings/leave_classifications/{id}`

Same body as POST, all fields optional.

### `DELETE /api/v1/settings/leave_classifications/{id}`

Response: `{ "success": true, "data": null, "message": "Leave classification deleted successfully" }`

---

## 2. Employee Override (Force-Include / Force-Exclude)

### `POST /api/v1/settings/leave_classifications/{id}/employees`

Add one or more employees as **force-include overrides** for this classification.

```json
{ "employee_ids": [101, 102, 103] }
```

Creates a pivot record with `status = "Active"`.

### `DELETE /api/v1/settings/leave_classifications/{id}/employees`

Remove override records (deletes the pivot row, reverts to rule-based eligibility).

```json
{ "employee_ids": [101, 102] }
```

---

## 3. Eligibility Queries

### `GET /api/v1/settings/leave_classifications/employee/{employeeId}/eligible`

Returns all classifications this specific employee is eligible for, with available balance.

```json
{
  "data": [{
    "id": 1,
    "name": "Vacation Leave",
    "code": "VL",
    "leave_per_year": 15,
    "leave_classification_is": "1",
    "is_paid": true,
    "applicable_gender": null,
    "applicable_employment_statuses": null,
    "status": "Active",
    "available_balance": 10.0
  }]
}
```

### `GET /api/v1/settings/leave_classifications/employees/eligible`

Paginated list of **all active employees** with their eligible leave classifications.

Query params: `?search=John&department=HR&per_page=10&page=1`

```json
{
  "data": [{
    "employee_id": 1,
    "employee_no": "EMP001",
    "first_name": "John",
    "last_name": "Doe",
    "full_name": "Doe, John",
    "position": "Developer",
    "division": "IT Department",
    "office": "Main Office",
    "email_address": "john@email.com",
    "leave_eligibilities": [{
      "classification_id": 1,
      "classification_name": "Vacation Leave",
      "classification_code": "VL",
      "available_balance": 10.0,
      "is_eligible": true
    }]
  }],
  "meta": { "current_page": 1, "last_page": 3, "per_page": 10, "total": 25 }
}
```

---

## 4. Eligibility Logic (for frontend understanding)

```
For each employee + classification:

  1. Pivot override exists?
     ─ status = "Excluded"  → NOT eligible (skip)
     ─ status = "Active"    → eligible (force-include)

  2. No pivot → evaluate rules:
     ─ applicable_gender = null              → any gender passes
     ─ applicable_gender = "male"/"female"   → must match employee.gender

     ─ applicable_employment_statuses = null  → any status passes
     ─ applicable_employment_statuses = [...] → employee's employment_status_id must be in array

     Both must pass → eligible
```

---

## 5. Data from PDS (not timekeeping)

The frontend should call **PDS endpoints** for these reference data:

| Data | PDS Endpoint (example) | Notes |
|------|------------------------|-------|
| Employee list | `GET /api/employee-information/api/v2/employees/get-all` | Search by name, ID |
| Gender values | Static | `"male"`, `"female"` |
| Employment statuses | PDS `/system-settings?category=employment_status` | IDs stored in `employee_position_details.employment_status_id` |
| Employee gender field | From employee data above | Field: `gender` |

The timekeeping microservice shares the same database but only copied the PDS models for Eloquent relationships — it does not expose its own employee/status endpoints.
