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:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Acciones vivas del proyecto. Formato: `[ ]` abierta · `[x]` cerrada (no se borran, dejan rastro). Cada una con responsable y, si aplica, fecha. Ver contexto en [REGISTRO.md](REGISTRO.md).
|
Acciones vivas del proyecto. Formato: `[ ]` abierta · `[x]` cerrada (no se borran, dejan rastro). Cada una con responsable y, si aplica, fecha. Ver contexto en [REGISTRO.md](REGISTRO.md).
|
||||||
|
|
||||||
_Última actualización: 2026-08-11, noche (Noé **confirmó la sesión del mié 12-ago, 7:00 am**, ruteó el ticket de ejemplo a **Araceli** y propuso explorar Azure en la misma sesión con una cuenta nueva. **El molde aún no existía la noche del 11** — plan B: captura en vivo al abrir. Ver [REGISTRO #63](REGISTRO.md); contexto de las definiciones en [#62](REGISTRO.md))._
|
_Última actualización: 2026-08-11, noche (sesión confirmada **mié 12-ago 7:00 am** [#63]; molde ruteado a Araceli, aún inexistente — plan B: captura en vivo. **La capa ticket→cotización BIND quedó CONSTRUIDA y probada** con dry-run + candados; el ejercicio ya no es simulación. Ver [REGISTRO #64](REGISTRO.md))._
|
||||||
|
|
||||||
## 🔥 Flujo Jira→BIND — abierto tras la definición del 7-ago
|
## 🔥 Flujo Jira→BIND — abierto tras la definición del 7-ago
|
||||||
|
|
||||||
@@ -16,7 +16,9 @@ _Última actualización: 2026-08-11, noche (Noé **confirmó la sesión del mié
|
|||||||
- [ ] 🔴 **¿El comercial ya genera la cotización en BIND, o la genera la plataforma?** Contradicción abierta: el 6-jul Ara dijo que **el comercial la genera y la plataforma la convierte** a prefactura ([REGISTRO #27](REGISTRO.md)); el 4-ago Arturo dijo que **la plataforma la genera**; y el formulario de Jira sigue exigiendo **adjuntar la cotización**. Si ambas cosas ocurren, **quedan dos cotizaciones por ticket**. Se resuelve viendo qué adjunto pone Arturo en el ticket de ejemplo: cotización de BIND ya existente (→ convertir) o documento comercial (→ crear).
|
- [ ] 🔴 **¿El comercial ya genera la cotización en BIND, o la genera la plataforma?** Contradicción abierta: el 6-jul Ara dijo que **el comercial la genera y la plataforma la convierte** a prefactura ([REGISTRO #27](REGISTRO.md)); el 4-ago Arturo dijo que **la plataforma la genera**; y el formulario de Jira sigue exigiendo **adjuntar la cotización**. Si ambas cosas ocurren, **quedan dos cotizaciones por ticket**. Se resuelve viendo qué adjunto pone Arturo en el ticket de ejemplo: cotización de BIND ya existente (→ convertir) o documento comercial (→ crear).
|
||||||
- [x] ~~**Alcance del ejercicio en vivo: ¿cotización o prefactura?**~~ → **Decidido (10-ago): termina en la COTIZACIÓN.** Es lo que contestó Arturo el 4-ago; la aprobación de Araceli va entre `En proceso de facturación` y `Facturado`, así que la prefactura pertenece después; Arturo pidió gradualismo explícito; y la cotización se cancela sin efecto fiscal mientras la prefactura es un registro en `Invoices` con `UUID = null`. La prefactura queda para la segunda sesión. Candados acordados: **cotización → prefactura → aprobación humana → timbrado** ([REGISTRO #55](REGISTRO.md)).
|
- [x] ~~**Alcance del ejercicio en vivo: ¿cotización o prefactura?**~~ → **Decidido (10-ago): termina en la COTIZACIÓN.** Es lo que contestó Arturo el 4-ago; la aprobación de Araceli va entre `En proceso de facturación` y `Facturado`, así que la prefactura pertenece después; Arturo pidió gradualismo explícito; y la cotización se cancela sin efecto fiscal mientras la prefactura es un registro en `Invoices` con `UUID = null`. La prefactura queda para la segunda sesión. Candados acordados: **cotización → prefactura → aprobación humana → timbrado** ([REGISTRO #55](REGISTRO.md)).
|
||||||
- [ ] ⚠️ **La transición automática depende de Azure.** En la prueba del miércoles el disparo es **manual** (pipeline `Draft→DryRun→Confirmed` de ADR-001 con flags apagados). Para que corra automática hace falta el ambiente publicado y corriendo continuo — otro argumento para insistir en el acceso a Azure.
|
- [ ] ⚠️ **La transición automática depende de Azure.** En la prueba del miércoles el disparo es **manual** (pipeline `Draft→DryRun→Confirmed` de ADR-001 con flags apagados). Para que corra automática hace falta el ambiente publicado y corriendo continuo — otro argumento para insistir en el acceso a Azure.
|
||||||
- [ ] 🔥 **Johann — preparar el flujo contra el ticket de ejemplo** en cuanto Araceli lo levante (la noche del 11 no existe — preparar la sesión con el plan B de captura en vivo). ⚠️ Realidad técnica a las puertas de la sesión: bandeja+detalle leen FAC en vivo, el **wizard es simulación (folio "SIM")** y el `BindClient` **bloquea POST por diseño** — la escritura real de la cotización no está construida ni su shape documentado (portal de developers pendiente con Pedro). El "flujo funcionando" de mañana es: molde → detección → wizard con datos reales → cotización simulada/DryRun; **la escritura real se ejecuta cuando Balam la vea y apruebe en la sesión, no antes** (protocolo del Bloque 6 de `../planeacion/Investigacion-API-Jira.md`).
|
- [x] ~~🔥 **Johann — preparar el flujo contra el ticket de ejemplo**~~ → **CONSTRUIDO (11-ago, noche):** contrato `Quotes_NewQuote` obtenido del portal público, `CreateQuoteAsync` con guardas, `POST /api/emision/cotizacion` (dry-run/confirmación auditadas en `WriteOperations`), pantalla `solicitudes/:id/cotizar` y vínculo ticket→cotización. 73/73 pruebas. **Corre contra cualquier ticket FAC** — el molde solo mejora los datos. La escritura real sigue gateada a `Bind:Mode=Write`, que se enciende SOLO en la sesión. Ver [REGISTRO #64](REGISTRO.md).
|
||||||
|
- [ ] 🔥 **Johann — enviar a Noé/Pedro el script de la prueba** esta noche (`../planeacion/Script-cotizacion-sesion-2026-08-12.md`) — cumple la condición del 24-jul de compartirlo antes.
|
||||||
|
- [ ] 🔥 **Johann — en la sesión: encender `Bind:Mode=Write` solo para emitir y regresarlo a ReadOnly antes de cerrar.** ⚠️ La semántica fina de partidas (`Type`/`SelectedUnit`/VAT) se valida contra la primera respuesta real; si BIND rechaza, el error se lee en pantalla y se ajusta en vivo.
|
||||||
- [x] ~~**Balam/Noé — fecha para la prueba acompañada de escritura.**~~ → **Es la sesión confirmada del mié 12-ago, 7:00 am** (Noé, 11-ago). Formato aceptado desde el 7-ago; **no habrá `FACTEST`**. Ver [REGISTRO #63](REGISTRO.md).
|
- [x] ~~**Balam/Noé — fecha para la prueba acompañada de escritura.**~~ → **Es la sesión confirmada del mié 12-ago, 7:00 am** (Noé, 11-ago). Formato aceptado desde el 7-ago; **no habrá `FACTEST`**. Ver [REGISTRO #63](REGISTRO.md).
|
||||||
- [ ] **Balam — ¿nacional vs extranjero cambia la cotización** o solo el paquete de salida (PDF+XML vs PDF)? Hay dos estatus de validación y una aprobación por rama.
|
- [ ] **Balam — ¿nacional vs extranjero cambia la cotización** o solo el paquete de salida (PDF+XML vs PDF)? Hay dos estatus de validación y una aprobación por rama.
|
||||||
- [ ] **Balam/Pedro — migrar a cuenta de servicio** en vez de la cuenta personal de Pedro. Planteado el 29-jul, sin respuesta: hoy todo lo que escriba la plataforma queda firmado como Pedro y una rotación suya mata la integración.
|
- [ ] **Balam/Pedro — migrar a cuenta de servicio** en vez de la cuenta personal de Pedro. Planteado el 29-jul, sin respuesta: hoy todo lo que escriba la plataforma queda firmado como Pedro y una rotación suya mata la integración.
|
||||||
|
|||||||
@@ -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)
|
## Resumen ejecutivo del hilo (para contexto rápido)
|
||||||
|
|
||||||
### Datos duros confirmados por Balam
|
### Datos duros confirmados por Balam
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# Script de la prueba acompañada — cotización BIND desde un ticket de Jira
|
||||||
|
|
||||||
|
**Sesión:** miércoles 12-ago-2026, 7:00 am · **Alcance:** el ejercicio termina en la **cotización** en BIND (sin prefactura, sin timbrado, sin tocar Jira).
|
||||||
|
|
||||||
|
> Para enviar a Noé/Pedro (correo o WhatsApp) ANTES de la sesión — cumple el compromiso del 24-jul de compartir el script de escritura para revisión previa.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Qué se va a ejecutar (una sola operación)
|
||||||
|
|
||||||
|
`POST https://api.bind.com.mx/api/Quotes` — la operación `Quotes_NewQuote` del portal de desarrolladores de BIND. Crea **una** cotización. La respuesta es el ID del documento creado, que verificamos al momento con una lectura (`GET /api/Quotes/{id}`) para ver folio y total, y que ustedes pueden ver en su pantalla de Ventas → Cotizaciones.
|
||||||
|
|
||||||
|
**Body de ejemplo** (los valores reales salen del ticket de ejemplo y del catálogo de BIND; este es el shape exacto):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"CurrencyID": "<GUID de la moneda, del catálogo de BIND>",
|
||||||
|
"VATRate": 16,
|
||||||
|
"Comments": "Generada desde el ticket FAC-nnn (prueba acompañada).",
|
||||||
|
"ClientProspect": {
|
||||||
|
"isNew": false,
|
||||||
|
"Client": {
|
||||||
|
"ClientId": "<GUID del cliente en BIND>",
|
||||||
|
"ClientName": "<nombre tal como está en BIND>"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Items": [
|
||||||
|
{
|
||||||
|
"Title": "<concepto según el ticket>",
|
||||||
|
"Unit": "Servicio",
|
||||||
|
"Price": 0.0,
|
||||||
|
"Qty": 1,
|
||||||
|
"VAT": 0.0,
|
||||||
|
"IEPS": 0,
|
||||||
|
"IndexNumber": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Datos que se toman del ticket de Jira: **cliente** (confirmado a mano contra el catálogo sincronizado de BIND — el ticket no trae RFC), **monto sin IVA**, **moneda** y el **resumen** como concepto. No se usa ningún dato del adjunto.
|
||||||
|
|
||||||
|
## Candados (ADR-001, ya operando en el código)
|
||||||
|
|
||||||
|
1. **Dry-run primero, en pantalla.** Antes de emitir se muestra el body EXACTO que saldría — lo revisamos juntos en la sesión. Cualquier edición invalida el dry-run.
|
||||||
|
2. **La escritura está apagada por default.** El servidor corre en modo solo-lectura; el modo escritura se enciende al iniciar la sesión y **se apaga al terminar**. Fuera de ese modo, el botón de emitir no funciona (el servidor lo rechaza).
|
||||||
|
3. **Una operación por confirmación humana explícita** (diálogo de confirmación con cliente y total). Sin lotes, sin reintentos automáticos de escritura.
|
||||||
|
4. **Todo queda auditado**: cada dry-run y cada confirmación se persisten (usuario, fecha, payload, resultado) en la bitácora de operaciones de la plataforma.
|
||||||
|
5. **Permisos por rol**: solo los roles de Finanzas/Administración de la plataforma pueden usar la pantalla de emisión.
|
||||||
|
|
||||||
|
## Reversa
|
||||||
|
|
||||||
|
La cotización **no tiene efecto fiscal**. Al cierre de la sesión, ustedes deciden: **cancelarla** en BIND (queda el rastro, sin efecto) o **conservarla** si el ticket de ejemplo es un caso real que va a facturarse. Ambas salidas son de un clic en su pantalla de cotizaciones.
|
||||||
|
|
||||||
|
## Qué NO hace este ejercicio
|
||||||
|
|
||||||
|
- No crea prefactura ni factura, no timbra (eso queda para la siguiente sesión, con los candados acordados: cotización → prefactura → aprobación humana → timbrado).
|
||||||
|
- No escribe nada en Jira (ni transiciones ni comentarios).
|
||||||
|
- No crea ni modifica clientes en BIND.
|
||||||
|
- No corre nada automático: el disparo es manual en esta prueba; la versión automática (detección del cruce a "En proceso de facturación") depende del ambiente en Azure.
|
||||||
Reference in New Issue
Block a user