Registro #87: la API key de cto entra a producción (el sync vuelve), la vista previa se valida contra el BIND real con FAC-171 y se construye en local el modal en vivo con "Aceptar", la campana y el modo automático configurable; capturas y video del recorrido

This commit is contained in:
Johann
2026-09-30 01:42:32 -06:00
parent 085e9037e8
commit bdafb06a03
13 changed files with 105 additions and 5 deletions
+16 -4
View File
@@ -2,14 +2,26 @@
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-09-30** — ⭐ el webhook de Jira FAC queda **en producción (paputec)**: publicado, secreto nuevo, webhook id 1 movido y prueba de punta a punta con FAC-170 en 1.05 s ([REGISTRO #85](REGISTRO.md)); y la vista previa automática de la cotización queda **publicada** ([#86](REGISTRO.md)). 🔥 **Causa del 500 de BIND encontrada:** la key de `arturo` dejó de servir; la de `cto` responde 200 y falta ponerla en paputec. Además, fusión de las dos sesiones paralelas del 29-sep: la del webhook pasa a ser el [#84](REGISTRO.md) (nació como #71 en la otra máquina). Anterior: **2026-09-29** — ⭐ Balam entrega **login web a BIND** con permisos de prefactura; endpoint interno de la UI confirmado (*Generar Venta → Prefactura*, petición `InvoiceDetails`) y el modelo de dos endpoints corroborado con el SDK oficial ([REGISTRO #83](REGISTRO.md)). **Huecos de registro cerrados:** las sesiones del 21-ago al 10-sep se reconstruyeron desde el buzón ([#71](REGISTRO.md)–[#82](REGISTRO.md)). Anterior: **2026-09-15** — corte de horas 10-ago→15-sep reconstruido y huecos de registro listados (seis sesiones sin bitácora). Anterior: **2026-08-21, mediodía** — ⭐ primera cotización real emitida (folio 1026; la 2.ª, corregida, pendiente de confirmar). Anterior: **2026-08-20, noche.** Cruce completo del buzón contra la bitácora (MCP ms365): se incorporaron 9 comunicaciones faltantes y se corrigieron 2 errores de registro. **Hay sesión mañana viernes 21-ago, 7:00 am** con Noé, Ara y Pedro sobre el formulario modificado y `FAC-106`. Ver [REGISTRO #65](REGISTRO.md)–[#68](REGISTRO.md)._ _Última actualización: **2026-09-30** — ⭐ el webhook de Jira FAC queda **en producción (paputec)**: publicado, secreto nuevo, webhook id 1 movido y prueba de punta a punta con FAC-170 en 1.05 s ([REGISTRO #85](REGISTRO.md)); y la vista previa automática de la cotización queda **publicada** ([#86](REGISTRO.md)). 🔥 **La API key de `cto` ya está en producción y el sync volvió**; la vista previa se validó contra el BIND real (FAC-171) y el **modal en vivo con "Aceptar"** quedó construido en local, sin publicar ([#87](REGISTRO.md)). Además, fusión de las dos sesiones paralelas del 29-sep: la del webhook pasa a ser el [#84](REGISTRO.md) (nació como #71 en la otra máquina). Anterior: **2026-09-29** — ⭐ Balam entrega **login web a BIND** con permisos de prefactura; endpoint interno de la UI confirmado (*Generar Venta → Prefactura*, petición `InvoiceDetails`) y el modelo de dos endpoints corroborado con el SDK oficial ([REGISTRO #83](REGISTRO.md)). **Huecos de registro cerrados:** las sesiones del 21-ago al 10-sep se reconstruyeron desde el buzón ([#71](REGISTRO.md)–[#82](REGISTRO.md)). Anterior: **2026-09-15** — corte de horas 10-ago→15-sep reconstruido y huecos de registro listados (seis sesiones sin bitácora). Anterior: **2026-08-21, mediodía** — ⭐ primera cotización real emitida (folio 1026; la 2.ª, corregida, pendiente de confirmar). Anterior: **2026-08-20, noche.** Cruce completo del buzón contra la bitácora (MCP ms365): se incorporaron 9 comunicaciones faltantes y se corrigieron 2 errores de registro. **Hay sesión mañana viernes 21-ago, 7:00 am** con Noé, Ara y Pedro sobre el formulario modificado y `FAC-106`. Ver [REGISTRO #65](REGISTRO.md)–[#68](REGISTRO.md)._
## 🔥 30-sep — modal en vivo, aceptación y modo automático ([REGISTRO #87](REGISTRO.md))
- [ ] 🚀 **Johann — decidir push + publicación del modal en vivo** (commit local `aac7447`; migración aditiva `CotizacionDesdeTicket`: 4 columnas en `JiraTicketEvents` y 1 en `Tenants`). Al publicar: comprobar el punto de la campana (verde = canal en vivo por Apache; ámbar = respaldo cada 4 s).
- [ ] 🧪 **Validar en producción con Johann frente a la app:** ticket de prueba (con autorización) → modal en vivo → "Aceptar". ⚠️ Eso crea una **cotización REAL en BIND**: usar un monto de prueba reconocible y cancelarla después.
- [ ] 🔴 **Decidir si el modo automático se enciende en producción** (`Jira__Webhook__AutoCreateQuoteAllowed=true` en `/opt/balam/.env`). Hoy está apagado: toda cotización la acepta una persona. El plan del 29-sep pide **autorización escrita de Balam y enmendar ADR-001**; conviene fijar también el tope (`AutoCreateMaxSubtotal`).
- [ ] 📋 **Pedir a Balam (Pedro) el código de BIND para 8 categorías** del combo Servicio/Producto que hoy no resuelven y caen en "Faltan datos": Gestión de Proyectos Senior / PMO · Gestión de Mesa de Servicio (SDM) · Soporte Especializado L1 · L2 · Gestión de Incidentes · de Cambios · de Capacidad · Servicio de Enlace (¿106 "Servicios de Enlace"?). Se cargan en `Emision__ServicioPorCategoria__…` del `.env`.
- [ ] 🧹 **Evento de prueba FAC-171** (id 2 en paputec, `Lista`, ticket ya borrado): descartarlo desde la campana al publicar, o limpiarlo por SQL.
- [ ] 🧹 La API key anterior (usuario `arturo`) quedó **comentada** en `/opt/balam/.env` para rollback: borrarla cuando la de `cto` lleve unos días estable.
- [ ] 👀 En esta Mac sigue corriendo desde el **3-sep** una instancia local del API (puerto 5078) y del frontend (4200), con el código de ese día: no se tocó. Apagarla o reiniciarla cuando convenga.
- [ ] 🔧 La tabla de la bandeja se sale del ancho a 1440 px (la columna BIND y los botones quedan cortados); ya pasaba antes del chip nuevo.
- [ ] 🔧 Deuda del modal: enseña el resumen de la cotización, no el JSON del dry-run (está en `WriteOperations`); agregar "ver el body" si Balam lo pide. El canal en vivo es en memoria: vale para una sola instancia del API.
## ⭐ 30-sep — webhook de Jira en producción ([REGISTRO #85](REGISTRO.md)) y vista previa automática ([#86](REGISTRO.md)) ## ⭐ 30-sep — webhook de Jira en producción ([REGISTRO #85](REGISTRO.md)) y vista previa automática ([#86](REGISTRO.md))
- [x] ~~🔧 **Siguiente meta:** con cada `JiraTicketEvent` verificado, armar la vista previa (dry-run) de la cotización y marcar el ticket "lista para revisar" en la bandeja.~~ → **CONSTRUIDA el 30-sep** (commits locales `1c37eaa` y `287cb65`, 147 pruebas en verde, [#86](REGISTRO.md)). La confirmación sigue siendo humana (ADR-001). - [x] ~~🔧 **Siguiente meta:** con cada `JiraTicketEvent` verificado, armar la vista previa (dry-run) de la cotización y marcar el ticket "lista para revisar" en la bandeja.~~ → **CONSTRUIDA el 30-sep** (commits locales `1c37eaa` y `287cb65`, 147 pruebas en verde, [#86](REGISTRO.md)). La confirmación sigue siendo humana (ADR-001).
- [x] ~~🚀 **Johann — decidir push + publicación de la vista previa automática**~~ → **HECHO el 30-sep por orden de Johann:** push de `1c37eaa` + `287cb65` y publicación en paputec (migración aplicada, trabajador activo, FAC-170 → `NoAplica`). Ver adenda del [#86](REGISTRO.md). - [x] ~~🚀 **Johann — decidir push + publicación de la vista previa automática**~~ → **HECHO el 30-sep por orden de Johann:** push de `1c37eaa` + `287cb65` y publicación en paputec (migración aplicada, trabajador activo, FAC-170 → `NoAplica`). Ver adenda del [#86](REGISTRO.md).
- [ ] 🔥🔑 **Johann — poner la API key del usuario `cto` en `Bind__ApiKey` de `/opt/balam/.env`** y `docker compose up -d api` (rotación de secreto del runbook). La key está en `backend/appsettings.local.json` de la Mac de desarrollo y **ya se probó: 200** en `/api/Currencies` y `/api/Clients`; la de `arturo`, la que hoy usa producción, es la que responde 500. Claude Code no pudo hacerlo (escritura de secretos bloqueada por permisos). Al entrar: verificar `[sync] Ciclo OK` en el log, y el barrido preparará solo las vistas previas pendientes. - [x] ~~🔥🔑 **Poner la API key del usuario `cto` en `Bind__ApiKey` de `/opt/balam/.env`**~~ → **HECHO el 30-sep con autorización de Johann** ([#87](REGISTRO.md)): `[sync] Ciclo OK`, el sync volvió tras 20 días.
- [ ] 🧪 Con la key nueva en producción: abrir la bandeja en el navegador (el chip no se ha visto en pantalla) y, con autorización, un ticket de prueba para ver una vista previa real de punta a punta. - [x] ~~🧪 Con la key nueva en producción: ticket de prueba para ver una vista previa real de punta a punta.~~ → **HECHO del lado del servidor con FAC-171** (vista previa `Lista` en 4.32 s, operación #155, [#87](REGISTRO.md)). Verla en el navegador pasa al bloque del modal en vivo, arriba.
- [ ] 🧹 Imagen de rollback `balam-api:pre-vistaprevia-20260930` en paputec (además de la `pre-webhook`): borrarlas cuando la versión lleve unos días estable. - [ ] 🧹 Imagen de rollback `balam-api:pre-vistaprevia-20260930` en paputec (además de la `pre-webhook`): borrarlas cuando la versión lleve unos días estable.
- [ ] 🔧 **Deuda:** las reglas de prellenado viven dos veces (`cotizacion-prefill.ts` y `CotizacionPrefill.cs`). Que las pantallas de cotización (individual y lote) consuman el prellenado y el dry-run ya preparado del servidor. - [ ] 🔧 **Deuda:** las reglas de prellenado viven dos veces (`cotizacion-prefill.ts` y `CotizacionPrefill.cs`). Que las pantallas de cotización (individual y lote) consuman el prellenado y el dry-run ya preparado del servidor.
- [ ] 🔧 Suscribir `jira:issue_updated` (o repetir la vista previa al abrir el ticket) para que "Faltan datos" se actualice cuando alguien completa el ticket en Jira. - [ ] 🔧 Suscribir `jira:issue_updated` (o repetir la vista previa al abrir el ticket) para que "Faltan datos" se actualice cuando alguien completa el ticket en Jira.
@@ -41,7 +53,7 @@ _Última actualización: **2026-09-30** — ⭐ el webhook de Jira FAC queda **e
- [x] ~~🔧 **Siguiente paso de la meta:** vista previa (dry-run) de la cotización por cada detección.~~ → **Construida el 30-sep** ([#86](REGISTRO.md)); su publicación está en el bloque del 30-sep, arriba. - [x] ~~🔧 **Siguiente paso de la meta:** vista previa (dry-run) de la cotización por cada detección.~~ → **Construida el 30-sep** ([#86](REGISTRO.md)); su publicación está en el bloque del 30-sep, arriba.
- [x] ~~☁️ **Destino productivo del webhook:** ngrok con dominio fijo (de pago) vs Azure (sigue bloqueado por el cliente).~~ → **Resuelto por ahora con paputec** (30-sep), el mismo ambiente provisional de la plataforma. Cuando exista Azure, el webhook se mueve con otro `PUT`. - [x] ~~☁️ **Destino productivo del webhook:** ngrok con dominio fijo (de pago) vs Azure (sigue bloqueado por el cliente).~~ → **Resuelto por ahora con paputec** (30-sep), el mismo ambiente provisional de la plataforma. Cuando exista Azure, el webhook se mueve con otro `PUT`.
- [ ] ⚠️ **Una sola sesión de Claude Code dueña de la API** en sesiones de escritura (el 29-sep otra sesión la relanzó en ReadOnly). - [ ] ⚠️ **Una sola sesión de Claude Code dueña de la API** en sesiones de escritura (el 29-sep otra sesión la relanzó en ReadOnly).
- [ ] 🔥 **API público de BIND en 500 en todos los endpoints** (key de Arturo) — sync detenido desde el 10-sep. Pedir a Balam la API key del usuario `CTO` o revisar el acceso de Arturo. **→ 30-sep: causa encontrada.** El API no está caído: la key de `arturo` es la que falla; la de `cto` responde 200. Falta cambiarla en paputec (bloque del 30-sep, arriba). - [x] ~~🔥 **API público de BIND en 500 en todos los endpoints** (key de Arturo)~~ → **RESUELTO el 30-sep** con la key del usuario `cto` en producción ([#87](REGISTRO.md)). Original: — sync detenido desde el 10-sep. Pedir a Balam la API key del usuario `CTO` o revisar el acceso de Arturo. **→ 30-sep: causa encontrada.** El API no está caído: la key de `arturo` es la que falla; la de `cto` responde 200. Falta cambiarla en paputec (bloque del 30-sep, arriba).
- [ ] 🔥 **Prefactura 2467 ($777,777 MXN, ACUNTIA, FAC-166):** confirmar con Balam si es prueba (cancelar/borrar antes de que alguien la timbre) o real; revisar que al timbrar quede **PPD**, no el PUE que BIND le puso. - [ ] 🔥 **Prefactura 2467 ($777,777 MXN, ACUNTIA, FAC-166):** confirmar con Balam si es prueba (cancelar/borrar antes de que alguien la timbre) o real; revisar que al timbrar quede **PPD**, no el PUE que BIND le puso.
- [ ] 📧 **Avisar a Pedro de la cotización 1079 marcada como Surtida por error** (`QuotesAPI/FillQuote` escribe por GET); sin efecto fiscal, irreversible desde la UI. - [ ] 📧 **Avisar a Pedro de la cotización 1079 marcada como Surtida por error** (`QuotesAPI/FillQuote` escribe por GET); sin efecto fiscal, irreversible desde la UI.
- [ ] 🔧 Tomar el bloque `Client` de `ClientsAPI/GetClientSelectedById` (hoy `CFDI_Use` puede heredarse de la factura de OTRO cliente) y que el wizard no muestre G03/16% cuando el puente manda lo de BIND. - [ ] 🔧 Tomar el bloque `Client` de `ClientsAPI/GetClientSelectedById` (hoy `CFDI_Use` puede heredarse de la factura de OTRO cliente) y que el wizard no muestre G03/16% cuando el puente manda lo de BIND.
+34 -1
View File
@@ -1863,11 +1863,44 @@ La bandeja permite marcar varios tickets (solo los que aún no tienen cotizació
--- ---
## 87 · Sep 30, 2026 — madrugada (≈1:00–1:45 AM) · Producción + desarrollo · La API key de `cto` entra a producción (el sync vuelve tras 20 días), la vista previa se valida contra el BIND REAL (FAC-171) y se construye el MODAL EN VIVO con "Aceptar", la campana y el modo automático configurable ⭐🔥
> Contexto: misma sesión del [#85](REGISTRO.md)/[#86](REGISTRO.md). Instrucciones de Johann en la sesión (sus palabras, con la ortografía normalizada): *"te autorizo cambiar el token en producción, lo siguiente que quiero hacer es validar el flujo de jira-cotización, que cuando se cree un ticket se cree la cotización automáticamente"*; sobre el alcance: *"por ahora, agrega un modal con un 'aceptar', y que después con una animación fluida se vaya a notificaciones si pasa mucho tiempo, y le puedas dar en ver detalle, quiero que se vea que fue en tiempo real, haz configurable el que se haga en automático o el que pida confirmación a través del modal"*; y para el ticket de prueba: *"Autorizo: cliente ACUNTIA, crear y borrar"*. Evidencia: commit local `aac7447` del repo del cliente (**sin push y sin desplegar**), capturas y video en [`../planeacion/modal-en-vivo-2026-09-30/`](../planeacion/modal-en-vivo-2026-09-30/), fila id 2 de `JiraTicketEvents` y operación #155 en la BD de paputec.
**1. La API key nueva ya está en producción.** Con la autorización de Johann se reemplazó `Bind__ApiKey` en `/opt/balam/.env` por la del usuario `cto` (sin imprimirla; huellas comparadas). La anterior quedó comentada en el mismo archivo para rollback. Al reiniciar: **`[sync] Ciclo OK`** — 17 clientes, 1,202 facturas vistas (2 nuevas, 2 actualizadas, 2 pagos detectados) y 3 cotizaciones nuevas. **El sync estaba detenido desde el 10-sep.**
**2. Radiografía del formulario y del catálogo (solo lecturas).** El formulario "Cotización Bind" (service desk 35, request type 1196) exige diez campos: empresa origen, título, cliente (17 opciones), servicio/producto (17), cantidad, moneda, monto sin IVA, IVA (16 %/0 %), vencimiento y descripción. El catálogo de servicios de BIND ya está depurado: **11 ítems, códigos 100–110**. Con las reglas de prellenado de hoy:
- **Clientes: 17 de 17** opciones del combo resuelven a un único cliente de BIND.
- **Categorías: 9 de 17.** Las ocho que NO resuelven y caerían en "Faltan datos": *Gestión de Proyectos Senior / PMO*, *Gestión de Mesa de Servicio (SDM)*, *Soporte Especializado Nivel 1 (L1)* y *Nivel 2 (L2)*, *Gestión de Incidentes*, *de Cambios* y *de Capacidad*, y *Servicio de Enlace* (en BIND se llama "Servicio**s** de Enlace", código 106). Falta que Balam diga a qué código va cada una (`Emision:ServicioPorCategoria`; sobran en BIND el 102 "Proffesional Services" y el 106).
**3. Vista previa validada contra Jira y BIND reales, en producción** (dos escrituras en Jira, autorizadas):
- **Jira-op 7 (01:07:21):** ticket de prueba **FAC-171** creado por el API de Jira Service Management con el formulario completo (ACUNTIA, Servicios Profesionales Generales, 1 × $1,234.00 MXN, IVA 16 %). → detectado **1.04 s** después (HMAC, verificado) → **vista previa `Lista` a los 4.32 s** (incluye la primera lectura de catálogos a BIND) → **operación #155 en `DryRun`**, firmada por `webhook-jira`, sin confirmar. El body quedó como lo armaría la pantalla: cliente ACUNTIA, ítem de código 101, concepto = título del ticket, `Price` 1234, `Qty` 1, `VAT` 0.16, `Type` 2, `VATRate` 0.16, lista de precios "A", `ExchangeRate` 1. **BIND solo recibió lecturas.**
- **Jira-op 8 (01:07:42):** FAC-171 **borrado** (204; GET → 404). Vivió 21 segundos.
- ⚠️ El evento id 2 quedó `Lista` en la BD de paputec (su ticket ya no existe). Aceptarlo no crearía nada — la aceptación verifica antes que el ticket siga en Jira — pero aparecerá como pendiente en la campana cuando se publique el modal: descartarlo ahí o limpiarlo al publicar.
**4. Lo construido: del ticket a la cotización, a un clic** (`aac7447`, local):
- **Modal en vivo.** Al crearse el ticket, a quien tenga la app abierta le aparece solo un modal con la línea de tiempo y sus tiempos reales (creado en Jira → detectado → vista previa → cotización), los números de la cotización y **"Aceptar y crear cotización"**. Llega por un canal abierto del servidor al navegador (SSE); si el canal no se sostiene, la app consulta cada 4 s. La bandeja de solicitudes también se actualiza sola.
- **Campana.** Si nadie decide en 30 s, el modal vuela con una animación al ícono de la barra superior y queda resaltado, con **"Ver detalle"** para reabrirlo. El cursor encima pausa la cuenta.
- **Aceptar es la confirmación humana de ADR-001:** se envía a BIND el body exacto del dry-run guardado, una sola vez, con candado en la base para que dos clics o dos personas no creen dos cotizaciones. Si BIND rechaza o no se sabe si creó, queda "sin confirmar" y **no se reintenta sola**. También se puede "Revisar y editar" (la pantalla de siempre) o descartar.
- **Modo configurable.** En la campana: "Pedir confirmación" (default) o "Crear en automático". El automático **nace apagado dos veces**: el servidor debe permitirlo (`Jira__Webhook__AutoCreateQuoteAllowed`, hoy `false` en paputec) y además elegirlo un usuario con rol de escritura. Tope de monto opcional.
- Se agregó `deploy/demo-local/`: Jira y BIND falsos para ver todo esto sin tocar los reales.
**5. Verificación.** Backend **170 pruebas** en verde (eran 147) y frontend 10. Incluyen: dos aceptaciones simultáneas → una sola cotización; rechazo de BIND → una sola escritura y sin reintento; ticket borrado → nada se escribe; roles; el canal en vivo entrega "Detectado" y luego "Lista"; modo automático con y sin permiso del servidor, con tope y con BIND en solo lectura. Se comprobó que tres pruebas fallan si se rompe el candado a propósito. **En un navegador real** (Chromium, contra los falsos): el modal apareció **1.3 s** después de crear el ticket (1.0 s es la entrega simulada del webhook), "Aceptar" disponible a los 2.2 s, guardado solo a los 30.5 s, modo automático en 2.3 s, y por sondeo (sin canal en vivo) en 4.3 s. Sin errores de consola. Capturas y video: [`../planeacion/modal-en-vivo-2026-09-30/`](../planeacion/modal-en-vivo-2026-09-30/).
⚠️ **No verificado:** nada de esto corre todavía en paputec. Falta ver el canal en vivo a través de Apache (si lo retuviera, entra el respaldo de 4 s) y **no se ha creado ninguna cotización real con "Aceptar"**: hacerlo en producción crea una cotización de verdad en BIND.
> **Lectura estratégica:**
> - **La petición literal era "que se cree la cotización automáticamente"; lo que quedó por default es el clic.** El plan del 29-sep dejó la creación sin confirmación fuera de alcance hasta tener autorización escrita de Balam y enmendar ADR-001. El modo automático existe y está probado, pero encenderlo en producción es una decisión que no se tomó en esta sesión.
> - **El cuello de botella dejó de ser técnico:** con 8 de 17 categorías sin mapear, casi la mitad de los tickets caería en "Faltan datos" aunque todo funcione. Es una tabla de ocho renglones que tiene que dar Balam.
> - **Tiempos reales medidos:** Jira entrega el aviso en ~1 s y la vista previa queda en 1–4 s. "En tiempo real" es verdad.
---
## Resumen ejecutivo del hilo (para contexto rápido) ## Resumen ejecutivo del hilo (para contexto rápido)
### Estado actual (al 30-sep-2026 — Etapa 2 en producción provisional) ### Estado actual (al 30-sep-2026 — Etapa 2 en producción provisional)
**La plataforma está publicada en https://paputec.mx/balam/** desde el 3-sep (ambiente provisional propio; Azure sigue sin entregarse, [#74](REGISTRO.md)/[#76](REGISTRO.md)) y Balam ya la opera en sesiones acompañadas: cotizaciones reales desde tickets, individuales y en lote ([#77](REGISTRO.md)–[#79](REGISTRO.md)). Producción corre con `Bind__Mode=Write` por decisión de Johann del 30-sep ([#85](REGISTRO.md)). **La cadena ya llegó a la prefactura:** por el API público es imposible — `false` = remisión, `true` = CFDI timbrado; incidente 2386 del 26-ago ([#70](REGISTRO.md)), confirmado con el SDK oficial ([#83](REGISTRO.md)) — pero el puente a la UI de BIND (`BindUiClient`, *Generar Venta → Prefactura*, con el login web que Balam entregó el 29-sep) creó ese mismo día la **primera prefactura real, folio 2467** ([#84](REGISTRO.md)); en paputec el puente sigue apagado. **Y la cadena ya arranca sola:** desde el 30-sep el webhook de Jira avisa a producción cada ticket creado en FAC ([#85](REGISTRO.md)). La vista previa automática de la cotización ("Lista para revisar" en la bandeja) también quedó publicada el 30-sep ([#86](REGISTRO.md)); la confirmación sigue siendo humana (ADR-001). **Siguiente hito:** poner en paputec la API key del usuario `cto` — la de `arturo` es la que responde 500; la de `cto` ya se probó con 200 — para que vuelvan el sync y los catálogos, y entonces validar una vista previa real de punta a punta. **Seguimiento con Pedro** (sesiones "Seguimiento PAF" a las 7:00 am o 1:00 pm; informes de Read AI de Noé). Horas al 16-sep: 94.58 h; Excel de avance en Google Sheets ([#82](REGISTRO.md)). **Abiertos:** cambiar en paputec la API key de BIND por la de `cto` (sync detenido desde el 10-sep), prefactura 2467 por confirmar con Balam, cancelación SAT de la 2386, remisiones 1000/1001, Azure, a quién se reportan horas, y el error al cargar la solicitud al crear cotización visto el 29-sep. **La plataforma está publicada en https://paputec.mx/balam/** desde el 3-sep (ambiente provisional propio; Azure sigue sin entregarse, [#74](REGISTRO.md)/[#76](REGISTRO.md)) y Balam ya la opera en sesiones acompañadas: cotizaciones reales desde tickets, individuales y en lote ([#77](REGISTRO.md)–[#79](REGISTRO.md)). Producción corre con `Bind__Mode=Write` por decisión de Johann del 30-sep ([#85](REGISTRO.md)). **La cadena ya llegó a la prefactura:** por el API público es imposible — `false` = remisión, `true` = CFDI timbrado; incidente 2386 del 26-ago ([#70](REGISTRO.md)), confirmado con el SDK oficial ([#83](REGISTRO.md)) — pero el puente a la UI de BIND (`BindUiClient`, *Generar Venta → Prefactura*, con el login web que Balam entregó el 29-sep) creó ese mismo día la **primera prefactura real, folio 2467** ([#84](REGISTRO.md)); en paputec el puente sigue apagado. **Y la cadena ya arranca sola:** desde el 30-sep el webhook de Jira avisa a producción cada ticket creado en FAC ([#85](REGISTRO.md)). La vista previa automática de la cotización ("Lista para revisar" en la bandeja) también quedó publicada el 30-sep ([#86](REGISTRO.md)); la confirmación sigue siendo humana (ADR-001). La API key del usuario `cto` entró a producción el 30-sep y el sync volvió; la vista previa se validó contra Jira y BIND reales con FAC-171 ([#87](REGISTRO.md)). **Siguiente hito:** publicar el modal en vivo con "Aceptar" y la campana (construido y probado en local, [#87](REGISTRO.md)) y validarlo en producción con Johann presente; y que Balam mapee las 8 categorías de servicio que hoy no resuelven. **Seguimiento con Pedro** (sesiones "Seguimiento PAF" a las 7:00 am o 1:00 pm; informes de Read AI de Noé). Horas al 16-sep: 94.58 h; Excel de avance en Google Sheets ([#82](REGISTRO.md)). **Abiertos:** decidir si el modo automático (sin confirmación) se enciende en producción — requiere autorización de Balam y enmendar ADR-001 —, prefactura 2467 por confirmar con Balam, cancelación SAT de la 2386, remisiones 1000/1001, Azure, a quién se reportan horas, y el error al cargar la solicitud al crear cotización visto el 29-sep.
### Datos duros confirmados por Balam ### Datos duros confirmados por Balam
- **BIND ERP:** API existe y es viable (confirmado 25-may). Límite 20K req/día. PAC para CFDI integrado en BIND. - **BIND ERP:** API existe y es viable (confirmado 25-may). Límite 20K req/día. PAC para CFDI integrado en BIND.
+55
View File
@@ -4,6 +4,11 @@
# url → lee la URL pública del túnel ngrok local (solo lectura) # url → lee la URL pública del túnel ngrok local (solo lectura)
# registrar → POST /rest/webhooks/1.0/webhook (ESCRIBE: 1 webhook de sitio) # registrar → POST /rest/webhooks/1.0/webhook (ESCRIBE: 1 webhook de sitio)
# crear-ticket → POST /rest/api/3/issue (ESCRIBE: 1 ticket de prueba en FAC) # crear-ticket → POST /rest/api/3/issue (ESCRIBE: 1 ticket de prueba en FAC)
# crear-cotizacion [CLIENTE] → POST /rest/servicedeskapi/request (ESCRIBE: 1 ticket de
# prueba COMPLETO por el formulario "Cotización Bind", el que sí
# alcanza para armar la vista previa; default ACUNTIA, S.A.U.)
# vista-previa CLAVE [paputec] → espera el resultado de la vista previa automática
# del ticket y lo muestra con su dry-run (solo lectura)
# esperar CLAVE [paputec] → espera la detección en la BD local o, con "paputec", # esperar CLAVE [paputec] → espera la detección en la BD local o, con "paputec",
# en la de producción por ssh (solo lectura) # en la de producción por ssh (solo lectura)
# borrar-ticket CLAVE → DELETE /rest/api/3/issue/CLAVE (ESCRIBE: borra el ticket de prueba) # borrar-ticket CLAVE → DELETE /rest/api/3/issue/CLAVE (ESCRIBE: borra el ticket de prueba)
@@ -120,6 +125,56 @@ elif cmd == "crear-ticket":
else: else:
print(f"[{st}] {r}") print(f"[{st}] {r}")
elif cmd == "crear-cotizacion":
# Formulario "Cotización Bind" (service desk 35, request type 1196): todos sus
# campos son obligatorios. Datos de prueba fijos y pequeños; el reporter es
# el dueño del token (Pedro), que recibe el correo de confirmación.
cliente = sys.argv[2] if len(sys.argv) > 2 else "ACUNTIA, S.A.U."
vence = time.strftime("%Y-%m-%d", time.localtime(time.time() + 7 * 86400))
st, r = jira("POST", "/rest/servicedeskapi/request", {
"serviceDeskId": "35", "requestTypeId": "1196",
"requestFieldValues": {
"summary": "[PRUEBA PLATAFORMA BALAM] Vista previa automática de cotización — se borra en minutos",
"description": f"Ticket de PRUEBA de la plataforma Balam ({time.strftime('%d/%m/%Y')}), autorizado por Johann, "
"para validar la vista previa automática de la cotización. Se elimina en cuanto se confirma.",
"customfield_11423": {"value": "Balam"}, # Empresa origen
"customfield_11598": {"value": cliente}, # Cliente
"customfield_11599": {"value": "Servicios Profesionales Generales"}, # Servicio/Producto
"customfield_11600": 1, # Cantidad
"customfield_10053": {"value": "MXN"}, # Tipo de Moneda
"customfield_11556": 1234, # Monto sin IVA
"customfield_11601": {"value": "16%"}, # IVA
"customfield_11597": vence, # Fecha de vencimiento
}})
if st == 201 and isinstance(r, dict):
estado(ticket=r["issueKey"], ticket_id=r["issueId"], creado=time.strftime("%Y-%m-%d %H:%M:%S"))
print(f"[201] ticket de prueba completo creado: {r['issueKey']} (id {r['issueId']}) · cliente {cliente}")
else:
print(f"[{st}] {r}")
elif cmd == "vista-previa":
clave = sys.argv[2]
destino = sys.argv[3] if len(sys.argv) > 3 else "local"
for i in range(60):
fila = sql(f"""SELECT e."Id", e."IssueKey", e."Verified", e."AuthMethod",
round(extract(epoch from (e."ReceivedAtUtc"-e."JiraTimestampUtc"))::numeric,2),
e."PreviewStatus", round(extract(epoch from (e."PreviewAtUtc"-e."JiraTimestampUtc"))::numeric,2),
coalesce(e."PreviewOperationId"::text,''), coalesce(e."PreviewDetail",'')
FROM "JiraTicketEvents" e WHERE e."IssueKey"='{clave}' AND e."PreviewStatus" IS NOT NULL""", destino)
if fila and "|" in fila:
print(f"VISTA PREVIA tras ~{i}s de espera: id | llave | verificado | auth | detección s | estado | lista a los s | operación | detalle")
print(" " + fila)
op = fila.split(" | ")[7].strip()
if op:
print(" dry-run guardado (WriteOperations): estatus | tipo | autor | confirmada")
print(" " + sql(f"""SELECT "Status", "Type", "CreatedBy", "ConfirmedAtUtc" IS NOT NULL
FROM "WriteOperations" WHERE "Id"={int(op)}""", destino))
print(sql(f"""SELECT "PayloadJson" FROM "WriteOperations" WHERE "Id"={int(op)}""", destino))
break
time.sleep(1)
else:
print(f"Sin vista previa de {clave} en 60 s.")
elif cmd == "esperar": elif cmd == "esperar":
clave = sys.argv[2] clave = sys.argv[2]
destino = sys.argv[3] if len(sys.argv) > 3 else "local" destino = sys.argv[3] if len(sys.argv) > 3 else "local"
Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB