# Anexo76 - Resumen de Arquitectura Técnica ## 📋 Índice 1. [Visión General](#visión-general) 2. [Stack Tecnológico](#stack-tecnológico) 3. [Arquitectura del Sistema](#arquitectura-del-sistema) 4. [Arquitectura de Schemas y Módulos](#arquitectura-de-schemas-y-módulos) 5. [Estructura del Proyecto](#estructura-del-proyecto) 6. [Flujos Principales](#flujos-principales) 7. [Seguridad](#seguridad) 8. [Base de Datos](#base-de-datos) 9. [API Reference](#api-reference) --- ## Visión General Anexo76 es una aplicación SaaS multi-tenant para gestión de comercio exterior en México, enfocada en cumplir con los Anexos 24, 31 y 22 del SAT. ### Objetivos de Negocio - Gestión de inventarios para maquilas e IMMEX - Control de pedimentos aduanales - Manejo de facturas de importación/exportación - Cumplimiento normativo SAT - Licenciamiento flexible por planes --- ## Stack Tecnológico ### Backend - **Framework**: FastAPI 0.110+ (Python 3.11+) - **ORM**: SQLAlchemy 2.0 - **Autenticación**: Keycloak (OpenID Connect) - **Base de Datos**: PostgreSQL 15+ - **Validación**: Pydantic 2.6+ - **Testing**: Pytest ### Frontend - **Framework**: SvelteKit 2.0+ (Svelte 5) - **Lenguaje**: TypeScript - **Auth Client**: keycloak-js - **Estilos**: TailwindCSS 4.1+ - **Build**: Vite 7+ ### Infraestructura - **Containerización**: Docker / Docker Compose - **Orquestación**: Kubernetes (futuro) - **CI/CD**: GitHub Actions / GitLab CI - **Monitoreo**: Prometheus + Grafana --- ## Arquitectura del Sistema ### Patrón Arquitectónico: Modular Layered (estilo NestJS) ``` ┌─────────────────────────────────────────────────────────┐ │ FRONTEND │ │ SvelteKit + Keycloak-js + TailwindCSS │ └────────────────┬────────────────────────────────────────┘ │ HTTP/REST + JWT ┌────────────────▼────────────────────────────────────────┐ │ API GATEWAY (FastAPI) │ │ Middleware: Tenant | License | Logging | CORS │ └────────────────┬────────────────────────────────────────┘ │ ┌────────┴────────┐ │ │ ┌───────▼──────┐ ┌──────▼────────┐ │ MODULES │ │ CORE LAYER │ │ │ │ │ │ • auth │ │ • config.py │ │ • tenants │ │ • database.py │ │ • licenses │ │ • security.py │ │ • ... │ │ • middleware │ └───────┬──────┘ └───────────────┘ │ ┌───────▼──────────────────────────┐ │ DATABASE LAYER (Multi-tenant) │ │ │ │ ┌──────────┐ ┌──────────────┐ │ │ │ Core DB │ │ Tenant 1 DB │ │ │ │ (shared) │ │ (dedicated) │ │ │ └──────────┘ └──────────────┘ │ └──────────────────────────────────┘ ``` ### Estructura Modular (por módulo) Cada módulo sigue el patrón: ``` modules/{module_name}/ ├── models.py # ORM Models (SQLAlchemy) ├── dto.py # Data Transfer Objects (Pydantic) ├── service.py # Business Logic Layer ├── routes.py # API Endpoints (FastAPI) └── __init__.py # Module exports ``` #### Responsabilidades por Capa 1. **models.py**: Representación de entidades en BD - Define tablas con SQLAlchemy - Relaciones entre entidades - Constraints y validaciones a nivel DB 2. **dto.py**: Contratos de entrada/salida de datos - DTOs de request (CreateDTO, UpdateDTO) - DTOs de response (ResponseDTO) - Validaciones de Pydantic 3. **service.py**: Lógica de negocio - Operaciones CRUD - Validaciones de negocio - Orquestación de operaciones complejas 4. **routes.py**: Exposición HTTP - Definición de endpoints - Documentación OpenAPI automática - Manejo de dependencias (auth, db) --- ## Arquitectura de Schemas y Módulos ### Estructura de Schemas en Base de Datos La aplicación utiliza una arquitectura de schemas para organizar lógicamente las tablas según su funcionalidad y alcance: #### **Schema `a24` (Anexo 24)** Contiene todas las tablas relacionadas con el **Anexo 24 del SAT** (control de inventarios para empresas IMMEX): - Gestión de inventarios - Control de entradas y salidas de mercancías - Reportes de existencias - Cumplimiento de obligaciones fiscales del Anexo 24 #### **Schema `a76` (Anexo 76)** Contiene todas las tablas relacionadas con el **Anexo 76 del SAT** (comercio exterior): - Pedimentos aduanales - Facturas de importación/exportación - Documentación de comercio exterior - Cumplimiento normativo de comercio exterior #### **Schema `public` (Catálogos Fijos)** Contiene **catálogos compartidos** y datos de referencia que no cambian frecuentemente: - Catálogos del SAT (tipos de material, unidades de medida, etc.) - Códigos de país - Catálogos de aduanas - Tipos de documento - Datos maestros compartidos entre módulos ### Convención de Prefijos de Tablas Para mantener claridad y trazabilidad, las tablas utilizan prefijos que identifican su módulo funcional: #### **Prefijo `inv_` (Inventarios)** Tablas relacionadas con el **control de inventarios**: - `inv_products`: Productos en inventario - `inv_movements`: Movimientos de entrada/salida - `inv_warehouses`: Almacenes - `inv_balances`: Saldos de inventario **Nota histórica**: Anteriormente se utilizaba el prefijo `s` (SCAII - Sistema de aduanas e Inventarios). #### **Prefijo `fa_` (Fixed Assets / Activos Fijos)** Tablas relacionadas con la **gestión de activos fijos**: - `fa_assets`: Registro de activos fijos - `fa_depreciation`: Depreciación de activos - `fa_maintenance`: Mantenimiento de activos - `fa_transfers`: Transferencias de activos **Nota histórica**: Anteriormente se utilizaba el prefijo `q` (SCAF - Sistema de Control de Activos Fijos). ### Diagrama de Arquitectura de Schemas ``` ┌─────────────────────────────────────────────────────────────┐ │ DATABASE: anexo76_db │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌────────────────┐ ┌────────────────┐ ┌───────────────┐ │ │ │ Schema: a24 │ │ Schema: a76 │ │Schema: public │ │ │ │ (Anexo 24) │ │ (Anexo 76) │ │ (Catálogos) │ │ │ ├────────────────┤ ├────────────────┤ ├───────────────┤ │ │ │ │ │ │ │ │ │ │ │ inv_products │ │ pedimentos │ │ material_types│ │ │ │ inv_movements │ │ facturas │ │ uom_codes │ │ │ │ inv_warehouses │ │ customs_docs │ │ countries │ │ │ │ inv_balances │ │ export_ops │ │ customs_list │ │ │ │ │ │ │ │ document_types│ │ │ │ fa_assets │ │ │ │ │ │ │ │ fa_depreciation│ │ │ │ │ │ │ │ fa_maintenance │ │ │ │ │ │ │ │ fa_transfers │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────────────┘ └────────────────┘ └───────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ ``` ### Ventajas de esta Arquitectura 1. **Separación Lógica**: Cada schema representa un dominio específico del negocio 2. **Escalabilidad**: Facilita la adición de nuevos módulos sin afectar los existentes 3. **Seguridad**: Permite aplicar permisos a nivel de schema 4. **Mantenibilidad**: Código y migraciones organizados por dominio 5. **Claridad**: Los prefijos hacen evidente la funcionalidad de cada tabla 6. **Migración Gradual**: Permite actualizar sistemas legados (SCAII/SCAF) sin interrupciones ### Mapeo de Sistemas Legados | Sistema Legacy | Prefijo Antiguo | Sistema Nuevo | Prefijo Nuevo | Schema | |----------------------|-----------------|-------------------|---------------|----------| | SCAII (Inventarios) | `s` | Inventarios | `inv_` | `a24` | | SCAF (Activos Fijos) | `q` | Fixed Assets | `fa_` | `a24` | | Winsaii (Pedimentos) | `w` | - | - | `a22` | | - | `g` | Comercio Exterior | - | `a76` | | - | `g` | Catálogos SAT | - | `public` | --- ## Estructura del Proyecto ``` anexo76/ ├── backend/ │ ├── main.py # Aplicación FastAPI principal │ ├── requirements.txt # Dependencias │ ├── init_db.py # Script de inicialización │ ├── Dockerfile │ │ │ ├── core/ # Capa core (shared) │ │ ├── config.py # Configuración (Pydantic Settings) │ │ ├── database.py # Gestión de BD multi-tenant │ │ ├── security.py # Auth Keycloak + JWT │ │ ├── middleware.py # Middlewares personalizados │ │ └── __init__.py │ │ │ └── api/ │ └── v1/ │ ├── router.py # Router principal v1 │ ├── common/ # Utilidades compartidas │ │ ├── base_models.py │ │ ├── crud_routes.py │ │ ├── dto_mixins.py │ │ └── tenant_crud_routes.py │ │ │ └── modules/ # Módulos de negocio por schema │ ├── a24/ # Módulo Anexo 24 (Inventarios) │ │ ├── inventarios/ │ │ └── activos_fijos/ │ │ │ ├── a76/ # Módulo Anexo 76 (Comercio Exterior) │ │ ├── pedimentos/ │ │ └── facturas/ │ │ │ └── public/ # Catálogos compartidos │ ├── material_types/ │ ├── uom_codes/ │ └── countries/ │ ├── frontend/ │ ├── src/ │ │ ├── routes/ # Páginas SvelteKit │ │ │ ├── +layout.svelte # Layout global con Keycloak │ │ │ ├── +page.svelte # Dashboard principal │ │ │ └── callback/ # OAuth callback │ │ │ │ │ └── lib/ │ │ ├── auth.ts # Servicio de autenticación │ │ └── api.ts # Cliente API │ │ │ ├── static/ │ │ └── silent-check-sso.html │ ├── package.json │ └── Dockerfile │ ├── docs/ │ ├── KEYCLOAK_SETUP.md # Guía de configuración │ └── ARCHITECTURE.md # Este documento │ ├── docker-compose.yml # Orquestación completa ├── start.sh # Script de inicio rápido ├── README.md # Documentación principal └── .gitignore ``` --- ## Flujos Principales ### 1. Flujo de Autenticación ``` ┌──────────┐ ┌──────────┐ ┌──────────┐ │ Frontend │ │ Keycloak │ │ Backend │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ │ 1. Clic "Login" │ │ ├────────────────────────────>│ │ │ │ │ │ 2. Formulario de login │ │ │<────────────────────────────┤ │ │ │ │ │ 3. Credenciales │ │ ├────────────────────────────>│ │ │ │ │ │ 4. Redirigir + auth code │ │ │<────────────────────────────┤ │ │ │ │ │ 5. Intercambiar code x token│ │ ├────────────────────────────>│ │ │ │ │ │ 6. JWT (access + refresh) │ │ │<────────────────────────────┤ │ │ │ │ │ 7. Request con Bearer token │ │ ├─────────────────────────────┼──────────────────────────>│ │ │ │ │ │ 8. Validar token │ │ │<──────────────────────────┤ │ │ │ │ │ 9. Public key │ │ ├──────────────────────────>│ │ │ │ │ 10. Respuesta con datos │ │ │<─────────────────────────────┼───────────────────────────┤ │ │ │ ``` ### 2. Flujo de Request Multi-tenant ``` Request con JWT ↓ TenantMiddleware ├─ Extrae tenant_id del token ├─ Valida tenant existe y está activo └─ Agrega tenant_id a request.state ↓ LicenseValidationMiddleware ├─ Consulta licencia del tenant ├─ Valida estado (active/expired) ├─ Valida fecha de vigencia └─ Agrega license_info a request.state ↓ Endpoint Handler ├─ Obtiene tenant_id de request.state ├─ Selecciona BD (shared o dedicated) └─ Procesa request ↓ Response ``` ### 3. Flujo de Selección de Base de Datos ```python # Pseudocódigo tenant_id = request.state.tenant_id tenant = db.query(Tenant).filter(Tenant.id == tenant_id).first() if tenant.type == "SHARED": # Usar BD compartida (core_db) db_session = CoreSessionLocal() # Queries incluyen tenant_id en WHERE elif tenant.type == "DEDICATED": # Usar BD dedicada del tenant db_config = json.loads(tenant.db_config) db_session = get_tenant_db(tenant_id, db_config) # No necesita filtrar por tenant_id ``` --- ## Seguridad ### Autenticación - **Keycloak** como Identity Provider - **OpenID Connect** (OIDC) - **JWT** con RS256 (firma asimétrica) - **Refresh tokens** para renovación ### Autorización - **RBAC** (Role-Based Access Control) - Roles: `admin`, `user`, `auditor`, `system` - Middleware `has_role()` para proteger endpoints ### Multi-tenancy - **Aislamiento por tenant_id** en JWT - **Row-level security** en BD compartida - **BD dedicada** para mayor aislamiento (enterprise) ### Validación de Licencias - Middleware verifica en cada request: - ✓ Licencia activa - ✓ No expirada - ✓ Límites no excedidos --- ## Base de Datos ### Modelo Híbrido Multi-tenant #### BD Core (Compartida) Tablas principales: - `tenants`: Información de clientes - `licenses`: Control de licencias por tenant - `license_usage`: Métricas de uso - `users` (futuro): Usuarios por tenant Todas las tablas operacionales incluyen `tenant_id` para segmentación. #### BD Dedicadas (Enterprise) - Una BD PostgreSQL por tenant - Configuración almacenada en `tenants.db_config` - Migración automática desde BD compartida ### Ejemplo de Tabla Multi-tenant ```sql CREATE TABLE inventories ( id SERIAL PRIMARY KEY, tenant_id INTEGER NOT NULL REFERENCES tenants(id), product_code VARCHAR(50) NOT NULL, quantity INTEGER NOT NULL, created_at TIMESTAMP DEFAULT NOW(), -- Índice compuesto para queries eficientes INDEX idx_tenant_product (tenant_id, product_code) ); ``` ### Migración y Upgrade ```python # Tenant en BD compartida → BD dedicada tenant_service.upgrade_to_dedicated( tenant_id=123, db_config={ "host": "dedicated-postgres.example.com", "port": 5432, "name": "tenant_123_db", "user": "tenant_123_user", "password": "secure_password" } ) ``` --- ## API Reference ### Módulo: Authentication (`/v1/auth`) | Endpoint | Método | Descripción | Auth | |----------|--------|-------------|------| | `/auth/login` | POST | Login con Keycloak | Público | | `/auth/refresh` | POST | Renovar access token | Público | | `/auth/me` | GET | Info del usuario actual | Bearer | | `/auth/logout` | POST | Cerrar sesión | Bearer | | `/auth/health` | GET | Health check | Público | ### Módulo: Tenants (`/v1/tenants`) | Endpoint | Método | Descripción | Rol Requerido | |----------|--------|-------------|---------------| | `/tenants` | POST | Crear tenant | admin | | `/tenants` | GET | Listar tenants | admin | | `/tenants/{id}` | GET | Obtener tenant | user | | `/tenants/{id}` | PUT | Actualizar tenant | admin | | `/tenants/{id}` | DELETE | Eliminar tenant | admin | | `/tenants/slug/{slug}` | GET | Obtener por slug | user | ### Módulo: Licenses (`/v1/licenses`) | Endpoint | Método | Descripción | Rol Requerido | |----------|--------|-------------|---------------| | `/licenses` | POST | Crear licencia | admin | | `/licenses/tenant/{id}` | GET | Obtener licencia | user | | `/licenses/tenant/{id}` | PUT | Actualizar licencia | admin | | `/licenses/validate/{id}` | GET | Validar licencia | user | | `/licenses/usage/{id}` | GET | Uso de licencia | user | | `/licenses/my-license` | GET | Mi licencia | user | ### Planes de Licencia | 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 | ∞ | ∞ | ∞ | + Soporte + BD dedicada | --- ## Próximas Implementaciones ### Backend - [ ] Módulo de inventarios - [ ] Módulo de pedimentos - [ ] Módulo de facturas - [ ] Webhooks para integraciones - [ ] Reportes avanzados - [ ] Export/Import de datos ### Frontend - [ ] Dashboard con gráficas - [ ] Gestión de inventarios UI - [ ] Formularios de pedimentos - [ ] Panel de administración - [ ] Reportes interactivos ### DevOps - [ ] CI/CD pipeline - [ ] Tests automatizados - [ ] Monitoreo con Prometheus - [ ] Dashboards de Grafana - [ ] Deploy a Kubernetes - [ ] Backup automatizado --- **Última actualización**: Octubre 2025 **Versión del documento**: 1.0