gigafibre-fsm/docs/CUSTOMER-360-FLOWS.md
louispaulb 607ea54b5c refactor: reduce token count, DRY code, consolidate docs
Backend services:
- targo-hub: extract deepGetValue to helpers.js, DRY disconnect reasons
  lookup map, compact CAPABILITIES, consolidate vision.js prompts/schemas,
  extract dispatch scoring weights, trim section dividers across 9 files
- modem-bridge: extract getSession() helper (6 occurrences), resetIdleTimer(),
  consolidate DM query factory, fix duplicate username fill bug, trim headers
  (server.js -36%, tplink-session.js -47%, docker-compose.yml -57%)

Frontend:
- useWifiDiagnostic: extract THRESHOLDS const, split processDiagnostic into
  6 focused helpers (processOnlineStatus, processWanIPs, processRadios,
  processMeshNodes, processClients, checkRadioIssues)
- EquipmentDetail: merge duplicate ROLE_LABELS, remove verbose comments

Documentation (17 → 13 files, -1,400 lines):
- New consolidated README.md (architecture, services, dependencies, auth)
- Merge ECOSYSTEM-OVERVIEW into ARCHITECTURE.md
- Merge MIGRATION-PLAN + ARCHITECTURE-COMPARE + FIELD-GAP + CHANGELOG → MIGRATION.md
- Merge COMPETITIVE-ANALYSIS into PLATFORM-STRATEGY.md
- Update ROADMAP.md with current phase status
- Delete CONTEXT.md (absorbed into README)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 08:39:58 -04:00

20 KiB

Customer 360° — Complete Data Map & Business Flows

Goal

Every piece of customer data linked in one place. All business flows documented so they can be:

  1. Displayed in the ops-app ClientDetailPage
  2. Driven by natural language ("suspend this customer", "create a quote for fibre 100M", "set up a payment plan for $150/month")
  3. Automated via rules/triggers

Current State — What ClientDetailPage Shows

Section Source Status
Customer header (name, status, group) Customer
Contact (phone, email, cell) Customer + Contact
Info card (PPA, commercial, VIP flags) Customer custom fields
Locations + connection type + OLT Service Location
Equipment per location (live status, signal, WiFi) Service Equipment + GenieACS
Subscriptions per location (monthly/annual, price) Service Subscription
Tickets per location Issue
All tickets table Issue
Invoices table Sales Invoice
Payments table Payment Entry
Notes (internal memos) Comment on Customer
Activity timeline (sidebar) Comment + audit

1. Soumissions (Quotes) — 908 records, 529 customers

Legacy: soumission
  id, account_id, name, po, date, tax
  materiel  → PHP serialized array [{sku, desc, amt, qte, tot}, ...]
  mensuel   → PHP serialized array [{sku, desc, amt, qte, tot}, ...]
  text      → terms/notes

  3 templates in soumission_template

ERPNext target: Quotation
  party_type = Customer, party = C-{account_id}
  items[] from deserialized materiel + mensuel
  terms = text field
  legacy_soumission_id = id

Flow: Sales rep creates quote → customer approves → services activated → first invoice generated Natural language: "Create a quote for client X for fibre 100M + WiFi router" UI: New expandable section in ClientDetailPage between Subscriptions and Tickets

2. Accords de paiement (Payment Arrangements) — 7,283 records, 1,687 customers

Legacy: accord_paiement
  id, account_id, staff_id
  date_accord   → date agreed (unix)
  date_echeance → due date (unix)
  date_coupure  → cutoff/disconnect date (unix)
  montant       → agreed payment amount
  method        → 0=unset, 1=portal, 2=cheque, 3=phone, 4=PPA
  status        → -1=pending, 0=open, 1=completed
  note          → staff notes ("Par téléphone avec Gen")
  raison_changement → reason for change

ERPNext target: Custom DocType "Payment Arrangement"
  linked_to Customer via party field
  OR import as structured Comments with type="Payment Arrangement"

Status breakdown: 5,068 completed | 2,205 open | 10 pending

Flow: Customer has overdue balance → support calls → negotiates amount + date → cutoff if missed Natural language: "Set up a payment plan for client X: $150 by March 26, disconnect on April 2 if missed" UI: Badge on CustomerHeader showing active arrangement + section in sidebar

3. Bons de travail (Work Orders) — 14,486 records, 10,110 customers

Legacy: bon_travail
  id, account_id, date (unix)
  tech1, heure_arrive_t1, heure_depart_t1
  tech2, heure_arrive_t2, heure_depart_t2
  note, subtotal, tps, tvq, total

Legacy: bon_travail_item (only 3 records — barely used)
  bon_id, product_id, qte, price, desc

ERPNext target: Linked to Dispatch Job or custom "Work Order" child
  tech1/tech2 → Employee via staff mapping
  Time tracking: arrive/depart for labor costing

Flow: Ticket created → tech dispatched → arrives on site → completes work → bon de travail logged Natural language: "Show me all work done at this address" or "How many hours did tech X spend at client Y?" UI: Timeline entry on location, or section under Tickets

4. Payment Methods & Tokens — Multi-provider

Active customer payment breakdown (6,681 active accounts):

Payment Method Count Notes
No payment method 5,274 Manual pay via portal/cheque
Bank PPA (pre-authorized debit) 655 Legacy bank draft via Paysafe/Bambora token
Stripe card (no auto) 564 Card on file, pays manually
Stripe PPA (auto-charge) 143 Stripe auto-recurring
Bank PPA + Stripe card 45 Both methods on file
Legacy: account_profile (658 records — Paysafe/Bambora tokens)
  account_id, profile_id (UUID), card_id (UUID), token, initial_transaction

Legacy: account table fields
  stripe_id         → Stripe customer ID (cus_xxx)
  stripe_ppa        → 1 = Stripe auto-charge enabled
  stripe_ppa_nocc   → Stripe PPA without CC
  ppa               → 1 = bank draft PPA enabled
  ppa_name/code/branch/account → bank info for PPA
  ppa_amount        → PPA amount limit
  ppa_amount_buffer → buffer above invoice total
  ppa_fixed         → fixed PPA amount
  ppa_cc            → PPA via credit card

ERPNext target: Custom DocType "Payment Method" linked to Customer
  type = stripe | paysafe | bank_draft
  token/profile_id for processor reference
  is_auto = PPA flag
  Stripe integration: use stripe_id to pull current payment methods via API

Flow: Customer adds card (portal or phone) → token stored → PPA auto-charges on invoice Future: Stripe as primary, migrate Paysafe tokens → Stripe, bank PPA stays for some Natural language: "Is client X set up for auto-pay?" / "Switch client X to Stripe auto-charge" UI: Payment method badge on CustomerHeader + card in sidebar

5. VoIP / DID / 911 — Complete Telephone Service

Three linked tables form one VoIP service per DID:

Table Records Unique DIDs Customers Purpose
pbx 790 790 745 SIP line config (creds, voicemail, routing)
phone_addr 1,014 1,014 909 911 address (provisioned to 911 provider)
phone_provisioning 786 779 739 Device provisioning (ATA model, MAC, password)

All 790 PBX lines have a matching 911 address. 224 additional 911 addresses exist without an active PBX line (decommissioned lines that still have 911 registration).

Legacy: pbx (SIP line)
  account_id, delivery_id, service_id
  phone (10-digit DID), name (caller ID display)
  password (SIP auth), vm_password, has_vm, vm_email
  int_code (extension), language, call_911
  max_calls, call_timeout, user_context (sip.targo.ca)
  country_whitelist, date_origin, date_update

Legacy: phone_addr (911 address — provisioned to external 911 provider)
  account_id, phone (DID)
  street_number, apt, street_name, city, state, zip
  first_name, last_name, info
  enhanced_capable (Y/N), code_cauca (municipality code), class_service (RES/BUS)

Legacy: phone_provisioning (ATA/device config)
  account_id, delivery_id, service_id
  phone (DID), app (device type: ht502, etc), mac (device MAC)
  password, internationnal (intl calling flag)

ERPNext target: Custom DocType "VoIP Line"
  parent: Service Location (via delivery_id)
  linked_to: Subscription (via service_id)
  Fields:
    did (phone number), caller_id (display name)
    sip_password, voicemail_enabled, vm_password, vm_email
    extension, max_calls, call_timeout
    e911_street, e911_city, e911_state, e911_zip
    e911_cauca_code, e911_class (RES/BUS)
    e911_synced (bool — matches 911 provider)
    ata_model, ata_mac, ata_password

Flow: Order → provision SIP line in PBX → register 911 address with provider → configure ATA → service active Address change → update 911 with provider (MANDATORY) → verify sync

Reports needed:

  • DID Report: All DIDs → linked customer → service location → 911 address → match status
  • 911 Audit: DIDs where service address ≠ 911 address (compliance risk)
  • Orphan 911: 224 addresses with no active PBX line (cleanup or deregister)

Natural language:

  • "Show all phone lines for client X"
  • "Update 911 address for 450-272-2408 to 123 Rue Principale"
  • "List all DIDs with mismatched 911 addresses"
  • "What's the voicemail password for 450-272-2408?"
  • "Generate the DID report for all active lines"

UI:

  • Phone icon in equipment strip per location (click → VoIP detail panel)
  • 911 status badge (green = synced, red = mismatch or missing)
  • DID report page accessible from main nav

7. Account Suspension — 1,049 records

Legacy: account_suspension
  account_id, date_start, date_end, note
  (most records have date_start=0, date_end=0 — just flags)

ERPNext target: Customer custom field "is_suspended" or Comment log

Flow: Overdue → auto-suspend → customer pays → reactivate Natural language: "Suspend client X" / "Reactivate client X" UI: Red badge on CustomerHeader, shown in activity timeline

8. IP History — 20,999 records, 5,769 customers

Legacy: ip_history
  account_id, delivery_id, service_id, ip, date (unix)

ERPNext target: Comment on Service Location (audit trail)
  OR custom child table on Service Location

Flow: Service provisioned → IP assigned → IP changes logged Natural language: "What IP did client X have on March 15?" UI: Collapsible history under location details

9. Service Snapshots (Bandwidth Usage) — 45,977 records

Legacy: service_snapshot
  account_id, service_id, date (unix)
  quota_day (bytes), quota_night (bytes)

ERPNext target: Skip import — historical analytics only
  Could feed a usage dashboard later

10. Delivery History (Address Changes) — 16,284 records

Legacy: delivery_history
  account_id, date_orig (unix)
  address1, address2, city, state, zip
  (previous addresses before changes)

ERPNext target: Comment on Customer or Service Location

Complete Business Flows

Flow 1: Sales → Activation

Quote created (soumission)
  ↓ Customer approves
Quote → Sales Order (or direct to Subscription)
  ↓ Address confirmed
Service Location created/selected
  ↓ Equipment assigned
Service Equipment linked to location
  ↓ Installation scheduled
Dispatch Job (from ticket or bon_travail)
  ↓ Tech completes work
Subscriptions activated
  ↓ First billing cycle
Sales Invoice generated

Natural language examples:

  • "Create a quote for client X: fibre 100M at 123 Rue Principale"
  • "Convert quote SOQ-908 to active subscriptions"
  • "Schedule installation for next Tuesday"

Flow 2: Billing → Collections

Subscription active
  ↓ Monthly/annual cycle
Sales Invoice auto-generated
  ↓ PPA active?
  YES → Auto-charge via payment token (account_profile)
  NO  → Invoice sent (email/portal)
  ↓ Payment received?
  YES → Payment Entry created, outstanding reduced
  NO  → Overdue
  ↓ Collections process
Payment arrangement negotiated (accord_paiement)
  ↓ Cutoff date passed?
  YES → Account suspended (account_suspension)
  ↓ Payment received
Account reactivated

Natural language examples:

  • "What does client X owe?"
  • "Set up a payment plan: $150 by the 15th, cut off on the 20th"
  • "Suspend client X for non-payment"
  • "Client X just paid, reactivate their service"

Flow 3: Support → Resolution

Customer calls / portal ticket
  ↓ Issue created
Ticket assigned to department/tech
  ↓ Remote diagnosis?
  YES → Check equipment live status (GenieACS/TR-069)
       → Reboot device, check signal, WiFi clients
  NO  → Schedule field visit
  ↓ Dispatch Job created
Tech dispatched → arrives → works
  ↓ Bon de travail logged (tech, hours, parts)
Issue resolved → closed
  ↓ Billable?
  YES → Invoice for labor/parts
  NO  → Done

Natural language examples:

  • "Client X has no internet — check their ONT status"
  • "Send a tech to 123 Rue Principale tomorrow morning"
  • "How many times have we sent a tech to this address?"

Flow 4: Provisioning → Service Management

Service ordered
  ↓ Equipment assigned
OLT port configured (fibre table)
  ↓ ONT registered
GenieACS discovers device → TR-069 parameters set
  ↓ VoIP ordered?
  YES → PBX line created (pbx table)
       → 911 address registered (phone_addr)
       → Voicemail configured
  ↓ IP assigned
IP logged in ip_history
  ↓ Service active
Subscription billing begins

Natural language examples:

  • "Provision fibre for client X at port 1/2/3 on OLT-EAST"
  • "Set up a phone line 819-555-1234 with voicemail"
  • "What's the 911 address for this line?"

ERPNext Data Model — Complete Customer Graph

Customer (C-{id})
│
├── SALES
│   ├── Quotation ←── soumission (908)              ◄ TO IMPORT
│   │   └── Quotation Item (materiel + mensuel)
│   └── (future: Sales Order)
│
├── BILLING
│   ├── Sales Invoice (629,935)                      ✅ DONE
│   │   ├── SI Item → income_account (SKU-mapped)    ✅ DONE
│   │   ├── SI Tax (TPS/TVQ)                         ✅ DONE
│   │   ├── GL Entry (4 per invoice)                 ✅ DONE
│   │   ├── PLE (outstanding tracking)               ✅ DONE
│   │   └── Comment (invoice notes, 580K)            ✅ DONE
│   ├── Payment Entry (343,684)                      ✅ DONE
│   │   ├── PE Reference (allocations)               ✅ DONE
│   │   └── GL Entry (2 per payment)                 ✅ DONE
│   ├── Payment Arrangement ←── accord_paiement      ◄ TO IMPORT
│   │   (7,283: amount, dates, cutoff, status)
│   └── Payment Method (custom doctype)              ◄ TO IMPORT
│       ├── Stripe (752 customers, 143 auto-PPA)
│       │   └── stripe_id → Stripe API for live card info
│       ├── Paysafe/Bambora (658 tokens from account_profile)
│       │   └── profile_id + card_id + token
│       └── Bank PPA (655 with bank account info)
│           └── ppa_name, ppa_code, ppa_branch, ppa_account
│
├── SERVICE
│   ├── Service Location (delivery)                  ✅ DONE
│   │   ├── Service Equipment (device)               ✅ DONE
│   │   │   ├── OLT data (fibre table)               ✅ DONE
│   │   │   ├── Live status (GenieACS TR-069)        ✅ LIVE
│   │   │   └── Provisioning data (WiFi/VoIP)        ✅ DONE
│   │   ├── VoIP Line ←── pbx (790 DIDs)             ◄ TO IMPORT
│   │   │   ├── 911 Address ←── phone_addr (1,014)   ◄ TO IMPORT
│   │   │   │   └── Synced to external 911 provider (CAUCA codes)
│   │   │   │   └── 224 orphan 911 records (no active PBX line)
│   │   │   └── ATA Config ←── phone_provisioning    ◄ TO IMPORT
│   │   │       (786 records: device type, MAC, SIP creds)
│   │   ├── IP History ←── ip_history (20,999)        ◄ TO IMPORT
│   │   └── Address History ←── delivery_history      ○ LOW PRIORITY
│   ├── Subscription (active services)               ✅ DONE
│   │   ├── Subscription Plan                        ✅ DONE
│   │   └── Billing frequency + price                ✅ DONE
│   └── Suspension Status ←── account_suspension     ◄ TO IMPORT
│       (1,049 records)
│
├── SUPPORT
│   ├── Issue / Ticket (98,524)                      ✅ DONE
│   │   ├── Communication (ticket messages)          ✅ DONE
│   │   ├── Dispatch Job                             ✅ DONE
│   │   └── Work Order ←── bon_travail (14,486)      ◄ TO IMPORT
│   │       (tech, hours, parts, billing)
│   └── Comment / Memo (29,245)                      ✅ DONE
│
├── ACCOUNT
│   ├── Portal User (Website User)                   ✅ DONE
│   │   └── Auth bridge (MD5 → pbkdf2)              ✅ DONE
│   ├── Stripe ID                                    ✅ DONE
│   └── PPA flags + bank info                        ✅ DONE
│
└── ANALYTICS (low priority)
    ├── Bandwidth Usage ←── service_snapshot (46K)    ○ SKIP
    ├── VoIP CDR ←── voicemeup (96)                   ○ SKIP
    └── TV Wizard ←── tele_wiz (1,065)                ○ SKIP

Import Priority & Plan

Phase 13: Remaining Customer Data

Step Table Target Records Depends on
13a soumission Quotation 908 Customer, Item
13b accord_paiement Payment Arrangement (custom) 7,283 Customer
13c bon_travail Work Order log on Issue/Customer 14,486 Customer, Employee
13d account_profile + account.*ppa* + account.stripe_id Payment Method (custom doctype) 658 + 655 + 752 Customer
13e pbx + phone_provisioning VoIP Line (custom doctype) linked to Location + Subscription 790 + 786 Customer, Service Location
13f phone_addr 911 Address fields on VoIP Line + sync status flag 1,014 VoIP Line
13f.1 DID Report: all DIDs → customer → location → 911 address → sync status report VoIP Line
13f.2 911 Audit Report: mismatches + 224 orphan 911 addresses report VoIP Line
13g account_suspension Customer.is_suspended flag 1,049 Customer
13h ip_history Comment on Service Location 20,999 Service Location

Phase 14: UI Sections in ClientDetailPage

Section Position Data
Soumissions After subscriptions, before tickets Quotation list with status
Accord de paiement Badge on header + sidebar card Active arrangement with countdown
Bons de travail Under ticket detail or in timeline Tech visits with hours
VoIP Under equipment strip per location Phone lines with 911 status
Suspension Red banner on header Active suspension with dates

Phase 15: Natural Language Actions

Each action maps to an API call on ERPNext or targo-hub:

Intent Action API
"Create a quote for..." Parse items + customer → POST Quotation ERPNext API
"Suspend client X" Set is_suspended=1, trigger OLT port disable targo-hub + OLT API
"Set up payment plan..." Create Payment Arrangement with dates/amount ERPNext API
"What does X owe?" SUM(outstanding_amount) from Sales Invoice ERPNext API
"Send a tech to..." Create Dispatch Job with location ERPNext API
"Check their internet" GenieACS device status + signal levels targo-hub
"Reboot their router" TR-069 reboot task via GenieACS targo-hub
"What IP did X have on..." Query ip_history or Comment ERPNext API
"Add a phone line" Create VoIP Line + register 911 PBX API + 911 provider API + targo-hub
"Update 911 address for..." Update phone_addr + push to 911 provider 911 provider API
"Show DID report" All DIDs with customer, location, 911 match ERPNext report
"List mismatched 911" DIDs where service addr ≠ 911 addr ERPNext report
"Switch client to Stripe" Create Stripe customer + set PPA flag Stripe API
"Is client X on auto-pay?" Check Payment Method for active PPA ERPNext API
"Convert quote to service" Quotation → Subscriptions + Location setup ERPNext API

Natural Language Architecture

User input (text or voice)
  ↓
Intent classifier (LLM)
  ↓ extracts: action, customer, parameters
Action router
  ↓ maps intent → API endpoint + payload
Confirmation step (show what will change)
  ↓ user approves
Execute via targo-hub API
  ↓ returns result
Response in natural language

Key principle: every action the UI can do, the NL interface can do. The ops-app becomes a visual confirmation layer for NL-driven changes.