Factura Global & fecha_efectiva: - Migracion 045_factura_global.sql: periodicidad, meses_global, año_global, fecha_efectiva - sat-parser.service.ts: extrae InformacionGlobal del XML - sat.service.ts: calcFechaEfectiva con soporte bimestral (periodicidad 05) - metricas-compute, dashboard, impuestos, cfdi, export, conciliacion, alertas: reemplaza fecha_emision-1h por COALESCE(fecha_efectiva, fecha_emision-1h) - Script recalc-metricas.ts para recalculo manual Fallback datos fiscales tenant → contribuyente: - contribuyente.service.ts: fetchTenantFiscalData + mergeContribuyenteWithTenant rellena regimenFiscal, codigoPostal y domicilio cuando el contribuyente tiene el mismo RFC que el tenant y sus campos estan vacios - contribuyente.controller.ts y contribuyente-config.controller.ts: pasan req.user!.tenantId al servicio Fix critico SAT sync: - sat.service.ts: anio_global → año_global en INSERT/UPDATE de CFDIs (la migracion creo 'año_global' con tilde; el codigo usaba 'anio_global', causando fallo en 100% de inserciones de CFDI) - determineChunkMonths: salta sondeo si existe job previo con requestIds - MAX_POLL_ATTEMPTS: 45 → 500 (~8h) para syncs iniciales grandes Docs: - docs/sessions/2026-05-22-factura-global-contribuyente-fallback.md
6.3 KiB
Sesión de cambios: 2026-05-22
Resumen
Tres líneas de trabajo: (1) implementación completa de facturas globales (InformacionGlobal) con fecha_efectiva, (2) fallback robusto de datos fiscales del tenant a contribuyentes con RFC coincidente, y (3) corrección crítica de typo anio_global → año_global en sincronización SAT.
1. Facturas Globales — InformacionGlobal y fecha_efectiva
Contexto
Las facturas globales del SAT usan el nodo <cfdi:InformacionGlobal> que indica la periodicidad, meses y año al que realmente corresponden los ingresos. Antes del cambio, todos los CFDIs se agrupaban por fecha_emision, lo que desplazaba facturas globales emitidas al cierre de un período (ej. 31 de marzo) al mes equivocado.
Cambios
Base de datos
- Nueva migración
apps/api/src/migrations/tenant/045_factura_global.sql:periodicidad VARCHAR(2)meses_global VARCHAR(10)año_global VARCHAR(4)fecha_efectiva DATE+ índiceidx_cfdis_fecha_efectiva
- Aplicada a todos los tenants activos vía script de migración.
Parser SAT
apps/api/src/services/sat/sat-parser.service.tsCfdiParsedahora incluyeperiodicidad,mesesGlobal,añoGlobal.- Extraídos del XML desde
comprobante.InformacionGlobal.
Cálculo de fecha_efectiva
apps/api/src/services/sat/sat.service.tscalcFechaEfectiva(cfdi): devuelvenew Date(año, mes-1, 1)para facturas globales.- Soporta periodicidad bimestral (
05): códigos13-18→ meses2,4,6,8,10,12.
Queries de métricas/reportes
Reemplazado fecha_emision - interval '1 hour' por COALESCE(fecha_efectiva, fecha_emision - interval '1 hour') en:
metricas-compute.service.ts(counts, min_anio, monthly compute)reportes.service.ts(flujo efectivo, comparativos)dashboard.service.ts(KPIs, neteo PPD/07)impuestos.service.ts(IVA mensual)alertas-auto.service.ts(alertas RESICO y régimen desconocido)cfdi.service.ts(list filters,getResumenCfdis)export.service.tsconciliacion.service.tsalertas.controller.ts
Backfill
- Ejecutado en todos los tenants activos:
horux_hts240708lja: 24 registroshorux_roem691011ez4: 2,238 registroshorux_auza640701ti9: 6 registroshorux_momc8311199va: 14 registros
- Métricas recalculadas para TORC9611214CA (enero-marzo 2026).
2. Fallback de datos fiscales del tenant al contribuyente
Problema
El tenant HORUX 360 (HTS240708LJA) tiene su régimen fiscal y domicilio en la base central (tenants), pero al existir como contribuyente dentro de su propia BD (contribuyentes), esos campos estaban vacíos. El frontend mostraba "Sin régimen" y "Sin domicilio" al seleccionar ese contribuyente.
Solución robusta
Cuando un contribuyente tiene el mismo RFC que su tenant, el backend ahora mezcla automáticamente los datos faltantes desde la base central.
Archivos
apps/api/src/services/contribuyente.service.tsfetchTenantFiscalData(tenantId): consultatenants+tenant_regimenes_activospara obtener régimen (CSV de claves), CP y domicilio JSON.mergeContribuyenteWithTenant(): rellenaregimenFiscal,codigoPostalydomiciliosi están vacíos en el contribuyente.listContribuyentes()ygetContribuyenteById()aceptantenantIdopcional.
apps/api/src/controllers/contribuyente.controller.ts- Pasa
req.user!.tenantIdalistContribuyentesygetContribuyenteById.
- Pasa
apps/api/src/controllers/contribuyente-config.controller.ts- Pasa
req.user!.tenantIdagetContribuyenteByIdenuploadFielycreateOrg.
- Pasa
3. Fix crítico: anio_global → año_global
Problema
La migración 045_factura_global.sql creó la columna año_global (con tilde), pero sat.service.ts usaba anio_global (sin tilde) en las queries INSERT/UPDATE de saveCfdis. Esto causaba que cada inserción de CFDI fallara con:
column "anio_global" of relation "cfdis" does not exist
Esto explicaba por qué el sync inicial del tenant DESPACHO_MPG95QP7_XZVFF insertó solo 174 de 8,284 CFDIs descargados.
Fix
apps/api/src/services/sat/sat.service.ts- Líneas 297 y 347:
anio_global→año_global.
- Líneas 297 y 347:
Optimización adicional en SAT sync
determineChunkMonths(): ahora detecta si existe un job previo completado consatRequestIdsy salta el sondeometadatalento, reutilizando directamente el tamaño de chunk (3 o 6 meses).MAX_POLL_ATTEMPTS: aumentado de 45 a 500 (~8 horas) para syncs iniciales grandes donde el SAT tarda horas en preparar paquetes.
Re-sync validado
Re-lanzado el sync inicial para DESPACHO_MPG95QP7_XZVFF tras el fix:
- Found: 8,284 | Downloaded: 7,781 | Inserted: 8,266
- Duración: ~7 minutos (vs. ~3.5 horas del intento anterior con el bug).
Archivos modificados
| Archivo | Cambio |
|---|---|
apps/api/src/migrations/tenant/045_factura_global.sql |
Nueva migración (untracked → added) |
apps/api/src/services/sat/sat-parser.service.ts |
Extrae periodicidad, mesesGlobal, añoGlobal |
apps/api/src/services/sat/sat.service.ts |
calcFechaEfectiva, fix año_global, determineChunkMonths optimizado, MAX_POLL_ATTEMPTS |
apps/api/src/services/metricas-compute.service.ts |
Usa COALESCE(fecha_efectiva, ...) |
apps/api/src/services/dashboard.service.ts |
Usa fecha_efectiva en KPIs y neteo |
apps/api/src/services/impuestos.service.ts |
Usa fecha_efectiva en IVA mensual |
apps/api/src/services/cfdi.service.ts |
Filtros y resumen por fecha_efectiva |
apps/api/src/services/export.service.ts |
Usa fecha_efectiva |
apps/api/src/services/conciliacion.service.ts |
Usa fecha_efectiva |
apps/api/src/services/alertas-auto.service.ts |
Usa fecha_efectiva en alertas |
apps/api/src/controllers/alertas.controller.ts |
Usa fecha_efectiva en queries de alertas |
apps/api/src/services/contribuyente.service.ts |
Fallback de datos fiscales del tenant |
apps/api/src/controllers/contribuyente.controller.ts |
Pasa tenantId al servicio |
apps/api/src/controllers/contribuyente-config.controller.ts |
Pasa tenantId al servicio |
apps/api/src/scripts/recalc-metricas.ts |
Script de recálculo manual (untracked → added) |
apps/web/... |
Múltiples ajustes frontend relacionados (fechas, alertas, drill-down) |