# ServiceManagerWeb — Mesa de Ayuda B2B > **Versión actual:** v1.15.1 — Módulo de reportes implementado > > Sistema multi-tenant de Mesa de Ayuda / Soporte Técnico empresarial desarrollado para Aduanasoft. > Arquitectura Modular Monolith con Clean Architecture, preparado para escalar a microservicios. --- ## Tabla de Contenidos 1. [Requisitos previos](#requisitos-previos) 2. [Inicio rápido con Docker (recomendado)](#inicio-rápido-con-docker-recomendado) 3. [Configuración de variables de entorno](#configuración-de-variables-de-entorno) 4. [Cargar datos de prueba](#cargar-datos-de-prueba) 5. [URLs y puertos por defecto](#urls-y-puertos-por-defecto) 6. [Credenciales de prueba](#credenciales-de-prueba) 7. [Desarrollo local sin Docker](#desarrollo-local-sin-docker) 8. [Arquitectura del proyecto](#arquitectura-del-proyecto) 9. [Roles y permisos](#roles-y-permisos) 10. [Comandos útiles](#comandos-útiles) 11. [Pruebas (testing)](#pruebas-testing) 12. [Solución de problemas](#solución-de-problemas) 13. [Contribución](#contribución) 14. [Historial de versiones](#historial-de-versiones) --- ## Requisitos previos Antes de clonar el proyecto, asegúrate de tener instalado: | Herramienta | Versión mínima | Descarga | |-------------|---------------|---------| | **Git** | 2.x | https://git-scm.com/downloads | | **Docker Desktop** | 24.x | https://www.docker.com/products/docker-desktop | | **Docker Compose** | v2.x (incluido en Docker Desktop) | — | > **Nota para desarrolladores que quieran editar código localmente (sin Docker):** > también necesitarás Python 3.11+ y Node.js 18+. Ver sección > [Desarrollo local sin Docker](#desarrollo-local-sin-docker). ### Verificar que Docker esté corriendo ```bash docker --version # Debe mostrar Docker version 24.x o superior docker compose version # Debe mostrar Docker Compose version v2.x ``` Si `docker compose version` falla, prueba `docker-compose --version` (versión standalone). --- ## Inicio rápido con Docker (recomendado) Este es el método más simple y funciona igual en **Windows, Linux y macOS**. Solo necesitas Docker Desktop instalado y corriendo. ### Paso 1 — Clonar el repositorio ```bash git clone https://git.aduanasoft.com/ADUANASOFT/service_manager.git cd service_manager ``` ### Paso 2 — Crear el archivo de variables de entorno **Linux / macOS:** ```bash cp .env.example .env ``` **Windows (PowerShell):** ```powershell Copy-Item .env.example .env ``` **Windows (CMD):** ```cmd copy .env.example .env ``` > **Importante:** El archivo `.env` nunca se sube a git (está en `.gitignore`). > Para desarrollo local los valores del `.env.example` funcionan sin cambios. > En producción **debes** generar claves secretas únicas (ver sección de variables de entorno). ### Paso 3 — Levantar todos los servicios ```bash docker compose up -d ``` Este comando descarga las imágenes, construye los contenedores e inicia todo el stack. La primera vez tarda entre 3 y 8 minutos dependiendo de la conexión a internet. > **Alternativa con herramientas de desarrollo** (Adminer, MailHog, Redis Commander): > ```bash > docker compose --profile dev up -d > ``` ### Paso 4 — Verificar que todo esté funcionando ```bash docker compose ps ``` Deberías ver todos los servicios con estado `Up` o `healthy`: ``` NAME STATUS servicemanager-db Up (healthy) servicemanager-redis Up (healthy) servicemanager-backend Up (healthy) servicemanager-worker Up servicemanager-beat Up servicemanager-client-frontend Up servicemanager-internal-... Up servicemanager-nginx Up ``` Si algún servicio muestra `Exit` o `Restarting`, revisa la sección [Solución de problemas](#solución-de-problemas). ### Paso 5 — Cargar datos de ejemplo (opcional pero recomendado) ```bash docker exec servicemanager-backend python /scripts/seed_data.py ``` Esto crea el tenant de demostración, categorías, usuarios y tickets de prueba. ### ¡Listo! Abre el navegador | Aplicación | URL | |------------|-----| | Portal de clientes | http://localhost:3000 | | Panel interno (staff) | http://localhost:3001 | | API REST | http://localhost:8000 | | Documentación API (Swagger) | http://localhost:8000/docs | | Documentación API (ReDoc) | http://localhost:8000/redoc | | Health check | http://localhost:8000/health | > **Con perfil dev** activo también tendrás: > - Adminer (gestor visual de PostgreSQL): http://localhost:8080 > - MailHog (pruebas de email): http://localhost:8025 > - Redis Commander (inspector de Redis): http://localhost:8081 --- ## Configuración de variables de entorno El archivo `.env` controla todo el comportamiento de la aplicación. Copia `.env.example` como `.env` y revisa los valores siguientes: ### Variables críticas | Variable | Descripción | Valor por defecto (dev) | |----------|-------------|-------------------------| | `SECRET_KEY` | Clave secreta general de Flask/FastAPI | _(cambiar en producción)_ | | `JWT_SECRET_KEY` | Clave para firmar tokens JWT | _(cambiar en producción)_ | | `DATABASE_URL` | Cadena de conexión a PostgreSQL | `postgresql+asyncpg://servicemanager:...@postgres:5432/servicemanager` | | `REDIS_URL` | URL de conexión a Redis | `redis://redis:6379/0` | | `ENVIRONMENT` | Entorno actual | `development` | | `DEBUG` | Modo debug (muestra errores detallados) | `true` | ### Generar claves seguras para producción **Linux / macOS:** ```bash openssl rand -base64 32 # Genera SECRET_KEY openssl rand -base64 32 # Genera JWT_SECRET_KEY ``` **Windows (PowerShell):** ```powershell [Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 })) ``` > **Advertencia:** Nunca uses las claves del `.env.example` en producción. > Cambiar las claves en producción invalida todas las sesiones activas. ### Desarrollo local vs Docker En `.env.example` las URLs apuntan a nombres de servicio Docker (`postgres`, `redis`, `backend`). Si ejecutas el backend directamente en tu máquina (sin Docker), cambia: ```dotenv # Para desarrollo local sin Docker: DATABASE_URL=postgresql+asyncpg://servicemanager:servicemanager123@localhost:5432/servicemanager REDIS_URL=redis://localhost:6379/0 CELERY_BROKER_URL=redis://localhost:6379/0 ``` --- ## Cargar datos de prueba El script `seed_data.py` crea datos iniciales en la base de datos. **Con Docker (recomendado):** ```bash docker exec servicemanager-backend python /scripts/seed_data.py ``` **Sin Docker:** ```bash cd backend python ../scripts/seed_data.py ``` El script crea: - Tenant de demostración: `aduanasoft-demo` - Categorías de tickets (Soporte Técnico, Facturación, Incidentes Críticos, etc.) - Sistemas registrados - Usuarios de prueba con distintos roles --- ## URLs y puertos por defecto | Servicio | Puerto | Descripción | |----------|--------|-------------| | Frontend Clientes | **3000** | Portal para usuarios clientes | | Frontend Interno | **3001** | Panel para staff (agentes, admins) | | Backend API | **8000** | FastAPI — endpoints REST | | PostgreSQL | **5432** | Base de datos (no exponer en producción) | | Redis | **6379** | Cache y broker Celery (no exponer en producción) | | Nginx | **80** | Reverse proxy | | Adminer *(perfil dev)* | **8080** | GUI para PostgreSQL | | MailHog *(perfil dev)* | **8025** | Capturador de emails en desarrollo | | Redis Commander *(perfil dev)* | **8081** | GUI para Redis | ### ¿Conflicto de puertos? Si algún puerto ya está en uso en tu máquina, edita `docker-compose.yml` y cambia el número **izquierdo** del mapeo `host:container`. Por ejemplo, para backend en el 8080: ```yaml ports: - "8080:8000" # ahora accesible en localhost:8080 ``` --- ## Credenciales de prueba Después de ejecutar el seed, puedes iniciar sesión con: | Campo | Valor | |-------|-------| | Email | `admin@aduanasoft.com` | | Contraseña | `admin123` | | Tenant | `aduanasoft-demo` | | Rol | `ADMIN` | > Otros usuarios creados por el seed tienen el mismo sufijo de contraseña (`123`). > Revisa `scripts/seed_data.py` para ver la lista completa. --- ## Desarrollo local sin Docker Útil cuando necesitas depurar el código con breakpoints o acelerar el ciclo de desarrollo. Requiere que **PostgreSQL y Redis sí corran en Docker** (o instalación nativa). ### Requisitos adicionales | Herramienta | Versión | Descarga | |------------|---------|---------| | Python | 3.11 o 3.12 | https://www.python.org/downloads/ | | Node.js (con npm) | 18 LTS | https://nodejs.org/ | | pip | incluido con Python | — | ### Iniciar solo la base de datos y Redis ```bash docker compose up -d postgres redis ``` ### Backend (FastAPI) ```bash cd backend # Crear entorno virtual (solo la primera vez) python -m venv ../.venv # Activar entorno virtual # Linux / macOS: source ../.venv/bin/activate # Windows (PowerShell): ..\.venv\Scripts\Activate.ps1 # Windows (CMD): ..\.venv\Scripts\activate.bat # Instalar dependencias (solo la primera vez o cuando cambie requirements.txt) pip install -r requirements.txt # Ejecutar migraciones de base de datos alembic upgrade head # Iniciar servidor de desarrollo uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 ``` > Si `uvicorn` no se encuentra, asegúrate de que el entorno virtual está activado > (`(.venv)` debe aparecer en tu terminal). ### Frontend Clientes ```bash cd frontend-client # Instalar dependencias (solo la primera vez) npm install # Iniciar servidor de desarrollo en puerto 3000 npm run dev ``` ### Frontend Interno (staff) ```bash cd frontend-internal # Instalar dependencias (solo la primera vez) npm install # Iniciar servidor de desarrollo en puerto 3001 npm run dev ``` > Los dos frontends tienen puertos distintos (3000 y 3001) para que no haya conflicto > cuando corren al mismo tiempo. ### Workers Celery (opcional en desarrollo) Necesario solo si desarrollas funcionalidades de notificaciones o SLAs automáticos. ```bash cd workers # Activar el mismo entorno virtual del backend: # Linux / macOS: source ../.venv/bin/activate # Windows: ..\.venv\Scripts\Activate.ps1 pip install -r requirements.txt # Worker principal celery -A app.celery worker --loglevel=info # Scheduler de tareas periódicas (en otra terminal) celery -A app.celery beat --loglevel=info --schedule=/tmp/celerybeat-schedule ``` --- ## Arquitectura del proyecto ``` ServiceManagerWeb/ ├── backend/ # Aplicación FastAPI (Python 3.11) │ ├── app/ │ │ ├── main.py # Punto de entrada, lifespan, middlewares │ │ ├── api/v1/ │ │ │ ├── router.py # Registro de todos los routers │ │ │ └── endpoints/ # Endpoints REST por dominio │ │ ├── core/ # Config, seguridad, base de datos, caché │ │ ├── models/ # Modelos SQLAlchemy (ORM) │ │ ├── services/ # Lógica de negocio │ │ └── middleware/ # Tenant context, Correlation ID │ ├── migrations/ # Migraciones Alembic │ ├── tests/ # Pruebas backend │ └── requirements.txt # Dependencias Python │ ├── frontend-client/ # Portal de clientes (SvelteKit + TypeScript) │ └── src/routes/ # Páginas: login, tickets, perfil │ ├── frontend-internal/ # Panel de staff (SvelteKit + TypeScript) │ └── src/routes/ # Páginas: dashboard, tickets, reportes, auditoría │ ├── workers/ # Tareas asíncronas Celery │ └── app/tasks/ # email_tasks.py, sla_tasks.py, etc. │ ├── docker/ # Dockerfiles y configuración Nginx ├── db/ # schema.sql inicial ├── docs/ # Documentación técnica adicional ├── scripts/ # seed_data.py, setup-dev.sh, etc. ├── docker-compose.yml # Orquestación completa └── .env.example # Plantilla de variables de entorno ``` ### Stack tecnológico **Backend:** Python 3.11 · FastAPI · Pydantic v2 · SQLAlchemy 2.0 (async) · Alembic · Argon2 · PyJWT · Celery · Redis **Frontend:** Node.js 18 · SvelteKit · TypeScript · TailwindCSS · Zod **Infraestructura:** PostgreSQL 15 · Redis 7 · Docker Compose · Nginx --- ## Roles y permisos ### Personal interno (staff) | Rol | Descripción | |-----|-------------| | `ADMIN` | Control total del sistema | | `SUPPORT_MANAGER` | Gestión de equipos y configuración de SLAs | | `AGENT` | Atención y resolución de tickets | | `AUDITOR` | Solo lectura para revisiones y cumplimiento | ### Clientes | Rol | Descripción | |-----|-------------| | `CLIENT_ADMIN` | Gestión de su organización cliente | | `CLIENT_USER` | Creación y seguimiento de sus propios tickets | --- ## Comandos útiles ### Docker Compose ```bash # Levantar todos los servicios (segundo plano) docker compose up -d # Levantar con herramientas de desarrollo docker compose --profile dev up -d # Ver logs en tiempo real de todos los servicios docker compose logs -f # Ver logs de un servicio específico docker compose logs -f backend docker compose logs -f frontend-internal # Detener todos los servicios (mantiene los datos) docker compose down # Detener Y borrar todos los volúmenes (¡borra la base de datos!) docker compose down -v # Reconstruir imagen de un servicio (después de cambiar Dockerfile o requirements) docker compose build backend docker compose up -d backend # Reiniciar un servicio docker compose restart backend ``` ### Base de datos (Alembic) ```bash # Aplicar todas las migraciones pendientes cd backend alembic upgrade head # Ver estado de migraciones alembic current # Revertir última migración alembic downgrade -1 # Crear nueva migración (después de modificar models/) alembic revision --autogenerate -m "nombre descriptivo del cambio" # Con Docker: docker exec servicemanager-backend alembic upgrade head ``` ### Calidad de código ```bash cd backend # Linter y auto-fix ruff check . --fix # Formateador black . # Verificación de tipos mypy . # Todo de una vez ruff check . --fix && black . && mypy . ``` --- ## Pruebas (testing) ### Backend ```bash cd backend # Ejecutar todas las pruebas pytest # Con cobertura detallada pytest --cov=app --cov-report=html # Abrir reporte de cobertura (Linux/macOS) open htmlcov/index.html # Windows start htmlcov/index.html # Prueba específica pytest tests/test_auth.py -v # Con Docker docker exec servicemanager-backend pytest -v --cov=app ``` ### Frontend ```bash cd frontend-internal # o frontend-client npm test # Ejecutar una vez npm run test:watch # Modo observador ``` --- ## Solución de problemas ### El backend no inicia — error en `DATABASE_URL` **Síntoma:** El contenedor `servicemanager-backend` reinicia continuamente. **Causa frecuente:** El archivo `.env` no existe o tiene `DATABASE_URL` apuntando a `localhost` en lugar del nombre del servicio Docker `postgres`. **Solución:** ```bash # Verificar que .env existe ls .env # Linux/macOS dir .env # Windows # Si no existe, crearlo cp .env.example .env # Linux/macOS Copy-Item .env.example .env # Windows PowerShell # Verificar el valor correcto en .env: # DATABASE_URL=postgresql+asyncpg://servicemanager:servicemanager123@postgres:5432/servicemanager # ^^^^^^^ # Nombre de servicio Docker, NO localhost ``` --- ### Error 500 en login / "connect ECONNREFUSED" **Síntoma:** El frontend muestra error 500 al hacer login, o la consola del navegador muestra `ECONNREFUSED 127.0.0.1:8000`. **Causa:** El proxy de Vite no encuentra el backend. **Solución en Docker:** El proxy ya está configurado para usar `PUBLIC_API_URL`. Verifica en `docker-compose.yml` que `frontend-internal` y `frontend-client` tienen: ```yaml environment: - PUBLIC_API_URL=http://backend:8000 ``` Después reinicia: ```bash docker compose restart frontend-internal frontend-client ``` **Solución en desarrollo local:** Asegúrate de que el backend está corriendo: ```bash curl http://localhost:8000/health # Debe responder: {"status": "ok", ...} ``` --- ### El frontend-internal y frontend-client usan el mismo puerto localmente **Síntoma:** Al correr ambos frontends sin Docker, uno de los dos falla con `Port 3000 is already in use`. **Solución:** - `frontend-client` → usa el puerto **3000** (por defecto con `npm run dev`) - `frontend-internal` → usa el puerto **3001** (configurado en `vite.config.js`) Nunca hay conflicto si los iniciaste con `npm run dev` en cada carpeta por separado. Si aún hay conflicto, mata el proceso en ese puerto: ```bash # Linux / macOS lsof -ti:3000 | xargs kill -9 # Windows (PowerShell) Get-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess | Stop-Process -Force ``` --- ### El tenant slug es incorrecto al hacer login **Síntoma:** Login falla con "credenciales inválidas" aunque el email y contraseña son correctos. **Causa:** El campo `tenant_slug` no corresponde a ningún tenant en la base de datos. **Solución:** ```bash # Ver los tenants disponibles docker exec servicemanager-backend python -c " import asyncio from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy import text import os async def main(): engine = create_async_engine(os.environ['DATABASE_URL']) async with AsyncSession(engine) as s: result = await s.execute(text('SELECT slug, name FROM tenants')) for row in result: print(row) asyncio.run(main()) " ``` Tenant por defecto (después del seed): **`aduanasoft-demo`** --- ### Puerto ocupado — cambiar puertos de los servicios Edita `docker-compose.yml` y modifica **solo el número izquierdo** del mapeo de puertos: ```yaml # Ejemplo: mover el backend al puerto 9000 backend: ports: - "9000:8000" # accesible en localhost:9000 # Ejemplo: mover el frontend al puerto 4000 frontend-client: ports: - "4000:3000" # accesible en localhost:4000 ``` --- ### Migraciones fallidas — `alembic upgrade head` da error ```bash # Verificar el estado actual docker exec servicemanager-backend alembic current # Si hay conflicto, hacer downgrade hasta la base y volver a subir docker exec servicemanager-backend alembic downgrade base docker exec servicemanager-backend alembic upgrade head ``` --- ### Módulo Python no encontrado (`ModuleNotFoundError`) **Con Docker:** El módulo no está en `requirements.txt` o la imagen no fue reconstruida. ```bash # Reconstruir la imagen del backend docker compose build backend docker compose up -d backend ``` **Local:** El entorno virtual no está activado. ```bash # Verificar que el venv está activo (debe aparecer (.venv) en el prompt) which python # Linux/macOS — debe apuntar a .venv/ # Windows: where python # debe apuntar a .venv\Scripts\python.exe ``` --- ### `npm: command not found` o versión de Node incorrecta ```bash node --version # Debe ser v18.x o superior npm --version # Debe ser 9.x o superior ``` Si Node no está instalado, descárgalo desde https://nodejs.org/ (elige "LTS"). En macOS con Homebrew: ```bash brew install node@18 ``` En Linux (Ubuntu/Debian): ```bash curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt-get install -y nodejs ``` --- ### `docker-compose` no se reconoce como comando En versiones modernas de Docker Desktop, el comando es `docker compose` (con espacio, sin guion). Si tienes instalación separada de Docker Compose v1, usa `docker-compose` (con guion). --- ### Logs de los contenedores ```bash # Ver qué está fallando docker compose logs backend --tail=50 docker compose logs frontend-internal --tail=50 docker compose logs postgres --tail=20 ``` --- ## Contribución 1. Haz fork del proyecto 2. Crea una rama de funcionalidad: `git checkout -b feature/nombre-funcionalidad` 3. Realiza tus cambios siguiendo las convenciones del proyecto 4. Ejecuta las pruebas: `pytest` y el linter: `ruff check .` 5. Haz commit con un mensaje descriptivo: `git commit -m "feat: agregar exportación a CSV"` 6. Sube tu rama: `git push origin feature/nombre-funcionalidad` 7. Abre un Pull Request hacia `main` ### Convenciones de nombres - **Modelos**: `PascalCase` → `User`, `Ticket`, `TenantOrganization` - **Endpoints (URL)**: `kebab-case` → `/api/v1/user-management/` - **Componentes Svelte**: `PascalCase.svelte` → `TicketCard.svelte` - **Stores**: `camelCase` → `ticketStore.ts` --- ## Historial de versiones | Versión | Descripción | |---------|-------------| | **v1.15.1** | Módulo de reportes implementado | | v1.14.x | Mejoras al módulo de auditoría | | v1.13.x | Sistema de SLAs automático | | v1.12.x | Notificaciones por email | | v1.0.0 | MVP inicial — tickets, tenants, autenticación | --- ## Licencia Propietario — Aduanasoft © 2026. Todos los derechos reservados.