# Dashboards & Reports — BAMS Legal

> Pure read-layer over every other module's data. No domain tables of its own
> besides lightweight async report-run tracking. Staff-only.

---

## Table of Contents

1. [Executive Dashboard](#executive-dashboard)
2. [My Day Dashboard](#my-day-dashboard)
3. [Matter Health View](#matter-health-view)
4. [Report Run](#report-run)
5. [Standard Reports](#standard-reports)
6. [Notes & Guidelines](#notes--guidelines)

---

## Executive Dashboard

Not a persisted model — a read-only aggregation endpoint. Permission:
`dashboard.executive`.

### Admin Routes

**Base:** `/admin/dashboard/executive`

| Method | Endpoint | Description |
|---|---|---|
| `GET` | `/admin/dashboard/executive` | Full dashboard payload (all widgets below) |
| `GET` | `/admin/dashboard/executive/attention` | Attention panel only (used for a lightweight polling refresh) |

### Request & Response Examples

**Full payload** — `GET /admin/dashboard/executive`

```json
{
  "success": true,
  "data": {
    "attention": {
      "missed_appearances_uncovered": 1,
      "hearings_awaiting_outcome": 3,
      "deadlines_due_14_days": 2,
      "overdue_invoices": 5,
      "pending_fee_approvals": 4
    },
    "kpis": {
      "active_matters": 118, "hearings_this_week": 14,
      "outstanding_receivables": 4820000, "retainer_balance_held": 6200000,
      "unbilled_time_value": 1150000, "pending_approvals": 4
    },
    "matter_pipeline": [{ "stage": "Filing", "count": 12 }, { "stage": "Trial", "count": 8 }],
    "financial_pulse": [{ "month": "2026-02", "invoiced": 3200000, "collected": 2900000 }]
  }
}
```

### Notes & Guidelines

- **Attention panel leads, not the KPI cards** — this endpoint is designed to
  answer "what needs my attention today," not just show vanity totals.
- Cached 5 minutes per firm, tagged, busted early by the relevant domain event
  (e.g. an invoice being paid busts the `financial_pulse` tag immediately
  rather than waiting out the TTL).
- Non-executive roles receive `403 Forbidden` on both routes.

---

## My Day Dashboard

Default landing page for non-executive roles. Permission: any authenticated user.

### Admin Routes

**Base:** `/admin/dashboard`

| Method | Endpoint | Description |
|---|---|---|
| `GET` | `/admin/dashboard` | Today's hearings, my open tasks, my pending fee claims, my unbilled time this week, recent activity on my matters |

### Notes & Guidelines

- Mobile-first — partners and counsel check this between court sittings.
  Verified at 390px width with no horizontal scroll.

---

## Matter Health View

### Admin Routes

**Base:** `/admin/dashboard/matters` · **Auth:** session, permission `matters.view` / `matters.viewAll`

| Method | Endpoint | Description |
|---|---|---|
| `GET` | `/admin/dashboard/matters` | Filterable grid (stage, practice area, lawyer, court, status, "no activity in N days") |
| `GET` | `/admin/dashboard/matters/:id/health` | Per-matter health strip: last event, next hearing, open tasks, unbilled time, outstanding balance, retainer left |

### Notes & Guidelines

- Backed by a single `MatterHealthQuery` service, reused by both this endpoint
  and the weekly "stale matters" scheduled command — one implementation, not
  duplicated logic.

---

## Report Run

Tracks async generation of heavy reports so the request cycle isn't blocked.

### Schema

| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `id` | Integer | Auto | — | Primary key |
| `firm_id` | FK | Yes | — | |
| `report_key` | String | Yes | — | e.g. `matter-progress`, `financials` |
| `parameters` | JSON | Yes | — | Filter parameters used |
| `format` | Enum | Yes | — | `pdf`, `excel` |
| `status` | Enum | No | `queued` | `queued`, `processing`, `ready`, `failed` |
| `file_path` | String | No | `null` | **Admin-only, streamed download, never a public URL** |
| `requested_by` | FK (User) | Yes | — | |

### Admin Routes

**Base:** `/admin/report-runs` · **Auth:** session, permission `reports.view`

| Method | Endpoint | Description |
|---|---|---|
| `GET` | `/admin/report-runs/:id` | Poll status |
| `GET` | `/admin/report-runs/:id/download` | Download once `status = ready` |

### Notes & Guidelines

- Large exports (e.g. a full-year Excel financial report) queue a job and
  return `202 Accepted` with a `report_run_id` — the client polls
  `/admin/report-runs/:id` rather than holding a request open.

---

## Standard Reports

**Base:** `/admin/reports` · **Auth:** session, permission `reports.view`

| Report | Endpoint | Description |
|---|---|---|
| Matter progress | `GET /admin/reports/matter-progress` | Stage history, hearings held, outcomes, next dates |
| Lawyer performance | `GET /admin/reports/lawyer-performance` | Appearances, matters handled, hours logged, fees generated per lawyer/period |
| Court activity | `GET /admin/reports/court-activity` | Hearings, outcome distribution, adjournment rate per court/period |
| Financial summary | `GET /admin/reports/financials` | Invoiced, collected, outstanding, expenses, appearance fees, profitability |
| Aging | `GET /admin/reports/aging` | Outstanding balances bucketed 0-30/31-60/61-90/90+ |
| Client report | `GET /admin/reports/client/:clientId` | Sanitized client-facing summary — **same output** feeds the M11 portal |
| Deadline compliance | `GET /admin/reports/deadlines` | On-time vs missed deadlines by type/period |

Every report supports `?format=html` (preview), `?format=pdf`, `?format=excel`
(the latter two return a `report_run_id` per above).

### Request & Response Examples

**Client report** — `GET /admin/reports/client/88?format=html`

```json
{
  "success": true,
  "data": {
    "client": "Zenith Traders Ltd",
    "matters": [
      { "matter_number": "MAT/2026/0055", "stage": "Trial", "next_hearing": "2026-09-14" }
    ],
    "invoices_outstanding": 115312.50,
    "retainer_balance": 84687.50
  }
}
```

### Notes & Guidelines

- **⚠️ The client report is generated by `ClientMatterReportService` —
  one implementation shared by this endpoint AND the M11 Client Portal's
  own-matter view.** It structurally excludes `hearings.remarks`,
  `matter_comments`, and any financial detail beyond the client's own
  invoices/balances. There is no separate, potentially-drifting serialization
  for the portal.
