# Database Schema

## Entity Relationship Diagram

```
┌─────────────────────┐     ┌────────────────────────┐
│     prospects        │────<│ prospect_tech_profiles │
├─────────────────────┤     ├────────────────────────┤
│ id                  │     │ id                     │
│ channel             │     │ prospect_id (FK)       │
│ business_name       │     │ cms, server            │
│ domain_name         │     │ hosting_provider       │
│ status              │     │ js_framework, cdn      │
│ source              │     │ analytics              │
│ has_website         │     │ ecommerce_platform     │
│ uses_https          │     │ tech_stack_json (JSON) │
│ ...                 │     └────────────────────────┘
└─────────────────────┘
        │
        │               ┌──────────────────────────────┐
        └──────────────<│ prospect_performance_profiles │
        │               ├──────────────────────────────┤
        │               │ id                           │
        │               │ prospect_id (FK)             │
        │               │ performance_score (0-100)    │
        │               │ accessibility_score          │
        │               │ seo_score                    │
        │               │ FCP, LCP, TBT, CLS          │
        │               │ is_mobile_friendly           │
        │               └──────────────────────────────┘
        │
        │               ┌───────────────────────┐
        └──────────────<│   prospect_scores     │
        │               ├───────────────────────┤
        │               │ id                    │
        │               │ prospect_id (FK)      │
        │               │ score (0-100)         │
        │               │ technical_health_score│
        │               │ modernity_score       │
        │               │ business_value_score  │
        │               │ engagement_score      │
        │               │ reason_flags (JSON)   │
        │               │ lead_tier             │
        │               └───────────────────────┘
        │
        │               ┌───────────────────────┐
        └──────────────<│  prospect_contacts    │
        │               ├───────────────────────┤
        │               │ id                    │
        │               │ prospect_id (FK)      │
        │               │ contact_type          │
        │               │ value                 │
        │               │ source_url            │
        │               │ is_primary            │
        │               └───────────────────────┘
        │
        │               ┌───────────────────────┐
        └──────────────<│ prospect_interactions │
        │               ├───────────────────────┤
        │               │ id                    │
        │               │ prospect_id (FK)      │
        │               │ interaction_type      │
        │               │ subject, notes        │
        │               │ outcome               │
        │               │ next_action           │
        │               │ next_action_date      │
        │               │ created_by_user_id    │
        │               └───────────────────────┘
        │
        │               ┌───────────────────────┐
        └──────────────<│   prospect_scan_jobs  │
                        ├───────────────────────┤
                        │ id                    │
                        │ job_type              │
                        │ status                │
                        │ total_items           │
                        │ processed_items       │
                        │ celery_task_id        │
                        └───────────────────────┘

┌──────────────────────┐     ┌──────────────────┐
│  campaign_templates  │────<│  campaign_sends  │
├──────────────────────┤     ├──────────────────┤
│ id                   │     │ id               │
│ name                 │     │ template_id (FK) │
│ lead_type            │     │ prospect_id (FK) │
│ channel              │     │ channel          │
│ language             │     │ rendered_subject │
│ subject_template     │     │ rendered_body    │
│ body_template        │     │ status           │
│ is_active            │     │ sent_at          │
└──────────────────────┘     │ sent_by_user_id  │
                             └──────────────────┘
```

## Tables

### prospects

Central table for all leads — both digital (domain-based) and offline (in-person).

| Column | Type | Description |
|--------|------|-------------|
| id | INTEGER PK | Auto-increment |
| channel | ENUM(digital, offline) | How the lead was discovered |
| business_name | VARCHAR(255) | Required for offline |
| domain_name | VARCHAR(255) | Required for digital, unique |
| status | ENUM | pending, active, inactive, parked, error, contacted, converted |
| source | VARCHAR(100) | e.g. "domain_scan", "networking_event", "street" |
| has_website | BOOLEAN | Determined by HTTP check |
| uses_https | BOOLEAN | SSL status |
| http_status_code | INTEGER | Last HTTP response |
| address | VARCHAR(500) | Physical address (offline) |
| city | VARCHAR(100) | City |
| postal_code | VARCHAR(10) | Postal code |
| country | VARCHAR(2) | Default "LU" |
| notes | TEXT | Free-form notes |
| tags | JSON | Flexible tagging |
| captured_by_user_id | INTEGER FK | Who captured this lead |
| location_lat / location_lng | FLOAT | GPS from mobile capture |
| last_*_at | DATETIME | Timestamps for each scan type |

### prospect_tech_profiles

Technology stack detection results. One per prospect.

| Column | Type | Description |
|--------|------|-------------|
| cms | VARCHAR(100) | WordPress, Drupal, Joomla, etc. |
| server | VARCHAR(100) | Nginx, Apache |
| hosting_provider | VARCHAR(100) | Hosting company |
| cdn | VARCHAR(100) | CDN provider |
| js_framework | VARCHAR(100) | React, Vue, Angular, jQuery |
| analytics | VARCHAR(200) | Google Analytics, Matomo, etc. |
| ecommerce_platform | VARCHAR(100) | Shopify, WooCommerce, etc. |
| tech_stack_json | JSON | Full detection results |

### prospect_performance_profiles

Lighthouse audit results. One per prospect.

| Column | Type | Description |
|--------|------|-------------|
| performance_score | INTEGER | 0-100 |
| accessibility_score | INTEGER | 0-100 |
| seo_score | INTEGER | 0-100 |
| first_contentful_paint_ms | INTEGER | FCP |
| largest_contentful_paint_ms | INTEGER | LCP |
| total_blocking_time_ms | INTEGER | TBT |
| cumulative_layout_shift | FLOAT | CLS |
| is_mobile_friendly | BOOLEAN | Mobile test |

### prospect_scores

Calculated opportunity scores. One per prospect. See [scoring.md](scoring.md) for algorithm details.

### prospect_contacts

Scraped or manually entered contact info. Many per prospect.

### prospect_interactions

CRM-style interaction log. Many per prospect. Types: note, call, email_sent, email_received, meeting, visit, sms, proposal_sent.

### prospect_scan_jobs

Background job tracking for batch operations.

### campaign_templates / campaign_sends

Marketing campaign templates and send tracking. Templates support placeholders like `{business_name}`, `{domain}`, `{score}`, `{issues}`.
