Uecko_ERP/docs/customer-invoices/proformas-reports.md

419 lines
8.7 KiB
Markdown
Raw Normal View History

2026-07-07 15:40:16 +00:00
# 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
```