# CRM — Aduanasoft Sistema CRM construido sobre la **plantilla Workspace de Aduanasoft** (SvelteKit 5 + FastAPI + PostgreSQL, multi-tenant con Keycloak/Hub). Gestiona cuentas, contactos, prospectos, oportunidades (pipeline Kanban) y actividades comerciales. > Base: `plantillas-proyectos`. Este repo conserva el core de la plantilla (auth, > tenants, permisos, licencias) y agrega el dominio **CRM** en backend y frontend. --- ## Stack | Capa | Tecnología | |---|---| | Frontend | SvelteKit 5 (runes) + Tailwind + shadcn-svelte | | Backend | FastAPI + SQLAlchemy 2.0 + Pydantic v2 | | Auth | Keycloak (OIDC) vía Workspace Hub | | Base de datos | PostgreSQL (schema `crm`) | | Cache / Queue | Valkey (Redis) + Celery | | Storage | MinIO (S3-compatible) | | Contenedores | Docker Compose | --- ## Módulo CRM Esquema dedicado `crm` con 7 tablas multi-tenant (`tenant_id` + `company_id`, soft delete): | Entidad | Tabla | Descripción | |---|---|---| | Cuentas | `crm.accounts` | Empresas cliente/prospecto (importador, IMMEX, agencia aduanal, transportista). Incluye RFC y patente aduanal. | | Contactos | `crm.contacts` | Personas asociadas a una cuenta. | | Prospectos | `crm.leads` | Leads sin calificar; se convierten en cuenta + contacto + oportunidad. | | Embudos | `crm.pipelines` | Embudos de venta por compañía. | | Etapas | `crm.pipeline_stages` | Columnas del Kanban (con probabilidad y etapas terminales ganada/perdida). | | Oportunidades | `crm.opportunities` | Negocios que avanzan por el embudo. | | Actividades | `crm.activities` | Llamadas, reuniones, tareas, correos y notas. | ### Endpoints (prefijo `/v1/crm`) Todos reciben `company_id` como query param y validan permisos vía Keycloak/`PermissionService`. - `GET|POST /accounts`, `GET|PATCH|DELETE /accounts/{id}` - `GET|POST /contacts`, `GET|PATCH|DELETE /contacts/{id}` - `GET|POST /leads`, `GET|PATCH|DELETE /leads/{id}`, `POST /leads/{id}/convert` - `GET|POST /pipelines`, `PATCH|DELETE /pipelines/{id}` - `GET|POST /stages`, `PATCH|DELETE /stages/{id}` - `GET|POST /opportunities`, `GET|PATCH|DELETE /opportunities/{id}`, `PATCH /opportunities/{id}/move` - `GET|POST /activities`, `GET|PATCH|DELETE /activities/{id}`, `PATCH /activities/{id}/complete` - `GET /metrics` — KPIs y embudo por etapa para el dashboard ### Permisos Se registran en el `PermissionRegistry` al arrancar (25 permisos: `crm.access` + `crm.{account,contact,lead,opportunity,pipeline,activity}.{view,create,edit,delete}`). Para persistirlos en BD: `POST /v1/core/permissions/sync` (o el CLI de sincronización). --- ## Inicio rápido (dev) ```bash cp .env.example .env # ajustar CORE_DB_NAME, Keycloak, etc. ./scripts/auth-mode.sh local # login local sin workspace docker compose up -d ``` Abre `http://localhost:5173` → **CRM** en el sidebar. ### Migraciones ```bash cd backend alembic upgrade head # crea el schema crm y sus tablas (revisión f1a2b3c4d5e6) alembic downgrade -1 # revierte el CRM (down() probado) ``` --- ## Pruebas Backend (servicios CRM): ```bash cd backend pytest tests/ -q # 24 pruebas de servicios (SQLite en memoria) ``` En CI/PostgreSQL, define `TEST_DATABASE_URL` para ejercitar el esquema real y las políticas RLS (ver `docs/ARCHITECTURE.md`). --- ## Estructura del CRM ``` backend/api/v1/modules/crm/ ├── router.py # agrega submódulos bajo /crm (y registra permisos) ├── permissions.py # alta de permisos CRM en el registry ├── accounts/ contacts/ leads/ pipelines/ opportunities/ activities/ metrics/ │ └── models.py · dto.py · service.py · routes.py backend/alembic/versions/f1a2b3c4d5e6_crm_schema.py frontend/src/ ├── lib/api/crm/ # clientes API tipados por entidad ├── lib/components/crm/ # helpers de formato/etiquetas └── routes/dashboard/crm/ ├── +page.svelte # panel (KPIs + embudo) ├── cuentas/ contactos/ prospectos/ actividades/ # CRUD └── oportunidades/ # Kanban con drag & drop ``` --- ## Convenciones - **Commits**: Conventional Commits (`feat:`, `fix:`, `refactor:`, `chore:`) - **Ramas**: `feature/AS-###-desc`, `fix/AS-###-desc` - **Código**: nombres en inglés, comentarios de negocio en español - **Backend**: Pydantic v2, routers por dominio, filtros multi-tenant explícitos - **Frontend**: runes (`$state`, `$derived`, `$effect`, `$props`), Tailwind utility-first