5.6 KiB
5.6 KiB
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 fieldsSincronización Sucursal(source) + tagsincronizado-sucursalcon CFs vacíosCristhian laura ramirez juarez,Hugo Lopez,Temixco,+527772582548,+527772162523nombres de custom field idénticos entre sucursal y Marca(descarta name-mismatch)Export_Contacts_leadsCSV 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)
mcp get_contact(cache) Marca →custom_fields: []. Cache SQLite consynced_atANTERIOR a la creación → stale, no concluir aún (positive_descuadre_stale_cache).search_contactspor fragmento de teléfono en sucursales de Morelos (777 = Cuernavaca) → ambos en Temixco (yjqKxoO02rsdwdJZSPmD) con 6-8 CFs completos.- 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). - 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).
- Marca (ambos):
- 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
- 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.
- NO es divergencia de nombres de esquema (verificado idénticos).
- 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_atpuede 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(novalue) 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
# 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
x4DqZ5FtSc43tdzBen 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'ycustomFields=0para 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; helperscripts/n8n_workflow_lib.py - Caso relacionado: 2026-05-29-n8n-2004-canal-origen-tiempo-real.md