Commit Graph

6 Commits

Author SHA1 Message Date
mivanchenko 4257bd3e55 Dashboard: add link to the onboarding form
Header button on the CRM linking back to the operator onboarding page at "/"
(same host, same basic-auth).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:43:03 +02:00
mivanchenko b84a5d4c6f Dashboard: full-width tables, no horizontal scrollbar
Remove the 1280px content cap and the table's overflow scroll; let cells wrap
(word-break) instead of forcing a horizontal scrollbar, so rows span the full
screen width and show full values.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:41:21 +02:00
mivanchenko 10fea59e05 Fix dashboard 404: derive API base from page path
Opening the dashboard at /crm (no trailing slash) made the relative `api/leads`
fetch resolve to /api/leads -> 404. Derive the API base from
location.pathname so it works at both /crm and /crm/.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:39:34 +02:00
mivanchenko e59996a385 Back office: one-way DB -> Sheets mirror
- After each mutation, the affected tab + activity_log are pushed to Sheets by
  a single serialized background worker (Postgres stays source of truth; a
  mirror failure never fails the DB write). Concurrency race fixed by
  serializing through one worker; PYTHONUNBUFFERED for visible logs.
- _cell() formats dates/timestamps/numbers/bools and neutralises formula
  injection. POST /api/sync does a full DB->Sheets resync of every tab.

Verified: add/edit/delete propagate to the Sheet; full resync aligns all tabs;
DB and Sheet consistent after cleanup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:26:42 +02:00
mivanchenko 9f42e46d6c Back office: add / edit / delete for Leads & Clients
- Token-protected mutation endpoints (POST/PATCH/DELETE), audit-logged to
  activity_log. Token injected into the basic-auth-gated dashboard.
- Add auto-generates IDs (next C-#### / L-<epoch>), sets created/received/status
  defaults, and computes client renewal_date from start + billing cycle
  (parity with the onboarding workflow).
- Dashboard: per-row edit (✎) and delete (🗑), "+ Neu" modal form per entity.

Verified end-to-end: add lead/client, edit, delete, renewal compute, token
gating (403), 404s. DB-only for now; DB->Sheets mirror is the next step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:18:28 +02:00
mivanchenko 18e346d67b Back office: Postgres source-of-truth + read dashboard
Stand up the DB-first CRM backbone (architecture pivot: Postgres is the
source of truth, Google Sheets becomes a one-way downstream mirror).

- backoffice/ stack: smb-db (Postgres 16) + smb-crm (Flask/waitress service).
- Schema mirrors the six Sheet tabs (clients, leads, projects, activity_log,
  bookings, invoices) with typed columns + updated_at triggers.
- Service-account Sheets client (PyJWT) for the one-time import + future mirror.
- import_from_sheets.py: idempotent seed of Postgres from the live Sheets.
- Read dashboard (Leads & Clients tables) at onboard.mivanchenko.de/crm,
  behind the existing Caddy basic-auth; JSON API reads straight from Postgres.

Deployed + verified: import seeded DB, dashboard/API live, no-auth blocked,
onboarding form unaffected. Add/edit/delete + DB->Sheets sync + n8n ingest
swap are the next steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:12:39 +02:00