From fd7252d77c0ba888345018e5308f836e39326013 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 7 Jul 2026 17:40:16 +0200 Subject: [PATCH] Docs --- docs/customer-invoices/proformas-reports.md | 418 ++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 docs/customer-invoices/proformas-reports.md diff --git a/docs/customer-invoices/proformas-reports.md b/docs/customer-invoices/proformas-reports.md new file mode 100644 index 00000000..a6afe19f --- /dev/null +++ b/docs/customer-invoices/proformas-reports.md @@ -0,0 +1,418 @@ +# Proformas Reports + +## Resumen funcional + +El flujo activo de reports de proformas en `modules/customer-invoices` ya no usa un endpoint ambiguo con `format`. + +El endpoint legacy eliminado era: + +```txt +GET /proformas/:proforma_id/report?format=pdf|html|json +``` + +El estado actual separa explícitamente: + +```txt +GET /proformas/:proforma_id/report/pdf +GET /proformas/:proforma_id/report/preview +``` + +No existe soporte JSON para reports de proformas. + +## Endpoints finales + +### Descarga PDF + +Endpoint: + +```txt +GET /proformas/:proforma_id/report/pdf +``` + +Comportamiento: + +```txt +- Content-Type: application/pdf +- descarga como attachment +- render con FastReport PDF +- plantilla: proforma.frx +- sin firma digital +- cache solo si la proforma no está en draft +- sin query format +``` + +### Preview HTML + +Endpoint: + +```txt +GET /proformas/:proforma_id/report/preview +``` + +Comportamiento: + +```txt +- Content-Type: text/html; charset=utf-8 +- render inline +- FastReport HTML +- plantilla: proforma.frx +- sin firma digital +- sin cache +- sin query format +``` + +Uso previsto: + +```txt +- visualizar el contenido de una proforma desde la lista +- previsualizar cómo quedaría la proforma antes de exportarla a PDF +``` + +Limitación actual: + +```txt +Solo previsualiza una proforma persistida. +No existe preview de cambios no guardados del formulario. +``` + +No existen todavía endpoints como: + +```txt +POST /proformas/report/preview +POST /proformas/:proforma_id/report/preview +``` + +## Flujo técnico + +Flujo conceptual: + +```txt +Route + -> Controller + -> Use case + -> Proforma finder / read model assembler + -> Full snapshot + -> Report snapshot + -> Document pipeline + -> FastReport renderer + -> HTTP response +``` + +Separación por capas: + +### Application + +Responsabilidades: + +```txt +- use cases +- builders +- modelos de report +- errores funcionales +- puertos como CompanyReportProfileFinder +``` + +Reglas: + +```txt +- Application no depende de Express, Sequelize, filesystem ni FastReport directamente +- los use cases devuelven Result +``` + +### Infrastructure + +Responsabilidades: + +```txt +- routes Express +- controllers +- adapters +- FastReport renderers +- document pipelines +- cache/storage +``` + +Reglas: + +```txt +- los controllers no contienen lógica documental +- FastReport vive en Infrastructure +- no hay firma digital en el pipeline de proformas +- no hay acoplamiento con issued-invoices +``` + +## Diferencias entre PDF y HTML preview + +| Aspecto | PDF | HTML preview | +| --- | --- | --- | +| Endpoint | `/report/pdf` | `/report/preview` | +| MIME type | `application/pdf` | `text/html; charset=utf-8` | +| Disposition | `attachment` | `inline` | +| Renderer | FastReport PDF | FastReport HTML | +| Cache | solo no `draft` | no | +| Firma digital | no | no | + +## Reglas de cache + +La cache PDF usa una `storageKey` determinista. + +La key V1 incluye: + +```txt +companyId +proformaId +status +format=pdf +languageCode +currencyCode +companyProfile.slug +companyProfile.version si existe +``` + +Regla funcional aplicada: + +```txt +Una proforma no draft no puede modificarse. +``` + +Por tanto: + +```txt +draft: + - no cachear PDF + +non-draft: + - cachear PDF +``` + +La cache se considera segura respecto al contenido de la proforma cuando `status !== "draft"` por la inmutabilidad funcional de estados no draft. + +Deuda pendiente: + +```txt +- invalidación por cambios de plantilla +- invalidación por cambios de branding/logo/datos empresa +- invalidación por una versión documental más rica cuando exista +``` + +## Reglas de firma digital + +Las proformas no se firman digitalmente. + +Regla explícita: + +```txt +La firma digital aplica a issued invoices, no a proformas. +``` + +Esto evita copiar incorrectamente el pipeline de `issued-invoices` dentro del flujo de proformas. + +## CompanyReportProfile y error 409 + +El report de proforma necesita datos reales de empresa. + +No se puede renderizar una proforma sin `CompanyReportProfile`. + +Si el perfil no existe: + +```txt +CompanyReportProfileNotFoundError +``` + +se mapea a: + +```txt +409 Conflict +``` + +Motivo: + +```txt +La proforma existe, pero falta configuración documental de empresa. +``` + +No está permitido: + +```txt +- inventar datos de empresa +- hardcodear companySlug +- continuar renderizando con datos incompletos +- devolver error genérico 500 +``` + +Actualmente `CompanyReportProfileFinder` usa el servicio público de `companies`. + +Campos que hoy pueden no venir expuestos por `companies` y quedan como `Maybe.none()`: + +```txt +locale +currencyCode +logo +address +version +``` + +## Localization + +El flujo usa un modelo explícito: + +```ts +export type ReportLocalization = { + languageCode: string; + locale: string; + currencyCode: string; +}; +``` + +Criterio funcional: + +```txt +- languageCode representa idioma: es, en, fr... +- locale representa formato regional: es-ES, en-GB... +- currencyCode representa moneda: EUR, USD... +``` + +Prioridad funcional deseada: + +```txt +1. valores guardados en el documento +2. valores del cliente/recipient si existen +3. valores de la empresa +4. fallback técnico controlado +``` + +No debe repetirse la incoherencia anterior entre `languageCode` y `locale`. + +## Ficheros principales + +Rutas y controllers: + +```txt +modules/customer-invoices/src/api/infrastructure/proformas/express/proformas.routes.ts +modules/customer-invoices/src/api/infrastructure/proformas/express/controllers/report-proforma-pdf.controller.ts +modules/customer-invoices/src/api/infrastructure/proformas/express/controllers/preview-proforma-report.controller.ts +``` + +Use cases: + +```txt +modules/customer-invoices/src/api/application/proformas/use-cases/report-proforma-pdf.use-case.ts +modules/customer-invoices/src/api/application/proformas/use-cases/preview-proforma-report.use-case.ts +``` + +Errores y mapping HTTP: + +```txt +modules/customer-invoices/src/api/application/proformas/errors/company-report-profile-not-found.error.ts +modules/customer-invoices/src/api/infrastructure/proformas/express/proformas-api-error-mapper.ts +``` + +Adapter de empresa: + +```txt +modules/customer-invoices/src/api/infrastructure/proformas/adapters/company-report-profile-finder.ts +``` + +Pipelines y renderers: + +```txt +modules/customer-invoices/src/api/infrastructure/proformas/documents/pipelines/proforma-pdf-document-pipeline-factory.ts +modules/customer-invoices/src/api/infrastructure/proformas/documents/pipelines/proforma-html-preview-pipeline-factory.ts +modules/customer-invoices/src/api/infrastructure/proformas/documents/renderers/fastreport/proforma-pdf-document-renderer.ts +modules/customer-invoices/src/api/infrastructure/proformas/documents/renderers/fastreport/proforma-html-preview-renderer.ts +``` + +Metadata, cache y persistencia de documentos: + +```txt +modules/customer-invoices/src/api/infrastructure/proformas/documents/services/proforma-pdf-document-metadata-factory.ts +modules/customer-invoices/src/api/infrastructure/proformas/documents/services/proforma-html-preview-document-metadata-factory.ts +modules/customer-invoices/src/api/infrastructure/proformas/documents/pre-processors/proforma-pdf-cache-pre-processor.ts +modules/customer-invoices/src/api/infrastructure/proformas/documents/side-effects/persist-proforma-pdf-side-effect.ts +``` + +Template: + +```txt +modules/customer-invoices/templates/rodax/es/proforma.frx +``` + +## Legacy eliminado + +Ya no existe: + +```txt +GET /proformas/:proforma_id/report +``` + +También se eliminó el soporte ambiguo: + +```txt +format=pdf|html|json +``` + +Legacy eliminado del árbol de aplicación: + +```txt +modules/customer-invoices/src/api/application/proformas/use-cases/report-proforma2 +``` + +Motivo: + +```txt +- legacy no cableado +- no referenciado por rutas, DI, exports ni tests +- contaminaba el typecheck del módulo +``` + +No debe reintroducirse: + +```txt +report-proforma2 +ReportProformaUseCase legacy +format=pdf|html|json +/proformas/:proforma_id/report +``` + +## Frontend + +No se ha cambiado todavía el frontend para preview HTML. + +Sí se actualizó la descarga PDF para apuntar al endpoint nuevo: + +```txt +/report/pdf +``` + +Pendiente: + +```txt +- crear cliente web para /report/preview +- integrar preview HTML en lista/editor +- probar si el HTML generado por FastReport es usable dentro de iframe/panel/modal +``` + +## Deuda pendiente + +Pendientes explícitos: + +```txt +- invalidación de cache por cambios de plantilla +- invalidación de cache por cambios de branding/logo/datos empresa +- exposición futura de logo, address, locale, currencyCode y version desde companies +- cliente frontend para /report/preview +- preview de cambios no guardados del formulario +- errores TypeScript restantes en otras zonas de customer-invoices no relacionadas con reports de proformas +``` + +## Próximos pasos recomendados + +Siguientes pasos razonables: + +```txt +1. exponer más campos documentales desde companies +2. introducir invalidación de cache por plantilla/branding +3. añadir cliente frontend para /report/preview +4. validar si el HTML de FastReport es usable en iframe/panel/modal +5. diseñar preview de cambios no guardados sin persistencia +```