FactuGES_ERP/docs/customer-invoices/proforma-issuance-readiness-contract.md
david 080dcaaa61 feat: implement GetProformaIssuanceReadiness use case and associated controller
- Add GetProformaIssuanceReadinessUseCase to check proforma issuance readiness.
- Create GetProformaIssuanceReadinessController to handle requests and responses.
- Introduce request and response DTOs for proforma issuance readiness.
- Develop tests for the use case and controller to ensure functionality.
- Implement adapter and hooks for integrating issuance readiness in the web application.
- Create UI components for displaying issuance readiness alerts and help popover.
- Add utility functions for translating blocker messages and details.
2026-08-18 23:03:04 +02:00

2.7 KiB

Contrato de readiness de emisión de proformas

Objetivo

La readiness de emisión es una lectura informativa del estado persistido de una proforma.

Su propósito es responder:

¿Puede emitirse esta proforma ahora mismo?

No sustituye la validación transaccional final de:

PUT /proformas/:id/issue

La emisión sigue revalidando siempre en backend para cubrir concurrencia y cambios entre consulta y submit.

Endpoint vigente

GET /proformas/:proforma_id/issuance-readiness

Comportamiento:

- 200 cuando la proforma existe dentro del scope de company
- 200 aunque can_issue sea false
- blockers con códigos estables orientados a frontend
- sin textos i18n en backend

No se expone readiness completa en el listado de proformas para evitar N+1 HTTP y resolución externa por fila.

Contrato HTTP

{
  "can_issue": false,
  "blockers": [
    { "code": "missing_operation_date" },
    { "code": "missing_description" }
  ]
}

Códigos públicos

Code Significado
already_issued La proforma ya tiene emisión materializada o enlazada.
invalid_status El estado actual no permite emitir; hoy debe estar aprobada.
missing_description Falta la descripción obligatoria para emitir.
missing_operation_date Falta la fecha de operación.
incomplete_recipient Faltan datos fiscales mínimos del destinatario.
missing_items No existen líneas de detalle persistidas.
missing_payment_method Falta la forma de pago.
missing_tax_regime Falta el régimen fiscal.
payment_method_unavailable La referencia company-scoped de forma de pago no se puede resolver.
payment_method_inactive La forma de pago resuelta existe, pero está inactiva.

Fuente de verdad

La semántica se reparte de forma explícita pero sin duplicar reglas:

Proforma.getIssuanceBlockers()
  -> blockers internos de dominio

Proforma.validateCanBeIssued()
  -> consume el primer blocker compatible con el contrato legacy de error

ProformaIssuanceReadinessChecker
  -> añade blockers externos dependientes de catálogos

Esto permite:

readiness
-> enumerar blockers útiles

issue
-> seguir fallando de forma autoritativa

Semántica importante en frontend

  • La readiness representa el estado guardado en backend.
  • Los cambios no guardados del editor no alteran este read model.
  • Tras guardar, cambiar estado o emitir, la query de readiness debe invalidarse.

Pendientes fuera de esta fase

  • exponer readiness en listado sin introducir N+1;
  • migrar la ruta legacy de emisión de PUT a un contrato nuevo si se aprueba;
  • deep-link o focus directo al campo bloqueado desde frontend.