5.4 KiB
5.4 KiB
PRD: WhatsApp Lead Management for go-crm
Problem Statement
Clients using the go-crm platform need to connect their personal WhatsApp number to capture leads. Currently, there is no way for clients to:
- Authenticate their WhatsApp account via QR code
- Automatically capture incoming WhatsApp messages (1:1 chats, not groups) as leads in the CRM
- Manage these leads (CRUD operations) through the platform
Solution
Add a "Leads" feature to go-crm that allows clients to:
- Connect their WhatsApp via QR code scanning from the client list
- Automatically sync incoming WhatsApp messages (not group chats) as leads in the CRM
- View, edit, and manage these leads through existing CRUD operations
User Stories
- As a client, I want to see a "QR Connect" button next to my client name in the client list, so that I can initiate WhatsApp connection
- As a client, I want to scan a QR code with my WhatsApp app to authenticate, so that my WhatsApp gets connected to my CRM account
- As a client, I want to see my connected WhatsApp phone number displayed in the client list, so that I know I'm connected
- As a client, I want my incoming WhatsApp messages (not groups) to automatically appear as leads in the CRM, so that I can manage them
- As a client, I want my existing WhatsApp contacts to sync as leads when I first connect, so that I have my historical data in the CRM
- As a client, I want to view all my leads in a dedicated "/leads" page, so that I can see my potential customers
- As a client, I want to search and filter my leads by name or phone number, so that I can find specific contacts quickly
- As a client, I want to edit lead details (name, phone, birth date, Instagram) from the Leads page, so that I can keep information up to date
- As a client, I want to delete a lead, so that I can remove spam or unwanted contacts
- As a client, I want my lead's phone number to be normalized (with country code), so that data is consistent
- As a client, I want the system to skip group messages from WhatsApp, so that I only get 1:1 chat leads
- As a client, if I reconnect my WhatsApp, I want the session to be reused, so that I don't need to scan QR every time
- As a client, if the WhatsApp background process crashes, I want it to automatically restart, so that I don't lose messages
- As a client, if I receive a message from an existing lead phone number, I want the system to update the existing record (not create duplicates), so that my data stays accurate
- As a client, I want my leads to display the phone number I connected with as my own, so that I know which WhatsApp is linked
Implementation Decisions
Architecture
- Go wraps Node.js whatsapp-web.js as a subprocess (spawn-and-keep after connection)
- IPC via stdout JSON lines + HTMX polling for frontend
- Per-client WhatsApp session folder (
.wwebjs_auth/{client_id}/)
Database Schema (clients table)
whatsapp_number TEXT— normalized phone number (e.g.,+5521...)whatsapp_connected INTEGER DEFAULT 0— connection status (0=false, 1=true)
Route Structure
GET /leads— list all leads for the logged-in client's accountGET /leads/connect?client_id={id}— QR code display page for connectionGET /leads/qr?client_id={id}— polling endpoint for QR/status (returns current QR string or status)
Node.js Script (whatsapp-leads.js)
- Spawned per-client with per-client session folder
- Filters group chats (only processes 1:1 messages)
- Upserts on duplicate phone number
- Syncs historical chats + new incoming messages
- Calls Go's existing
POST /customersendpoint with internal secret header
Process Lifecycle
- Ephemeral spawn for QR connection flow (spawns, waits for READY, then keeps running)
- Auto-restart if Node.js process exits unexpectedly
UI Flow
- Client list (
/clients) shows "Connect" button ifwhatsapp_number IS NULL, otherwise displays connected phone number - Leads page (
/leads) shows table of leads with edit/delete actions
Authentication
- Node.js → Go uses shared internal secret header (
X-Internal-Secret) to bypass session auth
Testing Decisions
Test Philosophy
- Tests should verify behavior through public interfaces, not implementation details
- Good tests read like specifications: "client can connect WhatsApp" tells you exactly what capability exists
- Tests should survive internal refactors — if renaming an internal function breaks tests, those tests were testing implementation
Modules to Test
- Database: Client WhatsApp columns (insert/query)
- Handler: Leads page rendering, connection status display
- Node.js script: JSON output to stdout, group message filtering
Prior Art
- No existing tests in go-crm to follow; will create new
handlers_test.goalongside implementation
Out of Scope
- Sending messages back to WhatsApp from the CRM (only receiving/syncing)
- WhatsApp profile pictures/avatars
- Multiple WhatsApp numbers per client (one per client)
- Group management features
- Message notifications/push to mobile
- WhatsApp Web client session restoration across Go server restarts (requires systemd/supervisor)
Further Notes
- Phone numbers are stored normalized (with country code) as received from WhatsApp
- Historical chat sync happens on first connection (all existing 1:1 chats become leads)
- New messages sync in real-time while the Node.js process runs
- If WhatsApp session expires/disconnects, client must reconnect via QR