- Updated Jenkinsfile to include Playwright's trace option for better debugging on test failures. - Added archiving of test results, including trace files, error context, and screenshots for failed tests. - Enhanced error handling in `auth.setup.ts` to log diagnostic information when authentication fails, improving visibility into issues. These changes aim to improve the reliability and debuggability of E2E tests.
Anexo76
Aplicación SaaS para gestión de comercio exterior conforme a Anexos 24, 30 y 22 del SAT
Anexo76 es una plataforma multi-tenant diseñada para maquilas, empresas IMMEX y agentes aduanales, que permite gestionar inventarios, pedimentos y facturas de importación/exportación con control de licencias y cumplimiento normativo.
🏗️ Arquitectura
Backend
- Framework: FastAPI 0.110+
- Autenticación: Keycloak (OpenID Connect)
- Base de Datos: PostgreSQL con SQLAlchemy
- Modelo Multi-tenant: Híbrido
- BD compartida para tenants pequeños/medianos
- BD dedicadas para clientes enterprise
- Estructura Modular: Patrón similar a NestJS
models.py: Modelos ORM (SQLAlchemy)dto.py: Data Transfer Objects (Pydantic)service.py: Lógica de negocioroutes.py: Endpoints API
Frontend
- Framework: SvelteKit
- Autenticación: keycloak-js
- UI: Dashboard moderno y responsivo
Infraestructura
- Containerización: Docker / Docker Compose
- Orquestación: Kubernetes (futuro)
- Monitoreo: Prometheus + Grafana
📁 Estructura del Proyecto
anexo76/
├── backend/
│ ├── main.py # Aplicación FastAPI principal
│ ├── requirements.txt # Dependencias Python
│ ├── .env.example # Variables de entorno de ejemplo
│ ├── core/ # Módulos core
│ │ ├── config.py # Configuración centralizada
│ │ ├── paths.py # Rutas base y layout_path() para importación CSV
│ │ ├── database.py # Configuración de BD multi-tenant
│ │ ├── security.py # Autenticación y autorización
│ │ └── middleware.py # Middlewares personalizados
│ ├── layouts/ # Directorio de datos: temp y errors de importación CSV (creado al arranque)
│ └── api/
│ └── v1/
│ ├── router.py # Router principal API v1
│ └── modules/ # Módulos de negocio
│ └── a76/
│ ├── layouts_csv/ # Lógica centralizada de cargas por CSV (routes, tasks, validaciones por proceso)
│ │ ├── facturas/
│ │ ├── customs_brokers/
│ │ ├── clients_and_providers/
│ │ └── ... # Una carpeta por proceso de importación
│ ├── csv_templates/
│ └── ...
│ ├── auth/
│ ├── tenants/ # Gestión de tenants
│ ├── licenses/ # Control de licencias
│ └── ...
├── frontend/
│ ├── src/
│ │ ├── routes/
│ │ ├── lib/
│ │ └── app.html
│ ├── package.json
│ └── svelte.config.js
├── docker-compose.yml
└── README.md
🚀 Inicio Rápido
Requisitos Previos
- Docker y Docker Compose
- Python 3.11+ (para desarrollo local)
- Node.js 18+ (para desarrollo frontend)
1. Clonar el repositorio
git clone <repository-url>
cd anexo76
2. Configurar variables de entorno
cp backend/.env.example backend/.env
# Editar backend/.env con tus configuraciones
3. Iniciar con Docker Compose
docker-compose up -d
Esto iniciará:
- PostgreSQL en
localhost:5432 - Keycloak en
localhost:8080 - Backend API en
localhost:8000 - Frontend en
localhost:5173
4. Configurar Keycloak
- Acceder a Keycloak: http://localhost:8080
- Login:
admin/admin - Crear un nuevo realm o usar el realm
master - Crear cliente para backend:
- Client ID:
anexo76-backend - Client Protocol:
openid-connect - Access Type:
confidential - Copiar el Secret y agregarlo a
.env
- Client ID:
- Crear cliente para frontend:
- Client ID:
anexo76-frontend - Client Protocol:
openid-connect - Access Type:
public - Valid Redirect URIs:
http://localhost:5173/*
- Client ID:
5. Inicializar base de datos
# Con Docker
docker-compose exec backend python -c "from core.database import init_db; init_db()"
# O localmente
cd backend
python -c "from core.database import init_db; init_db()"
6. Acceder a la aplicación
- API Documentation: http://localhost:8000/docs
- Frontend: http://localhost:5173
- Keycloak Admin: http://localhost:8080
🛠️ Produccion
docker build -t dev.aduanasoft.com/anexo76/backend:latest -f ./backend/Dockerfile ./backend
Importación CSV y workers Celery: La lógica de cargas por CSV está en api/v1/modules/a76/layouts_csv/ (una carpeta por proceso). Los workers Celery deben cargar los módulos api.v1.modules.a76.layouts_csv.<proceso>.tasks. El directorio de trabajo del worker debe ser la raíz del backend para que layout_path("imports", "temp") y layout_path("imports", "errors") apunten a los mismos directorios que la API. Si API y worker comparten volumen, los archivos temporales y de errores se escriben en backend/layouts/imports/temp y backend/layouts/imports/errors.
docker build \
--build-arg VITE_API_URL=http://10.47.80.196:3467/api/ \
--build-arg VITE_KEYCLOAK_URL=http://10.47.80.196/kcauth/ \
--build-arg INTERNAL_API_URL=http://backend:3467/api/ \
-t dev.aduanasoft.com/anexo76/frontend:latest \
-f ./frontend/Dockerfile.prod \
./frontend
Publica en el registro (ajusta el registry si corresponde):
docker login dev.aduanasoft.com
docker push dev.aduanasoft.com/anexo76/backend:latest
docker push dev.aduanasoft.com/anexo76/frontend:latest
🛠️ Desarrollo Local
Backend
cd backend
python -m venv .venv
source .venv/bin/activate # En Windows: .venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reload
Los directorios backend/layouts/imports/temp y backend/layouts/imports/errors se crean automáticamente al arrancar el backend para la importación CSV.
Frontend
cd frontend
npm install
npm run dev
📦 Módulos Principales
1. Auth (/v1/auth)
- Login con Keycloak
- Refresh token
- Logout
- Información de usuario
2. Tenants (/v1/tenants)
- Creación y gestión de tenants
- Upgrade de BD compartida a dedicada
- Gestión de realms de Keycloak
3. Licenses (/v1/licenses)
- Control de planes (Free, Basic, Professional, Enterprise)
- Validación de licencias activas
- Tracking de uso (usuarios, storage, operaciones)
- Límites por plan
🔐 Autenticación y Autorización
Flujo de Autenticación
- Usuario ingresa credenciales + tenant_slug
- Backend valida contra Keycloak del realm del tenant
- Keycloak retorna JWT con tenant_id y roles
- Middleware valida tenant y licencia en cada request
- Request procesado si todo es válido
Roles Disponibles
admin: Administrador con acceso totaluser: Usuario estándarauditor: Solo lectura con acceso a reportessystem: Para integraciones y servicios
🎯 Multi-Tenancy
Modelo Híbrido
BD Compartida (tenants pequeños/medianos):
- Tabla única con
tenant_idcomo foreign key - Row-level security
- Más económico para clientes con bajo volumen
BD Dedicada (tenants enterprise):
- Base de datos PostgreSQL independiente
- Máximo aislamiento y performance
- Configuración almacenada en
tenants.db_config
Migración de Shared a Dedicated
# Ejemplo de upgrade
from api.v1.modules.tenants.service import TenantService
db_config = {
"host": "dedicated-db-host.example.com",
"port": 5432,
"name": "tenant_123_db",
"user": "tenant_123_user",
"password": "secure_password"
}
service = TenantService(db)
service.upgrade_to_dedicated(tenant_id=123, db_config=db_config)
📊 Control de Licencias
Planes Disponibles
| Plan | Usuarios | Storage | Operaciones/mes | Features |
|---|---|---|---|---|
| Free | 5 | 10 GB | 1,000 | API básica |
| Basic | 20 | 50 GB | 10,000 | + Reportes |
| Professional | 100 | 200 GB | 50,000 | + Integraciones |
| Enterprise | Ilimitado | Ilimitado | Ilimitado | + Soporte dedicado + BD dedicada |
Middleware de Validación
El LicenseValidationMiddleware verifica en cada request:
- ✅ Licencia activa
- ✅ No expirada
- ✅ Límites no excedidos
- ✅ Features habilitadas
🧪 Testing
# Backend
cd backend
pytest
# Con cobertura
pytest --cov=. --cov-report=html
# Frontend
cd frontend
npm test
📈 Monitoreo
Prometheus Metrics
El backend expone métricas en /metrics:
- Request duration
- Request count por endpoint
- Error rate
- Active connections
Logging
Logs estructurados con nivel configurable:
- INFO: Operaciones normales
- WARNING: Validaciones fallidas
- ERROR: Errores de sistema
- DEBUG: Información detallada (solo desarrollo)
🤝 Contribución
- Fork el proyecto
- Crear rama feature (
git checkout -b feature/AmazingFeature) - Commit cambios (
git commit -m 'Add some AmazingFeature') - Push a la rama (
git push origin feature/AmazingFeature) - Abrir Pull Request
📝 Licencia
Este proyecto es privado y propietario.
📞 Soporte
Para soporte técnico o consultas:
- Email: soporte@anexo76.com
- Documentación: https://docs.anexo76.com
Desarrollado con ❤️ para la industria de comercio exterior mexicana