Registro #64: capa ticket→cotización BIND construida la noche previa a la sesión (contrato Quotes_NewQuote del portal público, dry-run + candados, 73/73); script de la prueba listo para enviar a Balam
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1280,6 +1280,35 @@ Johann envió el **avance por actividad en texto** (8:12 am), con 👍 de Erika
|
||||
|
||||
---
|
||||
|
||||
## 64 · Ago 11, 2026 — noche · Desarrollo · Capa de escritura mínima: ticket FAC → cotización BIND real, con dry-run y candados (lista para la sesión del 12) ⭐
|
||||
|
||||
> Sesión nocturna previa a la prueba acompañada. Objetivo pedido: llegar con un ejemplo real de **"leer de Jira y escribir en BIND"**, no con simulación. 2 commits en `balam-plataforma` (locales, sin push).
|
||||
|
||||
**El hueco que había:** el wizard de emisión (6-ago) simula la mitad *cotización → prefactura* y arranca desde una cotización BIND EXISTENTE; el ejercicio del 12 es la otra mitad, *ticket → cotización nueva*. Además el `BindClient` bloqueaba POST por diseño y el shape de creación nunca se había documentado (la doc "detallada tras login" seguía pendiente con Pedro).
|
||||
|
||||
**El contrato se consiguió sin login:** el data-plane del portal de developers (APIM) responde anónimo. Operación **`Quotes_NewQuote` = `POST /api/Quotes`**, body con `ClientProspect{isNew, Client{ClientId, ClientName}}`, `Items[{Title, Unit, Price, Qty, VAT, IEPS, …}]`, `CurrencyID/LocationID/VATRate/Comments`; responde el **GUID de la cotización creada**. También existen `Quotes_UpdateQuote` y `Quotes_DeleteQuote` (la reversa por API existe, aunque la cancelación de la prueba se hará desde la pantalla de BIND). ⚠️ El SDK oficial de GitHub (2018) es ANTERIOR al recurso Quotes — no sirve de referencia. ⚠️ Semántica fina de partidas (`Type`, `SelectedUnit`, VAT ¿monto o tasa?) sin documentar: se valida contra la primera respuesta real, en la sesión.
|
||||
|
||||
**Lo construido (73/73 pruebas verdes + smoke test de arranque):**
|
||||
- `BindClient.CreateQuoteAsync` — hereda las guardas del núcleo: en ReadOnly lanza, en DryRun loguea sin enviar, solo `Bind:Mode=Write` envía. 3 pruebas nuevas con `FakeHandler` (una por modo, la de Write valida el body PascalCase con `isNew` en minúsculas, sic del portal).
|
||||
- `POST /api/emision/cotizacion` (modo `DryRun`/`Confirmed`) — valida contra el catálogo sincronizado (el cliente DEBE existir en BIND), persiste **cada intento** en `WriteOperations` (ADR-001), y en Confirmed: crea, **verifica por lectura** (folio/total), refleja la Quote en nuestra BD y guarda el vínculo **ticket → cotización** en `QuoteInvoiceLink` (migración: `InvoiceId` ahora opcional — el vínculo nace en la emisión y se completa al facturar, ADR-003). Policy `PuedeOperarEscritura` (Finanzas/Administración). El 409 cuando el modo no es Write es el candado visible.
|
||||
- Pantalla **`solicitudes/:id/cotizar`** ("Generar cotización en BIND", botón nuevo en el detalle) — prellena cliente/moneda/monto/concepto desde el ticket, exige confirmar el cliente a mano (Jira no trae RFC), y aplica ADR-001 en la UI: **dry-run con el body exacto del wire** antes de habilitar Emitir; cualquier edición lo invalida; Emitir pide confirmación explícita con cliente y total.
|
||||
- Doc para Balam: `../planeacion/Script-cotizacion-sesion-2026-08-12.md` — el "script compartido antes" que pidió Noé el 24-jul (operación única, body de ejemplo, candados, reversa, qué NO hace). **Enviarlo esta noche.**
|
||||
|
||||
**Guion de la sesión (7:00 am):** (1) anunciar que el ejercicio crea UNA cotización real y su destino; (2) molde de Araceli — si no existe, que lo capture en vivo; (3) bandeja → detalle → "Generar cotización en BIND"; (4) dry-run en pantalla, revisado juntos; (5) encender `Bind:Mode=Write` (user-secrets) + reiniciar API; (6) Emitir → folio en pantalla → verlo en su BIND; (7) **apagar el modo Write ahí mismo**; (8) temas verbales (conceptos con el molde, ACUNTIA, Automation con FAC-98 de exhibit, PUE/PPD, cuenta de servicio, prefactura=2.ª sesión); (9) Azure con la cuenta nueva.
|
||||
|
||||
**Lecturas clave:**
|
||||
> - **El compromiso del correo ("llego a la sesión con el flujo ya funcionando") queda cumplible sin el molde:** el flujo corre contra cualquier ticket de FAC; el molde solo mejora los datos.
|
||||
> - **La primera escritura real ocurre EN la sesión, nunca antes** — es literalmente el formato de prueba acompañada que autorizó Noé. Si BIND rechaza el primer intento (semántica de partidas), el error se lee en pantalla y se ajusta en vivo: para eso es la sesión.
|
||||
> - El default ReadOnly y la pantalla con candado convierten la salvaguarda de ADR-001 en algo que Balam puede VER — vale más que explicarla.
|
||||
|
||||
**Pendientes que deja la sesión:**
|
||||
- [ ] 🔥 Johann — **enviar el script a Noé/Pedro esta noche** (doc listo en planeacion/).
|
||||
- [ ] 🔥 Johann — en la sesión: encender `Bind:Mode=Write` solo para emitir y **regresarlo a ReadOnly antes de cerrar**.
|
||||
- [ ] Johann — capturar las horas de esta sesión nocturna en el corte siguiente.
|
||||
- [ ] Johann — si BIND ajusta el shape en vivo (Type/SelectedUnit/VAT), documentar la semántica confirmada en `../planeacion/Investigacion-API-Jira.md` y en el CLAUDE.md del repo de la plataforma.
|
||||
|
||||
---
|
||||
|
||||
## Resumen ejecutivo del hilo (para contexto rápido)
|
||||
|
||||
### Datos duros confirmados por Balam
|
||||
|
||||
Reference in New Issue
Block a user