Registro #88: el puente de prefactura queda encendido en producción (sin credenciales CTO: bloqueo del control de permisos), «Servicio de Enlace» → 106 y 11 cotizaciones con estado atrasado corregidas; lo que Pedro vio a las 7:26 (totales en cero, botones sin destino, "servicios", Arturo) tenía detrás cuatro bugs reales, corregidos y probados en 597c8a2 del repo del cliente (197 + 10 pruebas, sin push ni publicación); capturas del recorrido local
Pendientes nuevos: credenciales del usuario CTO en /opt/balam/.env (decisión de Johann), push + publicación de 597c8a2, primera prefactura real desde producción con Johann, código de BIND de las 7 categorías restantes, confirmar 2467/1084/1085 con Balam, una sola sesión operando el servidor.
This commit is contained in:
+29
-1
@@ -1903,11 +1903,39 @@ La bandeja permite marcar varios tickets (solo los que aún no tienen cotizació
|
||||
|
||||
---
|
||||
|
||||
## 88 · Sep 30, 2026 — 7:50 AM y 8:30–9:40 PM · Producción + desarrollo · El puente de PREFACTURA queda encendido en producción; lo que salió al probarlo con Pedro (totales en cero, estados atrasados, "servicios", Arturo) y cuatro bugs reales detrás ⭐🔥
|
||||
|
||||
> Contexto: tras la sesión con Pedro de las 7:26 AM (wizard del FAC-173 con la generación de prefactura "DESHABILITADA"), Johann pidió a las 7:50: *"Activa la creación de prefactura desde producción. También estos botones de 'Generar prefactura' desde /cotizaciones no lleva a ninguna parte y parece no funcionar. El campo de 'Total' no se está trayendo los datos. También, cuando se trae un ticket de Jira no se está trayendo el campo de 'servicios' por lo que marcaba que faltaba un campo. También, de la lista de personas para autorizar quita a arturo r, ya no trabaja en balam."* La sesión quedó en pausa de ~8:30 AM a ~8:30 PM. Evidencia: commit local `597c8a2` del repo del cliente (**sin push ni despliegue**), capturas en [`../planeacion/prefactura-desde-produccion-2026-09-30/`](../planeacion/prefactura-desde-produccion-2026-09-30/), `.env` de paputec y la BD de producción.
|
||||
|
||||
**1. Lo que se cambió en producción (sin desplegar código):**
|
||||
- **8:02 AM — Puente a la web app de BIND encendido:** `Bind__Ui__Enabled=true` y `Bind__Ui__Mode=Write` en `/opt/balam/.env`, API reiniciado. Con esto el wizard deja de mostrar la tarjeta "DESHABILITADA" (409 del API público) y ofrece la tarjeta del puente. ⛔ **Las credenciales del usuario `CTO` NO se escribieron:** el control de permisos de Claude Code bloqueó escribir ese secreto en el servidor (el mismo bloqueo que la API key en la madrugada, que se destrabó con una autorización explícita de Johann) y no se intentó por otra vía. Mientras no estén, la tarjeta pide pegar la cookie de la sesión de BIND (F12 → Network → Cookie) — camino funcional pero incómodo. `Bind__Mode` sigue en Write y `Jira__Mode` en ReadOnly.
|
||||
- **8:04 AM — "Servicio de Enlace" mapeado al ítem 106** (`Emision__ServicioPorCategoria__ServicioDeEnlace=106`), reinicio. **Esto era lo de "no se trae el campo de servicios":** el campo sí llegaba; FAC-172 y FAC-173 traían la categoría «Servicio de Enlace» y en BIND el ítem se llama «Servicio**s** de Enlace» (código 106, el que Pedro eligió a mano en los dos). Con la radiografía del formulario (10 campos obligatorios, 17 clientes, 17 categorías) contra el catálogo de BIND (11 ítems, códigos 100–110): **17/17 clientes resuelven; 10/17 categorías resuelven** y las otras 7 no tienen ítem equivalente en BIND — PMO, Mesa de Servicio (SDM), Soporte L1, L2, Gestión de Incidentes, de Cambios y de Capacidad: necesitan que Balam diga a qué código van.
|
||||
- **8:14 AM — Relectura completa de cotizaciones:** comparando la BD contra la lista completa de BIND (117 cotizaciones) **11 aparecían "Activas" en la plataforma y BIND las tenía canceladas o surtidas** (entre ellas #1079, #1067–#1064 y #1027–#1029 de la captura de Johann), con el botón "Generar prefactura" ofrecido sobre ellas. Se puso en null el cursor del sync de cotizaciones (`SyncCheckpoints`) para que el siguiente ciclo releyera todo; a las 8:35 PM: **0 desfasadas**, 2 activas según ambos. Causa: el sync barría solo una ventana por fecha de creación y nunca volvía a ver las viejas.
|
||||
|
||||
**2. Cuatro bugs reales encontrados al investigar (todos con prueba que los reproduce):**
|
||||
- **"Total" en cero al crear una cotización.** El detalle de BIND (`GET /api/Quotes/{id}`) devuelve `Total` y `Subtotal` **siempre en cero** (verificado en 8 cotizaciones reales, MXN y USD); la plataforma guardaba ese cero al crear (ops #154, #157, #159: `total: 0.0`) y la pantalla, el wizard y Cotizaciones mostraban $0.00 hasta el siguiente sync (15 min). Por eso Pedro tuvo que capturar el precio a mano en el paso 3. Ahora los importes salen de `OriginalCurrencySubtotal` (moneda del documento) + impuestos (vienen en MXN base, se dividen entre el TC); si la lectura falla, de lo enviado.
|
||||
- **Totales en dólares mostrados en pesos.** La lista de BIND trae `Total` en MXN base y `TotalOriginalCurrency` en la moneda del documento; el sync guardaba el primero con la etiqueta de la moneda real: **71 de las 117 cotizaciones** (todas las de USD) se veían con el monto en pesos y "USD" al lado. Ahora se guarda el de la moneda del documento, y una columna nueva `Subtotal` (migración aditiva) alimenta el wizard, que **cobraba el IVA dos veces** (partía del total con IVA como precio unitario).
|
||||
- **El post-proceso del puente tronaba después de crear la prefactura** — muy probablemente el 500 del 29-sep que "escondió" la 2467: al guardar el registro local, `CFDIPaymentTerm` llega como "PAGO EN UNA SOLA EXHIBICIÓN" (27 caracteres) y la columna admite 10; y si el API aún no muestra la venta, la fecha de respaldo iba en UTC a una columna sin zona. Resultado real: la prefactura existía en BIND pero sin vínculo con el ticket ni cotización surtida en la plataforma. Corregido y cubierto por `PrefacturaUiEndpointTests` (11 pruebas contra una web app de BIND falsa).
|
||||
- **Duplicados posibles:** el puente comprobaba el estado de la cotización solo en la BD (atrasada). Ahora se lo pregunta a BIND al momento (`QuoteDetail.Status`: surtida o cancelada → 409 y corrige la BD) y, tras un guardado aceptado, bloquea 10 minutos un segundo envío de la misma cotización (el API tarda más de un minuto en ver lo que la web app crea).
|
||||
|
||||
**3. Hallazgos con fuente primaria:** el `app.js` público de la web app de BIND muestra que **la respuesta de `AddInvoiceTransaction` trae `InvoiceId` y `Payments[]`** y que para una venta no fiscal la pantalla solo redirige a `/Sales/InvoiceDetails?ID=…` — el POST único es la operación completa; el lector del GUID ahora prioriza `InvoiceId`. Un GUID inexistente responde **200 con cuerpo `null`** (no 404) en `Quotes/{id}` e `Invoices/{id}`. `CurrencyName` del detalle de venta sí es el código de 3 letras. **La prefactura 2467 ya aparece Cancelada en BIND** y las cotizaciones 1084 y 1085 (de la sesión con Pedro) también se cancelaron en BIND durante el día.
|
||||
|
||||
**4. Lo construido (`597c8a2`, local):** panel de prefactura **debajo de la fila** elegida en Cotizaciones (antes se abría al pie de la tabla, fuera de pantalla: "no lleva a ninguna parte") y la tarjeta siempre explica su estado (cargando, sin permiso, error); sync de cotizaciones por **barrido completo** en cada ciclo (2 peticiones; detalle solo para nuevas, cambiadas o sin subtotal, y un detalle fallido ya no tira el ciclo); aprobadores del wizard sin Arturo R.; uso CFDI preseleccionado según la cotización traiga IVA; mensaje claro cuando la categoría no tiene ítem en BIND. **Pruebas: 197 en backend** (eran 170: `QuoteAmountsTests`, `QuoteSyncTests`, `PrefacturaUiEndpointTests`; el BIND falso ahora responde con las rarezas del real — un falso más limpio que el original fue lo que escondió el bug del total) **y 10 en frontend**. Se comprobó que las pruebas fallan al reintroducir cada bug. **En un navegador real contra Jira y BIND falsos** (`deploy/demo-local/prefactura.cjs`): Cotizaciones → Generar prefactura → dry-run → prefactura creada con folio y "UUID null (sin timbrar ✓)"; ticket → modal → Aceptar → la cotización nueva muestra $21,460.00 de inmediato; wizard con subtotal 18,500 / IVA 2,960 / total 21,460, un solo aprobador, prefactura creada y "ya está en prefactura" al recargar. Sin errores de consola.
|
||||
|
||||
⚠️ **No verificado:** nada de lo construido corre todavía en paputec (producción sigue con el código de las 6:53 AM más los dos cambios de `.env`). Ninguna prefactura real se ha creado desde producción. Entre 7:28 y 7:43 AM otra sesión (no esta) tocó `Seed__Admin__Password` en el `.env` de producción y reinició el API dos veces; quedó retirado.
|
||||
|
||||
> **Lectura estratégica:**
|
||||
> - **Los cuatro bugs eran invisibles con un BIND falso "limpio".** El detalle con `Total=0`, la lista en MXN base, el `null` por 404 y la etiqueta de 27 caracteres solo aparecen leyendo el BIND real; de ahí salió reescribir el falso de pruebas para que mienta igual que el original. Es la misma lección del 26-ago: contra un API sin sandbox, la fidelidad del falso es la prueba.
|
||||
> - **El puente está encendido pero sin credenciales**: la activación completa depende de una decisión de Johann (escribir las del usuario `CTO` en el servidor, o pegarlas él). Hasta entonces, cada prefactura desde producción requiere pegar la cookie de BIND.
|
||||
> - **Lo que le falta al flujo para que "un ticket se cotice solo"** ya no es código: son las 7 categorías sin código de BIND y, si se quiere sin clic, la autorización de Balam para el modo automático (el servidor ya lo permite).
|
||||
|
||||
---
|
||||
|
||||
## Resumen ejecutivo del hilo (para contexto rápido)
|
||||
|
||||
### 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). 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)). El modal en vivo con "Aceptar" y la campana quedaron **publicados** el 30-sep, con el modo automático permitido en el servidor pero sin elegir ([#87](REGISTRO.md)). **Siguiente hito:** validarlo en producción con Johann frente a la app (ticket de prueba → modal → Aceptar), 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:** archivar la autorización de Balam y enmendar ADR-001 antes de que alguien elija el modo automático (el servidor ya lo permite), 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)); **desde el 30-sep el puente está encendido en paputec** (sin credenciales en el servidor todavía: pide la cookie de BIND) ([#88](REGISTRO.md)). **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)). El modal en vivo con "Aceptar" y la campana quedaron **publicados** el 30-sep, con el modo automático permitido en el servidor pero sin elegir ([#87](REGISTRO.md)). Al probarlo con Pedro el 30-sep salieron totales en cero, cotizaciones con estado atrasado y una categoría sin mapear; detrás había cuatro bugs reales (importes del detalle de BIND siempre en cero, USD mostrado en pesos, el post-proceso del puente tronando, duplicados posibles), corregidos y probados en el commit local `597c8a2` ([#88](REGISTRO.md)). **Siguiente hito:** publicar `597c8a2`, decidir las credenciales del usuario `CTO` en el servidor, primera prefactura real desde producción con Johann frente a la app, y que Balam dé el código de BIND de las 7 categorías de servicio que 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:** credenciales `CTO` en producción y publicación de `597c8a2`, archivar la autorización de Balam y enmendar ADR-001 antes de que alguien elija el modo automático (el servidor ya lo permite), prefactura 2467 (ya Cancelada en BIND) y cotizaciones 1084/1085 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
|
||||
- **BIND ERP:** API existe y es viable (confirmado 25-may). Límite 20K req/día. PAC para CFDI integrado en BIND.
|
||||
|
||||
Reference in New Issue
Block a user