Docs
This commit is contained in:
parent
588e9dd733
commit
fd7252d77c
418
docs/customer-invoices/proformas-reports.md
Normal file
418
docs/customer-invoices/proformas-reports.md
Normal file
@ -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
|
||||
```
|
||||
Loading…
Reference in New Issue
Block a user