79 lines
5.6 KiB
Markdown
79 lines
5.6 KiB
Markdown
---
|
|
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)
|