diff --git a/bitacora/PENDIENTES.md b/bitacora/PENDIENTES.md index 6f1ef6e..3db819e 100644 --- a/bitacora/PENDIENTES.md +++ b/bitacora/PENDIENTES.md @@ -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). -_Ú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 @@ -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). - [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. -- [ ] 🔥 **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). - [ ] **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. diff --git a/bitacora/REGISTRO.md b/bitacora/REGISTRO.md index 2425d9c..4ae225e 100644 --- a/bitacora/REGISTRO.md +++ b/bitacora/REGISTRO.md @@ -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 diff --git a/planeacion/Script-cotizacion-sesion-2026-08-12.md b/planeacion/Script-cotizacion-sesion-2026-08-12.md new file mode 100644 index 0000000..12629bd --- /dev/null +++ b/planeacion/Script-cotizacion-sesion-2026-08-12.md @@ -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": "", + "VATRate": 16, + "Comments": "Generada desde el ticket FAC-nnn (prueba acompañada).", + "ClientProspect": { + "isNew": false, + "Client": { + "ClientId": "", + "ClientName": "" + } + }, + "Items": [ + { + "Title": "", + "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.