# CRM Settings

**Date:** 2026-06-01
**Status:** Draft
**Spec:** 164
**Tier:** All tiers (lead scoring); Business+ (pipeline stage probability)
**Depends on:** `marketing-leads-pipeline`, `lead-qualification-scoring`, `revenue-forecasting`
**Referenced by:** `lead-qualification-scoring`, `revenue-forecasting`

---

## Overview

Spec 22 (`marketing-leads-pipeline`) defines lead management. Spec 118 (`lead-qualification-scoring`) defines BANT-based lead scoring and mentions "`/settings/crm` → Lead Scoring section" but provides no full page spec. Spec 116 (`revenue-forecasting`) defines pipeline stage-to-probability mapping as configurable in `/settings/crm` but again provides no page spec. This spec defines the full `/settings/crm` page covering both configuration areas.

---

## Route

`/settings/crm` — requires `settings:write`.

---

## Page Layout

```
┌──────────────────────────────────────────────────────────────┐
│  Settings > CRM                                              │
│                                                              │
│  ┌── Lead Scoring ──────────────────────────────────────────┐│
│  │                                                          ││
│  │  Scoring model   ● BANT (default)  ○ Disabled           ││
│  │                                                          ││
│  │  Score weights (must sum to 100)                         ││
│  │  Budget fit       [25___] %                              ││
│  │  Authority        [25___] %                              ││
│  │  Need alignment   [25___] %                              ││
│  │  Timeline fit     [25___] %                              ││
│  │                                                          ││
│  │  Activity bonus (added on top of BANT score)             ││
│  │  Email reply      [+5____] pts                           ││
│  │  Meeting booked   [+10___] pts                           ││
│  │  Proposal viewed  [+5____] pts                           ││
│  │                                                          ││
│  └─────────────────────────────────────────────────────────-┘│
│                                                              │
│  ┌── Pipeline Stages  [Business+] ──────────────────────────┐│
│  │                                                          ││
│  │  Stage               Win probability  Position           ││
│  │  ─────────────────────────────────────────────────────── ││
│  │  New Lead              [5___] %       1  ↑↓ [✕]         ││
│  │  Qualified             [20__] %       2  ↑↓ [✕]         ││
│  │  Proposal Sent         [40__] %       3  ↑↓ [✕]         ││
│  │  Negotiation           [70__] %       4  ↑↓ [✕]         ││
│  │  Closed Won            [100_] %       5  — (terminal)    ││
│  │  Closed Lost           [0___] %       6  — (terminal)    ││
│  │                                                          ││
│  │  [+ Add stage]                                           ││
│  │                                                          ││
│  └─────────────────────────────────────────────────────────-┘│
│                                                              │
│  ┌── Lead Statuses ─────────────────────────────────────────┐│
│  │                                                          ││
│  │  Lost reasons (shown in "Mark lost" dropdown):           ││
│  │  • Price too high  [✕]                                   ││
│  │  • No budget       [✕]                                   ││
│  │  • Chose competitor [✕]                                  ││
│  │  • No response     [✕]                                   ││
│  │  • Project cancelled [✕]                                 ││
│  │  [+ Add reason]                                          ││
│  │                                                          ││
│  └─────────────────────────────────────────────────────────-┘│
│                                                              │
│  [Save changes]                                             │
└──────────────────────────────────────────────────────────────┘
```

---

## Lead Scoring Section

Configures `tenant_settings.lead_scoring_criteria JSONB` (spec 118).

- **Scoring model toggle:** when set to `Disabled`, spec 118's scoring cron does not run; score column shows `NULL`.
- **BANT weights:** must sum to 100% (client-side validation). API rejects if sum ≠ 100.
- **Activity bonuses:** added to the BANT score; can push score above 100 (capped at 100 per spec 118).

---

## Pipeline Stages Section (Business+)

Configures `tenant_settings.pipeline_stages JSONB` (added by this spec):

```json
[
  { "id": "new",        "label": "New Lead",       "win_probability": 5,   "position": 1, "terminal": false },
  { "id": "qualified",  "label": "Qualified",      "win_probability": 20,  "position": 2, "terminal": false },
  { "id": "proposal",   "label": "Proposal Sent",  "win_probability": 40,  "position": 3, "terminal": false },
  { "id": "negotiation","label": "Negotiation",    "win_probability": 70,  "position": 4, "terminal": false },
  { "id": "won",        "label": "Closed Won",     "win_probability": 100, "position": 5, "terminal": true },
  { "id": "lost",       "label": "Closed Lost",    "win_probability": 0,   "position": 6, "terminal": true }
]
```

- Stages can be renamed, reordered, or deleted (if no leads are in that stage).
- Terminal stages (`Closed Won`, `Closed Lost`) cannot be deleted — shown with "—" in position controls.
- `win_probability` drives spec 116's revenue forecast (weighted pipeline value).
- Non-Business+ tenants see this section as upsell only.

---

## Lost Reasons Section

Configures `tenant_settings.lead_lost_reasons JSONB` (spec 111 `lead-lost-re-engagement` adds this column). Default reasons are pre-populated on first tenant setup.

- Add, rename, or delete reasons.
- At least one reason required (cannot delete all).

---

## Schema Delta

```sql
-- lead_scoring_criteria already added by spec 118
-- lead_lost_reasons already added by spec 111 (lead-lost-re-engagement)
ALTER TABLE tenant_settings
  ADD COLUMN IF NOT EXISTS pipeline_stages JSONB DEFAULT NULL,
  ADD COLUMN IF NOT EXISTS lead_scoring_enabled BOOLEAN NOT NULL DEFAULT true;
```

`pipeline_stages = NULL` means use the system default array above. When a tenant first saves custom stages, the JSONB is populated.

---

## API

```
GET  /api/settings/crm
     → get CRM settings
       Returns: { lead_scoring_enabled, lead_scoring_criteria,
                  pipeline_stages, lead_lost_reasons }
       Requires: settings:read

PATCH /api/settings/crm
      → update CRM settings
        body: { lead_scoring_enabled?, lead_scoring_criteria?,
                pipeline_stages?, lead_lost_reasons? }
        Requires: settings:write
        Validation:
          - lead_scoring_criteria weights must sum to 100
          - pipeline_stages: at least 2 stages; terminal stages not removable
          - lead_lost_reasons: at least 1 reason
```

---

## Architecture Decisions

| Decision | Choice | Reason |
|----------|--------|--------|
| JSONB for pipeline stages | Not a `pipeline_stages` table | Stage definitions are per-tenant config, not relational data; JSONB simpler than a full table for a bounded list |
| Terminal stages non-deletable | Not soft-delete | `Closed Won` and `Closed Lost` are semantically required for pipeline math (probability 100% and 0%); removing them would break spec 116's forecast |
| `pipeline_stages = NULL` = system defaults | Not pre-populate on tenant create | Lazy initialization; most tenants never customize stages; NULL avoids unnecessary JSONB write on signup |
| Lead scoring gated by `lead_scoring_enabled` boolean | Not by deleting criteria | Config preserved when disabled; easy to re-enable without re-entering weights |
