# OGCC Cumulative Leave (CL) Module — Frontend Integration Guide

> **Source of truth for menu hierarchy:** [`MENU_HIERARCHY.md`](../MENU_HIERARCHY.md) in the frontend repo.
> All `[name: "..."]` references below correspond to the `name` field in `src/App/links.tsx` and are used by the permission API (`POST /identity/api/v1/roles-routes/status`).

---

## 1. Where CL Features Live in the Actual Menu Hierarchy

The frontend has **three entry points** for CL features, each serving a different persona:

| Persona | Location in Menu | `[name]` |
|---------|-----------------|----------|
| **Employee (ESS)** | `My Account > Filings > Leave` | `filings-my-leave-profile` |
| **HR Admin (Setup)** | `System Settings > System Library > Leave Classification` | part of `SysSettings` |
| **HR Admin (Ops)** | `Time Management > Leave Ledger` | `LeaveLedger` |

---

### 1.1 System Settings — Leave Classification (Setup)

```
System Settings                           [name: "SystemSettings"]
└── System Library                        [name: "SysSettings"]
    └── Leave Classification
```

This is where **CL batch management** (defining batches, types, and employee assignments) belongs — analogous to how `SettingLeaveClassificationEligibleEmployee` works for regular leave types.

| CL Feature | Frontend Placement |
|-----------|-------------------|
| CL Batches (CRUD: NCL, CLE, CLA) | `System Settings > System Library > Leave Classification` → new sub-tab "Cumulative Leave" |
| CL Types (per batch) | Same sub-tab — inline or nested under batch detail |
| Batch Assignments (employee → batch) | Same sub-tab — reuse existing employee multi-select pattern |

---

### 1.2 Time Management — Leave Ledger (Operations & Monitoring)

```
Time Management                           [name: "PersonalAdministration"]
├── Leave Ledger                          [name: "LeaveLedger"]
│   ├── Leave Balance History             [name: "LeaveBalanceHistory"]
│   └── Leave Card                        [name: "LeaveCard"]
```

This is where **CL balance/ledger views and Force Leave** belong — operational HR monitoring alongside VL/SL balances.

| CL Feature | Frontend Placement |
|-----------|-------------------|
| CL Balances (NCL, CLE, CLA-30, CLA-16) | `Time Management > Leave Ledger` → new section "CL Balances" |
| CL Ledger (transaction log) | `Time Management > Leave Ledger` → new section "CL Ledger" |
| Force Leave (candidates & scheduling) | `Time Management > Leave Ledger` → new section "Force Leave" |
| Manual allocation triggers (buttons) | Same section — inline actions |

---

### 1.3 My Account — Filings (ESS / Employee Self-Service)

```
My Account                                [name: "MyAccount"]
├── Filings                               [name: "my-filings"]
│   └── Leave                             [name: "filings-my-leave-profile"]
```

For future scope: employees can view their own CL balances and force leave obligations here, alongside their regular leave profile.

| CL Feature | Frontend Placement |
|-----------|-------------------|
| My CL Balances (read-only) | `My Account > Filings > Leave` → new sub-section |
| My Force Leave Schedule | `My Account > Filings > Leave` → new sub-section |

---

## 2. API Endpoints

All endpoints exist under **both** v1 (`/api/v1`) and v2 (`/api/v2`) prefixes.

### 2.1 CL Batch Management (System Settings)

| Method | URL | Description |
|--------|-----|-------------|
| GET | `/api/v1/settings/cl-batches` | List all CL batches (paginated) |
| POST | `/api/v1/settings/cl-batches` | Create a new CL batch |
| GET | `/api/v1/settings/cl-batches/{id}` | Get single batch |
| PUT | `/api/v1/settings/cl-batches/{id}` | Update batch |
| DELETE | `/api/v1/settings/cl-batches/{id}` | Delete batch |

**Batch Model Fields:**

```json
{
  "id": 1,
  "code": "NCL",
  "name": "Non-Cumulative Leave",
  "description": "30-day block credited in full...",
  "status": "Active",
  "cl_types": [
    {
      "id": 1,
      "cl_batch_id": 1,
      "code": "NCL",
      "name": "Non-Cumulative Leave",
      "leave_credit_days": 30,
      "credit_frequency": "yearly",
      "is_pro_rated": true,
      "is_excludable": true,
      "description": "...",
      "status": "Active"
    }
  ],
  "assignments_count": 15,
  "created_at": "2026-05-18T10:11:24.000000Z",
  "updated_at": "2026-05-18T10:11:24.000000Z"
}
```

**There are exactly 3 seeded batches:**

| Code | Name | Types |
|------|------|-------|
| NCL | Non-Cumulative Leave (Batch 1) | NCL (30 days, yearly, pro-rated) |
| CLE | Cumulative Leave Earning (Batch 2) | CLE (2.5 days, monthly) |
| CLA | Anniversary Block Leaves (Batch 3) | CLA-30 (30 days), CLA-16 (16 days) |

**Create/Update Payload:**

```json
{
  "code": "NCL",
  "name": "Non-Cumulative Leave",
  "description": "Optional description",
  "status": "Active"
}
```

### 2.2 Employee Batch Assignments (System Settings)

| Method | URL | Description |
|--------|-----|-------------|
| GET | `/api/v1/settings/cl-assignments` | List all assignments (paginated) |
| POST | `/api/v1/settings/cl-assignments` | Create assignment |
| GET | `/api/v1/settings/cl-assignments/{id}` | Get single assignment |
| PUT | `/api/v1/settings/cl-assignments/{id}` | Update assignment |
| DELETE | `/api/v1/settings/cl-assignments/{id}` | Delete assignment |
| GET | `/api/v1/employees/{employeeId}/cl-assignment` | Get assignment for a specific employee |

**Assignment Model Fields:**

```json
{
  "id": 1,
  "employee_id": "EMP001",
  "employee": { "...employee details..." },
  "cl_batch_id": 1,
  "batch": { "...batch details..." },
  "assumption_to_duty_date": "2024-06-01",
  "dca_rank": "SG-24",
  "is_excluded": false,
  "status": "Active",
  "assigned_by": "admin@example.com",
  "assigned_at": "2026-05-18T10:11:24.000000Z"
}
```

**Create/Update Payload:**

```json
{
  "employee_id": "EMP001",
  "cl_batch_id": 1,
  "assumption_to_duty_date": "2024-06-01",
  "dca_rank": "SG-24",
  "is_excluded": false,
  "status": "Active"
}
```

### 2.3 CL Balances & Ledger (Time Management)

| Method | URL | Description |
|--------|-----|-------------|
| GET | `/api/v1/cl/balances?employee_id=EMP001` | Get all CL balances for an employee |
| GET | `/api/v1/cl/ledger?employee_id=EMP001&cl_type_id=1&year=2026` | Get CL ledger entries (filtered, paginated) |
| POST | `/api/v1/cl/allocate/ncl` | Manual trigger NCL allocation |
| POST | `/api/v1/cl/accrue/cle` | Manual trigger CLE accrual |
| POST | `/api/v1/cl/allocate/cla` | Manual trigger CLA allocation |

**Balances Response:**

```json
{
  "success": true,
  "message": "CL balances retrieved successfully",
  "data": {
    "employee_id": "EMP001",
    "employee_name": "Dela Cruz, Juan A.",
    "balances": [
      {
        "cl_type_id": 1,
        "code": "NCL",
        "name": "Non-Cumulative Leave",
        "batch": "NCL",
        "total_earned": 30,
        "total_used": 5,
        "balance": 25
      },
      {
        "cl_type_id": 2,
        "code": "CLE",
        "name": "Cumulative Leave Earning",
        "batch": "CLE",
        "total_earned": 12.5,
        "total_used": 2,
        "balance": 10.5
      },
      {
        "cl_type_id": 3,
        "code": "CLA-30",
        "name": "Anniversary Block Leave (30 days)",
        "batch": "CLA",
        "total_earned": 30,
        "total_used": 0,
        "balance": 30
      }
    ]
  }
}
```

**Manual Allocation Payloads:**

```json
// POST /api/v1/cl/allocate/ncl
{
  "year": 2026,
  "employee_id": "EMP001"
}
```

```json
// POST /api/v1/cl/accrue/cle
{
  "year": 2026,
  "month": 5,
  "employee_id": "EMP001"
}
```

```json
// POST /api/v1/cl/allocate/cla
{
  "date": "2026-05-18",
  "employee_id": "EMP001"
}
```

### 2.4 Force Leave (Time Management)

| Method | URL | Description |
|--------|-----|-------------|
| GET | `/api/v1/cl/force-leave/candidates?year=2026` | List employees exceeding 120-day VL cap |
| GET | `/api/v1/cl/force-leave/obligations?employee_id=EMP001&year=2026` | Get force leave obligations |
| POST | `/api/v1/cl/force-leave/schedule` | Schedule a force leave entry |

**Candidates Response:**

```json
{
  "success": true,
  "message": "Force leave candidates retrieved successfully",
  "data": [
    {
      "employee_id": "EMP001",
      "employee_name": "Dela Cruz, Juan A.",
      "vl_balance": 135,
      "excess_days": 15,
      "required_force_leave_days": 5,
      "batch": "NCL"
    }
  ]
}
```

**Schedule Payload:**

```json
{
  "employee_id": "EMP001",
  "year": 2026,
  "start_date": "2026-06-15",
  "end_date": "2026-06-19",
  "remarks": "Mandatory force leave per CSC rules"
}
```

---

## 3. Batch System Explained

The CL module uses a **three-batch system**. Each batch represents a different CL type with different accrual rules.

### Batch 1 — NCL (Non-Cumulative Leave)
| Property | Value |
|----------|-------|
| Credit | **30 days** credited in full at start of calendar year |
| Pro-rated? | **Yes** — mid-year hires get `30 × (remainingDays / 365)` |
| Excluded? | **DCA 3 rank employees** are excluded |
| Command | `php artisan cl:allocate-ncl` |

### Batch 2 — CLE (Cumulative Leave Earning)
| Property | Value |
|----------|-------|
| Credit | **2.5 days** accrued monthly |
| Pro-rated? | No |
| Command | `php artisan cl:accrue-cle` |
| Idempotent? | **Yes** — won't double-accrue for the same month |

### Batch 3 — CLA (Anniversary Block Leave)
| Property | Value |
|----------|-------|
| Credit | **30 days** (CLA-30) **or 16 days** (CLA-16) |
| Trigger | Employee's **work anniversary** (month + day matches) |
| Command | `php artisan cl:allocate-cla` |

---

## 4. Frontend Workflow (Step by Step)

### Step 1: Configure Batches

**Menu path:** `System Settings > System Library > Leave Classification > Cumulative Leave > CL Batches`

The 3 seed batches (NCL, CLE, CLA) already exist. This view is for editing name/description/status and viewing CL types within each batch.

### Step 2: Assign Employees to Batches

**Menu path:** `System Settings > System Library > Leave Classification > Cumulative Leave > Batch Assignments`

For each employee, you configure:
1. **Which batch** they belong to (NCL, CLE, or CLA)
2. **Assumption to duty date** — required for NCL pro-ration and CLA anniversary
3. **DCA rank** — DCA 3 is auto-excluded from NCL
4. **Exclusion flag** — manual override

**UI Suggestion:** Reuse the employee multi-select pattern from `SettingLeaveClassificationEligibleEmployee`.

### Step 3: Trigger Allocation (Manual Actions)

**Menu path:** `Time Management > Leave Ledger > Cumulative Leave` (action buttons)

Available manual triggers:
- **Allocate NCL** → `POST /api/v1/cl/allocate/ncl`
- **Accrue CLE** → `POST /api/v1/cl/accrue/cle`
- **Allocate CLA** → `POST /api/v1/cl/allocate/cla`

These are also callable via cron in production.

### Step 4: View Balances

**Menu path:** `Time Management > Leave Ledger > Cumulative Leave > CL Balances`

Search by employee, show CL balances per type alongside regular VL/SL balances.

### Step 5: View Ledger

**Menu path:** `Time Management > Leave Ledger > Cumulative Leave > CL Ledger`

Transaction log of all allocations, accruals, and usage. Filterable by employee, CL type, year, month.

### Step 6: Force Leave Management

**Menu path:** `Time Management > Leave Ledger > Force Leave`

- List **candidates** (employees with VL balance > 120 days)
- Show VL balance, excess days, required force leave days (5)
- **Schedule** force leave by picking dates + remarks
- View existing **obligations** per employee

---

## 5. Important Business Rules

1. **One batch per employee.** System enforces unique `(employee_id, cl_batch_id)`. Each employee belongs to exactly 1 batch.

2. **NCL excludes DCA 3.** DCA rank 3 employees are skipped during NCL allocation unless overridden by `is_excluded`.

3. **CLE is idempotent.** System checks `(employee_id, cl_type_id, year, month, 'monthly_accrual')` before crediting — safe to click twice.

4. **CLA checks anniversary.** Matches `(month, day)` of `assumption_to_duty_date` against today's date.

5. **CL credits mirror to `leave_managements`.** Each CL command creates:
   - A `cl_ledger` entry (CL-specific tracking)
   - A `leave_managements` entry (so existing balance APIs work)

6. **Force Leave threshold: 120 days VL.** Default obligation is 5 days per year for excess holders.

---

## 6. Error Handling

All endpoints return this format:

```json
// Success
{
  "success": true,
  "message": "CL balances retrieved successfully",
  "data": { "...response data..." }
}

// Paginated
{
  "success": true,
  "message": "CL batches retrieved successfully",
  "data": [ ...items... ],
  "pagination": {
    "current_page": 1,
    "per_page": 15,
    "total": 3,
    "last_page": 1
  }
}

// Error
{
  "success": false,
  "message": "Validation error message or CL batch not found.",
  "data": null,
  "status_code": 422
}
```

| HTTP Code | Meaning |
|-----------|---------|
| 200 | Success |
| 201 | Created (store) |
| 404 | Resource not found |
| 422 | Validation error |
| 500 | Server error |

---

## 7. Quick Reference: Menu → Endpoint Mapping

```
─── SYSTEM SETTINGS (Leave Classification Setup) ───

  Menu: System Settings > System Library > Leave Classification > Cumulative Leave

  GET     /api/v1/settings/cl-batches              list all CL batches
  POST    /api/v1/settings/cl-batches              create batch
  GET     /api/v1/settings/cl-batches/{id}         get batch
  PUT     /api/v1/settings/cl-batches/{id}         update batch
  DELETE  /api/v1/settings/cl-batches/{id}         delete batch

  GET     /api/v1/settings/cl-assignments          list assignments
  POST    /api/v1/settings/cl-assignments          create assignment
  GET     /api/v1/settings/cl-assignments/{id}     get assignment
  PUT     /api/v1/settings/cl-assignments/{id}     update assignment
  DELETE  /api/v1/settings/cl-assignments/{id}     delete assignment
  GET     /api/v1/employees/{employeeId}/cl-assignment  get by employee


─── TIME MANAGEMENT (Operations & Monitoring) ───

  Menu: Time Management > Leave Ledger > Cumulative Leave

  GET     /api/v1/cl/balances                      employee CL balances
  GET     /api/v1/cl/ledger                        CL ledger entries
  POST    /api/v1/cl/allocate/ncl                  trigger NCL allocation
  POST    /api/v1/cl/accrue/cle                    trigger CLE accrual
  POST    /api/v1/cl/allocate/cla                  trigger CLA allocation

  GET     /api/v1/cl/force-leave/candidates        list force leave candidates
  GET     /api/v1/cl/force-leave/obligations       list force leave obligations
  POST    /api/v1/cl/force-leave/schedule          schedule force leave


─── FUTURE: MY ACCOUNT (ESS Self-Service) ───

  Menu: My Account > Filings > Leave (future scope)

  GET     /api/v1/cl/balances?employee_id={me}     my CL balances (read-only)
```

---

## 8. Integration Checklist

1. **System Settings batch screens:**
   - Add "Cumulative Leave" sub-tab under `Leave Classification` in `SysSettings`
   - CL Batches list/detail/edit view
   - Batch Assignments list/create/edit view with employee multi-select

2. **Time Management screens:**
   - Add "Cumulative Leave" section under `Leave Ledger`
   - CL Balances view (employee search + table/card display)
   - CL Ledger transaction log (filterable table)
   - Manual allocation action buttons
   - Force Leave candidates list + schedule form

3. **Permission names** to register in the backend:
   - `cl-batches`
   - `cl-assignments`
   - `cl-balances`
   - `cl-ledger`
   - `force-leave`

4. **Route file:** Add new CL-related routes to both `api.php` and `with_api_gateway.php` (v2 prefix) as needed.

---

## 9. Testing the API

```bash
# List batches
curl http://localhost:8000/api/v1/settings/cl-batches

# Assign an employee to batch 1 (NCL)
curl -X POST http://localhost:8000/api/v1/settings/cl-assignments \
  -H "Content-Type: application/json" \
  -d '{
    "employee_id": "EMP001",
    "cl_batch_id": 1,
    "assumption_to_duty_date": "2024-06-01",
    "dca_rank": "SG-24",
    "status": "Active"
  }'

# Get CL balances for an employee
curl "http://localhost:8000/api/v1/cl/balances?employee_id=EMP001"
```
