# LeadPilot Dashboard — Metric Definitions

**Document Version:** 1.0.0 (Phase 10)

---

## 1. Period Boundaries

All period boundaries are calculated using the workspace timezone (`workspaces.timezone`, default: `UTC`). Timestamps are stored and compared in UTC.

```
now(workspace_timezone).startOfDay().utc() → from
now(workspace_timezone).endOfDay().utc()   → to
```

---

## 2. KPI Definitions

### New Leads
**Definition:** Count of leads created in the selected period, excluding archived leads.

```sql
SELECT COUNT(*) FROM leads
WHERE workspace_id = ?
  AND created_at BETWEEN ? AND ?
  AND status NOT IN ('archived')
```

---

### Needs Response
**Definition:** Count of active leads where no first contact has been recorded.

```sql
SELECT COUNT(*) FROM leads
WHERE workspace_id = ?
  AND first_contacted_at IS NULL
  AND status NOT IN ('won', 'lost', 'archived')
```

This counts the current state, not limited by the selected period.

---

### Follow-ups Due
**Definition:** Count of scheduled follow-up tasks with a due date ≤ now.

```sql
SELECT COUNT(*) FROM follow_ups
WHERE workspace_id = ?
  AND status = 'scheduled'
  AND due_at <= NOW()
```

---

### Hot Leads
**Definition:** Active leads with AI score ≥ 75.

```sql
SELECT COUNT(*) FROM leads
WHERE workspace_id = ?
  AND ai_score >= 75
  AND status IN ('active', 'new')
```

Hot threshold: `DashboardMetricsService::HOT_SCORE_THRESHOLD = 75`

---

### Won
**Definition:** Leads marked won during the selected period.

```sql
SELECT COUNT(*) FROM leads
WHERE workspace_id = ?
  AND status = 'won'
  AND won_at BETWEEN ? AND ?
```

---

### Lost
**Definition:** Leads marked lost during the selected period.

```sql
SELECT COUNT(*) FROM leads
WHERE workspace_id = ?
  AND status = 'lost'
  AND lost_at BETWEEN ? AND ?
```

---

### Conversion Rate
**Definition:** `Won ÷ (Won + Lost) × 100` for the selected period. Returns `null` if no closed deals exist.

> **Important:** Conversion rate measures closed-period outcomes only. It does not include open/active leads in the denominator.

---

### Revenue Attributed
**Definition:** Sum of `deal_value` on leads won during the selected period where `deal_value > 0`.

Revenue is only attributed to explicitly won leads with a recorded deal value. No estimation or projection is performed.

---

### Recovered Leads
**Definition:** Leads marked `is_recovered = true` with a `recovered_at` timestamp within the selected period.

See [Recovery Definition](#recovered-leads-definition) below.

---

### Automation Failed
**Definition:** Current count of follow-up records with `status = 'failed'` (not period-scoped). Represents the total outstanding failure backlog requiring attention.

---

## 3. Recovered Leads Definition

A lead is classified as **recovered** when all of the following are true:

1. The lead was previously **stale** — its `last_activity_at` exceeded the workspace stale threshold (`stale_lead_days`, default 7 days) at the time of recovery evaluation.
2. A qualifying **re-engagement event** occurred after the stale period began. Qualifying events: `followup_sent`, `stage_changed`, `lead_contacted`, `lead_enrolled`, `note_added`.
3. The lead is in an **active state** — not `won`, `lost`, or `archived`.
4. The lead has **not previously been recovered** — `is_recovered = false`.

When all conditions are met, `LeadRecoveryService::evaluateRecovery()` sets:
- `is_recovered = true`
- `recovered_at = NOW()`
- Records a `lead_recovered` activity event

**This metric cannot be fabricated.** A follow-up alone does not qualify a lead as recovered — the stale condition must have been true before the re-engagement.

---

## 4. Stale Lead Threshold

The stale threshold is stored per-workspace in `workspaces.stale_lead_days`.

- Default: **7 days**
- Configurable per workspace
- Applied in `AttentionCenterService` and `LeadRecoveryService`
- Not hard-coded in business logic

---

## 5. Pipeline Snapshot

The pipeline snapshot returns all active pipeline stages for the workspace, ordered by position, with:

- Lead count per stage (excluding archived leads)
- Total deal value per stage (sum of `deal_value`)

No cross-pipeline aggregation is performed. Each stage links to a filtered Lead Inbox view.
