feat(hosting): add HostWizard platform module and fix migration chain
Some checks failed
Some checks failed
- Add complete hosting module (models, routes, schemas, services, templates, migrations) - Add HostWizard platform to init_production seed (code=hosting, domain=hostwizard.lu) - Fix cms_002 migration down_revision to z_unique_subdomain_domain - Fix prospecting_001 migration to chain after cms_002 (remove branch label) - Add hosting/prospecting version_locations to alembic.ini - Fix admin_services delete endpoint to use proper response model - Add hostwizard.lu to deployment docs (DNS, Caddy, Cloudflare) - Add hosting and prospecting user journey docs to mkdocs nav Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
502
docs/features/user-journeys/hosting.md
Normal file
502
docs/features/user-journeys/hosting.md
Normal file
@@ -0,0 +1,502 @@
|
||||
# Hosting Module - User Journeys
|
||||
|
||||
## Personas
|
||||
|
||||
| # | Persona | Role / Auth | Description |
|
||||
|---|---------|-------------|-------------|
|
||||
| 1 | **Platform Admin** | `admin` role | Manages the POC → live website pipeline, tracks client services, monitors renewals |
|
||||
| 2 | **Prospect** | No auth (receives proposal link) | Views their POC website preview via a shared link |
|
||||
|
||||
!!! note "Admin-only module"
|
||||
The hosting module is primarily an admin-only module. The only non-admin page is the
|
||||
**POC Viewer** — a public preview page that shows the prospect's POC website with a
|
||||
HostWizard banner. Prospects do not have accounts until their proposal is accepted, at
|
||||
which point a Merchant account is created for them.
|
||||
|
||||
---
|
||||
|
||||
## Lifecycle Overview
|
||||
|
||||
The hosting module manages the complete POC → live website pipeline:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Prospect identified] --> B[Create Hosted Site]
|
||||
B --> C[Status: DRAFT]
|
||||
C --> D[Build POC website via CMS]
|
||||
D --> E[Mark POC Ready]
|
||||
E --> F[Status: POC_READY]
|
||||
F --> G[Send Proposal to prospect]
|
||||
G --> H[Status: PROPOSAL_SENT]
|
||||
H --> I{Prospect accepts?}
|
||||
I -->|Yes| J[Accept Proposal]
|
||||
J --> K[Status: ACCEPTED]
|
||||
K --> L[Merchant account created]
|
||||
L --> M[Go Live with domain]
|
||||
M --> N[Status: LIVE]
|
||||
I -->|No| O[Cancel]
|
||||
O --> P[Status: CANCELLED]
|
||||
N --> Q{Issues?}
|
||||
Q -->|Payment issues| R[Suspend]
|
||||
R --> S[Status: SUSPENDED]
|
||||
S --> T[Reactivate → LIVE]
|
||||
Q -->|Client leaves| O
|
||||
```
|
||||
|
||||
### Status Transitions
|
||||
|
||||
| From | Allowed Targets |
|
||||
|------|----------------|
|
||||
| `draft` | `poc_ready`, `cancelled` |
|
||||
| `poc_ready` | `proposal_sent`, `cancelled` |
|
||||
| `proposal_sent` | `accepted`, `cancelled` |
|
||||
| `accepted` | `live`, `cancelled` |
|
||||
| `live` | `suspended`, `cancelled` |
|
||||
| `suspended` | `live`, `cancelled` |
|
||||
| `cancelled` | _(terminal)_ |
|
||||
|
||||
---
|
||||
|
||||
## Dev URLs (localhost:9999)
|
||||
|
||||
The dev server uses path-based platform routing: `http://localhost:9999/platforms/hosting/...`
|
||||
|
||||
### 1. Admin Pages
|
||||
|
||||
Login as: `admin@orion.lu` or `samir.boulahtit@gmail.com`
|
||||
|
||||
| Page | Dev URL |
|
||||
|------|---------|
|
||||
| Dashboard | `http://localhost:9999/platforms/hosting/admin/hosting` |
|
||||
| Sites List | `http://localhost:9999/platforms/hosting/admin/hosting/sites` |
|
||||
| New Site | `http://localhost:9999/platforms/hosting/admin/hosting/sites/new` |
|
||||
| Site Detail | `http://localhost:9999/platforms/hosting/admin/hosting/sites/{site_id}` |
|
||||
| Client Services | `http://localhost:9999/platforms/hosting/admin/hosting/clients` |
|
||||
|
||||
### 2. Public Pages
|
||||
|
||||
| Page | Dev URL |
|
||||
|------|---------|
|
||||
| POC Viewer | `http://localhost:9999/platforms/hosting/hosting/sites/{site_id}/preview` |
|
||||
|
||||
### 3. Admin API Endpoints
|
||||
|
||||
**Sites** (prefix: `/platforms/hosting/api/admin/hosting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| GET | list sites | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites` |
|
||||
| GET | site detail | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}` |
|
||||
| POST | create site | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites` |
|
||||
| POST | create from prospect | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/from-prospect/{prospect_id}` |
|
||||
| PUT | update site | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}` |
|
||||
| DELETE | delete site | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}` |
|
||||
|
||||
**Lifecycle** (prefix: `/platforms/hosting/api/admin/hosting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| POST | mark POC ready | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/mark-poc-ready` |
|
||||
| POST | send proposal | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/send-proposal` |
|
||||
| POST | accept proposal | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/accept` |
|
||||
| POST | go live | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/go-live` |
|
||||
| POST | suspend | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/suspend` |
|
||||
| POST | cancel | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/cancel` |
|
||||
|
||||
**Client Services** (prefix: `/platforms/hosting/api/admin/hosting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| GET | list services | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services` |
|
||||
| POST | create service | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services` |
|
||||
| PUT | update service | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services/{id}` |
|
||||
| DELETE | delete service | `http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services/{id}` |
|
||||
|
||||
**Stats** (prefix: `/platforms/hosting/api/admin/hosting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| GET | dashboard stats | `http://localhost:9999/platforms/hosting/api/admin/hosting/stats/dashboard` |
|
||||
|
||||
---
|
||||
|
||||
## Production URLs (hostwizard.lu)
|
||||
|
||||
In production, the platform uses **domain-based routing**.
|
||||
|
||||
### Admin Pages & API
|
||||
|
||||
| Page / Endpoint | Production URL |
|
||||
|-----------------|----------------|
|
||||
| Dashboard | `https://hostwizard.lu/admin/hosting` |
|
||||
| Sites | `https://hostwizard.lu/admin/hosting/sites` |
|
||||
| New Site | `https://hostwizard.lu/admin/hosting/sites/new` |
|
||||
| Site Detail | `https://hostwizard.lu/admin/hosting/sites/{id}` |
|
||||
| Client Services | `https://hostwizard.lu/admin/hosting/clients` |
|
||||
| API - Sites | `GET https://hostwizard.lu/api/admin/hosting/sites` |
|
||||
| API - Stats | `GET https://hostwizard.lu/api/admin/hosting/stats/dashboard` |
|
||||
|
||||
### Public Pages
|
||||
|
||||
| Page | Production URL |
|
||||
|------|----------------|
|
||||
| POC Viewer | `https://hostwizard.lu/hosting/sites/{site_id}/preview` |
|
||||
|
||||
---
|
||||
|
||||
## Data Model
|
||||
|
||||
### Hosted Site
|
||||
|
||||
```
|
||||
HostedSite
|
||||
├── id (PK)
|
||||
├── store_id (FK → stores.id, unique) # The CMS-powered website
|
||||
├── prospect_id (FK → prospects.id, nullable) # Origin prospect
|
||||
├── status: draft | poc_ready | proposal_sent | accepted | live | suspended | cancelled
|
||||
├── business_name (str)
|
||||
├── contact_name, contact_email, contact_phone
|
||||
├── proposal_sent_at, proposal_accepted_at, went_live_at (datetime)
|
||||
├── proposal_notes (text)
|
||||
├── live_domain (str, unique)
|
||||
├── internal_notes (text)
|
||||
├── created_at, updated_at
|
||||
└── Relationships: store, prospect, client_services
|
||||
```
|
||||
|
||||
### Client Service
|
||||
|
||||
```
|
||||
ClientService
|
||||
├── id (PK)
|
||||
├── hosted_site_id (FK → hosted_sites.id, CASCADE)
|
||||
├── service_type: domain | email | ssl | hosting | website_maintenance
|
||||
├── name (str) # e.g., "acme.lu domain", "5 mailboxes"
|
||||
├── status: pending | active | suspended | expired | cancelled
|
||||
├── billing_period: monthly | annual | one_time
|
||||
├── price_cents (int), currency (str, default EUR)
|
||||
├── addon_product_id (FK, nullable) # Link to billing product
|
||||
├── domain_name, registrar # Domain-specific
|
||||
├── mailbox_count # Email-specific
|
||||
├── expires_at, period_start, period_end, auto_renew
|
||||
├── notes (text)
|
||||
└── created_at, updated_at
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## User Journeys
|
||||
|
||||
### Journey 1: Create Hosted Site from Prospect
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Convert a qualified prospect into a hosted site with a POC website
|
||||
|
||||
**Prerequisite:** A prospect exists in the prospecting module (see [Prospecting Journeys](prospecting.md))
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[View prospect in prospecting module] --> B[Click 'Create Hosted Site from Prospect']
|
||||
B --> C[HostedSite created with status DRAFT]
|
||||
C --> D[Store auto-created on hosting platform]
|
||||
D --> E[Contact info pre-filled from prospect]
|
||||
E --> F[Navigate to site detail]
|
||||
F --> G[Build POC website via CMS editor]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Create hosted site from prospect:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/from-prospect/{prospect_id}`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/from-prospect/{prospect_id}`
|
||||
2. This automatically:
|
||||
- Creates a Store on the hosting platform
|
||||
- Creates a HostedSite record linked to the Store and Prospect
|
||||
- Pre-fills business_name, contact_name, contact_email, contact_phone from prospect data
|
||||
3. View the new site:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/hosting/sites/{site_id}`
|
||||
- Prod: `https://hostwizard.lu/admin/hosting/sites/{site_id}`
|
||||
4. Click the Store link to open the CMS editor and build the POC website
|
||||
|
||||
---
|
||||
|
||||
### Journey 2: Create Hosted Site Manually
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Create a hosted site without an existing prospect (e.g., direct referral)
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Navigate to New Site page] --> B[Fill in business details]
|
||||
B --> C[Submit form]
|
||||
C --> D[HostedSite + Store created]
|
||||
D --> E[Navigate to site detail]
|
||||
E --> F[Build POC website]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Navigate to New Site form:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/hosting/sites/new`
|
||||
- Prod: `https://hostwizard.lu/admin/hosting/sites/new`
|
||||
2. Create the site:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites`
|
||||
- Body: `{ "business_name": "Boulangerie du Parc", "contact_name": "Jean Müller", "contact_email": "jean@boulangerie-parc.lu", "contact_phone": "+352 26 123 456" }`
|
||||
3. A Store is auto-created with subdomain `boulangerie-du-parc` on the hosting platform
|
||||
|
||||
---
|
||||
|
||||
### Journey 3: POC → Proposal Flow
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Build a POC website, mark it ready, and send a proposal to the prospect
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Site is DRAFT] --> B[Build POC website via CMS]
|
||||
B --> C[Mark POC Ready]
|
||||
C --> D[Site is POC_READY]
|
||||
D --> E[Preview the POC site]
|
||||
E --> F[Send Proposal with notes]
|
||||
F --> G[Site is PROPOSAL_SENT]
|
||||
G --> H[Share preview link with prospect]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Build the POC website using the Store's CMS editor (linked from site detail page)
|
||||
2. When the POC is ready, mark it:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/mark-poc-ready`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/mark-poc-ready`
|
||||
3. Preview the POC site (public link, no auth needed):
|
||||
- Dev: `http://localhost:9999/platforms/hosting/hosting/sites/{id}/preview`
|
||||
- Prod: `https://hostwizard.lu/hosting/sites/{id}/preview`
|
||||
4. Send proposal to the prospect:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/send-proposal`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/send-proposal`
|
||||
- Body: `{ "notes": "Custom website with 5 pages, domain registration included" }`
|
||||
5. Share the preview link with the prospect via email
|
||||
|
||||
!!! info "POC Viewer"
|
||||
The POC Viewer page renders the Store's storefront in an iframe with a teal
|
||||
HostWizard banner at the top. It only works for sites with status `poc_ready`
|
||||
or `proposal_sent`. Once the site goes live, the preview is disabled.
|
||||
|
||||
---
|
||||
|
||||
### Journey 4: Accept Proposal & Create Merchant
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** When a prospect accepts, create their merchant account and subscription
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Prospect accepts proposal] --> B{Existing merchant?}
|
||||
B -->|Yes| C[Link to existing merchant]
|
||||
B -->|No| D[Auto-create merchant + owner account]
|
||||
C --> E[Accept Proposal]
|
||||
D --> E
|
||||
E --> F[Site is ACCEPTED]
|
||||
F --> G[Store reassigned to merchant]
|
||||
G --> H[Subscription created on hosting platform]
|
||||
H --> I[Prospect marked as CONVERTED]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Accept the proposal (auto-creates merchant if no merchant_id provided):
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/accept`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/accept`
|
||||
- Body: `{}` (auto-create merchant) or `{ "merchant_id": 5 }` (link to existing)
|
||||
2. This automatically:
|
||||
- Creates a new Merchant from contact info (name, email, phone)
|
||||
- Creates a store owner account with a temporary password
|
||||
- Reassigns the Store from the system merchant to the new merchant
|
||||
- Creates a MerchantSubscription on the hosting platform (essential tier)
|
||||
- Marks the linked prospect as CONVERTED (if prospect_id is set)
|
||||
3. View the updated site detail:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/hosting/sites/{id}`
|
||||
- Prod: `https://hostwizard.lu/admin/hosting/sites/{id}`
|
||||
|
||||
!!! warning "Merchant account credentials"
|
||||
When accepting without an existing `merchant_id`, a new merchant owner account is
|
||||
created with a temporary password. The admin should communicate these credentials
|
||||
to the client so they can log in and self-edit their website via the CMS.
|
||||
|
||||
---
|
||||
|
||||
### Journey 5: Go Live with Custom Domain
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Assign a production domain to the website and make it live
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Site is ACCEPTED] --> B[Configure DNS for client domain]
|
||||
B --> C[Go Live with domain]
|
||||
C --> D[Site is LIVE]
|
||||
D --> E[StoreDomain created]
|
||||
E --> F[Website accessible at client domain]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Ensure DNS is configured for the client's domain (A/AAAA records pointing to the server)
|
||||
2. Go live:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/go-live`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/go-live`
|
||||
- Body: `{ "domain": "boulangerie-parc.lu" }`
|
||||
3. This automatically:
|
||||
- Sets `went_live_at` timestamp
|
||||
- Creates a StoreDomain record (primary) for the domain
|
||||
- Sets `live_domain` on the hosted site
|
||||
4. The website is now accessible at `https://boulangerie-parc.lu`
|
||||
|
||||
---
|
||||
|
||||
### Journey 6: Add Client Services
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Track operational services (domains, email, SSL, hosting) for a client
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Open site detail] --> B[Go to Services tab]
|
||||
B --> C[Add domain service]
|
||||
C --> D[Add email service]
|
||||
D --> E[Add SSL service]
|
||||
E --> F[Add hosting service]
|
||||
F --> G[Services tracked with expiry dates]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Navigate to site detail, Services tab:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/hosting/sites/{site_id}`
|
||||
- Prod: `https://hostwizard.lu/admin/hosting/sites/{site_id}`
|
||||
2. Add a domain service:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{site_id}/services`
|
||||
- Body: `{ "service_type": "domain", "name": "boulangerie-parc.lu domain", "domain_name": "boulangerie-parc.lu", "registrar": "Namecheap", "billing_period": "annual", "price_cents": 1500, "expires_at": "2027-03-01T00:00:00", "auto_renew": true }`
|
||||
3. Add an email service:
|
||||
- Body: `{ "service_type": "email", "name": "5 mailboxes", "mailbox_count": 5, "billing_period": "monthly", "price_cents": 999 }`
|
||||
4. Add an SSL service:
|
||||
- Body: `{ "service_type": "ssl", "name": "SSL certificate", "billing_period": "annual", "price_cents": 0, "expires_at": "2027-03-01T00:00:00" }`
|
||||
5. View all services for a site:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{site_id}/services`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/hosting/sites/{site_id}/services`
|
||||
|
||||
---
|
||||
|
||||
### Journey 7: Dashboard & Renewal Monitoring
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Monitor business KPIs and upcoming service renewals
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Navigate to Dashboard] --> B[View KPIs]
|
||||
B --> C[Total sites, live sites, POC sites]
|
||||
C --> D[Monthly revenue]
|
||||
D --> E[Active services count]
|
||||
E --> F[Upcoming renewals in 30 days]
|
||||
F --> G[Navigate to Client Services]
|
||||
G --> H[Filter by expiring soon]
|
||||
H --> I[Renew or update services]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Navigate to Dashboard:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/hosting`
|
||||
- Prod: `https://hostwizard.lu/admin/hosting`
|
||||
2. View dashboard stats:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/hosting/stats/dashboard`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/hosting/stats/dashboard`
|
||||
- Returns: `total_sites`, `live_sites`, `poc_sites`, `sites_by_status`, `active_services`, `monthly_revenue_cents`, `upcoming_renewals`, `services_by_type`
|
||||
3. Navigate to Client Services for detailed view:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/hosting/clients`
|
||||
- Prod: `https://hostwizard.lu/admin/hosting/clients`
|
||||
4. Filter by type (domain, email, ssl, hosting) or status
|
||||
5. Toggle "Expiring Soon" to see services expiring within 30 days
|
||||
|
||||
---
|
||||
|
||||
### Journey 8: Suspend & Reactivate
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Handle suspension (e.g., unpaid invoices) and reactivation
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Suspend a site:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/suspend`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/suspend`
|
||||
2. Site status changes to `suspended`
|
||||
3. Once payment is resolved, reactivate by transitioning back to live:
|
||||
- The `suspended → live` transition is allowed
|
||||
4. To permanently close a site:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/hosting/sites/{id}/cancel`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/hosting/sites/{id}/cancel`
|
||||
5. `cancelled` is a terminal state — no further transitions allowed
|
||||
|
||||
---
|
||||
|
||||
### Journey 9: Complete Pipeline (Prospect → Live Site)
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Walk the complete pipeline from prospect to live website
|
||||
|
||||
This journey combines the prospecting and hosting modules end-to-end:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Import domain / capture lead] --> B[Enrich & score prospect]
|
||||
B --> C[Create hosted site from prospect]
|
||||
C --> D[Build POC website via CMS]
|
||||
D --> E[Mark POC ready]
|
||||
E --> F[Send proposal + share preview link]
|
||||
F --> G{Prospect accepts?}
|
||||
G -->|Yes| H[Accept → Merchant created]
|
||||
H --> I[Add client services]
|
||||
I --> J[Go live with domain]
|
||||
J --> K[Website live at client domain]
|
||||
K --> L[Monitor renewals & services]
|
||||
G -->|No| M[Cancel or follow up later]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Prospecting phase** (see [Prospecting Journeys](prospecting.md)):
|
||||
- Import domain or capture lead offline
|
||||
- Run enrichment pipeline
|
||||
- Score and qualify the prospect
|
||||
2. **Create hosted site**: `POST /api/admin/hosting/sites/from-prospect/{prospect_id}`
|
||||
3. **Build POC**: Edit the auto-created Store via CMS
|
||||
4. **Mark POC ready**: `POST /api/admin/hosting/sites/{id}/mark-poc-ready`
|
||||
5. **Send proposal**: `POST /api/admin/hosting/sites/{id}/send-proposal`
|
||||
6. **Share preview**: Send `https://hostwizard.lu/hosting/sites/{id}/preview` to prospect
|
||||
7. **Accept proposal**: `POST /api/admin/hosting/sites/{id}/accept`
|
||||
8. **Add services**: `POST /api/admin/hosting/sites/{id}/services` (domain, email, SSL, hosting)
|
||||
9. **Go live**: `POST /api/admin/hosting/sites/{id}/go-live` with domain
|
||||
10. **Monitor**: Dashboard at `https://hostwizard.lu/admin/hosting`
|
||||
|
||||
---
|
||||
|
||||
## Recommended Test Order
|
||||
|
||||
1. **Journey 2** - Create a site manually first (simplest path, no prospect dependency)
|
||||
2. **Journey 3** - Walk the POC → proposal flow
|
||||
3. **Journey 4** - Accept proposal and verify merchant creation
|
||||
4. **Journey 5** - Go live with a test domain
|
||||
5. **Journey 6** - Add client services
|
||||
6. **Journey 7** - Check dashboard stats
|
||||
7. **Journey 1** - Test the prospect → hosted site conversion (requires prospecting data)
|
||||
8. **Journey 8** - Test suspend/reactivate/cancel
|
||||
9. **Journey 9** - Walk the complete end-to-end pipeline
|
||||
|
||||
!!! tip "Test Journey 2 before Journey 1"
|
||||
Journey 2 (manual creation) doesn't require any prospecting data and is the fastest
|
||||
way to verify the hosting module works. Journey 1 (from prospect) requires running
|
||||
the prospecting module first.
|
||||
435
docs/features/user-journeys/prospecting.md
Normal file
435
docs/features/user-journeys/prospecting.md
Normal file
@@ -0,0 +1,435 @@
|
||||
# Prospecting Module - User Journeys
|
||||
|
||||
## Personas
|
||||
|
||||
| # | Persona | Role / Auth | Description |
|
||||
|---|---------|-------------|-------------|
|
||||
| 1 | **Platform Admin** | `admin` role | Manages prospects, runs enrichment scans, sends campaigns, exports leads |
|
||||
|
||||
!!! note "Admin-only module"
|
||||
The prospecting module is exclusively for platform admins. There are no store-level
|
||||
or customer-facing pages. All access requires admin authentication.
|
||||
|
||||
---
|
||||
|
||||
## Platforms Using Prospecting
|
||||
|
||||
The prospecting module is enabled on multiple platforms:
|
||||
|
||||
| Platform | Domain | Path Prefix (dev) |
|
||||
|----------|--------|--------------------|
|
||||
| HostWizard | hostwizard.lu | `/platforms/hosting/` |
|
||||
|
||||
---
|
||||
|
||||
## Dev URLs (localhost:9999)
|
||||
|
||||
The dev server uses path-based platform routing: `http://localhost:9999/platforms/hosting/...`
|
||||
|
||||
### 1. Admin Pages
|
||||
|
||||
Login as: `admin@orion.lu` or `samir.boulahtit@gmail.com`
|
||||
|
||||
| Page | Dev URL |
|
||||
|------|---------|
|
||||
| Dashboard | `http://localhost:9999/platforms/hosting/admin/prospecting` |
|
||||
| Prospects List | `http://localhost:9999/platforms/hosting/admin/prospecting/prospects` |
|
||||
| Prospect Detail | `http://localhost:9999/platforms/hosting/admin/prospecting/prospects/{prospect_id}` |
|
||||
| Leads List | `http://localhost:9999/platforms/hosting/admin/prospecting/leads` |
|
||||
| Quick Capture | `http://localhost:9999/platforms/hosting/admin/prospecting/capture` |
|
||||
| Scan Jobs | `http://localhost:9999/platforms/hosting/admin/prospecting/scan-jobs` |
|
||||
| Campaigns | `http://localhost:9999/platforms/hosting/admin/prospecting/campaigns` |
|
||||
|
||||
### 2. Admin API Endpoints
|
||||
|
||||
**Prospects** (prefix: `/platforms/hosting/api/admin/prospecting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| GET | prospects | `http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects` |
|
||||
| GET | prospect detail | `http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/{id}` |
|
||||
| POST | create prospect | `http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects` |
|
||||
| PUT | update prospect | `http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/{id}` |
|
||||
| DELETE | delete prospect | `http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/{id}` |
|
||||
| POST | import CSV | `http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/import` |
|
||||
|
||||
**Leads** (prefix: `/platforms/hosting/api/admin/prospecting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| GET | leads (filtered) | `http://localhost:9999/platforms/hosting/api/admin/prospecting/leads` |
|
||||
| GET | top priority | `http://localhost:9999/platforms/hosting/api/admin/prospecting/leads/top-priority` |
|
||||
| GET | quick wins | `http://localhost:9999/platforms/hosting/api/admin/prospecting/leads/quick-wins` |
|
||||
| GET | export CSV | `http://localhost:9999/platforms/hosting/api/admin/prospecting/leads/export/csv` |
|
||||
|
||||
**Enrichment** (prefix: `/platforms/hosting/api/admin/prospecting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| POST | HTTP check (single) | `http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/http-check/{id}` |
|
||||
| POST | HTTP check (batch) | `http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/http-check/batch` |
|
||||
| POST | tech scan (single) | `http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/tech-scan/{id}` |
|
||||
| POST | tech scan (batch) | `http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/tech-scan/batch` |
|
||||
| POST | performance (single) | `http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/performance/{id}` |
|
||||
| POST | performance (batch) | `http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/performance/batch` |
|
||||
| POST | contacts (single) | `http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/contacts/{id}` |
|
||||
| POST | full enrichment | `http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/full/{id}` |
|
||||
| POST | score compute | `http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/score-compute/batch` |
|
||||
|
||||
**Interactions** (prefix: `/platforms/hosting/api/admin/prospecting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| GET | prospect interactions | `http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/{id}/interactions` |
|
||||
| POST | log interaction | `http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/{id}/interactions` |
|
||||
| GET | upcoming follow-ups | `http://localhost:9999/platforms/hosting/api/admin/prospecting/interactions/upcoming` |
|
||||
|
||||
**Campaigns** (prefix: `/platforms/hosting/api/admin/prospecting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| GET | list templates | `http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/templates` |
|
||||
| POST | create template | `http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/templates` |
|
||||
| PUT | update template | `http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/templates/{id}` |
|
||||
| DELETE | delete template | `http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/templates/{id}` |
|
||||
| POST | preview campaign | `http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/preview` |
|
||||
| POST | send campaign | `http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/send` |
|
||||
| GET | list sends | `http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/sends` |
|
||||
|
||||
**Stats** (prefix: `/platforms/hosting/api/admin/prospecting/`):
|
||||
|
||||
| Method | Endpoint | Dev URL |
|
||||
|--------|----------|---------|
|
||||
| GET | dashboard stats | `http://localhost:9999/platforms/hosting/api/admin/prospecting/stats` |
|
||||
| GET | scan jobs | `http://localhost:9999/platforms/hosting/api/admin/prospecting/stats/jobs` |
|
||||
|
||||
---
|
||||
|
||||
## Production URLs (hostwizard.lu)
|
||||
|
||||
In production, the platform uses **domain-based routing**.
|
||||
|
||||
### Admin Pages & API
|
||||
|
||||
| Page / Endpoint | Production URL |
|
||||
|-----------------|----------------|
|
||||
| Dashboard | `https://hostwizard.lu/admin/prospecting` |
|
||||
| Prospects | `https://hostwizard.lu/admin/prospecting/prospects` |
|
||||
| Prospect Detail | `https://hostwizard.lu/admin/prospecting/prospects/{id}` |
|
||||
| Leads | `https://hostwizard.lu/admin/prospecting/leads` |
|
||||
| Quick Capture | `https://hostwizard.lu/admin/prospecting/capture` |
|
||||
| Scan Jobs | `https://hostwizard.lu/admin/prospecting/scan-jobs` |
|
||||
| Campaigns | `https://hostwizard.lu/admin/prospecting/campaigns` |
|
||||
| API - Prospects | `GET https://hostwizard.lu/api/admin/prospecting/prospects` |
|
||||
| API - Leads | `GET https://hostwizard.lu/api/admin/prospecting/leads` |
|
||||
| API - Stats | `GET https://hostwizard.lu/api/admin/prospecting/stats` |
|
||||
|
||||
---
|
||||
|
||||
## Data Model
|
||||
|
||||
### Prospect
|
||||
|
||||
```
|
||||
Prospect
|
||||
├── id (PK)
|
||||
├── channel: DIGITAL | OFFLINE
|
||||
├── business_name (str)
|
||||
├── domain_name (str, unique)
|
||||
├── status: PENDING | ACTIVE | INACTIVE | PARKED | ERROR | CONTACTED | CONVERTED
|
||||
├── source (str)
|
||||
├── Digital fields: has_website, uses_https, http_status_code, redirect_url, scan timestamps
|
||||
├── Offline fields: address, city, postal_code, country, location_lat/lng, captured_by_user_id
|
||||
├── notes, tags (JSON)
|
||||
├── created_at, updated_at
|
||||
└── Relationships: tech_profile, performance_profile, score, contacts, interactions
|
||||
```
|
||||
|
||||
### Prospect Score (0-100)
|
||||
|
||||
```
|
||||
ProspectScore
|
||||
├── score (0-100, overall)
|
||||
├── Components: technical_health (max 40), modernity (max 25), business_value (max 25), engagement (max 10)
|
||||
├── reason_flags (JSON array)
|
||||
├── score_breakdown (JSON dict)
|
||||
└── lead_tier: top_priority | quick_win | strategic | low_priority
|
||||
```
|
||||
|
||||
### Status Flow
|
||||
|
||||
```
|
||||
PENDING
|
||||
↓ (HTTP check determines website status)
|
||||
ACTIVE (has website) or PARKED (no website / parked domain)
|
||||
↓ (contact attempt)
|
||||
CONTACTED
|
||||
↓ (outcome)
|
||||
CONVERTED (sale) or INACTIVE (not interested)
|
||||
|
||||
Alternative: PENDING → ERROR (invalid domain, technical issues)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## User Journeys
|
||||
|
||||
### Journey 1: Digital Lead Discovery (Domain Scanning)
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Import `.lu` domains, enrich them, and identify sales opportunities
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Import CSV of .lu domains] --> B[Prospects created with status PENDING]
|
||||
B --> C[Run HTTP check batch]
|
||||
C --> D[Run tech scan batch]
|
||||
D --> E[Run performance scan batch]
|
||||
E --> F[Run contact scrape]
|
||||
F --> G[Compute scores batch]
|
||||
G --> H[View scored leads]
|
||||
H --> I{Score tier?}
|
||||
I -->|>= 70: Top Priority| J[Export & contact immediately]
|
||||
I -->|50-69: Quick Win| K[Queue for campaign]
|
||||
I -->|30-49: Strategic| L[Monitor & nurture]
|
||||
I -->|< 30: Low Priority| M[Deprioritize]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Navigate to Dashboard:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/prospecting`
|
||||
- Prod: `https://hostwizard.lu/admin/prospecting`
|
||||
2. Import domains via CSV:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/import`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/prospects/import`
|
||||
3. Run HTTP batch check:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/http-check/batch`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/enrichment/http-check/batch`
|
||||
4. Run tech scan batch:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/tech-scan/batch`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/enrichment/tech-scan/batch`
|
||||
5. Run performance scan batch:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/performance/batch`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/enrichment/performance/batch`
|
||||
6. Compute scores:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/score-compute/batch`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/enrichment/score-compute/batch`
|
||||
7. Monitor scan jobs:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/prospecting/scan-jobs`
|
||||
- Prod: `https://hostwizard.lu/admin/prospecting/scan-jobs`
|
||||
8. View scored leads:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/prospecting/leads`
|
||||
- Prod: `https://hostwizard.lu/admin/prospecting/leads`
|
||||
9. Export top priority leads:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/prospecting/leads/export/csv?min_score=70`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/prospecting/leads/export/csv?min_score=70`
|
||||
|
||||
---
|
||||
|
||||
### Journey 2: Offline Lead Capture
|
||||
|
||||
**Persona:** Platform Admin (out in the field)
|
||||
**Goal:** Capture business details from in-person encounters using the mobile-friendly capture form
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Meet business owner in-person] --> B[Open Quick Capture on mobile]
|
||||
B --> C[Enter business name, address, contact info]
|
||||
C --> D[Prospect created with channel=OFFLINE]
|
||||
D --> E{Has website?}
|
||||
E -->|Yes| F[Run full enrichment]
|
||||
E -->|No| G[Score based on business value only]
|
||||
F --> H[Prospect fully enriched with score]
|
||||
G --> H
|
||||
H --> I[Log interaction: VISIT]
|
||||
I --> J[Set follow-up date]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Open Quick Capture (mobile-friendly):
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/prospecting/capture`
|
||||
- Prod: `https://hostwizard.lu/admin/prospecting/capture`
|
||||
2. Fill in business details and submit:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/prospects`
|
||||
- Body includes: `channel: "offline"`, `business_name`, `address`, `city`, `postal_code`
|
||||
3. Optionally run full enrichment (if domain known):
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/full/{id}`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/enrichment/full/{id}`
|
||||
4. Log the interaction:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/{id}/interactions`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/prospects/{id}/interactions`
|
||||
- Body: `{ "interaction_type": "visit", "notes": "Met at trade fair", "next_action": "Send proposal", "next_action_date": "2026-03-10" }`
|
||||
|
||||
---
|
||||
|
||||
### Journey 3: Lead Qualification & Export
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Filter enriched prospects by score tier and export qualified leads for outreach
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Navigate to Leads page] --> B[Filter by score tier]
|
||||
B --> C{View preset lists}
|
||||
C -->|Top Priority| D[Score >= 70]
|
||||
C -->|Quick Wins| E[Score 50-69]
|
||||
C -->|Custom filter| F[Set min/max score, channel, contact type]
|
||||
D --> G[Review leads]
|
||||
E --> G
|
||||
F --> G
|
||||
G --> H[Export as CSV]
|
||||
H --> I[Use in campaigns or CRM]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Navigate to Leads:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/prospecting/leads`
|
||||
- Prod: `https://hostwizard.lu/admin/prospecting/leads`
|
||||
2. View top priority leads:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/prospecting/leads/top-priority`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/prospecting/leads/top-priority`
|
||||
3. View quick wins:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/prospecting/leads/quick-wins`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/prospecting/leads/quick-wins`
|
||||
4. Filter with custom parameters:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/prospecting/leads?min_score=60&has_email=true&channel=digital`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/prospecting/leads?min_score=60&has_email=true&channel=digital`
|
||||
5. Export filtered leads as CSV:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/prospecting/leads/export/csv?min_score=50&lead_tier=quick_win`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/prospecting/leads/export/csv?min_score=50&lead_tier=quick_win`
|
||||
|
||||
---
|
||||
|
||||
### Journey 4: Campaign Creation & Outreach
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Create email campaign templates and send targeted outreach to qualified prospects
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Navigate to Campaigns] --> B[Create campaign template]
|
||||
B --> C[Choose lead type: no_website, bad_website, etc.]
|
||||
C --> D[Write email template with variables]
|
||||
D --> E[Preview rendered for specific prospect]
|
||||
E --> F{Looks good?}
|
||||
F -->|Yes| G[Select qualifying leads]
|
||||
G --> H[Send campaign]
|
||||
H --> I[Monitor send status]
|
||||
F -->|No| J[Edit template]
|
||||
J --> E
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Navigate to Campaigns:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/prospecting/campaigns`
|
||||
- Prod: `https://hostwizard.lu/admin/prospecting/campaigns`
|
||||
2. Create a campaign template:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/templates`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/campaigns/templates`
|
||||
- Body: `{ "name": "No Website Outreach", "lead_type": "no_website", "channel": "email", "language": "fr", "subject_template": "Votre presence en ligne", "body_template": "Bonjour {{business_name}}..." }`
|
||||
3. Preview the template for a specific prospect:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/preview`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/campaigns/preview`
|
||||
- Body: `{ "template_id": 1, "prospect_id": 42 }`
|
||||
4. Send campaign to selected prospects:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/send`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/campaigns/send`
|
||||
- Body: `{ "template_id": 1, "prospect_ids": [42, 43, 44] }`
|
||||
5. Monitor campaign sends:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/prospecting/campaigns/sends`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/prospecting/campaigns/sends`
|
||||
|
||||
---
|
||||
|
||||
### Journey 5: Interaction Tracking & Follow-ups
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Log interactions with prospects and track follow-up actions
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Open prospect detail] --> B[View interaction history]
|
||||
B --> C[Log new interaction]
|
||||
C --> D[Set next action & date]
|
||||
D --> E[View upcoming follow-ups]
|
||||
E --> F[Complete follow-up]
|
||||
F --> G{Positive outcome?}
|
||||
G -->|Yes| H[Mark as CONTACTED → CONVERTED]
|
||||
G -->|No| I[Schedule next follow-up or mark INACTIVE]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. View prospect detail:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/prospecting/prospects/{id}`
|
||||
- Prod: `https://hostwizard.lu/admin/prospecting/prospects/{id}`
|
||||
2. View interactions:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/{id}/interactions`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/prospecting/prospects/{id}/interactions`
|
||||
3. Log a new interaction:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/prospects/{id}/interactions`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/prospects/{id}/interactions`
|
||||
- Body: `{ "interaction_type": "call", "subject": "Follow-up call", "outcome": "positive", "next_action": "Send proposal", "next_action_date": "2026-03-15" }`
|
||||
4. View upcoming follow-ups across all prospects:
|
||||
- API Dev: `GET http://localhost:9999/platforms/hosting/api/admin/prospecting/interactions/upcoming`
|
||||
- API Prod: `GET https://hostwizard.lu/api/admin/prospecting/interactions/upcoming`
|
||||
|
||||
---
|
||||
|
||||
### Journey 6: Full Enrichment Pipeline (Single Prospect)
|
||||
|
||||
**Persona:** Platform Admin
|
||||
**Goal:** Run the complete enrichment pipeline for a single prospect to get all data at once
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[Open prospect detail] --> B[Click 'Full Enrichment']
|
||||
B --> C[Step 1: HTTP check]
|
||||
C --> D{Has website?}
|
||||
D -->|Yes| E[Step 2: Tech scan]
|
||||
D -->|No| H[Step 5: Compute score]
|
||||
E --> F[Step 3: Performance audit]
|
||||
F --> G[Step 4: Contact scrape]
|
||||
G --> H
|
||||
H --> I[Prospect fully enriched]
|
||||
I --> J[View score & breakdown]
|
||||
```
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Run full enrichment for a prospect:
|
||||
- API Dev: `POST http://localhost:9999/platforms/hosting/api/admin/prospecting/enrichment/full/{prospect_id}`
|
||||
- API Prod: `POST https://hostwizard.lu/api/admin/prospecting/enrichment/full/{prospect_id}`
|
||||
2. View the enriched prospect detail:
|
||||
- Dev: `http://localhost:9999/platforms/hosting/admin/prospecting/prospects/{prospect_id}`
|
||||
- Prod: `https://hostwizard.lu/admin/prospecting/prospects/{prospect_id}`
|
||||
|
||||
The full enrichment runs 5 sequential steps:
|
||||
|
||||
1. **HTTP check** — Verifies domain connectivity, checks HTTPS, records redirects
|
||||
2. **Tech scan** — Detects CMS, server, hosting provider, JS framework, SSL cert details
|
||||
3. **Performance audit** — Runs PageSpeed analysis, records load times and scores
|
||||
4. **Contact scrape** — Extracts emails, phones, addresses, social links from the website
|
||||
5. **Score compute** — Calculates 0-100 opportunity score with component breakdown
|
||||
|
||||
---
|
||||
|
||||
## Recommended Test Order
|
||||
|
||||
1. **Journey 1** (steps 1-3) - Import domains and run HTTP checks first
|
||||
2. **Journey 6** - Run full enrichment on a single prospect to test the complete pipeline
|
||||
3. **Journey 1** (steps 4-9) - Run batch scans and view scored leads
|
||||
4. **Journey 2** - Test offline capture on mobile
|
||||
5. **Journey 3** - Filter and export leads
|
||||
6. **Journey 4** - Create campaign templates and send to prospects
|
||||
7. **Journey 5** - Log interactions and check follow-ups
|
||||
|
||||
!!! tip "Enrichment order matters"
|
||||
The enrichment pipeline must run in order: HTTP check first (determines if website exists),
|
||||
then tech scan, performance, and contacts (all require a live website). Score computation
|
||||
should run last as it uses data from all other steps.
|
||||
Reference in New Issue
Block a user