diff --git a/docs/CAMBIOS-2026-05-09.md b/docs/CAMBIOS-2026-05-09.md index b459f34..bb3bfa6 100644 --- a/docs/CAMBIOS-2026-05-09.md +++ b/docs/CAMBIOS-2026-05-09.md @@ -429,3 +429,61 @@ Se agregaron 5 campos adicionales al visualizador de CFDI (`CfdiInvoice`) para m - **`regimenFiscalLabels`**: 20 regímenes fiscales (601–626) - **`tipoRelacionLabels`**: 7 tipos de relación SAT (`01` Nota de crédito … `07` Aplicación de anticipo) - **`usoCfdiLabels`**: ya existía, se reutiliza para el receptor + +--- + +## 9. Fix: Facturas Facturapi no aparecen en complemento de pago + +**Fecha:** 2026-05-20 + +**Problema:** Las facturas emitidas por Facturapi con método de pago PPD no aparecían en el dropdown de "complemento de pago" (tipo P). Solo aparecían las descargadas del SAT. + +**Causa raíz:** Al emitir vía Facturapi, el campo `saldo_pendiente_mxn` quedaba `NULL`. El endpoint `GET /facturacion/cfdis-ppd` filtra con `COALESCE(saldo_pendiente_mxn, 0) > 0`, excluyendo las facturas de Facturapi. + +**Fix:** +- Después del `INSERT` en `emitir()`, se llama `recomputarSaldoPendiente(pool, [uuid])` para facturas tipo I + método PPD. +- Backfill: se recalcularon 352 filas en la BD del tenant `horux_hts240708lja`. + +**Archivos:** +- `apps/api/src/controllers/facturacion.controller.ts` — Agregado `recomputarSaldoPendiente` post-emisión + +--- + +## 10. Seguridad: cancelación de facturas cruzada entre contribuyentes + +**Fecha:** 2026-05-20 + +**Problema:** Un usuario viendo como contribuyente **Horux 360** podía cancelar facturas emitidas por **Consultoria Alcaraz Salazar**. + +**Causa raíz:** El endpoint `POST /facturacion/cancelar/:uuid` no validaba ownership del contribuyente. Solo buscaba por UUID y cancelaba. + +**Fix (backend):** +- El endpoint ahora recibe `contribuyenteId` del body. +- Si el caller envía un `contribuyenteId` y el CFDI pertenece a otro contribuyente → **403 Forbidden**. + +**Fix (frontend):** +- `cancelarFactura` ahora pasa `selectedContribuyenteId` al backend. +- El botón de cancelar en la tabla de CFDIs solo se muestra si: + - Modo legacy: la factura no tiene `contribuyenteId` + - Modo multi-RFC: `cfdi.contribuyenteId === selectedContribuyenteId` + +**Archivos:** +- `apps/api/src/controllers/facturacion.controller.ts` — Validación 403 + recepción de contribuyenteId +- `apps/web/lib/api/facturacion.ts` — `cancelarFactura` acepta `contribuyenteId` +- `apps/web/app/(dashboard)/cfdi/page.tsx` — Condicional de visibilidad del botón cancelar + +--- + +## 11. Sync inicial SAT — Consultoria Alcaraz Salazar + +**Fecha:** 2026-05-20 + +**Contexto:** La FIEL de Alcaraz Salazar se subió el 2026-05-19, pero la extracción de CSF falló por timeout del SAT. La sincronización inicial nunca se ejecutó (no había job `initial` en `sat_sync_jobs`). + +**Acciones:** +- Creado job `initial` manualmente para contribuyente `bd9ba71c-55f9-40d5-a0d7-18909419298b`. +- El sync descubrió ~616 CFDIs en bloques 2024–2026. +- La tabla `rfcs` se pobló, habilitando el autocompletado del receptor en facturación. + +**Estado:** ✅ Sync completado exitosamente +