# Resumen de cambios - 24 de mayo de 2026 --- ## 1. Refactor: Descarga masiva de XMLs por filtros **Fecha:** 2026-05-24 ### Problema El mecanismo anterior requería que el usuario seleccionara individualmente cada CFDI mediante checkboxes. Era lento, propenso a errores y no permitía descargar rangos grandes eficientemente. ### Solución Reemplazo completo por descarga basada en filtros: un botón "Descargar XMLs" descarga todos los CFDIs que coincidan con los filtros activos en la tabla (tipo, estado, fechas, RFC, emisor, receptor, búsqueda, contribuyente). ### Cambios - **Backend:** `POST /cfdi/download-xmls` acepta `{ filters: CfdiFilters }` en lugar de `{ ids: number[] }`. Usa `getXmlsByFilters()` con `LIMIT 1000`. - **Frontend:** Eliminados checkboxes de tabla y estado `selectedIds`. Botón de descarga permanente que usa filtros actuales. - **Warning >1,000:** Si los filtros devuelven más de 1,000 CFDIs, se muestra `confirm()` con "Solo se descargarán los primeros 1,000 XMLs. ¿Continuar?" y se procede. ### Archivos | Archivo | Cambio | |---------|--------| | `apps/api/src/services/cfdi.service.ts` | `getXmlsByFilters()` reusa `whereClause` de `getCfdis` | | `apps/api/src/controllers/cfdi.controller.ts` | `downloadXmlsZip()` acepta filtros, genera ZIP | | `apps/web/lib/api/cfdi.ts` | `downloadXmlsZip(filters: CfdiFilters)` | | `apps/web/app/(dashboard)/cfdi/page.tsx` | Sin checkboxes; botón usa filtros actuales | --- ## 2. Conciliación: filtros con autocompletado **Fecha:** ~2026-05-12 Filtros de columna en tablas de conciliación (RFC Emisor, Nombre Emisor, RFC Receptor, Nombre Receptor, Banco) con: - Debounce de 300ms - Dropdown de sugerencias clickeables (máx 8 items) - Botones "Aplicar" y "Limpiar" dentro del Popover ### Archivos | Archivo | Cambio | |---------|--------| | `apps/web/app/(dashboard)/conciliacion/page.tsx` | `FilterHeader` component con `useDebounce` | --- ## 3. Conciliación: columnas dinámicas según tab **Fecha:** ~2026-05-12 Las tablas "Conciliadas" y "Por conciliar" muestran columnas diferentes según el tab activo (EMITIDO / RECIBIDO): - **EMITIDO:** RFC Receptor, Nombre Receptor - **RECIBIDO:** RFC Emisor, Nombre Emisor En Pendientes se agregó también la columna de régimen fiscal correspondiente: - **EMITIDO:** Régimen Emisor - **RECIBIDO:** Régimen Receptor ### Archivos | Archivo | Cambio | |---------|--------| | `apps/web/app/(dashboard)/conciliacion/page.tsx` | Renderizado condicional de columnas | | `apps/api/src/services/conciliacion.service.ts` | SELECT incluye `regimen_fiscal_emisor` y `regimen_fiscal_receptor` | --- ## 4. Conciliación: métricas I+P-E **Fecha:** ~2026-05-12 El cálculo de "Monto Conciliado" y "Pendiente" ahora aplica la fórmula contable: - **Ingresos (I)** y **Pagos (P)** suman - **Egresos (E)** restan Implementado en `getMonto()` del frontend. --- ## 5. Conciliación: headers visibles sin datos **Fecha:** ~2026-05-12 Las tablas de conciliación mantienen encabezados y filtros visibles incluso cuando no hay resultados (antes desaparecían completamente). Se muestra mensaje "No hay datos" en el `tbody`. --- ## 6. Conciliación: aumento de tamaño de fuente **Fecha:** ~2026-05-12 - Tablas: `text-xs` → `text-base` - Celdas: `text-xs` → `text-sm` --- ## 7. Backfill masivo de datos CFDI faltantes **Fecha:** ~2026-05-10 **Problema:** ~63,618 CFDIs tenían campos vacíos (`serie`, `folio`, `metodo_pago`, `forma_pago`, `uso_cfdi`, `regimen_fiscal`) porque los INSERTs fallaron durante sincronización SAT al no existir la columna `año_global` en ese momento. **Fix:** - Se parsearon los XMLs originales desde disco - Se actualizaron masivamente las filas faltantes vía script Node.js --- ## 8. Fix: Visor de CFDI en conciliación — campos faltantes **Fecha:** 2026-05-09 (continuación) El visor de CFDI desde conciliación ahora muestra correctamente: - Status (Vigente/Cancelado) - Forma de pago - Serie/Folio - Uso CFDI - Subtotal, descuento, impuestos desglosados - Moneda y tipo de cambio Ver `docs/CAMBIOS-2026-05-09.md` sección 7 para detalles completos. --- ## Archivos modificados (consolidado) ### Backend (`apps/api/`) | Archivo | Cambio | |---------|--------| | `src/services/cfdi.service.ts` | `getXmlsByFilters()` para descarga masiva por filtros | | `src/controllers/cfdi.controller.ts` | `downloadXmlsZip()` refactorizado | | `src/services/conciliacion.service.ts` | SELECT régimen fiscal + campos visor + fecha_pago_p | ### Frontend (`apps/web/`) | Archivo | Cambio | |---------|--------| | `app/(dashboard)/cfdi/page.tsx` | Descarga XMLs por filtros, sin checkboxes | | `lib/api/cfdi.ts` | `downloadXmlsZip()` recibe filtros | | `app/(dashboard)/conciliacion/page.tsx` | Filtros debounce, columnas dinámicas, métricas I+P-E, font size, headers siempre visibles | --- ## Deploy ```bash cd /root/HoruxDespachosNuevo npm run build --filter=@horux/api npm run build --filter=@horux/web pm2 reload horux-api pm2 reload horux-web ``` **Estado:** ✅ Exitoso