gigafibre-fsm/docs/CUSTOMER-FLOW-ARCHITECTURE.md
louispaulb e9324b45bc docs: complete customer flow architecture (lead → live service)
End-to-end design covering:
- Address fuzzy search → fibre availability (16,056 entries, 30 OLTs)
- Plan selection + pricing engine (FTTH 25M-1.5G, TV, Phone, combos)
- Checkout → Stripe → n8n automation pipeline
- ERPNext: Customer → Service Location → Subscriptions → Equipment
- Project/task auto-creation for installation workflow
- Dispatch job with preferred dates and tag-based tech matching
- Field tech barcode scanning → Service Equipment creation
- ACS auto-provisioning on device bootstrap (WiFi, VoIP, firmware)
- Lead funnel for non-covered addresses (phone-only, business)
- Customer portal (invoices, WiFi management, tickets)
- Full product catalog mapped from legacy (Internet/TV/Phone/discounts)
- 5-sprint build order with dependencies

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 09:28:20 -04:00

543 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Complete Customer Flow — From Lead to Live Service
## Overview
```
┌──────────────────────────────────────────────────────────────────────┐
│ CUSTOMER-FACING WEBSITE │
│ www.gigafibre.ca │
│ │
│ [Vérifier la disponibilité] ← Visitor enters address │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ ┌──────────────────────────────┐ │
│ │ Address Fuzzy Search │───▶│ Supabase / Address Server │ │
│ │ (pg_trgm) │ │ 5.2M RQA addresses │ │
│ └─────────────────────┘ │ + fiber_availability table │ │
│ │ └──────────────────────────────┘ │
│ ▼ │
│ ┌──── AVAILABLE ────┐ ┌──── NOT AVAILABLE ────┐ │
│ │ Show plans/pricing │ │ "Pas encore disponible"│ │
│ │ Internet speeds │ │ Capture contact info │ │
│ │ TV packages │ │ → Lead / Waitlist │ │
│ │ Phone service │ └────────────────────────┘ │
│ └────────┬───────────┘ │
│ ▼ │
│ ┌──── CHECKOUT ─────┐ │
│ │ Summary: Internet │ │
│ │ + TV (1st free) │ │
│ │ + Phone optional │ │
│ │ Choose 3 dates │ │
│ │ Stripe payment │ │
│ └────────┬───────────┘ │
└───────────┼──────────────────────────────────────────────────────────┘
▼ WEBHOOK / API
┌──────────────────────────────────────────────────────────────────────┐
│ BACK-OFFICE AUTOMATION │
│ │
│ n8n / targo-hub │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 1. Create Customer in ERPNext │ │
│ │ 2. Create Service Location (address + OLT port) │ │
│ │ 3. Create Service Subscriptions (internet/tv/phone) │ │
│ │ 4. Create Project "Installation {customer}" │ │
│ │ └─ Task: Assign tech + schedule from chosen dates │ │
│ │ └─ Task: Prepare equipment (ONT + Deco + STB) │ │
│ │ └─ Task: Activate OLT port (VLAN provisioning) │ │
│ │ └─ Task: Configure WiFi/VoIP in provisioning DB │ │
│ │ 5. Create Dispatch Job (tech assignment) │ │
│ │ 6. Send SMS confirmation (Twilio) │ │
│ │ 7. Send email confirmation (Mailjet) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────┘
▼ TECHNICIAN ARRIVES
┌──────────────────────────────────────────────────────────────────────┐
│ FIELD TECH APP │
│ │
│ 1. Open Dispatch Job → see address, OLT port, equipment list │
│ 2. Scan ONT barcode (RCMG/TPLG serial) → creates Service Equipment│
│ 3. Scan Deco barcode → links to Service Location │
│ 4. Scan STB barcode (if TV) → links to Service Location │
│ 5. Connect fiber → ONT powers up → TR-069 INFORM to ACS │
│ │
└──────────────────────────────────────────────────────────────────────┘
▼ DEVICE CONNECTS (TR-069 INFORM)
┌──────────────────────────────────────────────────────────────────────┐
│ ACS (GenieACS → Oktopus) │
│ │
│ ┌─── ON BOOTSTRAP (first connect) ───┐ │
│ │ 1. Identify device (OUI, model, SN) │ │
│ │ 2. Match to Service Equipment │ │
│ │ (serial tag → ERPNext lookup) │ │
│ │ 3. Apply device profile: │ │
│ │ - Bridge mode (Raisecom) │ │
│ │ - WiFi SSID/pwd (Deco) │ │
│ │ - VoIP SIP credentials │ │
│ │ - NTP, DSCP, UPnP settings │ │
│ │ 4. Push firmware if needed │ │
│ │ 5. Notify targo-hub (SSE) │ │
│ │ → "Device online" event │ │
│ └──────────────────────────────────────┘ │
│ │
│ ┌─── ON INFORM (periodic) ───┐ │
│ │ Refresh: IP, signal, hosts │ │
│ │ Check firmware version │ │
│ │ Report to monitoring │ │
│ └─────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────┘
▼ SERVICE LIVE
┌──────────────────────────────────────────────────────────────────────┐
│ CUSTOMER PORTAL │
│ client.gigafibre.ca │
│ │
│ - View/pay invoices (Stripe QR) │
│ - View subscriptions │
│ - Change WiFi SSID/password → pushes to ACS │
│ - Open support tickets │
│ - View service status │
│ │
└──────────────────────────────────────────────────────────────────────┘
```
---
## Phase 1: Address Search & Availability
### Current State
- AvailabilityDialog.tsx exists on www.gigafibre.ca
- Fuzzy search via `search_addresses()` RPC (pg_trgm on Supabase)
- 5.2M RQA addresses loaded
- `fiber_availability` table with zone_tarifaire + max_speed
- Lead capture sends email to support@targo.ca via Mailjet
### What Needs to Change
**Address source**: The `fiber_availability` table needs to be linked to the `fibre` table (legacy). Currently fiber_availability has generic coverage data. It needs the actual OLT port availability:
```
fiber_availability (current)
uuidadresse → address → zone_tarifaire + max_speed
fiber_availability (target)
uuidadresse → address → fibre.id → OLT/slot/port → has_available_port (bool)
→ max_speed (from OLT capacity)
→ zone_tarifaire (pricing zone)
```
**The fibre table IS the availability database:**
- 16,056 entries = 16,056 physical fibre drops to premises
- 4,949 have an ONT installed (sn populated) = occupied port
- 11,107 have no ONT = available for new service (but 1,149 are "boitier_pas_install")
- Each entry has: address, OLT IP, frame/slot/port, ontid slot
**Matching RQA addresses to fibre entries:**
- fibre.rue + fibre.ville + fibre.zip → fuzzy match to RQA address
- OR fibre.latitude/longitude → nearest RQA address
- Once matched: each RQA address either has a fibre entry (available) or not
### OLT Capacity (30 OLTs, 25 locations)
| OLT | Location | Total | Connected | Available |
|-----|----------|-------|-----------|-----------|
| 172.17.16.2 | Saint-Anicet | 2,155 | 844 | 1,311 |
| 172.17.32.2 | Hemmingford | 1,742 | 689 | 1,053 |
| 172.17.48.2 | Saint-Antoine | 1,383 | 594 | 789 |
| 172.17.64.2 | Havelock | 1,347 | 484 | 863 |
| 172.17.208.4 | Athelstan | 1,167 | 589 | 578 |
| 172.17.112.2 | Saint-Louis | 1,054 | 329 | 725 |
| ... | ... | ... | ... | ... |
| **Total** | **25 locations** | **16,056** | **4,949** | **~11,000** |
---
## Phase 2: Pricing & Plan Selection
### Product Catalog (from legacy, combo_ready=1)
**Internet (Mensualités fibre):**
| SKU | Speed ↓/↑ | Price | Profile |
|-----|-----------|-------|---------|
| FTTH25 | 25/5 Mbps | $49.95 | LP:100 |
| FTTH80I | 80/80 Mbps | $79.95 | LP:101 |
| FTTH150I | 150/150 Mbps | $99.95 | LP:102 |
| FTTH500I | 500/500 Mbps | $99.95 | LP:103 |
| FTTH1500I | 1.5G/1G | $109.95 | LP:104 |
**TV (Mensualités télévision):**
| SKU | Name | Price | Note |
|-----|------|-------|------|
| TVBSKINNY | Skinny | $25 | Base package |
| TVBSTANDARD | Standard | $30 | Mid package |
| TVBEVO | Evo | $35 | Premium |
| TELE | Base TV | $0 | Included with internet? |
| + add-ons | Sports, Films, etc. | $5-$25 each | |
**Phone (Téléphonie):**
| SKU | Price | Note |
|-----|-------|------|
| TELEPMENS | $28.95/mo | Residential SIP line |
| SERV911 | $0.69/mo | 911 fee |
| ACTTELEP | $69.95 once | Activation |
**Discounts (combo):**
| SKU | Discount | Condition |
|-----|----------|-----------|
| RAB2X | -$5 | 2 services |
| RAB3X | -$10 | 3 services |
| RAB4X | -$15 | 4 services |
| RAB_X | -$20 | Special |
| RAB24M | -$15 | 24-month commitment |
| RAB36M | -$15 | 36-month commitment |
### Checkout Logic
```
Monthly total = Internet plan
+ TV package (if selected)
+ TV add-ons
+ Phone ($28.95 if selected)
+ 911 fee ($0.69 if phone)
- Combo discount (2x/3x/4x)
- Commitment discount (24m/36m)
One-time charges:
+ Installation ($0 for standard FTTH)
+ TV box: 1st FREE, 2nd+ at regular price
+ Phone activation ($69.95)
```
### First TV Box Credit
- Detect: if order includes TV + this is customer's first box
- Apply credit equal to STB equipment price
- Show on summary: "1er décodeur offert"
---
## Phase 3: Checkout & Order Submission
### Customer Input
1. **Service selection** (internet speed + TV package + phone yes/no)
2. **Address** (pre-filled from availability check)
3. **Contact info** (name, email, phone)
4. **Installation preference**:
- Choose from 3 available dates (next 2 weeks, exclude weekends)
- OR "Contactez-moi" (we call to schedule)
5. **Payment** via Stripe (first month + one-time charges)
### What Happens on Submit
```
POST /api/checkout
{
address: { fibre_id, rue, ville, zip, olt_port, lat, lng },
customer: { name, email, phone },
services: [
{ sku: "FTTH150I", type: "internet" },
{ sku: "TVBSTANDARD", type: "tv" },
{ sku: "TELEPMENS", type: "phone" }
],
preferred_dates: ["2026-04-07", "2026-04-09", "2026-04-11"],
stripe_payment_intent: "pi_xxx"
}
```
---
## Phase 4: Back-Office Automation (n8n + targo-hub)
### Trigger: New Order Webhook
```
n8n workflow: "New Customer Order"
═══════════════════════════════════
1. VALIDATE
- Verify Stripe payment
- Verify fibre port still available
- Verify address matches fibre.id
2. CREATE CUSTOMER (ERPNext API)
POST /api/resource/Customer
{
customer_name: "Jean Tremblay",
customer_group: "Résidentiel",
email_id, mobile_no,
legacy_customer_id: null (new customer)
}
3. CREATE SERVICE LOCATION
POST /api/resource/Service Location
{
customer, address_line, city, postal_code,
connection_type: "FTTH",
olt_name, olt_ip, olt_frame, olt_slot, olt_port, ont_id,
status: "Pending Install"
}
4. CREATE SUBSCRIPTIONS (one per service)
POST /api/resource/Service Subscription
× Internet: { item: FTTH150I, location, status: "Pending" }
× TV: { item: TVBSTANDARD, location, status: "Pending" }
× Phone: { item: TELEPMENS, location, status: "Pending" }
5. CREATE SERVICE EQUIPMENT (pre-assigned)
× ONT: { type: "ONT", serial: TBD (tech assigns on site) }
× Deco: { type: "Routeur", serial: TBD }
× STB: { type: "Décodeur TV", serial: TBD } (if TV)
× ATA: { type: "Téléphone IP", serial: TBD } (if phone)
6. CREATE PROJECT "Installation - Jean Tremblay"
Tasks:
☐ Préparer équipement (support)
☐ Assigner technicien (dispatch)
☐ Activer port OLT - frame/slot/port (support)
☐ Configurer WiFi dans DB provisioning (support)
☐ Configurer VoIP dans DB provisioning (if phone)
☐ Installation sur site (tech)
☐ Vérifier signal ONT (tech)
☐ Confirmer service fonctionnel (tech)
7. CREATE DISPATCH JOB
{
customer, location,
preferred_dates: [...],
required_tags: ["Fibre", "Installation"],
equipment_list: [ONT, Deco, STB?],
notes: "FTTH 150M + TV Standard + Phone"
}
8. RESERVE FIBRE PORT
UPDATE fibre SET sn = 'RESERVED-{order_id}'
WHERE id = {fibre_id} AND (sn IS NULL OR sn = '')
9. SEND NOTIFICATIONS
× SMS to customer: "Commande confirmée! Installation prévue le..."
× Email to customer: order summary
× SSE to Ops: new order event
× Slack/Teams to dispatch: new installation job
```
---
## Phase 5: Installation Day
### Field Tech App Flow
```
1. Tech opens Dispatch Job on mobile
→ Sees: address, customer info, equipment list, OLT port
2. Tech picks up equipment from warehouse
→ Scans each barcode:
- ONT: RCMG19E0XXXX → Service Equipment created, linked to location
- Deco: 403F8CXXXXXX → Service Equipment created
- STB: (ministra MAC) → Service Equipment created
3. Tech drives to site (GPS tracked via Traccar)
→ Customer gets SMS: "Technicien en route"
4. Tech installs fiber drop + ONT
→ ONT powers up → sends TR-069 BOOTSTRAP to ACS
5. ACS receives BOOTSTRAP
→ Matches ONT serial to Service Equipment
→ Applies provisioning profile:
- Bridge mode, VLANs, DSCP
- WiFi SSID/password (via ext script → provisioning DB)
- VoIP SIP credentials (if phone service)
- Firmware check/upgrade
6. Tech connects Deco router behind ONT
→ Deco sends TR-069 INFORM
→ ACS configures WiFi (SSID/password from DB)
7. Tech verifies:
☐ Internet speed test
☐ WiFi working on both bands
☐ TV channels loading (if applicable)
☐ Phone dial tone (if applicable)
8. Tech marks job complete in app
→ Service Location status → "Active"
→ Service Subscriptions → "Active"
→ Service Equipment status → "Actif"
→ Customer gets SMS: "Service activé!"
→ First invoice generated (pro-rated)
```
---
## Phase 6: ACS Provisioning (GenieACS → Oktopus)
### Current GenieACS Flow
```
ONT connects → CWMP INFORM
→ Preset matches (by ProductClass tag)
→ Provision script runs:
1. bootstrap: clear tree, force refresh
2. default: refresh hourly params (IP, MAC, hosts, firmware)
3. model-specific inform:
- HT803G-W: VoIP DSCP, NTP, bridge mode, UPnP off
- Device2 (Deco): WiFi from DB (ext→provisioning.js→MariaDB)
- XX230v/430v/530v: VoIP digit map, SIP server, DTMF
4. firmware-upgrade: auto-push if version mismatch
```
### Target Oktopus Flow
```
ONT connects → MQTT/CWMP
→ Device identified → matched to device group
→ Device profile applied:
1. Webhook to targo-hub: GET /devices/{serial}/provision
→ targo-hub looks up Service Equipment in ERPNext
→ Returns: WiFi config, VoIP config, VLAN settings
2. Oktopus pushes params to device
3. Webhook to targo-hub: POST /devices/{serial}/activated
→ targo-hub updates Service Equipment status
→ Broadcasts SSE event to Ops UI
```
### n8n Trigger for Device Events
```
Oktopus → MQTT topic: device/bootstrap/{serial}
→ n8n MQTT listener
→ n8n workflow:
1. Look up serial in ERPNext Service Equipment
2. If found: mark "Connected", update IP/firmware
3. If NOT found: create Issue "Unknown device {serial}"
4. Broadcast to targo-hub SSE
```
---
## Phase 7: Not Available → Lead Funnel
### When Address Has No Fiber
```
Visitor searches "123 rue Principale, Somewhere"
→ No fibre entry found
→ Show: "La fibre n'est pas encore disponible à votre adresse"
┌─────────────────────────────────────────────┐
│ Options presented: │
│ │
│ 📱 Phone service is available anywhere! │
│ VoIP works over any internet connection │
│ → [Voir les forfaits téléphonie] │
│ │
│ 🏢 Business fiber? Custom installation! │
│ → [Demander une soumission] │
│ │
│ 📧 Be notified when fiber arrives: │
│ [email/phone] → [M'aviser] │
└─────────────────────────────────────────────┘
On "M'aviser" submit:
→ Create Lead in ERPNext (name, contact, address, interest)
→ Tag with area/municipality for future coverage planning
→ n8n: if address is in planned expansion zone, notify sales
On "Demander une soumission" (business):
→ Create Lead with type "Enterprise"
→ Create Issue "Soumission fibre entreprise - {address}"
→ Assign to sales team
→ n8n: send email to sales@targo.ca
```
---
## Data Migration: What Needs to Happen
### 1. Link Fibre Table to RQA Addresses
```sql
-- Match fibre entries to RQA addresses by fuzzy address + postal code
-- This enables the website availability check to return OLT port info
UPDATE fiber_availability fa
SET fibre_id = f.id,
olt_ip = f.info_connect,
olt_port = CONCAT(f.frame, '/', f.slot, '/', f.port),
available = (f.sn IS NULL OR f.sn = '')
FROM fibre f
WHERE fa.address matches f.rue + f.ville (fuzzy)
```
### 2. Migrate Provisioning DB to ERPNext
```
For each device in genieacs.wifi:
→ Find Service Equipment by MAC (Deco) or serial (ONT)
→ Store WiFi SSID/password as custom fields on Service Equipment
→ Or: keep in a separate provisioning table that targo-hub queries
For each device in genieacs.voip:
→ Find Service Equipment by RCMG serial
→ Store SIP username/password as custom fields
→ Or: keep in Fonoster/Routr as SIP accounts
```
### 3. Map Legacy Customers to ERPNext
```
fibre.service_id → service.delivery_id → delivery.account_id
→ ERPNext Customer (legacy_customer_id = account_id)
```
---
## Systems Inventory
| System | Role | Current | Target |
|--------|------|---------|--------|
| **www.gigafibre.ca** | Website + availability | React/Vite + Supabase | Same + checkout flow |
| **Supabase** | Address DB + search | 5.2M RQA addresses | + fibre availability link |
| **ERPNext** | CRM, billing, inventory | Running | Add provisioning fields |
| **targo-hub** | SSE relay + API proxy | SMS, voice, telephony, ACS | + checkout webhook, device events |
| **n8n** | Workflow automation | Exists, minimal use | Order→project→dispatch pipeline |
| **GenieACS** | TR-069 ACS | Running, 7,550 devices | → Migrate to Oktopus |
| **Oktopus** | TR-369 ACS | At oss.gigafibre.ca | Take over from GenieACS |
| **Stripe** | Payments | Planned | Checkout + recurring billing |
| **Twilio** | SMS/Voice | Running via targo-hub | Order confirmations, tech ETA |
| **Mapbox** | Maps | Dispatch app | + coverage map on website? |
| **Traccar** | GPS tracking | Running for techs | Continue |
| **Fonoster/Routr** | SIP/VoIP | Running | SIP account provisioning |
| **MariaDB (10.100.80.100)** | Legacy + provisioning | wifi/voip tables | Migrate to ERPNext or keep |
| **MongoDB (10.5.2.116)** | GenieACS device DB | 7,550 devices | Archive after Oktopus migration |
---
## Build Order (Recommended)
### Sprint 1: Data Foundation (1 week)
1. Match fibre entries to RQA addresses (geo + fuzzy)
2. Expose OLT port availability via Supabase/API
3. Migrate product catalog to ERPNext Items (if not already done)
4. Create ERPNext provisioning fields on Service Equipment
### Sprint 2: Checkout Flow (1-2 weeks)
1. Build plan selection UI on website (internet + TV + phone)
2. Build checkout page (summary, date picker, Stripe)
3. Build targo-hub `/checkout` webhook endpoint
4. Build n8n "New Order" workflow (customer → location → subscriptions → project)
### Sprint 3: Dispatch Integration (1 week)
1. Auto-create Dispatch Job from new order
2. SMS notifications (confirmation, tech en route, completed)
3. Field tech app: barcode scanner → Service Equipment creation
### Sprint 4: Auto-Provisioning (2 weeks)
1. targo-hub `/devices/{serial}/provision` endpoint
2. Oktopus webhook integration (device connect → provision request)
3. WiFi/VoIP credential auto-push on device bootstrap
4. "Device online" SSE events to Ops UI
### Sprint 5: Customer Portal (1-2 weeks)
1. Login via email/SMS OTP (no legacy MD5)
2. Invoice list + Stripe payment
3. WiFi SSID/password change (pushes to ACS)
4. Support ticket creation