- 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.
101 lines
2.7 KiB
Markdown
101 lines
2.7 KiB
Markdown
# 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:
|
|
|
|
```txt
|
|
¿Puede emitirse esta proforma ahora mismo?
|
|
```
|
|
|
|
No sustituye la validación transaccional final de:
|
|
|
|
```txt
|
|
PUT /proformas/:id/issue
|
|
```
|
|
|
|
La emisión sigue revalidando siempre en backend para cubrir concurrencia y cambios entre consulta y submit.
|
|
|
|
## Endpoint vigente
|
|
|
|
```http
|
|
GET /proformas/:proforma_id/issuance-readiness
|
|
```
|
|
|
|
Comportamiento:
|
|
|
|
```txt
|
|
- 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
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```txt
|
|
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:
|
|
|
|
```txt
|
|
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.
|