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