--- id: CASE-2026-05-29-tienda-vacia-formulario-sitio-web fecha: 2026-05-29 categoria: custom_field | cascada_n8n | config_location location_ids: ["GbKkBpCmKu2QmloKFHy3 (Marca)", "rQYjjwsGnjEGagskOxix (85930 TULYEHUALCO)", "nRSeOhlhQ3vyirTKYhPi (85961 VILLAS DEL SOL)", "blRZ21GlzgUCA7bl2uVw (85975 Querétaro)", "R34lUVVpltnB8Z1RqnEB (85971 Satélite)", "uZnMH5bO6MXTHcgHeyq9 (85935 Pilares)"] run_ids: ["26217ad9-934f-40d5-af69-bd0cbb5c02e4 (backfill TIENDA)", "bb27026c-1d99-458d-be1d-d34b7498b1a4 (delete Guco)"] snapshots: [] status: parcial memorias: [[tienda_gap_formulario_sitio_web]], [[baserow_api_y_corrector]], [[sucursal_to_marca_cf_drop_on_create]], [[name_account_with_location_id]] playbooks: [docs/PLAYBOOK_DESCUADRE.md] --- ## TRIGGERS - `TIENDA vacía`, `campo TIENDA empty`, `lead sin tienda`, `Formulario - Sitio Web TIENDA` - `Baserow 750 más de un resultado`, `Si hay más de un resultado`, `SUCURSAL contains ambiguo` - `Toluca Estado de México 3 filas`, `Metepec 3 filas`, `750 filas duplicadas SUCURSAL` - `createdBy INTEGRATION OAUTH`, `source Formulario - Sitio Web`, `CANAL DE ORIGEN FORMULARIO` - contactos: `Juan Carlos espiritu`, `Adrian Garza`, `Gerardo Juárez`, `Luis Fernando mejía`, `Jesús Niño`, `Jorge Erick hernandez`, `Miguel Velasquez`, `Jorge Enrique ibarra`, `Guco Aseram` ## SÍNTOMA Export de Marca: 9 leads `source="Formulario - Sitio Web"` con campo **TIENDA vacío**. Hipótesis inicial del owner: "creados antes de la optimización n8n". FALSA (ver causa). ## DIAGNÓSTICO (read-only) 1. GET live (no cache) de los 9 en Marca → TIENDA vacía confirmada; 8 traen `ID Contacto Sucursal`. 2. Ubicación de la sucursal por `ID Contacto Sucursal` (tabla `contacts` cache) + GET live → **TIENDA vacía TAMBIÉN en la sucursal** (no es gap de replicación; nunca se asignó en origen). 3. `createdBy.source=INTEGRATION` / `Formulario - Sitio Web` → ni [2004] ni `fix_branch_user_origin.py` los cubren (esos = WEB_USER/MOBILE_USER). 4. Conteo global: de **175** contactos `Formulario - Sitio Web`, solo **16 (9%)** con TIENDA vacía = estos 8 × 2 (Marca+sucursal). El 91% sí la tiene → NO sistémico por source. 5. TIENDA canónica por sucursal (consenso 85-119 contactos): se deriva del **branch físico**, no del texto `Sucursal`. (`object_schemas` + `contacts.custom_fields_json`.) 6. Workflow Marca→Sucursal V2 `4UMRwxJdHFfOGHBp` (webhook formulario): nodo Baserow `Obtener Info de cuenta objetivo - SUCURSAL` filtra **tabla 750, field 7240 (SUCURSAL), operador `contains` = `$json.Contacto.Sucursal`**, y hay IF **`Si hay más de un resultado`**. 7. Test directo Baserow 750 (`baserow_client.BaserowClient.from_credentials`, `list_rows(750)`): - `Toluca, Estado de México` → **3 filas** (SC `85935 - MP - Pilares`, TIENDA GRAND PLAZA / ISIDRO FABELA / INDEPENDENCIA). - `Metepec, Estado de México` → **3 filas** (Pilares/PILARES + 2× METEPEC/METEPEC dup). - Tulyehualco / Playa del Carmen / Querétaro / Satélite → **1 fila** (resuelven bien). ## CAUSA RAÍZ (doble) 1. **Determinística (Luis Fernando=Toluca, Jorge Enrique=Metepec):** Baserow 750 tiene filas **ambiguas/duplicadas** donde el mismo `SUCURSAL` mapea a múltiples TIENDA → el filtro `contains` devuelve >1 → IF `Si hay más de un resultado` → el flujo no asigna TIENDA. **Recurrirá** en todo lead Toluca/Metepec hasta limpiar 750. 2. **Transitoria (los otros 6, match único en 750):** debían resolver; TIENDA vacía = fallo puntual de ejecución. Confirmación 100% requeriría logs n8n del momento (probablemente no retenidos). - **DESCARTADO:** "pre-optimización" (7 de 8 son 2026-05-29, post-fix 05-28) y "name-mismatch de esquema". ## ACCIÓN 1. Backfill TIENDA (sucursal + Marca), valor = TIENDA canónica del branch físico, `run_id=26217ad9-934f-40d5-af69-bd0cbb5c02e4`: TULYEHUALCO (Juan Carlos, Jorge Erick), VILLAS DEL SOL (Adrian), QUERETARO (Gerardo, Miguel), SATELITE (Jesús), PILARES (Luis Fernando, Jorge Enrique). 16 PUTs, piloto Juan Carlos → verificado → lote. - Nota: a Luis Fernando/Jorge Enrique se les puso **PILARES** (consenso de su branch real), que es más correcto que las filas rotas de Baserow. 2. Delete contacto huérfano **Guco Aseram** `HEb1qBGilEReVITtq0GZ` (Marca; sucursal Villahermosa ya no existe, sin contraparte). `run_id=bb27026c-1d99-458d-be1d-d34b7498b1a4`. DELETE → `succeeded:true`; GET posterior → HTTP 400 (gone). ## VERIFICACIÓN - Backfill: GET live de los 16 → TIENDA = valor esperado (16/16 OK). - Delete: GET `/contacts/HEb1qBGilEReVITtq0GZ` → HTTP 400. - Pendiente re-sync de las 5 sucursales + Marca para que la cache refleje (la verdad viva ya es correcta). ## EDGE-CASES / TRAMPAS - TIENDA se deriva del **branch físico**, NO del texto libre `Sucursal` (Luis Fernando: Sucursal="Toluca" pero branch=Pilares → TIENDA=PILARES). - Verificar SIEMPRE en vivo: la cache puede no reflejar asignaciones recientes. - Baserow 750: el filtro del workflow es `contains` sobre `SUCURSAL` (field 7240), distinto del match por `SC BUCEFALO` (7247) que usa el corrector. Las filas ambiguas rompen este path aunque el corrector de nombres esté OK. ## REUTILIZABLE ```python # Test de ambigüedad Baserow 750 por SUCURSAL (lo que ve el workflow) from scripts.baserow_client import BaserowClient c=BaserowClient.from_credentials(); rows=c.list_rows(750) hits=[r for r in rows if r.get('SUCURSAL') and 'Toluca, Estado de México'.lower() in str(r['SUCURSAL']).lower()] # >1 hit => el lead de esa Sucursal NO recibirá TIENDA ``` ```python # TIENDA canónica de un branch (consenso de sus contactos) from collections import Counter; import json # parse contacts.custom_fields_json, contar valores del field_id de TIENDA del branch ``` ## PENDIENTES - **Limpiar Baserow 750:** deduplicar / desambiguar filas con mismo `SUCURSAL` y distinta TIENDA (Toluca→3, Metepec→3). Mientras existan, los leads Toluca/Metepec seguirán sin TIENDA. Evaluar extender el corrector (`fix_baserow_verificador.py`) o añadir desambiguación en el workflow (`Si hay más de un resultado`). - **6 casos transitorios:** si recurren, revisar ejecuciones de `4UMRwxJdHFfOGHBp` en la ventana de creación. - **Sucursal text de Luis Fernando** ("Toluca") inconsistente con su branch (Pilares/Metepec). No tocado; reportado. - Re-sync de las 5 sucursales + Marca. ## ENLACES - Memorias: [[tienda_gap_formulario_sitio_web]], [[baserow_api_y_corrector]], [[sucursal_to_marca_cf_drop_on_create]] - Workflow: `4UMRwxJdHFfOGHBp` (Marca→Sucursal V2); helper `scripts/n8n_workflow_lib.py`, `scripts/baserow_client.py` - Caso relacionado: [2026-05-29-corrector-baserow-verificador.md](2026-05-29-corrector-baserow-verificador.md)