# LBDI BRAIN — Apex Loans: Application Status & Approval Workflow Explainer

> **Scope:** `apex_facilities` table · `apex_loans` table · `ApexFacilityModel::syncFacilityStatus()` · `show.php` approval panel  
> **Last reviewed:** 2026-05-28

---

## 1. Facility Application Statuses

Every corporate facility record (`apex_facilities`) carries a `status` column that reflects exactly where it sits in its lifecycle.  There are **six possible values**.

| Status | Badge Colour | Plain-English Meaning |
|---|---|---|
| `draft` | Grey | The application has been created but not yet submitted. Credit officers can still edit all fields freely. |
| `submitted` | Blue (Info) | The application has been sent for approval. Editing is now restricted to privileged roles. The Credit Supervisor can now act on it. |
| `under_review` | Amber (Warning) | The Credit Supervisor has approved Tier 1. The file is now moving through the remaining tiers. |
| `active` | Green (Success) | All required approval tiers have been satisfied. The facility is live and employee sub-loans can be disbursed. |
| `suspended` | Grey (Secondary) | The facility has been temporarily suspended. (Currently managed directly in DB; no UI action yet.) |
| `closed` | Grey (Secondary) | The facility is permanently closed. No further transactions are permitted. |

> **Rule:** Status only ever moves **forward** — it never automatically regresses.  
> `draft → submitted → under_review → active`  
> `suspended` and `closed` are terminal states set manually.

---

## 2. How Status Transitions Work (`syncFacilityStatus`)

Status transitions after the initial submission are handled automatically by `ApexFacilityModel::syncFacilityStatus(int $id, array $facility)`.  
This method is called every time an approval tier is saved via the `updateApproval()` controller action.

### Entry Guard
The method **exits immediately** (does nothing) if the current status is anything other than `submitted` or `under_review`.  
This protects `draft`, `active`, `suspended`, and `closed` facilities from being touched by the approval engine.

```
if status NOT IN ('submitted', 'under_review') → return, do nothing
```

### Transition Rules (evaluated in order)

```
Rule 1 — Activate
  IF  credit_head_status    = 'Approved'
  AND risk_mgmt_status      = 'Approved'
  AND evp_finance_status    = 'Approved'
  AND (evp_operations_status = 'Approved' OR ceo_president_status = 'Approved')
  THEN  SET status = 'active'
        RETURN (do not evaluate Rule 2)

Rule 2 — Advance to Under Review
  IF  current status = 'submitted'
  AND credit_supervisor_status = 'Approved'
  THEN  SET status = 'under_review'
```

> **Why this order?**  Rule 1 is evaluated first so that a facility can jump directly from `submitted` to `active` if all tiers were somehow pre-approved — it never gets "stuck" at `under_review` on a re-run.

---

## 3. Six-Tier Approval Workflow

Each tier is sequential — a tier's action controls are only unlocked when the preceding tier has been approved.  Attempting to save a locked tier through the UI is blocked; attempting to save it via the API is rejected by the controller.

```
┌──────────────────────────────────────────────────────────┐
│  Tier 1 — Credit Supervisor                              │
│  Prerequisite : Facility must be submitted (any status   │
│                 other than draft)                        │
│  Authorised roles : credit_supervisor · super_admin      │
│  On Approve → status moves to  under_review              │
└───────────────────────┬──────────────────────────────────┘
                        ↓ (Credit Supervisor = Approved)
┌──────────────────────────────────────────────────────────┐
│  Tier 2 — Credit Head                                    │
│  Prerequisite : Tier 1 = Approved                        │
│  Authorised roles : credit_manager · super_admin         │
└───────────────────────┬──────────────────────────────────┘
                        ↓ (Credit Head = Approved)
┌──────────────────────────────────────────────────────────┐
│  Tier 3 — Risk Management                                │
│  Prerequisite : Tier 2 = Approved                        │
│  Authorised roles : risk_officer · risk_manager          │
│                     super_admin                          │
└───────────────────────┬──────────────────────────────────┘
                        ↓ (Risk Management = Approved)
┌──────────────────────────────────────────────────────────┐
│  Tier 4 — EVP Finance                                    │
│  Prerequisite : Tier 3 = Approved                        │
│  Authorised roles : evp_finance · super_admin            │
└───────────────────────┬──────────────────────────────────┘
                        ↓ (EVP Finance = Approved)
┌──────────────────────────────────────────────────────────┐
│  Tier 5 — CEO / Management                               │
│  Prerequisite : Tier 4 = Approved                        │
│  Authorised roles : evp_operations · ceo · president     │
│                     super_admin                          │
│  On Approve (or EVP Operations approves) → status moves  │
│  to  active  (Rule 1 fires in syncFacilityStatus)        │
└──────────────────────────────────────────────────────────┘
```

### Tier Action Values

Each tier's `_status` column stores one of three values:

| Value | Meaning |
|---|---|
| `Pending` | No decision yet (default). |
| `Approved` | The tier officer has approved. Unlocks the next tier. |
| `Denied` | The tier officer has denied. The facility is not automatically closed — manual intervention is required. A `Denied` at any tier does NOT advance the status; it keeps the facility in its current status until corrected. |

### Locking Logic (UI)

A tier's save controls are shown only when **all** of the following are true:

1. The logged-in user holds one of the tier's authorised roles.
2. The facility is not in `draft` status (i.e., it has been submitted).
3. The preceding tier is `Approved` (the `prereq` flag is `true`).

If conditions 1 and 2 are met but condition 3 is not, the tier shows a **locked** indicator with the message explaining which tier is still outstanding.

---

## 4. Action Button Visibility Rules

The action buttons in the facility detail header (`show.php`) are shown or hidden based on the combination of facility status, user role, and permission flag.

| Button | Shown When |
|---|---|
| **Add Employee Loan** | `facility.status = 'active'` AND user has `applications.edit` permission |
| **Edit** | Facility is NOT fully approved (`$fullyApproved = false`) AND user holds `super_admin`, `credit_manager`, or `credit_supervisor` role |
| **Submit for Review** | User has `applications.submit` permission AND `facility.status = 'draft'` |
| **Record Repayment** | `facility.status = 'active'` AND user has `applications.edit` permission |
| **Back** | Always visible |

> **`$fullyApproved` (edit lock) definition:**  
> The Edit button is hidden when ALL five tiers have status = `Approved`:  
> `credit_supervisor` + `credit_head` + `risk_mgmt` + `evp_finance` + `ceo_president`  
> Note: this is stricter than the activation rule — the Edit lock requires all five; activation only needs tiers 2–4 plus tier 5 OR EVP Operations.

---

## 5. Privilege Levels Summary

```
super_admin          → Can act on all tiers. Can edit at any stage (before full approval).
credit_supervisor    → Tier 1 approvals. Can edit facilities.
credit_manager       → Tier 2 (Credit Head) approvals. Can edit facilities.
risk_officer         → Tier 3 approvals.
risk_manager         → Tier 3 approvals.
evp_finance          → Tier 4 approvals.
evp_operations       → Tier 5 approvals (satisfies the EVP Operations OR CEO/President rule).
ceo / president      → Tier 5 approvals.
```

---

## 6. Employee Sub-Loan Statuses (`apex_loans.status`)

Individual employee loans under a facility carry their own status, separate from the parent facility.

| Status | Meaning |
|---|---|
| `draft` | Loan record created but not submitted for internal approval. |
| `submitted` | Submitted for credit review. |
| `active` | Approved and currently being repaid. Repayment schedule is live. |
| `paid_off` | All instalments have been received. Loan is closed with zero balance. |
| `defaulted` | Borrower has missed payments beyond the threshold. Included in outstanding totals. |
| `written_off` | Principal has been written off the books after recovery failure. |

> Sub-loan status is **independent** of facility status, except:  
> - A sub-loan can only be **created** when the parent facility status is `active`.  
> - `refreshTotals()` on `ApexFacilityModel` aggregates only sub-loans with status `active` or `defaulted` when computing facility utilisation.

---

## 7. Repayment Batch Statuses (`apex_repayment_batches.status`)

Corporate bulk payment batches also have their own lifecycle.

| Status | Meaning |
|---|---|
| `pending` | Batch created, awaiting processing. |
| `processed` | All expected amounts received and posted. |
| `partial` | Batch was partially paid — a shortfall exists. |
| `failed` | Processing failed entirely. |

---

## 8. Utilisation Indicators (Active Facilities Only)

When a facility is `active`, the detail page shows a utilisation strip.  The progress bar colour changes based on the utilisation percentage:

| Utilisation | Bar Colour | Meaning |
|---|---|---|
| 0 – 69% | Green | Healthy headroom available. |
| 70 – 89% | Amber | Approaching limit; review before further disbursements. |
| 90 – 100% | Red | Near or at capacity. New sub-loans may be blocked. |

```
Utilisation % = (total_disbursed / facility_limit) × 100
```

---

## 9. Quick Reference: Status Flow Diagram

```
                       [ Credit Officer ]
                              │
                      Creates application
                              │
                           ┌──▼──┐
                           │draft│  ← Editable by privileged roles
                           └──┬──┘
                              │  Click "Submit for Review"
                           ┌──▼──────┐
                           │submitted│  ← Tier 1 (Credit Supervisor) can now act
                           └──┬──────┘
                              │  Tier 1 approves
                        ┌─────▼──────┐
                        │under_review│  ← Tiers 2–5 work through sequentially
                        └─────┬──────┘
                              │  Tiers 2 + 3 + 4 + (5 or EVP Ops) all approve
                           ┌──▼────┐
                           │active │  ← Sub-loans can be created & disbursed
                           └───────┘

         (At any point, admin can manually set: suspended / closed)
```

---

## 10. Database Column Mapping

| Business Name | DB Column (`apex_facilities`) | Values |
|---|---|---|
| Application Status | `status` | `draft` · `submitted` · `under_review` · `active` · `suspended` · `closed` |
| Tier 1 | `credit_supervisor_status` / `credit_supervisor_comment` | `Pending` · `Approved` · `Denied` |
| Tier 2 | `credit_head_status` / `credit_head_comment` | `Pending` · `Approved` · `Denied` |
| Tier 3 | `risk_mgmt_status` / `risk_mgmt_comment` | `Pending` · `Approved` · `Denied` |
| Tier 4 | `evp_finance_status` / `evp_finance_comment` | `Pending` · `Approved` · `Denied` |
| Tier 5a | `evp_operations_status` / `evp_operations_comment` | `Pending` · `Approved` · `Denied` |
| Tier 5b | `ceo_president_status` / `ceo_president_comment` | `Pending` · `Approved` · `Denied` |

> **Tier 5 note:** `evp_operations` and `ceo_president` are treated as **alternate signatories** for the final sign-off. Either one approving is sufficient to satisfy Rule 1 in `syncFacilityStatus`. The UI panel labels this tier "CEO / Management" and accepts roles `evp_operations`, `ceo`, or `president`.
