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
122 lines
6.3 KiB
Markdown
122 lines
6.3 KiB
Markdown
# 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` + índice `idx_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.ts`
|
|
- `CfdiParsed` ahora incluye `periodicidad`, `mesesGlobal`, `añoGlobal`.
|
|
- Extraídos del XML desde `comprobante.InformacionGlobal`.
|
|
|
|
**Cálculo de `fecha_efectiva`**
|
|
- `apps/api/src/services/sat/sat.service.ts`
|
|
- `calcFechaEfectiva(cfdi)`: devuelve `new Date(año, mes-1, 1)` para facturas globales.
|
|
- Soporta periodicidad bimestral (`05`): códigos `13-18` → meses `2,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.ts`
|
|
- `conciliacion.service.ts`
|
|
- `alertas.controller.ts`
|
|
|
|
**Backfill**
|
|
- Ejecutado en todos los tenants activos:
|
|
- `horux_hts240708lja`: 24 registros
|
|
- `horux_roem691011ez4`: 2,238 registros
|
|
- `horux_auza640701ti9`: 6 registros
|
|
- `horux_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.ts`
|
|
- `fetchTenantFiscalData(tenantId)`: consulta `tenants` + `tenant_regimenes_activos` para obtener régimen (CSV de claves), CP y domicilio JSON.
|
|
- `mergeContribuyenteWithTenant()`: rellena `regimenFiscal`, `codigoPostal` y `domicilio` si están vacíos en el contribuyente.
|
|
- `listContribuyentes()` y `getContribuyenteById()` aceptan `tenantId` opcional.
|
|
- `apps/api/src/controllers/contribuyente.controller.ts`
|
|
- Pasa `req.user!.tenantId` a `listContribuyentes` y `getContribuyenteById`.
|
|
- `apps/api/src/controllers/contribuyente-config.controller.ts`
|
|
- Pasa `req.user!.tenantId` a `getContribuyenteById` en `uploadFiel` y `createOrg`.
|
|
|
|
---
|
|
|
|
## 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`.
|
|
|
|
### Optimización adicional en SAT sync
|
|
- `determineChunkMonths()`: ahora detecta si existe un job previo completado con `satRequestIds` y salta el sondeo `metadata` lento, 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) |
|