# 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) |
