---
id: CASE-2026-05-29-backfill-cf-vehiculo-temixco-marca
fecha: 2026-05-29
categoria: custom_field | cascada_n8n
location_ids: ["GbKkBpCmKu2QmloKFHy3 (Monte Providencia / Marca)", "yjqKxoO02rsdwdJZSPmD (85950 - MP - Temixco)"]
run_ids: ["4b26f163-f87c-48c5-be53-462b2e6f53da"]
snapshots: []
status: parcial
memorias: [[sucursal_to_marca_cf_drop_on_create]], [[positive_descuadre_stale_cache]], [[n8n_realtime_replication]]
playbooks: [docs/PLAYBOOK_DESCUADRE.md]
---

## TRIGGERS
- `contacto en Marca sin datos de vehículo`, `customFields count: 0 en Marca`, `réplica Sucursal→Marca sin custom fields`
- `Sincronización Sucursal` (source) + tag `sincronizado-sucursal` con CFs vacíos
- `Cristhian laura ramirez juarez`, `Hugo Lopez`, `Temixco`, `+527772582548`, `+527772162523`
- `nombres de custom field idénticos entre sucursal y Marca` (descarta name-mismatch)
- `Export_Contacts_leads` CSV con columnas de vehículo vacías

## SÍNTOMA
CSV export de Marca: 2 leads de Temixco (`Cristhian` `U9DWipeW9XhQTZZMzFl9`, `Hugo` `bUNqMZaLI1QCn4yQM6qT`)
llegaron a Marca **sin** Versión/Marca/Año de vehículo, Modalidad, Fuente, Sucursal. Edgar (Tampico) sí llegó completo.

## DIAGNÓSTICO (read-only)
1. `mcp get_contact` (cache) Marca → `custom_fields: []`. Cache SQLite con `synced_at` ANTERIOR a la creación → stale, no concluir aún ([[positive_descuadre_stale_cache]]).
2. `search_contacts` por fragmento de teléfono en sucursales de Morelos (777 = Cuernavaca) → ambos en **Temixco** (`yjqKxoO02rsdwdJZSPmD`) con 6-8 CFs completos.
3. Comparación de nombres de contact CFs Temixco vs Marca vs Tampico (tabla `object_schemas`): **idénticos**. → **DESCARTA** la hipótesis de name-mismatch del workflow [1604] (el análisis estático del jsCode sugería divergencia de nombres; es FALSO).
4. GET en VIVO (no cache) de los 4 contactos vía `ghl_client._request('GET', f'/contacts/{id}', token)`:
   - Marca (ambos): `customFields=0`, `dateAdded == dateUpdated` (nunca actualizados).
   - Temixco (ambos): 8 CFs; `dateUpdated` ~4h después de creación (= workflow [2004] que añadió CANAL DE ORIGEN + TIENDA).
5. Ejecuciones n8n del workflow Sucursal→Marca (`x4DqZ5FtSc43tdzB`) consultadas, pero el set reciente no cubre la ventana de creación real (2026-05-29 ~22:40/22:48 **UTC**); no se obtuvo el log del momento exacto.

## CAUSA RAÍZ
1. **Confirmada:** la réplica Sucursal→Marca creó el contacto en Marca (39-40 s después del de sucursal) **sin copiar ningún custom field**, y no hubo UPDATE posterior.
2. **NO es** divergencia de nombres de esquema (verificado idénticos).
3. **Probable (confianza media):** carrera de tiempo — el flujo leyó el contacto origen antes de que los CFs del formulario estuvieran disponibles. Es intermitente (Edgar/Tampico sí funcionó por el mismo path). Confirmación pendiente requiere log de ejecución n8n del momento de creación.

## ACCIÓN
Backfill manual de 8 CFs Temixco→Marca (mapeo por nombre → `object_schemas` de Marca), confirmado por el owner.
- `run_id=4b26f163-f87c-48c5-be53-462b2e6f53da` (script_audit, reversible). Script inline (no archivo).
- Patrón: `gc._request('PUT', f'/contacts/{cid}', mtok, json={'customFields':[{'id':marca_field_id,'field_value':val}, ...]})`.
- Orden: piloto Cristhian → verificación live (8 CFs) → Hugo.

## VERIFICACIÓN
Antes: ambos Marca `customFields=0`. Después (GET live): ambos `customFields=8` con valores correctos
(Año 2026/2011, Marca ITALIKA/mercedes benz, Versión DM 200/c280, Modalidad Tradicional (Resguardo),
Fuente SUCURSAL/PROSPECCIÓN, Sucursal "Temixco, Morelos", CANAL DE ORIGEN SUCURSAL, TIENDA TEMIXCO).

## EDGE-CASES / TRAMPAS
- **No confiar en la cache SQLite** para concluir CFs vacíos: `synced_at` puede ser anterior a la creación del contacto. Verificar SIEMPRE en vivo antes de backfillear.
- El análisis estático del jsCode del workflow puede mentir: dio "name-mismatch" como causa, falso. Verificar nombres reales en `object_schemas`.
- PUT contacto usa clave `field_value` (no `value`) y mergea CFs (no reemplaza).
- Edgar (Tampico) se omitió a pedido del owner: ya tenía datos completos (control de que el path SÍ funciona a veces).

## REUTILIZABLE
```python
# Nombre de CF -> field_id de una location (tabla object_schemas)
import sqlite3, paths
conn=sqlite3.connect(paths.DB_PATH); conn.row_factory=sqlite3.Row
nameid={}
for r in conn.execute("SELECT field_id,field_name FROM object_schemas WHERE location_id=? AND object_key='contact'",(loc,)):
    nameid.setdefault(r['field_name'], r['field_id'])
# GET live + PUT CFs
import sync_engine; from sync_engine import ghl_client as gc
tok={a['location_id']:a for a in sync_engine.parse_accounts_csv()}[loc]['token']
gc._request('PUT', f'/contacts/{cid}', tok, json={'customFields':[{'id':fid,'field_value':v}]})
```

## PENDIENTES
- **Causa raíz n8n al 100%:** revisar ejecuciones de `x4DqZ5FtSc43tdzB` en la ventana 2026-05-29 ~22:40/22:48 UTC
  (paginar más atrás con `/api/v1/executions?workflowId=...&includeData=true`) para confirmar carrera vs gap de lógica.
- **Sistémico:** si es carrera, hay riesgo de más contactos Temixco (u otras sucursales) con CFs vacíos en Marca.
  Considerar un audit que liste contactos Marca con `source='Sincronización Sucursal'` y `customFields=0` para barrido masivo.

## ENLACES
- Memorias: [[sucursal_to_marca_cf_drop_on_create]], [[positive_descuadre_stale_cache]], [[n8n_realtime_replication]], [[n8n_2004_canal_origen_complemento]]
- Workflow Sucursal→Marca: `x4DqZ5FtSc43tdzB`; helper `scripts/n8n_workflow_lib.py`
- Caso relacionado: [2026-05-29-n8n-2004-canal-origen-tiempo-real.md](2026-05-29-n8n-2004-canal-origen-tiempo-real.md)
