# 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
