Add leads handlers, WhatsApp integration, and test files
This commit is contained in:
122
docs/whatsapp-leads-prd.md
Normal file
122
docs/whatsapp-leads-prd.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# 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:
|
||||
1. Authenticate their WhatsApp account via QR code
|
||||
2. Automatically capture incoming WhatsApp messages (1:1 chats, not groups) as leads in the CRM
|
||||
3. Manage these leads (CRUD operations) through the platform
|
||||
|
||||
---
|
||||
|
||||
## Solution
|
||||
|
||||
Add a "Leads" feature to go-crm that allows clients to:
|
||||
1. Connect their WhatsApp via QR code scanning from the client list
|
||||
2. Automatically sync incoming WhatsApp messages (not group chats) as leads in the CRM
|
||||
3. View, edit, and manage these leads through existing CRUD operations
|
||||
|
||||
---
|
||||
|
||||
## User Stories
|
||||
|
||||
1. 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
|
||||
2. 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
|
||||
3. As a client, I want to see my connected WhatsApp phone number displayed in the client list, so that I know I'm connected
|
||||
4. 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
|
||||
5. 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
|
||||
6. As a client, I want to view all my leads in a dedicated "/leads" page, so that I can see my potential customers
|
||||
7. As a client, I want to search and filter my leads by name or phone number, so that I can find specific contacts quickly
|
||||
8. 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
|
||||
9. As a client, I want to delete a lead, so that I can remove spam or unwanted contacts
|
||||
10. As a client, I want my lead's phone number to be normalized (with country code), so that data is consistent
|
||||
11. As a client, I want the system to skip group messages from WhatsApp, so that I only get 1:1 chat leads
|
||||
12. 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
|
||||
13. As a client, if the WhatsApp background process crashes, I want it to automatically restart, so that I don't lose messages
|
||||
14. 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
|
||||
15. 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 account
|
||||
- `GET /leads/connect?client_id={id}` — QR code display page for connection
|
||||
- `GET /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 /customers` endpoint 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 if `whatsapp_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.go` alongside 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
|
||||
Reference in New Issue
Block a user