# BellSystems CRM — Build Plan & Step Prompts ## Overview A bespoke CRM module built directly into the existing BellSystems web console. Stack: FastAPI backend (Firestore), React + Vite frontend. No new auth — uses the existing JWT + permission system. No file storage on VPS — all media lives on Nextcloud via WebDAV. --- ## Architecture Summary ### Backend - New module: `backend/crm/` with `models.py`, `service.py`, `router.py` - Firestore collections: `crm_customers`, `crm_orders`, `crm_products` - SQLite (existing `mqtt_data.db`) for comms_log (high-write, queryable) - Router registered in `backend/main.py` as `/api/crm` ### Frontend - New section: `frontend/src/crm/` - Routes added to `frontend/src/App.jsx` - Nav entries added to `frontend/src/layout/Sidebar.jsx` ### Integrations (later steps) - Nextcloud: WebDAV via `httpx` in backend - Email: IMAP (read) + SMTP (send) via `imaplib` / `smtplib` - WhatsApp: Meta Cloud API webhook - FreePBX: Asterisk AMI socket listener --- ## Data Model Reference ### `crm_customers` (Firestore) ```json { "id": "auto", "name": "Στέλιος Μπιμπης", "organization": "Ενορία Αγ. Παρασκευής", "contacts": [ { "type": "email", "label": "personal", "value": "...", "primary": true }, { "type": "phone", "label": "mobile", "value": "...", "primary": true } ], "notes": [ { "text": "...", "by": "user_name", "at": "ISO datetime" } ], "location": { "city": "", "country": "", "region": "" }, "language": "el", "tags": [], "owned_items": [ { "type": "console_device", "device_id": "UID", "label": "..." }, { "type": "product", "product_id": "pid", "product_name": "...", "quantity": 1, "serial_numbers": [] }, { "type": "freetext", "description": "...", "serial_number": "", "notes": "" } ], "linked_user_ids": [], "nextcloud_folder": "05_Customers/FOLDER_NAME", "created_at": "ISO", "updated_at": "ISO" } ``` ### `crm_orders` (Firestore) ```json { "id": "auto", "customer_id": "ref", "order_number": "ORD-2026-001", "status": "draft", "items": [ { "type": "console_device|product|freetext", "product_id": "", "product_name": "", "description": "", "quantity": 1, "unit_price": 0.0, "serial_numbers": [] } ], "subtotal": 0.0, "discount": { "type": "percentage|fixed", "value": 0, "reason": "" }, "total_price": 0.0, "currency": "EUR", "shipping": { "method": "", "tracking_number": "", "carrier": "", "shipped_at": null, "delivered_at": null, "destination": "" }, "payment_status": "pending", "invoice_path": "", "notes": "", "created_at": "ISO", "updated_at": "ISO" } ``` ### `crm_products` (Firestore) ```json { "id": "auto", "name": "Vesper Plus", "sku": "VSP-001", "category": "controller|striker|clock|part|repair_service", "description": "", "price": 0.0, "currency": "EUR", "costs": { "pcb": 0.0, "components": 0.0, "enclosure": 0.0, "labor_hours": 0, "labor_rate": 0.0, "shipping_in": 0.0, "total": 0.0 }, "stock": { "on_hand": 0, "reserved": 0, "available": 0 }, "nextcloud_folder": "02_Products/FOLDER", "linked_device_type": "", "active": true, "created_at": "ISO", "updated_at": "ISO" } ``` ### `crm_comms_log` (SQLite table — existing mqtt_data.db) ```sql CREATE TABLE crm_comms_log ( id TEXT PRIMARY KEY, customer_id TEXT NOT NULL, type TEXT NOT NULL, -- email|whatsapp|call|sms|note|in_person direction TEXT NOT NULL, -- inbound|outbound|internal subject TEXT, body TEXT, attachments TEXT, -- JSON array of {filename, nextcloud_path} ext_message_id TEXT, -- IMAP uid, WhatsApp msg id, AMI call id logged_by TEXT, occurred_at TEXT NOT NULL, created_at TEXT NOT NULL ); ``` ### `crm_media` (SQLite table — existing mqtt_data.db) ```sql CREATE TABLE crm_media ( id TEXT PRIMARY KEY, customer_id TEXT, order_id TEXT, filename TEXT NOT NULL, nextcloud_path TEXT NOT NULL, mime_type TEXT, direction TEXT, -- received|sent|internal tags TEXT, -- JSON array uploaded_by TEXT, created_at TEXT NOT NULL ); ``` --- ## IMPORTANT NOTES FOR ALL STEPS - **Backend location**: `c:\development\bellsystems-cp\backend\` - **Frontend location**: `c:\development\bellsystems-cp\frontend\` - **Auth pattern**: All routes use `Depends(require_permission("crm", "view"))` or `"edit"`. Import from `auth.dependencies`. - **Firestore pattern**: Use `from shared.firebase import get_db`. See `backend/devices/service.py` for reference patterns. - **SQLite pattern**: Use `from mqtt import database as mqtt_db` — `mqtt_db.db` is the aiosqlite connection. See `backend/mqtt/database.py`. - **Frontend auth**: `getAuthHeaders()` from `../api/auth` gives Bearer token headers. See any existing page for pattern. - **Frontend routing**: Routes live in `frontend/src/App.jsx`. Sidebar nav in `frontend/src/layout/Sidebar.jsx`. - **Token**: localStorage key is `"access_token"`. - **UI pattern**: Use existing component style — `SectionCard`, `FieldRow`, inline styles for grids. See `frontend/src/devices/` for reference. - **No new dependencies unless absolutely necessary.** --- ## Step 1 — Backend: CRM Module Scaffold + Products CRUD **File**: `.claude/crm-step-01.md` --- ## Step 2 — Backend: Customers CRUD **File**: `.claude/crm-step-02.md` --- ## Step 3 — Backend: Orders CRUD **File**: `.claude/crm-step-03.md` --- ## Step 4 — Backend: Comms Log + Media (SQLite) **File**: `.claude/crm-step-04.md` --- ## Step 5 — Frontend: Products Module **File**: `.claude/crm-step-05.md` --- ## Step 6 — Frontend: Customers List + Detail Page **File**: `.claude/crm-step-06.md` --- ## Step 7 — Frontend: Orders Module **File**: `.claude/crm-step-07.md` --- ## Step 8 — Frontend: Comms Log + Media Tab (manual entry) **File**: `.claude/crm-step-08.md` --- ## Step 9 — Integration: Nextcloud WebDAV **File**: `.claude/crm-step-09.md` --- ## Step 10 — Integration: IMAP/SMTP Email **File**: `.claude/crm-step-10.md` --- ## Step 11 — Integration: WhatsApp Business API **File**: `.claude/crm-step-11.md` --- ## Step 12 — Integration: FreePBX AMI Call Logging **File**: `.claude/crm-step-12.md`