# Implementación de Sincronización SAT ## Resumen Sistema de sincronización automática de CFDIs con el SAT (Servicio de Administración Tributaria de México) para Horux360. ## Componentes Implementados ### 1. Backend (API) #### Servicios | Archivo | Descripción | |---------|-------------| | `src/services/fiel.service.ts` | Gestión de credenciales FIEL (e.firma) | | `src/services/sat/sat-client.service.ts` | Cliente para el servicio web del SAT | | `src/services/sat/sat.service.ts` | Lógica principal de sincronización | | `src/services/sat/sat-crypto.service.ts` | Encriptación AES-256-GCM para credenciales | | `src/services/sat/sat-parser.service.ts` | Parser de XMLs de CFDI | #### Controladores | Archivo | Descripción | |---------|-------------| | `src/controllers/fiel.controller.ts` | Endpoints para gestión de FIEL | | `src/controllers/sat.controller.ts` | Endpoints para sincronización SAT | #### Job Programado | Archivo | Descripción | |---------|-------------| | `src/jobs/sat-sync.job.ts` | Cron job para sincronización diaria (3:00 AM) | ### 2. Frontend (Web) #### Componentes | Archivo | Descripción | |---------|-------------| | `components/sat/FielUploadModal.tsx` | Modal para subir certificado y llave FIEL | | `components/sat/SyncStatus.tsx` | Estado de sincronización con selector de fechas | | `components/sat/SyncHistory.tsx` | Historial de sincronizaciones | #### Página | Archivo | Descripción | |---------|-------------| | `app/(dashboard)/configuracion/sat/page.tsx` | Página de configuración SAT | ### 3. Base de Datos #### Tabla Principal (schema public) ```sql -- sat_sync_jobs: Almacena los trabajos de sincronización CREATE TABLE sat_sync_jobs ( id UUID PRIMARY KEY, tenant_id UUID NOT NULL, type VARCHAR(20) NOT NULL, -- 'initial' | 'daily' status VARCHAR(20) NOT NULL, -- 'pending' | 'running' | 'completed' | 'failed' date_from TIMESTAMP NOT NULL, date_to TIMESTAMP NOT NULL, cfdi_type VARCHAR(20), sat_request_id VARCHAR(100), sat_package_ids TEXT[], cfdis_found INTEGER DEFAULT 0, cfdis_downloaded INTEGER DEFAULT 0, cfdis_inserted INTEGER DEFAULT 0, cfdis_updated INTEGER DEFAULT 0, progress_percent INTEGER DEFAULT 0, error_message TEXT, started_at TIMESTAMP, completed_at TIMESTAMP, created_at TIMESTAMP DEFAULT NOW(), retry_count INTEGER DEFAULT 0 ); -- fiel_credentials: Almacena las credenciales FIEL encriptadas CREATE TABLE fiel_credentials ( id UUID PRIMARY KEY, tenant_id UUID UNIQUE NOT NULL, rfc VARCHAR(13) NOT NULL, cer_data BYTEA NOT NULL, key_data BYTEA NOT NULL, key_password_encrypted BYTEA NOT NULL, encryption_iv BYTEA NOT NULL, encryption_tag BYTEA NOT NULL, serial_number VARCHAR(100), valid_from TIMESTAMP NOT NULL, valid_until TIMESTAMP NOT NULL, is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); ``` #### Columnas agregadas a tabla cfdis (por tenant) ```sql ALTER TABLE tenant_xxx.cfdis ADD COLUMN xml_original TEXT; ALTER TABLE tenant_xxx.cfdis ADD COLUMN updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP; ALTER TABLE tenant_xxx.cfdis ADD COLUMN last_sat_sync TIMESTAMP; ALTER TABLE tenant_xxx.cfdis ADD COLUMN sat_sync_job_id UUID; ALTER TABLE tenant_xxx.cfdis ADD COLUMN source VARCHAR(20) DEFAULT 'manual'; ``` ## Dependencias ```json { "@nodecfdi/sat-ws-descarga-masiva": "^2.0.0", "@nodecfdi/credentials": "^2.0.0", "@nodecfdi/cfdi-core": "^1.0.1" } ``` ## Flujo de Sincronización ``` 1. Usuario configura FIEL (certificado .cer + llave .key + contraseña) ↓ 2. Sistema valida y encripta credenciales (AES-256-GCM) ↓ 3. Usuario inicia sincronización (manual o automática 3:00 AM) ↓ 4. Sistema desencripta FIEL y crea cliente SAT ↓ 5. Por cada mes en el rango: a. Solicitar CFDIs emitidos al SAT b. Esperar respuesta (polling cada 30s) c. Descargar paquetes ZIP d. Extraer y parsear XMLs e. Guardar en BD del tenant f. Repetir para CFDIs recibidos ↓ 6. Marcar job como completado ``` ## API Endpoints ### FIEL | Método | Ruta | Descripción | |--------|------|-------------| | GET | `/api/fiel/status` | Estado de la FIEL configurada | | POST | `/api/fiel/upload` | Subir nueva FIEL | | DELETE | `/api/fiel` | Eliminar FIEL | ### Sincronización SAT | Método | Ruta | Descripción | |--------|------|-------------| | POST | `/api/sat/sync` | Iniciar sincronización | | GET | `/api/sat/sync/status` | Estado actual | | GET | `/api/sat/sync/history` | Historial de syncs | | GET | `/api/sat/sync/:id` | Detalle de un job | | POST | `/api/sat/sync/:id/retry` | Reintentar job fallido | ### Parámetros de sincronización ```typescript interface StartSyncRequest { type?: 'initial' | 'daily'; // default: 'daily' dateFrom?: string; // ISO date, ej: "2025-01-01T00:00:00" dateTo?: string; // ISO date, ej: "2025-12-31T23:59:59" } ``` ## Configuración ### Variables de entorno ```env # Clave para encriptar credenciales FIEL (32 bytes hex) FIEL_ENCRYPTION_KEY=tu_clave_de_32_bytes_en_hexadecimal # Zona horaria para el cron TZ=America/Mexico_City ``` ### Límites del SAT - **Antigüedad máxima**: 6 años - **Solicitudes por día**: Limitadas (se reinicia cada 24h) - **Tamaño de paquete**: Variable ## Errores Comunes del SAT | Código | Mensaje | Solución | |--------|---------|----------| | 5000 | Solicitud Aceptada | OK - esperar verificación | | 5002 | Límite de solicitudes agotado | Esperar 24 horas | | 5004 | No se encontraron CFDIs | Normal si no hay facturas en el rango | | 5005 | Solicitud duplicada | Ya existe una solicitud pendiente | | - | Información mayor a 6 años | Ajustar rango de fechas | | - | No se permite descarga de cancelados | Facturas canceladas no disponibles | ## Seguridad 1. **Encriptación de credenciales**: AES-256-GCM con IV único 2. **Almacenamiento seguro**: Certificado, llave y contraseña encriptados 3. **Autenticación**: JWT con tenantId embebido 4. **Aislamiento**: Cada tenant tiene su propio schema en PostgreSQL ## Servicios Systemd ```bash # API Backend systemctl status horux-api # Web Frontend systemctl status horux-web ``` ## Comandos Útiles ```bash # Ver logs de sincronización SAT journalctl -u horux-api -f | grep "\[SAT\]" # Estado de jobs psql -U postgres -d horux360 -c "SELECT * FROM sat_sync_jobs ORDER BY created_at DESC LIMIT 5;" # CFDIs sincronizados por tenant psql -U postgres -d horux360 -c "SELECT COUNT(*) FROM tenant_xxx.cfdis WHERE source = 'sat';" ``` ## Changelog ### 2026-01-25 - Implementación inicial de sincronización SAT - Integración con librería @nodecfdi/sat-ws-descarga-masiva - Soporte para fechas personalizadas en sincronización - Corrección de cast UUID en queries SQL - Agregadas columnas faltantes a tabla cfdis - UI para selección de periodo personalizado - Cambio de servicio web a modo producción (next start) ## Próximos Pasos - [ ] Implementar reintentos automáticos para errores temporales - [ ] Notificaciones por email al completar sincronización - [ ] Dashboard con estadísticas de CFDIs por periodo - [ ] Soporte para filtros adicionales (RFC emisor/receptor, tipo de comprobante)