Files
balam/planeacion/Sondeo-FAC-106-y-payload-2026-08-20.md
Johann 82f9fa5d25 Sondeo de FAC-106 y diagnóstico del 500: el payload tenía tres defectos de escala y semántica
Preparación para la sesión del 21-ago. Todo solo lectura + dry-run.

FAC-106 (creado por Pedro el 20-ago, asignado a Araceli) trae el
formulario nuevo con request type "Cotización Bind". Servicio/Producto,
Cantidad, IVA y Cliente ya son campos estructurados: el hueco de
conceptos/partidas que bloqueaba B7 queda resuelto en el origen.

Diagnóstico del 500 del 12-ago, leyendo 4 cotizaciones reales de BIND:
- VATRate va como fracción (0.16), no como 16
- el VAT de partida es un MONTO, no una tasa (Price*Qty*0.16)
- cada cotización usa un PriceListID distinto y ninguno coincide con el
  único que devuelve GET /api/PriceLists; conviene omitirlo

Dry-run corregido ejecutado (operación #18); el body queda en el informe.

Tres preguntas nuevas para la sesión: Empresa origen tiene 3 valores y
hay un solo token; el combo IVA no ofrece 0% aunque hay clientes de
exportación; y "Servicio de Enlace" existe 5 veces en BIND con unidad,
unidad SAT y ChargeVAT distintos, sin mapeo definido.

Bind:Mode está en Write fuera de sesión — hay que regresarlo a ReadOnly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 23:41:14 -06:00

109 lines
7.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Sondeo de `FAC-106` y payload de cotización — 20-ago-2026, noche
Preparación para la sesión del **viernes 21-ago, 7:00 am**. Todo lo de aquí es **solo lectura**: sondeo del ticket por API de Jira, lectura de catálogos de BIND y **dry-run** del endpoint de emisión (ninguna escritura). Ver [REGISTRO #65](../bitacora/REGISTRO.md) (la sesión del 12-ago que terminó en 500) y [#67](../bitacora/REGISTRO.md).
---
## 1 · `FAC-106` — el formulario nuevo existe y es mucho mejor de lo esperado
Creado por **Pedro** el 20-ago 4:12 pm, asignado a **Araceli**. Request type nuevo: **`Cotización Bind`** (id 1196, portal 35). Estatus `Open` (⚠️ **no** `En proceso de facturación`: mañana el disparo es manual, como estaba previsto).
| Campo | ID | Tipo | Valor en FAC-106 |
|---|---|---|---|
| Empresa origen | `customfield_11423` | select | **Balam** |
| Cliente | `customfield_11598` | **select** | **CEMEX** |
| Servicio/Producto | `customfield_11599` | **select** | **Servicio de Enlace** |
| Cantidad | `customfield_11600` | number | **1.0** |
| Monto sin IVA | `customfield_11556` | number | **1234.0** |
| IVA | `customfield_11601` | select | **16%** |
| Tipo de Moneda | `customfield_10053` | select | **MXN** |
| Fecha de vencimiento | `customfield_11597` | date | **2026-08-27** |
⭐ **El hueco de conceptos/partidas quedó resuelto.** `Servicio/Producto` + `Cantidad` + `IVA` son campos estructurados: ya hay con qué armar una partida sin parsear texto ni adjuntos.
⭐ **`Cliente` dejó de ser ADF y ahora es combo** con **17 opciones** que corresponden a los clientes de BIND: ACUNTIA S.A.U. · ATC CONSOLIDADOS · BANCA AFIRME · CEMEX · DEACERO · FRISA FORJADOS · (persona física) · HELMSTONE · IAMCFORWARDER · PLAN CREDI · Público en General · REGIOTURK · SERVICIOS COMPARTIDOS TSM · SERVICIOS LOGISTICOS DYLO · TRANSPORTES LOGISTICOS ESPECIALIZADOS · TRASLADOS Y LOGISTICA ESPECIALIZADA · VictTec LLC.
⭐ **Las 17 categorías de servicio de Pedro, confirmadas** en `Servicio/Producto`: Consultoría y Administración Corporativa · Servicios Profesionales Generales · Gestión de Proyectos Senior / PMO · Gestión de Mesa de Servicio (SDM) · Soporte Especializado L1 · Soporte Especializado L2 · Gestión de Incidentes · Gestión de Cambios · Gestión de Capacidad · Mesa de Ayuda / Service Desk · Desarrollo de Software · Reclutamiento (Headhunting) · Servicio de Enlace · Horas Extraordinarias · Viáticos · Licencias y Software · Liquidaciones y Finiquitos.
### Pendientes que deja el formulario
- 🔴 **`Empresa origen` tiene 3 valores: Balam, RegioTurk y Helmstone.** ¿La cotización se emite siempre en la misma cuenta de BIND, o hay una por empresa? El token actual es uno solo. **Preguntarlo mañana.**
- 🔴 **`IVA` solo ofrece `16%`.** No hay `0%` — y hay clientes de exportación en el combo (ACUNTIA S.A.U., VictTec LLC, IAMCFORWARDER). El Discovery registró **IVA 16%/0%**. Además, en BIND existe al menos una cotización real con `VAT = 0` pese a `VATRate = 0.16`. **Falta la opción 0%.**
- ⚠️ **Sobrevive `Nombre del cliente` (`customfield_11596`, texto libre)** además del combo `11598`. Dos campos de cliente en el mismo sitio: hay que fijar por escrito que **manda el combo**.
- ⚠️ **`customfield_10202`, el campo de cliente que la plataforma leía, ya no aplica.** Era la causa de que el 12-ago *"el cliente no se detectó"*. **Corregido** en `appsettings.Development.json` → `customfield_11598`.
---
## 2 · El catálogo de BIND está peor de lo que se vio en la sesión
`GET /api/Services` devuelve **67 servicios**; `GET /api/Products`, **3 productos**. Buscando el que trae el ticket:
**"SERVICIO DE ENLACE" existe 5 veces**, con IDs distintos y **atributos fiscales que no coinciden entre sí**:
| Code | Unit | SATUnit | ChargeVAT |
|---|---|---|---|
| `81111500` | *(vacío)* | 3984 | **true** |
| `Código - 00000` | E48 | 4376 | false |
| `Código - 00000` | E48 | 4376 | false |
| `Código - 00000` | Servicio | 4376 | false |
| `027` | E48 | 3984 | false |
> 🔴 **Riesgo directo para mañana:** el combo de Jira manda **una etiqueta**, "Servicio de Enlace", y en BIND hay **cinco filas** que difieren en unidad, unidad SAT e incluso en si cobran IVA. **La correspondencia etiqueta → ítem de BIND es ambigua y nadie la ha definido.** Es la segunda mitad de la depuración que Araceli pidió el 12-ago: se depuró el combo de Jira, **falta depurar BIND y fijar el mapeo**.
---
## 3 · Los tres errores que explican el 500 del 12-ago
Verificado leyendo **4 cotizaciones reales** de BIND (folios 1001, 1005, 1012, 1021):
1. 🔴 **`VATRate` va como fracción, no como porcentaje.** Todas las cotizaciones reales traen **`VATRate = 0.16`**. Mandar `16` es un factor de 100 de diferencia.
2. 🔴 **`VAT` de partida es un MONTO, no una tasa.** Comprobado en 3 de 4: `Price × Qty × 0.16 = VAT` (p. ej. 32,422.04 → 5,187.5264). El endpoint **pasa el valor tal cual**, así que quien llame tiene que calcularlo. Para FAC-106: 1234 × 1 × 0.16 = **197.44**.
3. 🟠 **`PriceListID`: cada cotización real usa una lista distinta** (`041d4514…`, `0c4bb05e…`, `0dfbe083…`, `1087dac9…`) y **ninguna coincide** con la única que devuelve `GET /api/PriceLists` (`03e4bb2d…`, "A"). Mandar la lista equivocada es candidato serio al 500. **Recomendación: omitirlo** y dejar que BIND aplique su default — el cliente ya omite los nulos.
Además, sin confirmar:
- ⚠️ **`ID` de partida.** El read model distingue `ID` (renglón) de `ProductID` (ítem del catálogo); el write model **solo tiene `ID`**. Mandar el GUID del servicio en `ID` puede ser justo lo que BIND rechaza. El body de abajo **omite `ID`** y manda la partida como texto con `Title`/`Unit` — que además es como Araceli captura.
- ⚠️ `Type` y `SelectedUnit` siguen sin documentar; van omitidos.
---
## 4 · Body listo para mañana (dry-run ejecutado, operación #18)
IDs resueltos contra BIND en vivo: **MXN** `b7e2c065-bd52-40ca-b508-3accdd538860` · **Matriz** `65ee189a-a163-4f23-8466-87627a5ba776` (única ubicación) · **CEMEX** `6f17c5bd-e7a0-4152-9702-4a486c1b7c69` (RFC `CEM880726UZA`, 90 días de crédito).
```json
{
"LocationID": "65ee189a-a163-4f23-8466-87627a5ba776",
"CurrencyID": "b7e2c065-bd52-40ca-b508-3accdd538860",
"ExchangeRate": 1.0,
"Items": [
{ "Title": "SERVICIO DE ENLACE", "Unit": "E48", "Price": 1234.0,
"Qty": 1.0, "VAT": 197.44, "IEPS": 0, "IndexNumber": 1 }
],
"ClientProspect": {
"isNew": false,
"Client": { "ClientId": "6f17c5bd-…", "ClientName": "CEMEX" }
},
"VATRate": 0.16,
"Comments": "Generada desde el ticket FAC-106 (prueba acompañada)."
}
```
**Si BIND vuelve a rechazar**, el orden de ataque es: (1) agregar `PriceListID` con el de una cotización reciente del mismo cliente; (2) mandar el GUID del servicio en `ID`; (3) probar `Type`. El endpoint ya expone `ex.Body` de BIND en el 502, así que el diagnóstico se lee en pantalla — no se repite el 500 ciego del 12-ago.
---
## 5 · ⚠️ Seguridad: `Bind:Mode` está en **Write** ahora mismo
`GET /api/emision/estado` responde `{"modo":"Write"}` — el candado de ADR-001 está **abierto** fuera de la sesión acompañada, contra lo que se le prometió a Noé ([REGISTRO #31a](../bitacora/REGISTRO.md)). Una confirmación accidental escribiría en producción. **Regresarlo a `ReadOnly`** y encenderlo solo durante la sesión:
```bash
dotnet user-secrets set "Bind:Mode" "ReadOnly" --project src/Balam.Api
```
---
## 6 · Lo que falta cablear (no bloquea la prueba manual)
El dry-run de arriba se armó **a mano** con los datos de `FAC-106`. Para que la pantalla lo arme sola faltan cuatro campos en la configuración y en el DTO de detalle: `Servicio/Producto` (11599), `Cantidad` (11600), `IVA` (11601) y `Fecha de vencimiento` (11597). Con eso el wizard prellena la partida completa desde el ticket.