diff --git a/docs/casos/2026-05-30-comparativa-auditoria-completa-buckets.md b/docs/casos/2026-05-30-comparativa-auditoria-completa-buckets.md
index 23dcbef..c03072e 100644
--- a/docs/casos/2026-05-30-comparativa-auditoria-completa-buckets.md
+++ b/docs/casos/2026-05-30-comparativa-auditoria-completa-buckets.md
@@ -89,9 +89,15 @@ python -c "import sync_engine as se; a=next(x for x in se.parse_accounts_csv() i
- Descomponer cualquier bucket grande por (expected_branch → actual_branch) con Counter antes de concluir "error de datos": muchas veces es mapeo del Verificador, no datos.
- `cleanup_brand_duplicate_replica_opps.py --only-link ` es el camino seguro para el descuadre positivo de opps por doble réplica (verifica en vivo + snapshot + script_audit).
+## ACCIÓN (3ª tanda — reasignación opp por homónimos)
+Al ir a "crear la opp de miguel en Temixco" se descubrió que **NO procedía**: el lead digital $80,200 es de OTRO "Miguel Angel" (Eugenia `+525530454950`, contacto Marca `hE9U9Q`), distinto del Miguel-Temixco (`+527775114949`, contacto `RwxMQr0`). Ese lead ya estaba replicado (Eugenia `kGda02`↔Marca `1A3P5b`), pero `1A3P5b` colgaba del contacto EQUIVOCADO (`RwxMQr0`) porque la réplica n8n matcheó por nombre. `hE9U9Q` (su dueño real) tenía 0 opps.
+- **Fix:** `PUT /opportunities/1A3P5b` con `contactId=hE9U9Q` (+ name/pipeline/stage/mv). **GHL v2 SÍ acepta cambiar contactId vía PUT** (status 200) — el gotcha de `build_brand_opp_payload` no aplicó. run_id `reassign-miguel-opp-20260530`, snapshot `reassign_miguel_opp_20260530_155526.json`. Verificado: RwxMQr0 solo $56,671, hE9U9Q solo $80,200.
+
## PENDIENTES
-- **test21** (fantasma de índice): GET 400 / search 200. No accionable; se auto-corrige cuando GHL reconcilie el índice. Sigue en `without_tienda` + `not_in_any_branch`.
-- **Lead digital de miguel** (opp Marca 1A3P5b $80,200, sin link): es un lead digital creado directo en Marca que nunca bajó a su sucursal (Temixco). Idealmente lo baja la cascada n8n Marca→Sucursal. Queda solo-Marca; el conteo cuadra igual. Revisar si ese lead digital es válido y debe cascar.
+- **test21** (fantasma de índice): GET 400 / search 200. No accionable; se auto-corrige cuando GHL reconcilie el índice.
+- **Causa raíz n8n homónimos**: la réplica Sucursal→Marca debe matchear por teléfono/`id_contacto_sucursal` antes que por nombre (si no, vuelve a colgar opps de homónimos en el contacto equivocado). Ver [[matching_rules]], [[n8n_workflows_v2_hardened]].
+- ~~Leads digitales nuevos~~ **RESUELTO**: `David Arturo Vega` (Satélite) y `PER,LA MARIA VILLA` (La Viga) aparecieron ~15:56 (actividad viva) como descuadre +2. NO eran leads sin cascar: sus contactos+opps YA estaban en sucursal; el +2 eran **réplicas duplicadas en Marca sin link** (mismo patrón isai/Patricia, pero sin link compartido → caían en `missing_id_field`, no `duplicate_link`). Fix: (1) TIENDA llenada (`leads-tienda-20260530`); (2) borradas las 2 duplicadas sin link `LJPKIsd`+`OyRtrlGb`, conservadas las enlazadas `Mt9Dafz3`+`aZf3pzuc` (run_id `delete-dup-leads-opps-20260530`, snapshot `delete_dup_leads_opps_20260530_160744.json`). → opps 1342=1342, diff 0.
+- Patrón a vigilar: el n8n de opps sigue generando réplicas duplicadas en Marca (Patricia, isai, PER,LA, David — 4 en un día). Unas con link compartido, otras sin link. La causa raíz (idempotencia) está en [[n8n_opp_idempotency_baserow_mapping]]; revisar por qué siguen apareciendo.
## ENLACES
- Memorias: [[positive_opp_descuadre_double_replica]], [[verificador_tipo_de_tienda_colapso]], [[positive_descuadre_stale_cache]], [[name_account_with_location_id]], [[audit_hub_map_metepec_pilares]]
diff --git a/docs/casos/2026-05-30-incoherencia-canal-fuente-lead-digital.md b/docs/casos/2026-05-30-incoherencia-canal-fuente-lead-digital.md
new file mode 100644
index 0000000..302eefa
--- /dev/null
+++ b/docs/casos/2026-05-30-incoherencia-canal-fuente-lead-digital.md
@@ -0,0 +1,94 @@
+---
+id: CASE-2026-05-30-incoherencia-canal-fuente-lead-digital
+fecha: 2026-05-30
+categoria: custom_field, cascada_n8n, descuadre
+location_ids: [GbKkBpCmKu2QmloKFHy3 (Monte Providencia/Marca), KEZ7dAhgwzK4uZfMvZuj (Puebla), uJEn2iuUficuml9zxAnt (Cancún), uZnMH5bO6MXTHcgHeyq9 (Pilares), nF1uEaYB3mCK5em9bPn2 (Eugenia), jE41bVhhnb5T505BFm4F (Morelia 1), WCHyow6KpjLFYriQWdbJ (Tampico)]
+run_ids: [origen-fuente-3c50e43ec6a9, "n8n ddUEORBEtZLzsQF2 versionId 11c7184b→e8f6f33f (Patrón A)→37f780e1 (Patrón B)"]
+snapshots: [n8n/backup_fuente_reconcile_ddUEORBEtZLzsQF2_20260530_190108.json, n8n/backup_redes_sociales_ddUEORBEtZLzsQF2_20260530_192343.json]
+status: resuelto
+memorias: [[incoherencia_canal_fuente_lead_digital]], [[super_script_fix_branch_user_origin]], [[n8n_2004_canal_origen_complemento]], [[createdby_only_in_individual_get]]
+playbooks: []
+---
+
+## TRIGGERS
+- `LEAD DIGITAL no cuadra con FORMULARIO + FACEBOOK`, `Recuento de Contactos por CANAL DE ORIGEN vs Fuente de prospecto`
+- `929 vs 901`, `descuadre 28 LEAD DIGITAL`, `Canal=SUCURSAL pero Fuente=LEAD DIGITAL`, viola AGENTS Cap.3
+- `REDES SOCIALES` fuente de prospecto (valor no canónico), Tampico 7 contactos
+- `fix_branch_user_origin.py NO toca Fuente de Prospecto`, n8n `[2004]` pone Canal=SUCURSAL a WEB_USER sin reconciliar Fuente
+- `createdBy.source WEB_USER MOBILE_USER` = captura manual sucursal; `source` de Marca (Formulario/Sucursal) lo estampa la replicación n8n y NO es fiable
+- scripts: `audit_origen_fuente_incoherencia.py`, `fix_origen_fuente_incoherencia.py`
+
+## SÍNTOMA
+Panel de Marca (GbKkBpCmKu2QmloKFHy3, 1328 contactos). Dos widgets descuadran:
+- `Recuento por CANAL DE ORIGEN`: FORMULARIO 612, SUCURSAL 426, FACEBOOK 289 (digital = 901).
+- `Fuente de prospecto`: LEAD DIGITAL 929, SUCURSAL 374, PROSPECCIÓN 11, REDES SOCIALES 7, CLIENTE CONOCIDO 3, ALIANZA 2, GALLARDETES 1.
+Regla: LEAD DIGITAL debería = FORMULARIO + FACEBOOK. 929 ≠ 901 → descuadre +28. Además REDES SOCIALES sospechoso (canal digital mal clasificado).
+
+## DIAGNÓSTICO
+Cross-tab Canal × Fuente desde la cache (`generated/data/mp_manager.sqlite`, `contacts.custom_fields_json` + `object_schemas`):
+- FUENTE=LEAD DIGITAL (929) → 612 FORMULARIO + 289 FACEBOOK + **28 SUCURSAL** ← el descuadre.
+- FUENTE=REDES SOCIALES (7) → 7 canal=SUCURSAL.
+- PROSPECCIÓN/CLIENTE CONOCIDO/ALIANZA/GALLARDETES → todos canal=SUCURSAL (OK, fuentes de prospección manual válidas).
+
+Global (todas las cuentas): los 28 incoherentes de Marca = 16 Puebla + 4 Cancún + 3 Pilares + 3 Eugenia + 2 Morelia (suma 28 → replica 1:1 a Marca). Los 7 REDES SOCIALES = todos Tampico. **La incoherencia nace en sucursal, no es artefacto de replicación.**
+
+Callejón descartado: el `source` de los contactos en Marca decía 19 "Sucursal" / 9 "Formulario", sugiriendo partir los 28 en dos. PERO el `source` del lado **sucursal** era 26 null + 2 Formulario (no coincide). Verificación en vivo con `createdBy.source` (GET individual, `audit_origen_fuente_incoherencia.py --all`): **los 28 son WEB_USER/MOBILE_USER** (captura manual sucursal), incluidos los 9 que en Marca figuraban "Formulario". El `source` de Marca lo estampa la replicación n8n y NO es fiable; `createdBy.source` es el gold standard.
+
+## CAUSA RAÍZ
+1. Workflow n8n `[2004]` (ddUEORBEtZLzsQF2) y su gemelo Python `fix_branch_user_origin.py` ponen `Canal de Origen=SUCURSAL` a los contactos creados por empleado (WEB_USER/MOBILE_USER) **pero deliberadamente NO tocan "Fuente de Prospecto"** ([fix_branch_user_origin.py:27-29,234](../../scripts/fix_branch_user_origin.py#L234)) para no pisar ALIANZA/PROSPECCIÓN. Efecto colateral: cuando voltean canal a SUCURSAL dejan el `LEAD DIGITAL` viejo huérfano → los 28 (Patrón A).
+2. En Tampico se usó el valor no canónico `REDES SOCIALES` como Fuente de Prospecto en 7 contactos digitales (social), que quedaron con canal=SUCURSAL (Patrón B).
+
+## ACCIÓN
+Decisión del usuario (2 rondas AskUserQuestion): Patrón A → todos a SUCURSAL (createdBy manda sobre source de Marca); Patrón B → FACEBOOK + LEAD DIGITAL.
+
+Script nuevo `scripts/fix_origen_fuente_incoherencia.py` (idempotente, detecta por estado actual, dry-run default, `script_audit` reversible, resuelve field ids por FIELD_ALIASES). Plan por patrón:
+- A: contacto Fuente→SUCURSAL; opps: Canal de Origen de la Oportunidad→Sucursal, Fuente→SUCURSAL.
+- B: contacto Canal→FACEBOOK + Fuente→LEAD DIGITAL; opps: Canal Opp→Facebook, Tipo de Lead→Lead digital, Fuente→LEAD DIGITAL.
+
+Secuencia (RUN_ID `origen-fuente-3c50e43ec6a9`):
+```
+# dry-run (las 7 cuentas) -> A=28, B=7, 35 opps
+# piloto Tampico (Patrón B)
+python scripts/fix_origen_fuente_incoherencia.py --location WCHyow6KpjLFYriQWdbJ --apply --run-id origen-fuente-3c50e43ec6a9
+# verificación live 7/7 OK -> batch resto:
+for LOC in GbKkBpCmKu2QmloKFHy3 KEZ7dAhgwzK4uZfMvZuj uJEn2iuUficuml9zxAnt uZnMH5bO6MXTHcgHeyq9 nF1uEaYB3mCK5em9bPn2 jE41bVhhnb5T505BFm4F; do
+ python scripts/fix_origen_fuente_incoherencia.py --location $LOC --apply --run-id origen-fuente-3c50e43ec6a9; done
+```
+Marca en el batch reportó B=1 (no 7): los otros 6 REDES SOCIALES de Marca ya se habían corregido solos por replicación n8n desde Tampico. 0 errores en todas.
+
+## VERIFICACIÓN
+Cross-tab **en vivo** en Marca (re-GET de 1328+ contactos vía API, no cache):
+- LEAD DIGITAL = 908 = FORMULARIO 612 + FACEBOOK 296 → **COHERENTE** (antes 929 vs 901).
+- canal=SUCURSAL & fuente=LEAD DIGITAL: **0** (antes 28).
+- REDES SOCIALES: **0** (antes 7).
+- Canal SUCURSAL 419 (antes 426; −7 que pasaron a FACEBOOK).
+Piloto Tampico verificado 7/7 (canal=FACEBOOK, fuente=LEAD DIGITAL sostenido; n8n [2004] no revirtió en el momento).
+
+## EDGE-CASES / TRAMPAS
+- **NO confiar en `contact.source` de Marca** para clasificar origen: la replicación n8n lo estampa (Formulario/Sucursal) y diverge del lado sucursal. Usar `createdBy.source` en vivo (GET individual).
+- Tampico tiene los campos con capitalización distinta (`CANAL DE ORIGEN`): resolver field ids **case-insensitive** / por FIELD_ALIASES, nunca por nombre exacto.
+- Falso positivo en verificación: match difuso de nombre ("edgar") atrapó "edgar alejandro pozos" y "edgard radiadores" (PROSPECCIÓN/SUCURSAL, no eran target). Filtrar por id, no por substring de nombre.
+- Riesgo de reversión del Patrón B: los 7 de Tampico son WEB_USER y n8n [2004] re-pone canal=SUCURSAL a WEB_USER. Si se re-editan, podrían revertir. Pendiente endurecer [2004].
+
+## REUTILIZABLE
+- `python scripts/audit_origen_fuente_incoherencia.py --all` → clasifica incoherentes con createdBy en vivo (read-only).
+- `python scripts/fix_origen_fuente_incoherencia.py --all` (dry-run) / `--apply --run-id ` → corrige + propaga a opps. Idempotente: re-correr no re-toca.
+- Rollback: dashboard → run `origen-fuente-3c50e43ec6a9`.
+
+## CAUSA RAÍZ — CIERRE EN TIEMPO REAL (2026-05-30)
+Endurecido el workflow n8n **[2004]** (ddUEORBEtZLzsQF2) con `n8n/_add_fuente_reconcile.py` (backup→dry-run→apply→verify→E2E). En la rama "Creado por usuario" (esUsuario=true), tras `Tag- facebook-ads` se añadió: IF `fuenteEsLeadDigital` → PUT Fuente de Prospecto=SUCURSAL. El Code node se extendió para resolver el field `contact.fuente_de_prospecto` y leer su VALOR ACTUAL del GET del contacto (`contact.customFields[].value`), exponiendo `fuente`/`fuenteActual`/`fuenteEsLeadDigital`. Solo reconcilia si vale exactamente LEAD DIGITAL → preserva ALIANZA/PROSPECCIÓN/etc. versionId `11c7184b`→`e8f6f33f`, 19→21 nodos. Backup `n8n/backup_fuente_reconcile_ddUEORBEtZLzsQF2_20260530_190108.json`.
+
+**E2E en vivo (Cancún, esau sotelo do3ClHt57hfHj0hw4tKk, WEB_USER):** (1) ensuciado FORMULARIO/LEAD DIGITAL → webhook 8d574598 → **SUCURSAL/SUCURSAL** ✓. (2) ensuciado FORMULARIO/PROSPECCIÓN → webhook → **SUCURSAL/PROSPECCIÓN intacta** ✓ (preservación). Contacto restaurado a su estado real SUCURSAL/SUCURSAL.
+
+## CAUSA RAÍZ PATRÓN B — CIERRE EN TIEMPO REAL (2026-05-30)
+Cerrado con `n8n/_add_redes_sociales_branch.py`. En la rama esUsuario, ANTES del PUT canal=SUCURSAL, se intercaló IF "Fuente es REDES SOCIALES": [true]→PUT Canal=FACEBOOK→PUT Fuente=LEAD DIGITAL (camino digital, igual que el fix de datos Patrón B); [false]→PUT Canal=SUCURSAL (camino existente intacto). Code node expone `fuenteEsRedesSociales`. versionId `e8f6f33f`→`37f780e1`, 21→24 nodos. Backup `n8n/backup_redes_sociales_ddUEORBEtZLzsQF2_20260530_192343.json`.
+**E2E vivo (Cancún, esau):** T1 SUCURSAL/REDES SOCIALES→**FACEBOOK/LEAD DIGITAL** ✓; T2 regresión FORMULARIO/LEAD DIGITAL→**SUCURSAL/SUCURSAL** ✓ (la rama Patrón A sigue intacta por el false branch). Restaurado.
+
+## PENDIENTES
+1. [HECHO 2026-05-30] Causa raíz Patrón A cerrada en [2004] (`_add_fuente_reconcile.py`). Nota: `fix_branch_user_origin.py` (batch) sigue sin reconciliar Fuente, pero `fix_origen_fuente_incoherencia.py` cubre el backlog y [2004] cubre lo nuevo en tiempo real.
+2. [HECHO 2026-05-30] Causa raíz Patrón B (REDES SOCIALES) cerrada en [2004] (`_add_redes_sociales_branch.py`, ver sección arriba).
+3. Re-sync de la cache local de las 7 cuentas (el panel GHL ya está bien; la cache SQLite quedó stale para los 35 contactos).
+
+## ENLACES
+- Memorias: [[incoherencia_canal_fuente_lead_digital]], [[super_script_fix_branch_user_origin]], [[n8n_2004_canal_origen_complemento]], [[createdby_only_in_individual_get]], [[sucursal_tag_on_digital_leads]]
+- Scripts: `scripts/fix_origen_fuente_incoherencia.py`, `scripts/audit_origen_fuente_incoherencia.py`, `n8n/_add_fuente_reconcile.py` (cierre raíz Patrón A [2004]), `n8n/_add_redes_sociales_branch.py` (cierre raíz Patrón B [2004]), `n8n/_add_canal_origen_branch.py` (rama previa), `scripts/fix_branch_user_origin.py`, `scripts/fuente_prospecto_workflow.py`, `scripts/tag_canal_origen_workflow.py`, `scripts/canal_origen_resolver.py`
diff --git a/docs/casos/2026-05-30-opp-marca-cf-vacios-mapeo-contacto.md b/docs/casos/2026-05-30-opp-marca-cf-vacios-mapeo-contacto.md
new file mode 100644
index 0000000..43da78c
--- /dev/null
+++ b/docs/casos/2026-05-30-opp-marca-cf-vacios-mapeo-contacto.md
@@ -0,0 +1,63 @@
+---
+id: CASE-2026-05-30-opp-marca-cf-vacios-mapeo-contacto
+fecha: 2026-05-30
+categoria: cascada_n8n
+location_ids: ["GbKkBpCmKu2QmloKFHy3 (Monte Providencia / Marca)", "yjqKxoO02rsdwdJZSPmD (85950 - MP - Temixco)"]
+run_ids: ["backfill-opp-cf-20260530-164821"]
+snapshots: ["generated/migrations/backfill_opp_cf_8HITkGkOn3gN23Tl8LBr_backfill-opp-cf-20260530-164821.json"]
+status: resuelto
+memorias: ["[[n8n_opp_sync_match]]", "[[opp_multiplicity_replication_gap]]", "[[sucursal_to_marca_cf_drop_on_create]]", "[[sucursal_datatype_divergence_intentional]]"]
+playbooks: ["docs/PLAYBOOK_ENLACE_OPORTUNIDADES.md"]
+---
+
+## TRIGGERS
+- opp de Marca con `Sucursal` / `TIENDA` / `Canal de Origen` (CANAL DE ORIGEN) **vacíos**
+- "desde sucursal no se están trayendo los datos de las oportunidades"
+- opp de Marca con **solo** `opportunity.id_oportunidad_sucursal` y ningún otro CF (opp "solo-link")
+- workflow `Cfgwp0bOtDW8zuKW` "Sincronizar Oportunidad - Nodos Nuevos (Create/Update)"
+- `8HITkGkOn3gN23Tl8LBr` (opp Marca), `OQBrOQN9mNlybjlzB8Jk` (opp Temixco), Miguel Angel `mahernandez2282@gmail.com`
+- `opportunity.fuente_de_posible_cliente` == CANAL DE ORIGEN (opp y contacto comparten el sufijo de fieldKey)
+
+## SÍNTOMA
+La opp de Marca `8HITkGkOn3gN23Tl8LBr` (Miguel Angel, viene de Temixco) tenía vacíos Sucursal, TIENDA y Canal de Origen. Hipótesis del owner: la réplica n8n no mapea esos campos.
+
+## DIAGNÓSTICO (read-only)
+- `get_opportunities(GbKkBpCmKu2QmloKFHy3)` agregado por CF: de **1342** opps de Marca, `opportunity.sucursal` poblado en **1341**, `tienda` 1295, `fuente_de_posible_cliente` 711. → el mapeo genérico SÍ funciona; `8HIT` era la **única** opp "solo-link".
+- Los nodos `Armar Body - CREATE` y `Armar Body - UPDATE (v2)` ya copian *todos* los CF de la opp de sucursal → Marca por `fieldKey` (fallback `name`), enriquecidos por `Mapeo completo oportunidad origen - SUCURSAL`.
+- La opp de sucursal `OQBrOQN9…` SÍ tiene `opportunity.sucursal`="Temixco, Morelos", `tienda`="TEMIXCO", pero **NO** tiene `fuente_de_posible_cliente` (CANAL DE ORIGEN). El **contacto** de Temixco (`eE6374FcwI7zlmQmTgGO`) sí: `contact.fuente_de_posible_cliente`="SUCURSAL".
+- Schema en vivo: el `fieldKey` canónico (sufijo) es **idéntico** contact↔opportunity: `*.sucursal`, `*.tienda`, `*.fuente_de_posible_cliente`. `contact.sucursal` es SINGLE_OPTIONS pero su label = el texto-ciudad que `opportunity.sucursal` (TEXT) espera ([[sucursal_datatype_divergence_intentional]]).
+
+## CAUSA RAÍZ
+1. **Caso puntual `8HIT`**: opp creada fuera del flujo normal (creación manual + `backfill_opp_sucursal_link.py`, que solo escribe el link) — por eso quedó solo-link. No es bug del mapeo genérico.
+2. **Gap general**: cuando la opp de sucursal NO trae un CF (p.ej. CANAL DE ORIGEN, que vive solo en el contacto, o por carrera de tiempo intermitente [[sucursal_to_marca_cf_drop_on_create]]), Marca queda sin ese campo. El contacto es la fuente estable que faltaba consultar.
+
+## ACCIÓN
+1. **Workflow `Cfgwp0bOtDW8zuKW`** (script `n8n/_add_contact_to_opp_mapping.py`, dry-run → confirmación → `--apply`):
+ - Nodo nuevo `Obtener Contacto - SUCURSAL` (GET `/contacts/{{ Datos de Lead.Cliente['Contact ID'] }}`, token sucursal, `onError=continue`) insertado entre `Obtener info de Oportunidad - SUCURSAL` y `Obtener Pipelines - SUCURSAL`.
+ - Code `Mapeo completo oportunidad origen - SUCURSAL` extendido: upsert de `opportunity.sucursal` / `tienda` / `fuente_de_posible_cliente` con prioridad **(a)** opp sucursal → **(b)** contacto → **(c)** webhook. El loop genérico de `Armar Body` lo propaga a Marca por `fieldKey` (sin race lectura/escritura).
+ - Aplicado y verificado (`verify_post`), workflow reactivado. Backups en `n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_*.json`.
+2. **Backfill `8HIT`** (`scripts/backfill_brand_opp_cf_from_source.py --brand-opp-id 8HITkGkOn3gN23Tl8LBr --branch-location-id yjqKxoO02rsdwdJZSPmD --apply`): rellenó 5 CF vacíos desde la opp de sucursal + contacto. `run_id=backfill-opp-cf-20260530-164821` (reversible desde dashboard).
+
+## VERIFICACIÓN
+`GET /opportunities/8HITkGkOn3gN23Tl8LBr` (Marca) — después:
+- Sucursal = `Temixco, Morelos`, TIENDA = `TEMIXCO`, CANAL DE ORIGEN = `SUCURSAL` (del contacto), Fuente de Prospecto = `LEAD DIGITAL`, Vehículo = `March 2014`, link intacto.
+
+## EDGE-CASES / TRAMPAS
+- **No confundir** `opportunity.fuente_de_prospecto` (LEAD DIGITAL / REFERIDO / REDES SOCIALES) con `opportunity.fuente_de_posible_cliente` (= CANAL DE ORIGEN: SUCURSAL / FACEBOOK / FORMULARIO / WHATSAPP). Mismo nombre "Fuente…" en GHL, fieldKeys distintos.
+- **No** sourcear `8HIT` del contacto de **Marca** (`RwxMQr0`): por el lío de homónimos su `contact.sucursal`="Narvarte Oriente…" (incorrecto para Temixco). La opp de **sucursal** es la fuente limpia.
+- El valor de CANAL DE ORIGEN debe ser opción válida del picklist de Marca (`SUCURSAL` lo es). [[custom_fields_picklist_alignment]]
+- El backfill solo rellena campos **vacíos** (no sobreescribe).
+
+## REUTILIZABLE
+- Agregado por CF para detectar opps "solo-link" en Marca: cargar el dump de `get_opportunities` y contar ids de CF (1342 vs 1341 reveló el outlier).
+- `scripts/backfill_brand_opp_cf_from_source.py`: backfill genérico de CF descriptivos de una opp de Marca desde su opp de sucursal enlazada (+ contacto como respaldo), dry-run/snapshot/audit.
+
+## PENDIENTES
+- Validar E2E el cambio del workflow en la **próxima sincronización real** de una opp de Temixco (o construir un E2E para `Cfgwp0bOtDW8zuKW`, hoy el harness `scripts/n8n_e2e_test.py` solo cubre los workflows de contactos).
+- (Opcional 2ª iteración) Persistir también los 3 campos en la opp de **sucursal** vía el PUT de `Mapear ID Oportunidad Sucursal - SUCURSAL`.
+- Re-sync de Marca para refrescar el cache SQLite del dashboard.
+
+## ENLACES
+- [[n8n_opp_sync_match]] · [[opp_multiplicity_replication_gap]] · [[sucursal_to_marca_cf_drop_on_create]] · [[sucursal_datatype_divergence_intentional]] · [[custom_fields_picklist_alignment]]
+- `n8n/_add_contact_to_opp_mapping.py` · `scripts/backfill_brand_opp_cf_from_source.py`
+- docs/PLAYBOOK_ENLACE_OPORTUNIDADES.md
diff --git a/docs/casos/INDEX.md b/docs/casos/INDEX.md
index 118e47b..2314b24 100644
--- a/docs/casos/INDEX.md
+++ b/docs/casos/INDEX.md
@@ -34,6 +34,8 @@ No registres: lecturas triviales, consultas de un solo dato, o trabajo puramente
| Fecha | ID | Categoría | Triggers (keywords para grep) | Status | Enlace |
|---|---|---|---|---|---|
+| 2026-05-30 | CASE-2026-05-30-incoherencia-canal-fuente-lead-digital | custom_field, cascada_n8n, descuadre | `LEAD DIGITAL no cuadra con FORMULARIO + FACEBOOK`, `929 vs 901 descuadre 28`, `Canal=SUCURSAL pero Fuente=LEAD DIGITAL`, `REDES SOCIALES fuente no canónica Tampico`, `fix_branch_user_origin NO toca Fuente`, `[2004] pone Canal=SUCURSAL a WEB_USER sin reconciliar Fuente`, `source de Marca lo estampa n8n no es fiable usar createdBy.source`, `fix_origen_fuente_incoherencia.py`, `audit_origen_fuente_incoherencia.py`, `run origen-fuente-3c50e43ec6a9` | resuelto | [caso](2026-05-30-incoherencia-canal-fuente-lead-digital.md) |
+| 2026-05-30 | CASE-2026-05-30-opp-marca-cf-vacios-mapeo-contacto | cascada_n8n, custom_field | `opp Marca Sucursal TIENDA Canal de Origen vacíos`, `desde sucursal no se traen datos de oportunidades`, `opp solo-link solo id_oportunidad_sucursal`, `Cfgwp0bOtDW8zuKW mapear campos del contacto a la opp`, `Obtener Contacto - SUCURSAL nodo nuevo`, `Mapeo completo oportunidad origen - SUCURSAL`, `8HITkGkOn3gN23Tl8LBr OQBrOQN9mNlybjlzB8Jk Miguel mahernandez2282`, `fuente_de_posible_cliente CANAL DE ORIGEN del contacto`, `backfill_brand_opp_cf_from_source.py` | resuelto | [caso](2026-05-30-opp-marca-cf-vacios-mapeo-contacto.md) |
| 2026-05-30 | CASE-2026-05-30-comparativa-auditoria-completa-buckets | descuadre, cascada_n8n, config_location | `Comparativa Marca vs Sucursales auditar todos los buckets`, `opps +1 opportunities_in_brand_duplicate_link`, `present_in_other_branch_not_assigned 84 falsos positivos`, `TIENDA=METEPEC vive en Pilares 85935`, `DIGITAL_HUB_BY_SHELL hub-map en código`, `audit lee Verificador CSV no Baserow`, `PATRICIA PARRA zzBzWC4adBrdTA8WhQph réplica abandoned $0`, `redirect Windows cp1252 no utf-8`, `re-sync Marca antes de re-auditar` | resuelto | [caso](2026-05-30-comparativa-auditoria-completa-buckets.md) |
| 2026-05-30 | CASE-2026-05-30-descuadre-opp-deadlink | descuadre, cascada_n8n | `DIFERENCIA OPORTUNIDADES +2`, `descuadre positivo todos los buckets de opps en 0`, `opp Marca link muerto GET 400 Opportunity doesn't exist or is deleted`, `réplica obsoleta n8n no borró id rotado`, `contacto 2 opps Marca 1 sola viva sucursal`, `cleanup scripts no atrapan dead-link único`, `re-enlazar vs borrar opp 1:1` | resuelto | [caso](2026-05-30-descuadre-opp-deadlink.md) |
| 2026-05-30 | CASE-2026-05-30-descuadre-opp-replica-duplicada-marca | descuadre, cascada_n8n, duplicado | `DIFERENCIA OPORTUNIDADES +10`, `descuadre positivo Marca > Sucursales`, `réplicas duplicadas mismo ID Oportunidad Sucursal`, `dos opps Marca misma opp sucursal`, `opportunities_in_brand_duplicate_link`, `Cfgwp0bOtDW8zuKW CREATE en vez de UPDATE`, `Decidir Match Create vs Update`, `cleanup_brand_orphan cero huérfanas pero descuadre`, `antelmo anselmo mismo teléfono distinto contacto`, `cleanup_brand_duplicate_replica_opps.py` | parcial | [caso](2026-05-30-descuadre-opp-replica-duplicada-marca.md) |
diff --git a/n8n/_add_contact_to_opp_mapping.py b/n8n/_add_contact_to_opp_mapping.py
new file mode 100644
index 0000000..12f7877
--- /dev/null
+++ b/n8n/_add_contact_to_opp_mapping.py
@@ -0,0 +1,233 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""Garantiza que la opp sincronizada a Marca traiga Sucursal / TIENDA / Canal de
+Origen, derivándolos del CONTACTO de sucursal cuando la opp de origen no los
+trae (workflow `Cfgwp0bOtDW8zuKW` "Sincronizar Oportunidad - Nodos Nuevos").
+
+Contexto: los nodos `Armar Body - CREATE/UPDATE` ya copian TODOS los custom
+fields de la opp de sucursal → Marca por `fieldKey`. Pero si la opp de origen
+llega sin esos CF (carrera de tiempo / creación fuera de flujo), la opp de Marca
+queda vacía (caso `8HIT…` de Miguel Temixco). El CONTACTO siempre los tiene
+(poblados por [1604]/[2004]) y usa el MISMO `fieldKey` canónico que la opp:
+ contact.sucursal -> opportunity.sucursal
+ contact.tienda -> opportunity.tienda
+ contact.fuente_de_posible_cliente-> opportunity.fuente_de_posible_cliente (CANAL DE ORIGEN)
+
+Cambios (solo AÑADE / enriquece, preserva el flujo actual):
+ 1. Nodo nuevo `Obtener Contacto - SUCURSAL` (GET /contacts/{id}) insertado
+ entre `Obtener info de Oportunidad - SUCURSAL` y `Obtener Pipelines - SUCURSAL`.
+ 2. Extiende el Code node `Mapeo completo oportunidad origen - SUCURSAL` para,
+ tras enriquecer los CF de la opp, hacer upsert de Sucursal/TIENDA/Canal con
+ prioridad (a) valor de la opp → (b) valor del contacto → (c) webhook.
+ El loop genérico de `Armar Body` los propaga a Marca por `fieldKey`.
+ No depende de leer-después-de-escribir (sin race).
+
+Uso:
+ python n8n/_add_contact_to_opp_mapping.py # dry-run (dumpea payload)
+ python n8n/_add_contact_to_opp_mapping.py --apply # aplica + reactiva
+"""
+
+import argparse
+import os
+import sys
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if ROOT_DIR not in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+from scripts.n8n_workflow_lib import N8NClient, load_credentials # noqa: E402
+
+WID = "Cfgwp0bOtDW8zuKW"
+
+# Nodos existentes (referencias).
+MAPEO_NODE = "Mapeo completo oportunidad origen - SUCURSAL"
+OBTENER_INFO_NODE = "Obtener info de Oportunidad - SUCURSAL"
+OBTENER_PIPELINES_NODE = "Obtener Pipelines - SUCURSAL"
+DATOS_API_SUCURSAL = "DATOS API - SUCURSAL"
+CF_DEFS_NODE = "Conseguir Custom Fields - Opportunity - SUCURSAL"
+
+# Nodo nuevo.
+GET_CONTACT_NODE = "Obtener Contacto - SUCURSAL"
+
+# Marca de idempotencia dentro del jsCode extendido.
+ENRICH_MARKER = "CONTACT->OPP ENRICH"
+
+CONTACT_ID_EXPR = "{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}"
+TOKEN_EXPR = "{{ $('" + DATOS_API_SUCURSAL + "').item.json['Token/API'] }}"
+
+# Bloque que se inyecta en el Code node, justo antes de `const stageInfo`.
+ENRICH_BLOCK = r"""
+// ── CONTACT->OPP ENRICH: garantizar Sucursal / TIENDA / Canal de Origen ──
+// Respaldo cuando la opp de sucursal no trae el CF: tomar el valor del CONTACTO
+// (siempre poblado por [1604]/[2004]) y, en ultimo caso, del webhook. El fieldKey
+// canonico (sufijo) es identico en contact y opportunity.
+const contactResp = $('Obtener Contacto - SUCURSAL').first().json;
+const contact = (contactResp && contactResp.contact) ? contactResp.contact : (contactResp || {});
+const webhookBody = ($('Webhook').first().json && $('Webhook').first().json.body) || {};
+const norm2 = (s) => (s == null ? '' : String(s)).trim();
+
+// Valores del contacto por fieldKey (contacts traen {id, value}).
+const contactValueByFieldKey = {};
+for (const cf of (contact.customFields || [])) {
+ const fk = fieldMap[cf.id] ? fieldMap[cf.id].fieldKey : null;
+ if (fk) contactValueByFieldKey[fk] = cf.value;
+}
+
+const ENRICH_TARGETS = [
+ { oppKey: 'opportunity.sucursal', contactKey: 'contact.sucursal', webhookKey: 'Sucursal' },
+ { oppKey: 'opportunity.tienda', contactKey: 'contact.tienda', webhookKey: 'TIENDA' },
+ { oppKey: 'opportunity.fuente_de_posible_cliente', contactKey: 'contact.fuente_de_posible_cliente', webhookKey: 'CANAL DE ORIGEN' },
+];
+
+for (const t of ENRICH_TARGETS) {
+ const existing = enrichedCustomFields.find(cf => cf.fieldKey === t.oppKey);
+ if (existing && norm2(existing.fieldValue) !== '') continue; // (a) ya viene de la opp
+ let value = norm2(contactValueByFieldKey[t.contactKey]); // (b) contacto
+ if (value === '') value = norm2(webhookBody[t.webhookKey]); // (c) webhook
+ if (value === '') continue;
+ if (existing) {
+ existing.fieldValue = value;
+ } else {
+ const def = customFieldsDefs.find(d => d.fieldKey === t.oppKey);
+ enrichedCustomFields.push({ id: def ? def.id : null, name: def ? def.name : null, fieldKey: t.oppKey, fieldValue: value });
+ }
+}
+// ── fin CONTACT->OPP ENRICH ──
+"""
+
+
+def ensure_model_all(cf_node):
+ """Asegura que `Conseguir Custom Fields…` pase ?model=all (sin esto el
+ endpoint /locations/{id}/customFields solo devuelve campos de CONTACTO, y el
+ mapeo genérico descarta TODOS los CF nativos de la opp). Devuelve True si
+ cambió algo."""
+ p = cf_node.setdefault("parameters", {})
+ p["sendQuery"] = True
+ qp = p.setdefault("queryParameters", {})
+ params = qp.setdefault("parameters", [])
+ for entry in params:
+ if entry.get("name") == "model":
+ if entry.get("value") == "all":
+ return False
+ entry["value"] = "all"
+ return True
+ params.append({"name": "model", "value": "all"})
+ return True
+
+
+def build_get_contact_node():
+ return {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/" + CONTACT_ID_EXPR,
+ "sendHeaders": True,
+ "headerParameters": {
+ "parameters": [
+ {"name": "Accept", "value": "application/json"},
+ {"name": "Version", "value": "2021-07-28"},
+ {"name": "Authorization", "value": "=Bearer " + TOKEN_EXPR},
+ ]
+ },
+ "options": {"redirect": {"redirect": {}}},
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [1750, -32],
+ "name": GET_CONTACT_NODE,
+ "onError": "continueRegularOutput",
+ "notes": "Trae el contacto de sucursal para derivar Sucursal/TIENDA/Canal de Origen de la opp cuando la opp de origen no los trae. onError=continue para no romper el sync.",
+ }
+
+
+def inject_enrich(js_code):
+ """Inserta ENRICH_BLOCK antes de `const stageInfo` (anchor estable)."""
+ anchor_candidates = [
+ "// Resolve pipeline and stage info",
+ "const stageInfo =",
+ ]
+ for anchor in anchor_candidates:
+ idx = js_code.find(anchor)
+ if idx != -1:
+ return js_code[:idx] + ENRICH_BLOCK + "\n" + js_code[idx:]
+ raise SystemExit(
+ "No se encontró un anchor para inyectar el bloque de enriquecimiento "
+ "en el jsCode del nodo Mapeo. Revisar el Code node manualmente."
+ )
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Mapea Sucursal/TIENDA/Canal de Origen del contacto a la opp en el workflow Cfgwp0bOtDW8zuKW."
+ )
+ parser.add_argument("--apply", action="store_true", help="Aplica el PUT real (sin esto: dry-run).")
+ args = parser.parse_args()
+
+ client = N8NClient(*load_credentials())
+ wf, backup_path = client.backup_workflow(WID, label="contact_to_opp_mapping")
+ prev_version = wf.get("versionId")
+ print(f"Workflow: {wf.get('name')}")
+ print(f" active={wf.get('active')} nodes={len(wf.get('nodes') or [])} versionId={prev_version}")
+ print(f" backup -> {backup_path}")
+
+ # Validar que existen los nodos de referencia.
+ for nm in (MAPEO_NODE, OBTENER_INFO_NODE, OBTENER_PIPELINES_NODE, DATOS_API_SUCURSAL, CF_DEFS_NODE):
+ if client.find_node(wf, nm) is None:
+ raise SystemExit(f"No se encontró el nodo esperado {nm!r}.")
+
+ # Idempotencia.
+ code_node = client.find_node(wf, MAPEO_NODE)
+ cf_node = client.find_node(wf, CF_DEFS_NODE)
+ already_node = client.find_node(wf, GET_CONTACT_NODE) is not None
+ already_code = ENRICH_MARKER in (code_node["parameters"].get("jsCode") or "")
+ cf_params = (cf_node.get("parameters") or {}).get("queryParameters", {}).get("parameters", [])
+ already_query = any(e.get("name") == "model" and e.get("value") == "all" for e in cf_params)
+ if already_node and already_code and already_query:
+ raise SystemExit("El complemento ya fue aplicado (nodo + jsCode + model=all). Nada que hacer.")
+
+ # 0. Asegurar ?model=all en el fetch de custom fields (trae defs de opp).
+ if ensure_model_all(cf_node):
+ print(f" Nodo {CF_DEFS_NODE!r}: query 'model=all' añadido (ahora trae defs de opportunity).")
+ else:
+ print(f" Nodo {CF_DEFS_NODE!r} ya tenía 'model=all'.")
+
+ # 1. Nodo nuevo GET contacto + cableado.
+ if not already_node:
+ client.add_node(wf, build_get_contact_node())
+ client.insert_between(wf, OBTENER_INFO_NODE, GET_CONTACT_NODE, OBTENER_PIPELINES_NODE)
+ print(f" Nodo {GET_CONTACT_NODE!r} insertado entre "
+ f"{OBTENER_INFO_NODE!r} y {OBTENER_PIPELINES_NODE!r}.")
+ else:
+ print(f" Nodo {GET_CONTACT_NODE!r} ya existía (no se re-inserta).")
+
+ # 2. Enriquecer el Code node.
+ if not already_code:
+ code_node["parameters"]["jsCode"] = inject_enrich(code_node["parameters"]["jsCode"])
+ print(f" Code node {MAPEO_NODE!r}: bloque de enriquecimiento inyectado.")
+ else:
+ print(f" Code node {MAPEO_NODE!r} ya tenía el bloque (no se re-inyecta).")
+
+ expected = [GET_CONTACT_NODE]
+
+ if not args.apply:
+ res = client.put_workflow(WID, wf, dry_run=True)
+ print(f"\nDRY-RUN. Payload -> {res['path']} ({res['node_count']} nodos).")
+ print("Revisa el JSON y vuelve a correr con --apply para aplicar.")
+ return
+
+ was_active = bool(wf.get("active"))
+ if was_active:
+ try:
+ client.deactivate(WID)
+ print(" Workflow desactivado para PUT estructural.")
+ except Exception as exc:
+ print(f" WARN al desactivar: {exc}")
+ client.put_workflow(WID, wf, dry_run=False)
+ print(" PUT aplicado.")
+ if was_active:
+ client.activate(WID)
+ print(" Workflow reactivado.")
+ client.verify_post(WID, expected_node_names=expected, prev_version_id=prev_version)
+ print("\nOK: complemento aplicado y verificado. Backup en:", backup_path)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/n8n/_add_fuente_reconcile.py b/n8n/_add_fuente_reconcile.py
new file mode 100644
index 0000000..9f5fd15
--- /dev/null
+++ b/n8n/_add_fuente_reconcile.py
@@ -0,0 +1,255 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""Endurece el workflow n8n [2004] (ddUEORBEtZLzsQF2) para CERRAR LA CAUSA RAÍZ
+del Patrón A (Canal=SUCURSAL & Fuente=LEAD DIGITAL).
+
+Contexto: la rama "Creado por usuario" (añadida por `_add_canal_origen_branch.py`)
+pone Canal de Origen=SUCURSAL a los contactos WEB_USER/MOBILE_USER pero NO toca
+Fuente de Prospecto, dejando huérfano un `LEAD DIGITAL` previo -> incoherencia.
+
+Este complemento (solo AÑADE, preserva el flujo) reconcilia la Fuente SOLO cuando
+vale exactamente "LEAD DIGITAL" (preserva ALIANZA / PROSPECCIÓN / CLIENTE CONOCIDO
+/ etc., que con Canal=SUCURSAL son válidas):
+
+ 1. Extiende el Code node para resolver el field "Fuente de Prospecto"
+ (fieldKey `contact.fuente_de_prospecto`, fallback por nombre) y leer su VALOR
+ ACTUAL del GET individual del contacto -> expone `fuente`, `fuenteActual`,
+ `fuenteEsLeadDigital`.
+ 2. Tras `Tag- facebook-ads` añade:
+ IF "Fuente = LEAD DIGITAL (reconciliar)" -> [true] PUT Fuente=SUCURSAL
+ [false] (fin: no se toca).
+
+Solo corre dentro de la rama esUsuario=true (ya gateada aguas arriba por el IF
+"Creado por usuario"). El [2004] dispara al CREAR contacto, así que no revierte
+ediciones manuales posteriores.
+
+Uso:
+ python n8n/_add_fuente_reconcile.py # dry-run (dumpea payload)
+ python n8n/_add_fuente_reconcile.py --apply # aplica + reactiva
+"""
+
+import argparse
+import os
+import sys
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if ROOT_DIR not in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+from scripts.n8n_workflow_lib import N8NClient, load_credentials # noqa: E402
+
+WID = "ddUEORBEtZLzsQF2"
+
+# Nodos existentes (referencias).
+CODE_NODE = 'Buscar "contact.sucursal" y "contact.tienda"'
+GET_CONTACT_NODE = "Obtener Contacto Cuenta Origen - SUCURSAL"
+VERIFICADOR_NODE = "Buscar Sucursal en Verificador de Sucursales"
+TAG_RM_FB_NODE = "Tag- facebook-ads" # último nodo de la rama canal de origen
+
+# Nodos nuevos.
+IF_FUENTE_NODE = "Fuente = LEAD DIGITAL (reconciliar)"
+PUT_FUENTE_NODE = "PUT Fuente de Prospecto = SUCURSAL"
+
+CONTACT_ID_EXPR = "{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}"
+TOKEN_EXPR = "{{ $('" + VERIFICADOR_NODE + "').item.json['SC TOKEN BUCEFALO'] }}"
+CODE_REF = "$('" + CODE_NODE + "').item.json"
+
+HEADERS = [
+ {"name": "Accept", "value": "application/json"},
+ {"name": "Version", "value": "2021-07-28"},
+ {"name": "Authorization", "value": "=Bearer " + TOKEN_EXPR},
+]
+
+# Code node extendido: preserva VERBATIM la lógica sucursal/tienda/canal/esUsuario
+# y AÑADE la resolución de Fuente + su valor actual + flag fuenteEsLeadDigital.
+NEW_JSCODE = r"""const customFields = $input.first().json.customFields;
+
+function findField(key, names) {
+ let f = customFields.find(x => x.fieldKey === key);
+ if (!f) {
+ const wanted = names.map(n => n.toLowerCase().trim());
+ f = customFields.find(x => wanted.includes((x.name || "").toLowerCase().trim()));
+ }
+ return f || null;
+}
+
+const sucursalField = findField("contact.sucursal", ["Sucursal"]);
+const tiendaField = findField("contact.tienda", ["TIENDA", "Tienda"]);
+const canalField = findField("contact.fuente_de_posible_cliente", ["CANAL DE ORIGEN", "Canal de Origen"]);
+const fuenteField = findField("contact.fuente_de_prospecto", ["Fuente de Prospecto", "FUENTE DE PROSPECTO"]);
+
+// createdBy.source SOLO viene del GET individual del contacto.
+const contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;
+const createdBySource =
+ (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||
+ (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||
+ null;
+const esUsuario = createdBySource === "WEB_USER" || createdBySource === "MOBILE_USER";
+
+// Valor ACTUAL de "Fuente de Prospecto" en el contacto (para reconciliar SOLO si = LEAD DIGITAL).
+const contactCFs =
+ (contactResp && contactResp.contact && contactResp.contact.customFields) ||
+ (contactResp && contactResp.customFields) ||
+ [];
+let fuenteActual = null;
+if (fuenteField && fuenteField.id) {
+ const hit = contactCFs.find(cf => cf.id === fuenteField.id);
+ fuenteActual = hit ? (hit.value != null ? hit.value : (hit.fieldValue != null ? hit.fieldValue : null)) : null;
+}
+const fuenteEsLeadDigital = String(fuenteActual || "").trim().toUpperCase() === "LEAD DIGITAL";
+
+return [
+ {
+ json: {
+ sucursal: {
+ id: sucursalField?.id ?? null,
+ name: sucursalField?.name ?? null,
+ fieldKey: sucursalField?.fieldKey ?? null,
+ picklistOptions: sucursalField?.picklistOptions ?? [],
+ },
+ tienda: {
+ id: tiendaField?.id ?? null,
+ name: tiendaField?.name ?? null,
+ fieldKey: tiendaField?.fieldKey ?? null,
+ picklistOptions: tiendaField?.picklistOptions ?? [],
+ },
+ canal: {
+ id: canalField?.id ?? null,
+ name: canalField?.name ?? null,
+ fieldKey: canalField?.fieldKey ?? null,
+ picklistOptions: canalField?.picklistOptions ?? [],
+ },
+ fuente: {
+ id: fuenteField?.id ?? null,
+ name: fuenteField?.name ?? null,
+ fieldKey: fuenteField?.fieldKey ?? null,
+ picklistOptions: fuenteField?.picklistOptions ?? [],
+ },
+ createdBySource: createdBySource,
+ esUsuario: esUsuario,
+ fuenteActual: fuenteActual,
+ fuenteEsLeadDigital: fuenteEsLeadDigital,
+ },
+ },
+];"""
+
+
+def build_nodes():
+ if_node = {
+ "parameters": {
+ "conditions": {
+ "options": {"caseSensitive": True, "leftValue": "", "typeValidation": "loose", "version": 3},
+ "conditions": [
+ {
+ "id": "fuente-es-lead-digital",
+ "leftValue": "={{ " + CODE_REF + ".fuenteEsLeadDigital }}",
+ "rightValue": "",
+ "operator": {"type": "boolean", "operation": "true", "singleValue": True},
+ }
+ ],
+ "combinator": "and",
+ },
+ "options": {},
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [1820, -120],
+ "name": IF_FUENTE_NODE,
+ }
+
+ fuente_body = (
+ "={\n"
+ ' "customFields": [\n'
+ " {\n"
+ ' "id": "{{ ' + CODE_REF + '.fuente.id }}",\n'
+ ' "key": "{{ ' + CODE_REF + '.fuente.fieldKey }}",\n'
+ ' "field_value": "SUCURSAL"\n'
+ " }\n"
+ " ]\n"
+ "}"
+ )
+ put_fuente = {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/" + CONTACT_ID_EXPR,
+ "sendHeaders": True,
+ "headerParameters": {"parameters": [dict(h) for h in HEADERS]},
+ "sendBody": True,
+ "specifyBody": "json",
+ "jsonBody": fuente_body,
+ "options": {"redirect": {"redirect": {}}},
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [2040, -120],
+ "name": PUT_FUENTE_NODE,
+ }
+ return if_node, put_fuente
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Reconcilia Fuente=LEAD DIGITAL->SUCURSAL en [2004].")
+ parser.add_argument("--apply", action="store_true", help="Aplica el PUT real (sin esto: dry-run).")
+ args = parser.parse_args()
+
+ client = N8NClient(*load_credentials())
+ wf, backup_path = client.backup_workflow(WID, label="fuente_reconcile")
+ prev_version = wf.get("versionId")
+ print(f"Workflow: {wf.get('name')}")
+ print(f" active={wf.get('active')} nodes={len(wf.get('nodes') or [])} versionId={prev_version}")
+ print(f" backup -> {backup_path}")
+
+ # Idempotencia.
+ for nm in (IF_FUENTE_NODE, PUT_FUENTE_NODE):
+ if client.find_node(wf, nm) is not None:
+ raise SystemExit(f"El nodo {nm!r} ya existe; el complemento ya fue aplicado. Nada que hacer.")
+
+ # Pre-requisito: la rama canal de origen debe existir (TAG_RM_FB_NODE es su cola).
+ if client.find_node(wf, TAG_RM_FB_NODE) is None:
+ raise SystemExit(f"No existe {TAG_RM_FB_NODE!r}; corre antes _add_canal_origen_branch.py.")
+
+ # 1. Extender el Code node (preserva lógica previa, añade fuente).
+ code_node = client.find_node(wf, CODE_NODE)
+ if code_node is None:
+ raise SystemExit(f"No se encontró el Code node {CODE_NODE!r}.")
+ code_node["parameters"]["jsCode"] = NEW_JSCODE
+ print(f" Code node {CODE_NODE!r}: jsCode extendido (fuente + fuenteEsLeadDigital).")
+
+ # 2. Añadir nodos.
+ if_node, put_fuente = build_nodes()
+ for n in (if_node, put_fuente):
+ client.assert_idempotent(wf, n["name"])
+ client.add_node(wf, n)
+ print(" Nodos añadidos: IF Fuente + PUT Fuente=SUCURSAL.")
+
+ # 3. Conexiones: Tag- facebook-ads -> IF -> [true] PUT Fuente. [false] fin.
+ client.set_connection(wf, TAG_RM_FB_NODE, IF_FUENTE_NODE)
+ client.set_connection(wf, IF_FUENTE_NODE, PUT_FUENTE_NODE, output_index=0)
+ print(" Conexiones cableadas.")
+
+ expected = [IF_FUENTE_NODE, PUT_FUENTE_NODE]
+
+ if not args.apply:
+ res = client.put_workflow(WID, wf, dry_run=True)
+ print(f"\nDRY-RUN. Payload -> {res['path']} ({res['node_count']} nodos).")
+ print("Revisa el JSON y vuelve a correr con --apply para aplicar.")
+ return
+
+ was_active = bool(wf.get("active"))
+ if was_active:
+ try:
+ client.deactivate(WID)
+ print(" Workflow desactivado para PUT estructural.")
+ except Exception as exc:
+ print(f" WARN al desactivar: {exc}")
+ client.put_workflow(WID, wf, dry_run=False)
+ print(" PUT aplicado.")
+ if was_active:
+ client.activate(WID)
+ print(" Workflow reactivado.")
+ client.verify_post(WID, expected_node_names=expected, prev_version_id=prev_version)
+ print("\nOK: complemento aplicado y verificado. Backup en:", backup_path)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/n8n/_add_redes_sociales_branch.py b/n8n/_add_redes_sociales_branch.py
new file mode 100644
index 0000000..8fa404c
--- /dev/null
+++ b/n8n/_add_redes_sociales_branch.py
@@ -0,0 +1,273 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""Cierra el Patrón B (Fuente=REDES SOCIALES) en el workflow n8n [2004]
+(ddUEORBEtZLzsQF2).
+
+Contexto: la rama "Creado por usuario" pone Canal=SUCURSAL a los WEB_USER/
+MOBILE_USER. Para un contacto con Fuente=REDES SOCIALES eso es incoherente
+(redes sociales = canal digital). Decisión de negocio (2026-05-30): tratarlos
+como digital -> Canal=FACEBOOK + Fuente=LEAD DIGITAL (igual que hizo el fix de
+datos `scripts/fix_origen_fuente_incoherencia.py` Patrón B).
+
+Cambio (solo AÑADE / re-cablea, preserva el camino SUCURSAL existente):
+ 1. Extiende el Code node para exponer `fuenteEsRedesSociales`.
+ 2. Intercala, en la rama true del IF "Creado por usuario", un IF
+ "Fuente es REDES SOCIALES":
+ [true] -> PUT Canal=FACEBOOK -> PUT Fuente=LEAD DIGITAL (camino digital)
+ [false] -> PUT Canal de Origen = SUCURSAL (camino existente intacto)
+
+ Antes: Creado por usuario --true--> [PUT Canal=SUCURSAL -> tags -> IF LEAD DIGITAL -> PUT Fuente=SUCURSAL]
+ Ahora: Creado por usuario --true--> IF REDES SOCIALES
+ --true--> PUT Canal=FACEBOOK -> PUT Fuente=LEAD DIGITAL
+ --false-> [PUT Canal=SUCURSAL -> ... (igual que antes)]
+
+Solo toca custom fields del contacto (no tags ni opps), igual que el fix de datos.
+[2004] dispara al CREAR contacto.
+
+Uso:
+ python n8n/_add_redes_sociales_branch.py # dry-run (dumpea payload)
+ python n8n/_add_redes_sociales_branch.py --apply # aplica + reactiva
+"""
+
+import argparse
+import os
+import sys
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if ROOT_DIR not in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+from scripts.n8n_workflow_lib import N8NClient, load_credentials # noqa: E402
+
+WID = "ddUEORBEtZLzsQF2"
+
+# Nodos existentes.
+CODE_NODE = 'Buscar "contact.sucursal" y "contact.tienda"'
+VERIFICADOR_NODE = "Buscar Sucursal en Verificador de Sucursales"
+IF_USUARIO_NODE = "Creado por usuario (Canal de Origen)"
+PUT_CANAL_SUCURSAL_NODE = "PUT Canal de Origen = SUCURSAL"
+
+# Nodos nuevos.
+IF_REDES_NODE = "Fuente es REDES SOCIALES"
+PUT_CANAL_FB_NODE = "PUT Canal de Origen = FACEBOOK"
+PUT_FUENTE_LD_NODE = "PUT Fuente de Prospecto = LEAD DIGITAL"
+
+CONTACT_ID_EXPR = "{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}"
+TOKEN_EXPR = "{{ $('" + VERIFICADOR_NODE + "').item.json['SC TOKEN BUCEFALO'] }}"
+CODE_REF = "$('" + CODE_NODE + "').item.json"
+
+HEADERS = [
+ {"name": "Accept", "value": "application/json"},
+ {"name": "Version", "value": "2021-07-28"},
+ {"name": "Authorization", "value": "=Bearer " + TOKEN_EXPR},
+]
+
+# Code node: versión con fuente (de _add_fuente_reconcile.py) + flag fuenteEsRedesSociales.
+NEW_JSCODE = r"""const customFields = $input.first().json.customFields;
+
+function findField(key, names) {
+ let f = customFields.find(x => x.fieldKey === key);
+ if (!f) {
+ const wanted = names.map(n => n.toLowerCase().trim());
+ f = customFields.find(x => wanted.includes((x.name || "").toLowerCase().trim()));
+ }
+ return f || null;
+}
+
+const sucursalField = findField("contact.sucursal", ["Sucursal"]);
+const tiendaField = findField("contact.tienda", ["TIENDA", "Tienda"]);
+const canalField = findField("contact.fuente_de_posible_cliente", ["CANAL DE ORIGEN", "Canal de Origen"]);
+const fuenteField = findField("contact.fuente_de_prospecto", ["Fuente de Prospecto", "FUENTE DE PROSPECTO"]);
+
+// createdBy.source SOLO viene del GET individual del contacto.
+const contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;
+const createdBySource =
+ (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||
+ (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||
+ null;
+const esUsuario = createdBySource === "WEB_USER" || createdBySource === "MOBILE_USER";
+
+// Valor ACTUAL de "Fuente de Prospecto" en el contacto.
+const contactCFs =
+ (contactResp && contactResp.contact && contactResp.contact.customFields) ||
+ (contactResp && contactResp.customFields) ||
+ [];
+let fuenteActual = null;
+if (fuenteField && fuenteField.id) {
+ const hit = contactCFs.find(cf => cf.id === fuenteField.id);
+ fuenteActual = hit ? (hit.value != null ? hit.value : (hit.fieldValue != null ? hit.fieldValue : null)) : null;
+}
+const fuenteNorm = String(fuenteActual || "").trim().toUpperCase();
+const fuenteEsLeadDigital = fuenteNorm === "LEAD DIGITAL";
+const fuenteEsRedesSociales = fuenteNorm === "REDES SOCIALES";
+
+return [
+ {
+ json: {
+ sucursal: {
+ id: sucursalField?.id ?? null,
+ name: sucursalField?.name ?? null,
+ fieldKey: sucursalField?.fieldKey ?? null,
+ picklistOptions: sucursalField?.picklistOptions ?? [],
+ },
+ tienda: {
+ id: tiendaField?.id ?? null,
+ name: tiendaField?.name ?? null,
+ fieldKey: tiendaField?.fieldKey ?? null,
+ picklistOptions: tiendaField?.picklistOptions ?? [],
+ },
+ canal: {
+ id: canalField?.id ?? null,
+ name: canalField?.name ?? null,
+ fieldKey: canalField?.fieldKey ?? null,
+ picklistOptions: canalField?.picklistOptions ?? [],
+ },
+ fuente: {
+ id: fuenteField?.id ?? null,
+ name: fuenteField?.name ?? null,
+ fieldKey: fuenteField?.fieldKey ?? null,
+ picklistOptions: fuenteField?.picklistOptions ?? [],
+ },
+ createdBySource: createdBySource,
+ esUsuario: esUsuario,
+ fuenteActual: fuenteActual,
+ fuenteEsLeadDigital: fuenteEsLeadDigital,
+ fuenteEsRedesSociales: fuenteEsRedesSociales,
+ },
+ },
+];"""
+
+
+def put_cf_node(name, position, *, code_field, value):
+ """Nodo httpRequest PUT /contacts/{id} que setea un custom field por id+key."""
+ body = (
+ "={\n"
+ ' "customFields": [\n'
+ " {\n"
+ ' "id": "{{ ' + CODE_REF + "." + code_field + '.id }}",\n'
+ ' "key": "{{ ' + CODE_REF + "." + code_field + '.fieldKey }}",\n'
+ ' "field_value": "' + value + '"\n'
+ " }\n"
+ " ]\n"
+ "}"
+ )
+ return {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/" + CONTACT_ID_EXPR,
+ "sendHeaders": True,
+ "headerParameters": {"parameters": [dict(h) for h in HEADERS]},
+ "sendBody": True,
+ "specifyBody": "json",
+ "jsonBody": body,
+ "options": {"redirect": {"redirect": {}}},
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": position,
+ "name": name,
+ }
+
+
+def build_nodes():
+ if_redes = {
+ "parameters": {
+ "conditions": {
+ "options": {"caseSensitive": True, "leftValue": "", "typeValidation": "loose", "version": 3},
+ "conditions": [
+ {
+ "id": "fuente-es-redes-sociales",
+ "leftValue": "={{ " + CODE_REF + ".fuenteEsRedesSociales }}",
+ "rightValue": "",
+ "operator": {"type": "boolean", "operation": "true", "singleValue": True},
+ }
+ ],
+ "combinator": "and",
+ },
+ "options": {},
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [820, -320],
+ "name": IF_REDES_NODE,
+ }
+ put_canal_fb = put_cf_node(PUT_CANAL_FB_NODE, [1040, -320], code_field="canal", value="FACEBOOK")
+ put_fuente_ld = put_cf_node(PUT_FUENTE_LD_NODE, [1260, -320], code_field="fuente", value="LEAD DIGITAL")
+ return if_redes, put_canal_fb, put_fuente_ld
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Cierra Patrón B (REDES SOCIALES) en [2004].")
+ parser.add_argument("--apply", action="store_true", help="Aplica el PUT real (sin esto: dry-run).")
+ args = parser.parse_args()
+
+ client = N8NClient(*load_credentials())
+ wf, backup_path = client.backup_workflow(WID, label="redes_sociales")
+ prev_version = wf.get("versionId")
+ print(f"Workflow: {wf.get('name')}")
+ print(f" active={wf.get('active')} nodes={len(wf.get('nodes') or [])} versionId={prev_version}")
+ print(f" backup -> {backup_path}")
+
+ # Idempotencia.
+ for nm in (IF_REDES_NODE, PUT_CANAL_FB_NODE, PUT_FUENTE_LD_NODE):
+ if client.find_node(wf, nm) is not None:
+ raise SystemExit(f"El nodo {nm!r} ya existe; ya fue aplicado. Nada que hacer.")
+
+ # Pre-requisitos.
+ for nm in (IF_USUARIO_NODE, PUT_CANAL_SUCURSAL_NODE):
+ if client.find_node(wf, nm) is None:
+ raise SystemExit(f"No existe {nm!r}; corre antes _add_canal_origen_branch.py.")
+
+ # Verifica que el IF "Creado por usuario" hoy conecta su rama true a PUT Canal=SUCURSAL.
+ cur = client.get_connection_targets(wf, IF_USUARIO_NODE, output_index=0)
+ cur_names = [t.get("node") for t in cur]
+ if cur_names != [PUT_CANAL_SUCURSAL_NODE]:
+ raise SystemExit(f"Topología inesperada: {IF_USUARIO_NODE!r} true -> {cur_names} (esperaba [{PUT_CANAL_SUCURSAL_NODE!r}]).")
+
+ # 1. Extender Code node.
+ code_node = client.find_node(wf, CODE_NODE)
+ code_node["parameters"]["jsCode"] = NEW_JSCODE
+ print(f" Code node {CODE_NODE!r}: jsCode extendido (fuenteEsRedesSociales).")
+
+ # 2. Añadir nodos.
+ if_redes, put_canal_fb, put_fuente_ld = build_nodes()
+ for n in (if_redes, put_canal_fb, put_fuente_ld):
+ client.assert_idempotent(wf, n["name"])
+ client.add_node(wf, n)
+ print(" Nodos añadidos: IF REDES + PUT Canal=FACEBOOK + PUT Fuente=LEAD DIGITAL.")
+
+ # 3. Re-cablear: Creado por usuario[true] -> IF REDES;
+ # IF REDES[true] -> PUT Canal=FACEBOOK -> PUT Fuente=LEAD DIGITAL;
+ # IF REDES[false] -> PUT Canal=SUCURSAL (camino existente).
+ client.set_connection(wf, IF_USUARIO_NODE, IF_REDES_NODE, output_index=0)
+ client.set_connection(wf, IF_REDES_NODE, PUT_CANAL_FB_NODE, output_index=0)
+ client.set_connection(wf, IF_REDES_NODE, PUT_CANAL_SUCURSAL_NODE, output_index=1)
+ client.set_connection(wf, PUT_CANAL_FB_NODE, PUT_FUENTE_LD_NODE)
+ print(" Conexiones re-cableadas.")
+
+ expected = [IF_REDES_NODE, PUT_CANAL_FB_NODE, PUT_FUENTE_LD_NODE]
+
+ if not args.apply:
+ res = client.put_workflow(WID, wf, dry_run=True)
+ print(f"\nDRY-RUN. Payload -> {res['path']} ({res['node_count']} nodos).")
+ print("Revisa el JSON y vuelve a correr con --apply para aplicar.")
+ return
+
+ was_active = bool(wf.get("active"))
+ if was_active:
+ try:
+ client.deactivate(WID)
+ print(" Workflow desactivado para PUT estructural.")
+ except Exception as exc:
+ print(f" WARN al desactivar: {exc}")
+ client.put_workflow(WID, wf, dry_run=False)
+ print(" PUT aplicado.")
+ if was_active:
+ client.activate(WID)
+ print(" Workflow reactivado.")
+ client.verify_post(WID, expected_node_names=expected, prev_version_id=prev_version)
+ print("\nOK: Patrón B cerrado y verificado. Backup en:", backup_path)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_163623.json b/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_163623.json
new file mode 100644
index 0000000..abbee52
--- /dev/null
+++ b/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_163623.json
@@ -0,0 +1,4148 @@
+{
+ "updatedAt": "2026-05-30T22:21:10.460Z",
+ "createdAt": "2026-03-02T01:12:56.387Z",
+ "id": "Cfgwp0bOtDW8zuKW",
+ "name": "Sincronizar Oportunidad - Nodos Nuevos (Create/Update)",
+ "description": null,
+ "active": true,
+ "isArchived": false,
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4208,
+ 1152
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "alwaysOutputData": true,
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6048,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6288,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1",
+ "binaryMode": "separate",
+ "availableInMCP": false
+ },
+ "staticData": null,
+ "meta": {
+ "templateCredsSetupCompleted": true
+ },
+ "pinData": {
+ "Webhook": [
+ {
+ "json": {
+ "headers": {
+ "host": "webhookn8.consultoriae3.com",
+ "user-agent": "axios/1.13.2",
+ "content-length": "1839",
+ "accept": "application/json, text/plain, */*",
+ "accept-encoding": "gzip, compress, deflate, br",
+ "content-type": "application/json",
+ "traceparent": "00-00e6586cc6967f6985b8aa87332de4e0-932bdb81faeff7c4-01",
+ "x-forwarded-for": "34.55.150.6",
+ "x-forwarded-host": "webhookn8.consultoriae3.com",
+ "x-forwarded-port": "443",
+ "x-forwarded-proto": "https",
+ "x-forwarded-server": "f569f6e85d30",
+ "x-real-ip": "34.55.150.6"
+ },
+ "params": {},
+ "query": {},
+ "body": {
+ "¿Cuándo necesitas el dinero?": "",
+ "[Número de Teléfono para Atender]": "",
+ "Información Adicional": "",
+ "Presupuesto": "",
+ "CANAL DE ORIGEN": "",
+ "[Número de WhatsApp para Atender]": "",
+ "[Dirección de la Empresa]": "",
+ "Año del Vehículo": "2015",
+ "¿Qué modalidad prefieres?": "Tradicional (Resguardo)",
+ "Marca del Vehiculo": "RENAULT",
+ "TIENDA": "TAMPICO",
+ "Sucursal": "Tampico, Tamaulipas",
+ "Descripción": "",
+ "[Correo_Empresa]": "",
+ "ID Contacto Monte Providencia": "",
+ "Fuente de Prospecto": "REDES SOCIALES",
+ "[Correo_Canalizados]": "",
+ "Version del Vehiculo": "LOGAN",
+ "Acepta los terminos para tu cotización": "",
+ "[Nombre de la Empresa]": "",
+ "Check Comunicaciones de Marketing": "",
+ "Archivos Adicionales": "",
+ "contact_id": "B9oJWsFXy6Ol9NdHL5Jh",
+ "first_name": "RAUL",
+ "last_name": "LOGAN",
+ "full_name": "RAUL LOGAN",
+ "email": "raulsincorreo@gmail.com",
+ "phone": "+528332937527",
+ "tags": "sucursal",
+ "country": "MX",
+ "date_created": "2026-05-27T21:16:44.369Z",
+ "full_address": "",
+ "contact_type": "lead",
+ "opportunity_name": "RAUL LOGAN",
+ "status": "open",
+ "lead_value": 40000,
+ "opportunity_source": "REDES SOCIALES",
+ "source": "REDES SOCIALES",
+ "pipleline_stage": "Cliente interesado",
+ "pipeline_id": "ep1d4VpzRezVqWayFbBf",
+ "id": "NuFArKAQL72I8QC69MDa",
+ "pipeline_name": "Standar",
+ "user": {
+ "firstName": "Tampico - 85969",
+ "lastName": "Tampico",
+ "email": "ezstore85969@ezcorp.com"
+ },
+ "owner": "Tampico - 85969 Tampico",
+ "location": {
+ "name": "85969 - MP - Tampico",
+ "address": "Tampico",
+ "city": "Tampico",
+ "state": "Tamaulipas",
+ "country": "MX",
+ "postalCode": "10000",
+ "fullAddress": "Tampico, Tampico Tamaulipas 10000",
+ "id": "WCHyow6KpjLFYriQWdbJ"
+ },
+ "workflow": {
+ "id": "8ba8fdf1-85f2-4f1f-bf28-56400e1adcd6",
+ "name": "Sincronizar Oportunidad V2"
+ },
+ "triggerData": {},
+ "contact": {
+ "attributionSource": {
+ "sessionSource": "CRM UI",
+ "mediumId": null,
+ "medium": "manual"
+ },
+ "lastAttributionSource": {}
+ },
+ "attributionSource": {},
+ "customData": {}
+ },
+ "webhookUrl": "https://webhookn8.consultoriae3.com/webhook/3eecb45a-e24c-49ac-aef7-99843f485819",
+ "executionMode": "production"
+ },
+ "pairedItem": {
+ "item": 0
+ }
+ }
+ ]
+ },
+ "versionId": "23dedba0-39b4-4edc-8751-03808c7af4d7",
+ "activeVersionId": "65decdcb-f97e-493d-8eb9-b872905b3d35",
+ "versionCounter": 433,
+ "triggerCount": 1,
+ "shared": [
+ {
+ "updatedAt": "2026-03-02T01:12:56.387Z",
+ "createdAt": "2026-03-02T01:12:56.387Z",
+ "role": "workflow:owner",
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "projectId": "aycNlMpnzsxvXbfG",
+ "project": {
+ "updatedAt": "2025-11-27T04:06:26.313Z",
+ "createdAt": "2025-11-27T03:54:24.410Z",
+ "id": "aycNlMpnzsxvXbfG",
+ "name": "Consultoria E3 ® ",
+ "type": "personal",
+ "icon": null,
+ "description": null,
+ "creatorId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ }
+ ],
+ "tags": [
+ {
+ "updatedAt": "2025-11-27T05:48:12.272Z",
+ "createdAt": "2025-11-27T05:48:12.272Z",
+ "id": "pHkPpq3Httzx4hnb",
+ "name": "Bucefalo"
+ }
+ ],
+ "activeVersion": {
+ "updatedAt": "2026-05-30T17:03:07.471Z",
+ "createdAt": "2026-05-30T17:03:07.471Z",
+ "versionId": "65decdcb-f97e-493d-8eb9-b872905b3d35",
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4200,
+ 1140
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "alwaysOutputData": true,
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6040,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6280,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "authors": "Consultoria E3 ®",
+ "name": null,
+ "description": null,
+ "autosaved": false,
+ "workflowPublishHistory": [
+ {
+ "createdAt": "2026-05-30T17:03:07.625Z",
+ "id": 674,
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "versionId": "65decdcb-f97e-493d-8eb9-b872905b3d35",
+ "event": "deactivated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ },
+ {
+ "createdAt": "2026-05-30T17:03:07.684Z",
+ "id": 675,
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "versionId": "65decdcb-f97e-493d-8eb9-b872905b3d35",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_164248.json b/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_164248.json
new file mode 100644
index 0000000..abbee52
--- /dev/null
+++ b/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_164248.json
@@ -0,0 +1,4148 @@
+{
+ "updatedAt": "2026-05-30T22:21:10.460Z",
+ "createdAt": "2026-03-02T01:12:56.387Z",
+ "id": "Cfgwp0bOtDW8zuKW",
+ "name": "Sincronizar Oportunidad - Nodos Nuevos (Create/Update)",
+ "description": null,
+ "active": true,
+ "isArchived": false,
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4208,
+ 1152
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "alwaysOutputData": true,
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6048,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6288,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1",
+ "binaryMode": "separate",
+ "availableInMCP": false
+ },
+ "staticData": null,
+ "meta": {
+ "templateCredsSetupCompleted": true
+ },
+ "pinData": {
+ "Webhook": [
+ {
+ "json": {
+ "headers": {
+ "host": "webhookn8.consultoriae3.com",
+ "user-agent": "axios/1.13.2",
+ "content-length": "1839",
+ "accept": "application/json, text/plain, */*",
+ "accept-encoding": "gzip, compress, deflate, br",
+ "content-type": "application/json",
+ "traceparent": "00-00e6586cc6967f6985b8aa87332de4e0-932bdb81faeff7c4-01",
+ "x-forwarded-for": "34.55.150.6",
+ "x-forwarded-host": "webhookn8.consultoriae3.com",
+ "x-forwarded-port": "443",
+ "x-forwarded-proto": "https",
+ "x-forwarded-server": "f569f6e85d30",
+ "x-real-ip": "34.55.150.6"
+ },
+ "params": {},
+ "query": {},
+ "body": {
+ "¿Cuándo necesitas el dinero?": "",
+ "[Número de Teléfono para Atender]": "",
+ "Información Adicional": "",
+ "Presupuesto": "",
+ "CANAL DE ORIGEN": "",
+ "[Número de WhatsApp para Atender]": "",
+ "[Dirección de la Empresa]": "",
+ "Año del Vehículo": "2015",
+ "¿Qué modalidad prefieres?": "Tradicional (Resguardo)",
+ "Marca del Vehiculo": "RENAULT",
+ "TIENDA": "TAMPICO",
+ "Sucursal": "Tampico, Tamaulipas",
+ "Descripción": "",
+ "[Correo_Empresa]": "",
+ "ID Contacto Monte Providencia": "",
+ "Fuente de Prospecto": "REDES SOCIALES",
+ "[Correo_Canalizados]": "",
+ "Version del Vehiculo": "LOGAN",
+ "Acepta los terminos para tu cotización": "",
+ "[Nombre de la Empresa]": "",
+ "Check Comunicaciones de Marketing": "",
+ "Archivos Adicionales": "",
+ "contact_id": "B9oJWsFXy6Ol9NdHL5Jh",
+ "first_name": "RAUL",
+ "last_name": "LOGAN",
+ "full_name": "RAUL LOGAN",
+ "email": "raulsincorreo@gmail.com",
+ "phone": "+528332937527",
+ "tags": "sucursal",
+ "country": "MX",
+ "date_created": "2026-05-27T21:16:44.369Z",
+ "full_address": "",
+ "contact_type": "lead",
+ "opportunity_name": "RAUL LOGAN",
+ "status": "open",
+ "lead_value": 40000,
+ "opportunity_source": "REDES SOCIALES",
+ "source": "REDES SOCIALES",
+ "pipleline_stage": "Cliente interesado",
+ "pipeline_id": "ep1d4VpzRezVqWayFbBf",
+ "id": "NuFArKAQL72I8QC69MDa",
+ "pipeline_name": "Standar",
+ "user": {
+ "firstName": "Tampico - 85969",
+ "lastName": "Tampico",
+ "email": "ezstore85969@ezcorp.com"
+ },
+ "owner": "Tampico - 85969 Tampico",
+ "location": {
+ "name": "85969 - MP - Tampico",
+ "address": "Tampico",
+ "city": "Tampico",
+ "state": "Tamaulipas",
+ "country": "MX",
+ "postalCode": "10000",
+ "fullAddress": "Tampico, Tampico Tamaulipas 10000",
+ "id": "WCHyow6KpjLFYriQWdbJ"
+ },
+ "workflow": {
+ "id": "8ba8fdf1-85f2-4f1f-bf28-56400e1adcd6",
+ "name": "Sincronizar Oportunidad V2"
+ },
+ "triggerData": {},
+ "contact": {
+ "attributionSource": {
+ "sessionSource": "CRM UI",
+ "mediumId": null,
+ "medium": "manual"
+ },
+ "lastAttributionSource": {}
+ },
+ "attributionSource": {},
+ "customData": {}
+ },
+ "webhookUrl": "https://webhookn8.consultoriae3.com/webhook/3eecb45a-e24c-49ac-aef7-99843f485819",
+ "executionMode": "production"
+ },
+ "pairedItem": {
+ "item": 0
+ }
+ }
+ ]
+ },
+ "versionId": "23dedba0-39b4-4edc-8751-03808c7af4d7",
+ "activeVersionId": "65decdcb-f97e-493d-8eb9-b872905b3d35",
+ "versionCounter": 433,
+ "triggerCount": 1,
+ "shared": [
+ {
+ "updatedAt": "2026-03-02T01:12:56.387Z",
+ "createdAt": "2026-03-02T01:12:56.387Z",
+ "role": "workflow:owner",
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "projectId": "aycNlMpnzsxvXbfG",
+ "project": {
+ "updatedAt": "2025-11-27T04:06:26.313Z",
+ "createdAt": "2025-11-27T03:54:24.410Z",
+ "id": "aycNlMpnzsxvXbfG",
+ "name": "Consultoria E3 ® ",
+ "type": "personal",
+ "icon": null,
+ "description": null,
+ "creatorId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ }
+ ],
+ "tags": [
+ {
+ "updatedAt": "2025-11-27T05:48:12.272Z",
+ "createdAt": "2025-11-27T05:48:12.272Z",
+ "id": "pHkPpq3Httzx4hnb",
+ "name": "Bucefalo"
+ }
+ ],
+ "activeVersion": {
+ "updatedAt": "2026-05-30T17:03:07.471Z",
+ "createdAt": "2026-05-30T17:03:07.471Z",
+ "versionId": "65decdcb-f97e-493d-8eb9-b872905b3d35",
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4200,
+ 1140
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "alwaysOutputData": true,
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6040,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6280,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "authors": "Consultoria E3 ®",
+ "name": null,
+ "description": null,
+ "autosaved": false,
+ "workflowPublishHistory": [
+ {
+ "createdAt": "2026-05-30T17:03:07.625Z",
+ "id": 674,
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "versionId": "65decdcb-f97e-493d-8eb9-b872905b3d35",
+ "event": "deactivated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ },
+ {
+ "createdAt": "2026-05-30T17:03:07.684Z",
+ "id": 675,
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "versionId": "65decdcb-f97e-493d-8eb9-b872905b3d35",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_165900.json b/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_165900.json
new file mode 100644
index 0000000..fb3de80
--- /dev/null
+++ b/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_165900.json
@@ -0,0 +1,4228 @@
+{
+ "updatedAt": "2026-05-30T22:42:49.703Z",
+ "createdAt": "2026-03-02T01:12:56.387Z",
+ "id": "Cfgwp0bOtDW8zuKW",
+ "name": "Sincronizar Oportunidad - Nodos Nuevos (Create/Update)",
+ "description": null,
+ "active": true,
+ "isArchived": false,
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n\n// ── CONTACT->OPP ENRICH: garantizar Sucursal / TIENDA / Canal de Origen ──\n// Respaldo cuando la opp de sucursal no trae el CF: tomar el valor del CONTACTO\n// (siempre poblado por [1604]/[2004]) y, en ultimo caso, del webhook. El fieldKey\n// canonico (sufijo) es identico en contact y opportunity.\nconst contactResp = $('Obtener Contacto - SUCURSAL').first().json;\nconst contact = (contactResp && contactResp.contact) ? contactResp.contact : (contactResp || {});\nconst webhookBody = ($('Webhook').first().json && $('Webhook').first().json.body) || {};\nconst norm2 = (s) => (s == null ? '' : String(s)).trim();\n\n// Valores del contacto por fieldKey (contacts traen {id, value}).\nconst contactValueByFieldKey = {};\nfor (const cf of (contact.customFields || [])) {\n const fk = fieldMap[cf.id] ? fieldMap[cf.id].fieldKey : null;\n if (fk) contactValueByFieldKey[fk] = cf.value;\n}\n\nconst ENRICH_TARGETS = [\n { oppKey: 'opportunity.sucursal', contactKey: 'contact.sucursal', webhookKey: 'Sucursal' },\n { oppKey: 'opportunity.tienda', contactKey: 'contact.tienda', webhookKey: 'TIENDA' },\n { oppKey: 'opportunity.fuente_de_posible_cliente', contactKey: 'contact.fuente_de_posible_cliente', webhookKey: 'CANAL DE ORIGEN' },\n];\n\nfor (const t of ENRICH_TARGETS) {\n const existing = enrichedCustomFields.find(cf => cf.fieldKey === t.oppKey);\n if (existing && norm2(existing.fieldValue) !== '') continue; // (a) ya viene de la opp\n let value = norm2(contactValueByFieldKey[t.contactKey]); // (b) contacto\n if (value === '') value = norm2(webhookBody[t.webhookKey]); // (c) webhook\n if (value === '') continue;\n if (existing) {\n existing.fieldValue = value;\n } else {\n const def = customFieldsDefs.find(d => d.fieldKey === t.oppKey);\n enrichedCustomFields.push({ id: def ? def.id : null, name: def ? def.name : null, fieldKey: t.oppKey, fieldValue: value });\n }\n}\n// ── fin CONTACT->OPP ENRICH ──\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4208,
+ 1152
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "alwaysOutputData": true,
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6048,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6288,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1750,
+ -32
+ ],
+ "name": "Obtener Contacto - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Trae el contacto de sucursal para derivar Sucursal/TIENDA/Canal de Origen de la opp cuando la opp de origen no los trae. onError=continue para no romper el sync.",
+ "id": "3636d605-1c44-4f2d-b64c-10a5c346cd24"
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1",
+ "binaryMode": "separate",
+ "availableInMCP": false
+ },
+ "staticData": null,
+ "meta": {
+ "templateCredsSetupCompleted": true
+ },
+ "pinData": {
+ "Webhook": [
+ {
+ "json": {
+ "headers": {
+ "host": "webhookn8.consultoriae3.com",
+ "user-agent": "axios/1.13.2",
+ "content-length": "1839",
+ "accept": "application/json, text/plain, */*",
+ "accept-encoding": "gzip, compress, deflate, br",
+ "content-type": "application/json",
+ "traceparent": "00-00e6586cc6967f6985b8aa87332de4e0-932bdb81faeff7c4-01",
+ "x-forwarded-for": "34.55.150.6",
+ "x-forwarded-host": "webhookn8.consultoriae3.com",
+ "x-forwarded-port": "443",
+ "x-forwarded-proto": "https",
+ "x-forwarded-server": "f569f6e85d30",
+ "x-real-ip": "34.55.150.6"
+ },
+ "params": {},
+ "query": {},
+ "body": {
+ "¿Cuándo necesitas el dinero?": "",
+ "[Número de Teléfono para Atender]": "",
+ "Información Adicional": "",
+ "Presupuesto": "",
+ "CANAL DE ORIGEN": "",
+ "[Número de WhatsApp para Atender]": "",
+ "[Dirección de la Empresa]": "",
+ "Año del Vehículo": "2015",
+ "¿Qué modalidad prefieres?": "Tradicional (Resguardo)",
+ "Marca del Vehiculo": "RENAULT",
+ "TIENDA": "TAMPICO",
+ "Sucursal": "Tampico, Tamaulipas",
+ "Descripción": "",
+ "[Correo_Empresa]": "",
+ "ID Contacto Monte Providencia": "",
+ "Fuente de Prospecto": "REDES SOCIALES",
+ "[Correo_Canalizados]": "",
+ "Version del Vehiculo": "LOGAN",
+ "Acepta los terminos para tu cotización": "",
+ "[Nombre de la Empresa]": "",
+ "Check Comunicaciones de Marketing": "",
+ "Archivos Adicionales": "",
+ "contact_id": "B9oJWsFXy6Ol9NdHL5Jh",
+ "first_name": "RAUL",
+ "last_name": "LOGAN",
+ "full_name": "RAUL LOGAN",
+ "email": "raulsincorreo@gmail.com",
+ "phone": "+528332937527",
+ "tags": "sucursal",
+ "country": "MX",
+ "date_created": "2026-05-27T21:16:44.369Z",
+ "full_address": "",
+ "contact_type": "lead",
+ "opportunity_name": "RAUL LOGAN",
+ "status": "open",
+ "lead_value": 40000,
+ "opportunity_source": "REDES SOCIALES",
+ "source": "REDES SOCIALES",
+ "pipleline_stage": "Cliente interesado",
+ "pipeline_id": "ep1d4VpzRezVqWayFbBf",
+ "id": "NuFArKAQL72I8QC69MDa",
+ "pipeline_name": "Standar",
+ "user": {
+ "firstName": "Tampico - 85969",
+ "lastName": "Tampico",
+ "email": "ezstore85969@ezcorp.com"
+ },
+ "owner": "Tampico - 85969 Tampico",
+ "location": {
+ "name": "85969 - MP - Tampico",
+ "address": "Tampico",
+ "city": "Tampico",
+ "state": "Tamaulipas",
+ "country": "MX",
+ "postalCode": "10000",
+ "fullAddress": "Tampico, Tampico Tamaulipas 10000",
+ "id": "WCHyow6KpjLFYriQWdbJ"
+ },
+ "workflow": {
+ "id": "8ba8fdf1-85f2-4f1f-bf28-56400e1adcd6",
+ "name": "Sincronizar Oportunidad V2"
+ },
+ "triggerData": {},
+ "contact": {
+ "attributionSource": {
+ "sessionSource": "CRM UI",
+ "mediumId": null,
+ "medium": "manual"
+ },
+ "lastAttributionSource": {}
+ },
+ "attributionSource": {},
+ "customData": {}
+ },
+ "webhookUrl": "https://webhookn8.consultoriae3.com/webhook/3eecb45a-e24c-49ac-aef7-99843f485819",
+ "executionMode": "production"
+ },
+ "pairedItem": {
+ "item": 0
+ }
+ }
+ ]
+ },
+ "versionId": "be97beec-1bd0-43c9-a70e-c3a268d47c3e",
+ "activeVersionId": "be97beec-1bd0-43c9-a70e-c3a268d47c3e",
+ "versionCounter": 437,
+ "triggerCount": 1,
+ "shared": [
+ {
+ "updatedAt": "2026-03-02T01:12:56.387Z",
+ "createdAt": "2026-03-02T01:12:56.387Z",
+ "role": "workflow:owner",
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "projectId": "aycNlMpnzsxvXbfG",
+ "project": {
+ "updatedAt": "2025-11-27T04:06:26.313Z",
+ "createdAt": "2025-11-27T03:54:24.410Z",
+ "id": "aycNlMpnzsxvXbfG",
+ "name": "Consultoria E3 ® ",
+ "type": "personal",
+ "icon": null,
+ "description": null,
+ "creatorId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ }
+ ],
+ "tags": [
+ {
+ "updatedAt": "2025-11-27T05:48:12.272Z",
+ "createdAt": "2025-11-27T05:48:12.272Z",
+ "id": "pHkPpq3Httzx4hnb",
+ "name": "Bucefalo"
+ }
+ ],
+ "activeVersion": {
+ "updatedAt": "2026-05-30T22:42:49.706Z",
+ "createdAt": "2026-05-30T22:42:49.706Z",
+ "versionId": "be97beec-1bd0-43c9-a70e-c3a268d47c3e",
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n\n// ── CONTACT->OPP ENRICH: garantizar Sucursal / TIENDA / Canal de Origen ──\n// Respaldo cuando la opp de sucursal no trae el CF: tomar el valor del CONTACTO\n// (siempre poblado por [1604]/[2004]) y, en ultimo caso, del webhook. El fieldKey\n// canonico (sufijo) es identico en contact y opportunity.\nconst contactResp = $('Obtener Contacto - SUCURSAL').first().json;\nconst contact = (contactResp && contactResp.contact) ? contactResp.contact : (contactResp || {});\nconst webhookBody = ($('Webhook').first().json && $('Webhook').first().json.body) || {};\nconst norm2 = (s) => (s == null ? '' : String(s)).trim();\n\n// Valores del contacto por fieldKey (contacts traen {id, value}).\nconst contactValueByFieldKey = {};\nfor (const cf of (contact.customFields || [])) {\n const fk = fieldMap[cf.id] ? fieldMap[cf.id].fieldKey : null;\n if (fk) contactValueByFieldKey[fk] = cf.value;\n}\n\nconst ENRICH_TARGETS = [\n { oppKey: 'opportunity.sucursal', contactKey: 'contact.sucursal', webhookKey: 'Sucursal' },\n { oppKey: 'opportunity.tienda', contactKey: 'contact.tienda', webhookKey: 'TIENDA' },\n { oppKey: 'opportunity.fuente_de_posible_cliente', contactKey: 'contact.fuente_de_posible_cliente', webhookKey: 'CANAL DE ORIGEN' },\n];\n\nfor (const t of ENRICH_TARGETS) {\n const existing = enrichedCustomFields.find(cf => cf.fieldKey === t.oppKey);\n if (existing && norm2(existing.fieldValue) !== '') continue; // (a) ya viene de la opp\n let value = norm2(contactValueByFieldKey[t.contactKey]); // (b) contacto\n if (value === '') value = norm2(webhookBody[t.webhookKey]); // (c) webhook\n if (value === '') continue;\n if (existing) {\n existing.fieldValue = value;\n } else {\n const def = customFieldsDefs.find(d => d.fieldKey === t.oppKey);\n enrichedCustomFields.push({ id: def ? def.id : null, name: def ? def.name : null, fieldKey: t.oppKey, fieldValue: value });\n }\n}\n// ── fin CONTACT->OPP ENRICH ──\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4208,
+ 1152
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "alwaysOutputData": true,
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6048,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6288,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1750,
+ -32
+ ],
+ "name": "Obtener Contacto - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Trae el contacto de sucursal para derivar Sucursal/TIENDA/Canal de Origen de la opp cuando la opp de origen no los trae. onError=continue para no romper el sync.",
+ "id": "3636d605-1c44-4f2d-b64c-10a5c346cd24"
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "authors": "Consultoria E3 ®",
+ "name": null,
+ "description": null,
+ "autosaved": false,
+ "workflowPublishHistory": [
+ {
+ "createdAt": "2026-05-30T22:42:50.131Z",
+ "id": 677,
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "versionId": "be97beec-1bd0-43c9-a70e-c3a268d47c3e",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_165946.json b/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_165946.json
new file mode 100644
index 0000000..fb3de80
--- /dev/null
+++ b/n8n/backup_contact_to_opp_mapping_Cfgwp0bOtDW8zuKW_20260530_165946.json
@@ -0,0 +1,4228 @@
+{
+ "updatedAt": "2026-05-30T22:42:49.703Z",
+ "createdAt": "2026-03-02T01:12:56.387Z",
+ "id": "Cfgwp0bOtDW8zuKW",
+ "name": "Sincronizar Oportunidad - Nodos Nuevos (Create/Update)",
+ "description": null,
+ "active": true,
+ "isArchived": false,
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n\n// ── CONTACT->OPP ENRICH: garantizar Sucursal / TIENDA / Canal de Origen ──\n// Respaldo cuando la opp de sucursal no trae el CF: tomar el valor del CONTACTO\n// (siempre poblado por [1604]/[2004]) y, en ultimo caso, del webhook. El fieldKey\n// canonico (sufijo) es identico en contact y opportunity.\nconst contactResp = $('Obtener Contacto - SUCURSAL').first().json;\nconst contact = (contactResp && contactResp.contact) ? contactResp.contact : (contactResp || {});\nconst webhookBody = ($('Webhook').first().json && $('Webhook').first().json.body) || {};\nconst norm2 = (s) => (s == null ? '' : String(s)).trim();\n\n// Valores del contacto por fieldKey (contacts traen {id, value}).\nconst contactValueByFieldKey = {};\nfor (const cf of (contact.customFields || [])) {\n const fk = fieldMap[cf.id] ? fieldMap[cf.id].fieldKey : null;\n if (fk) contactValueByFieldKey[fk] = cf.value;\n}\n\nconst ENRICH_TARGETS = [\n { oppKey: 'opportunity.sucursal', contactKey: 'contact.sucursal', webhookKey: 'Sucursal' },\n { oppKey: 'opportunity.tienda', contactKey: 'contact.tienda', webhookKey: 'TIENDA' },\n { oppKey: 'opportunity.fuente_de_posible_cliente', contactKey: 'contact.fuente_de_posible_cliente', webhookKey: 'CANAL DE ORIGEN' },\n];\n\nfor (const t of ENRICH_TARGETS) {\n const existing = enrichedCustomFields.find(cf => cf.fieldKey === t.oppKey);\n if (existing && norm2(existing.fieldValue) !== '') continue; // (a) ya viene de la opp\n let value = norm2(contactValueByFieldKey[t.contactKey]); // (b) contacto\n if (value === '') value = norm2(webhookBody[t.webhookKey]); // (c) webhook\n if (value === '') continue;\n if (existing) {\n existing.fieldValue = value;\n } else {\n const def = customFieldsDefs.find(d => d.fieldKey === t.oppKey);\n enrichedCustomFields.push({ id: def ? def.id : null, name: def ? def.name : null, fieldKey: t.oppKey, fieldValue: value });\n }\n}\n// ── fin CONTACT->OPP ENRICH ──\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4208,
+ 1152
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "alwaysOutputData": true,
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6048,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6288,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1750,
+ -32
+ ],
+ "name": "Obtener Contacto - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Trae el contacto de sucursal para derivar Sucursal/TIENDA/Canal de Origen de la opp cuando la opp de origen no los trae. onError=continue para no romper el sync.",
+ "id": "3636d605-1c44-4f2d-b64c-10a5c346cd24"
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1",
+ "binaryMode": "separate",
+ "availableInMCP": false
+ },
+ "staticData": null,
+ "meta": {
+ "templateCredsSetupCompleted": true
+ },
+ "pinData": {
+ "Webhook": [
+ {
+ "json": {
+ "headers": {
+ "host": "webhookn8.consultoriae3.com",
+ "user-agent": "axios/1.13.2",
+ "content-length": "1839",
+ "accept": "application/json, text/plain, */*",
+ "accept-encoding": "gzip, compress, deflate, br",
+ "content-type": "application/json",
+ "traceparent": "00-00e6586cc6967f6985b8aa87332de4e0-932bdb81faeff7c4-01",
+ "x-forwarded-for": "34.55.150.6",
+ "x-forwarded-host": "webhookn8.consultoriae3.com",
+ "x-forwarded-port": "443",
+ "x-forwarded-proto": "https",
+ "x-forwarded-server": "f569f6e85d30",
+ "x-real-ip": "34.55.150.6"
+ },
+ "params": {},
+ "query": {},
+ "body": {
+ "¿Cuándo necesitas el dinero?": "",
+ "[Número de Teléfono para Atender]": "",
+ "Información Adicional": "",
+ "Presupuesto": "",
+ "CANAL DE ORIGEN": "",
+ "[Número de WhatsApp para Atender]": "",
+ "[Dirección de la Empresa]": "",
+ "Año del Vehículo": "2015",
+ "¿Qué modalidad prefieres?": "Tradicional (Resguardo)",
+ "Marca del Vehiculo": "RENAULT",
+ "TIENDA": "TAMPICO",
+ "Sucursal": "Tampico, Tamaulipas",
+ "Descripción": "",
+ "[Correo_Empresa]": "",
+ "ID Contacto Monte Providencia": "",
+ "Fuente de Prospecto": "REDES SOCIALES",
+ "[Correo_Canalizados]": "",
+ "Version del Vehiculo": "LOGAN",
+ "Acepta los terminos para tu cotización": "",
+ "[Nombre de la Empresa]": "",
+ "Check Comunicaciones de Marketing": "",
+ "Archivos Adicionales": "",
+ "contact_id": "B9oJWsFXy6Ol9NdHL5Jh",
+ "first_name": "RAUL",
+ "last_name": "LOGAN",
+ "full_name": "RAUL LOGAN",
+ "email": "raulsincorreo@gmail.com",
+ "phone": "+528332937527",
+ "tags": "sucursal",
+ "country": "MX",
+ "date_created": "2026-05-27T21:16:44.369Z",
+ "full_address": "",
+ "contact_type": "lead",
+ "opportunity_name": "RAUL LOGAN",
+ "status": "open",
+ "lead_value": 40000,
+ "opportunity_source": "REDES SOCIALES",
+ "source": "REDES SOCIALES",
+ "pipleline_stage": "Cliente interesado",
+ "pipeline_id": "ep1d4VpzRezVqWayFbBf",
+ "id": "NuFArKAQL72I8QC69MDa",
+ "pipeline_name": "Standar",
+ "user": {
+ "firstName": "Tampico - 85969",
+ "lastName": "Tampico",
+ "email": "ezstore85969@ezcorp.com"
+ },
+ "owner": "Tampico - 85969 Tampico",
+ "location": {
+ "name": "85969 - MP - Tampico",
+ "address": "Tampico",
+ "city": "Tampico",
+ "state": "Tamaulipas",
+ "country": "MX",
+ "postalCode": "10000",
+ "fullAddress": "Tampico, Tampico Tamaulipas 10000",
+ "id": "WCHyow6KpjLFYriQWdbJ"
+ },
+ "workflow": {
+ "id": "8ba8fdf1-85f2-4f1f-bf28-56400e1adcd6",
+ "name": "Sincronizar Oportunidad V2"
+ },
+ "triggerData": {},
+ "contact": {
+ "attributionSource": {
+ "sessionSource": "CRM UI",
+ "mediumId": null,
+ "medium": "manual"
+ },
+ "lastAttributionSource": {}
+ },
+ "attributionSource": {},
+ "customData": {}
+ },
+ "webhookUrl": "https://webhookn8.consultoriae3.com/webhook/3eecb45a-e24c-49ac-aef7-99843f485819",
+ "executionMode": "production"
+ },
+ "pairedItem": {
+ "item": 0
+ }
+ }
+ ]
+ },
+ "versionId": "be97beec-1bd0-43c9-a70e-c3a268d47c3e",
+ "activeVersionId": "be97beec-1bd0-43c9-a70e-c3a268d47c3e",
+ "versionCounter": 437,
+ "triggerCount": 1,
+ "shared": [
+ {
+ "updatedAt": "2026-03-02T01:12:56.387Z",
+ "createdAt": "2026-03-02T01:12:56.387Z",
+ "role": "workflow:owner",
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "projectId": "aycNlMpnzsxvXbfG",
+ "project": {
+ "updatedAt": "2025-11-27T04:06:26.313Z",
+ "createdAt": "2025-11-27T03:54:24.410Z",
+ "id": "aycNlMpnzsxvXbfG",
+ "name": "Consultoria E3 ® ",
+ "type": "personal",
+ "icon": null,
+ "description": null,
+ "creatorId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ }
+ ],
+ "tags": [
+ {
+ "updatedAt": "2025-11-27T05:48:12.272Z",
+ "createdAt": "2025-11-27T05:48:12.272Z",
+ "id": "pHkPpq3Httzx4hnb",
+ "name": "Bucefalo"
+ }
+ ],
+ "activeVersion": {
+ "updatedAt": "2026-05-30T22:42:49.706Z",
+ "createdAt": "2026-05-30T22:42:49.706Z",
+ "versionId": "be97beec-1bd0-43c9-a70e-c3a268d47c3e",
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n\n// ── CONTACT->OPP ENRICH: garantizar Sucursal / TIENDA / Canal de Origen ──\n// Respaldo cuando la opp de sucursal no trae el CF: tomar el valor del CONTACTO\n// (siempre poblado por [1604]/[2004]) y, en ultimo caso, del webhook. El fieldKey\n// canonico (sufijo) es identico en contact y opportunity.\nconst contactResp = $('Obtener Contacto - SUCURSAL').first().json;\nconst contact = (contactResp && contactResp.contact) ? contactResp.contact : (contactResp || {});\nconst webhookBody = ($('Webhook').first().json && $('Webhook').first().json.body) || {};\nconst norm2 = (s) => (s == null ? '' : String(s)).trim();\n\n// Valores del contacto por fieldKey (contacts traen {id, value}).\nconst contactValueByFieldKey = {};\nfor (const cf of (contact.customFields || [])) {\n const fk = fieldMap[cf.id] ? fieldMap[cf.id].fieldKey : null;\n if (fk) contactValueByFieldKey[fk] = cf.value;\n}\n\nconst ENRICH_TARGETS = [\n { oppKey: 'opportunity.sucursal', contactKey: 'contact.sucursal', webhookKey: 'Sucursal' },\n { oppKey: 'opportunity.tienda', contactKey: 'contact.tienda', webhookKey: 'TIENDA' },\n { oppKey: 'opportunity.fuente_de_posible_cliente', contactKey: 'contact.fuente_de_posible_cliente', webhookKey: 'CANAL DE ORIGEN' },\n];\n\nfor (const t of ENRICH_TARGETS) {\n const existing = enrichedCustomFields.find(cf => cf.fieldKey === t.oppKey);\n if (existing && norm2(existing.fieldValue) !== '') continue; // (a) ya viene de la opp\n let value = norm2(contactValueByFieldKey[t.contactKey]); // (b) contacto\n if (value === '') value = norm2(webhookBody[t.webhookKey]); // (c) webhook\n if (value === '') continue;\n if (existing) {\n existing.fieldValue = value;\n } else {\n const def = customFieldsDefs.find(d => d.fieldKey === t.oppKey);\n enrichedCustomFields.push({ id: def ? def.id : null, name: def ? def.name : null, fieldKey: t.oppKey, fieldValue: value });\n }\n}\n// ── fin CONTACT->OPP ENRICH ──\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4208,
+ 1152
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "alwaysOutputData": true,
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6048,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6288,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1750,
+ -32
+ ],
+ "name": "Obtener Contacto - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Trae el contacto de sucursal para derivar Sucursal/TIENDA/Canal de Origen de la opp cuando la opp de origen no los trae. onError=continue para no romper el sync.",
+ "id": "3636d605-1c44-4f2d-b64c-10a5c346cd24"
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "authors": "Consultoria E3 ®",
+ "name": null,
+ "description": null,
+ "autosaved": false,
+ "workflowPublishHistory": [
+ {
+ "createdAt": "2026-05-30T22:42:50.131Z",
+ "id": 677,
+ "workflowId": "Cfgwp0bOtDW8zuKW",
+ "versionId": "be97beec-1bd0-43c9-a70e-c3a268d47c3e",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/n8n/backup_fuente_reconcile_ddUEORBEtZLzsQF2_20260530_185416.json b/n8n/backup_fuente_reconcile_ddUEORBEtZLzsQF2_20260530_185416.json
new file mode 100644
index 0000000..0560546
--- /dev/null
+++ b/n8n/backup_fuente_reconcile_ddUEORBEtZLzsQF2_20260530_185416.json
@@ -0,0 +1,1903 @@
+{
+ "updatedAt": "2026-05-30T07:15:08.610Z",
+ "createdAt": "2026-04-20T22:29:00.636Z",
+ "id": "ddUEORBEtZLzsQF2",
+ "name": "[2004][Monte Providencia] Actualizar \"contact.sucursal\", \"contact.tienda\" al crear contacto",
+ "description": null,
+ "active": true,
+ "isArchived": false,
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1",
+ "binaryMode": "separate",
+ "availableInMCP": false
+ },
+ "staticData": null,
+ "meta": {
+ "templateCredsSetupCompleted": true
+ },
+ "pinData": {
+ "Webhook": [
+ {
+ "json": {
+ "headers": {
+ "host": "webhookn8.consultoriae3.com",
+ "user-agent": "axios/1.13.2",
+ "content-length": "1572",
+ "accept": "application/json, text/plain, */*",
+ "accept-encoding": "gzip, compress, deflate, br",
+ "content-type": "application/json",
+ "traceparent": "00-bfdb4ad6378402bf71f61ff3c72d0d02-ee175e0dcbcec88e-01",
+ "x-forwarded-for": "35.253.135.103",
+ "x-forwarded-host": "webhookn8.consultoriae3.com",
+ "x-forwarded-port": "443",
+ "x-forwarded-proto": "https",
+ "x-forwarded-server": "f569f6e85d30",
+ "x-real-ip": "35.253.135.103"
+ },
+ "params": {},
+ "query": {},
+ "body": {
+ "Canal de Origen": "",
+ "¿Qué modalidad prefieres?": "Sin Dejarlo (GPS)",
+ "Fuente de Prospecto": "GALLARDETES",
+ "Marca del Vehiculo": "VW",
+ "[Número de WhatsApp para Atender]": "",
+ "TIENDA": "",
+ "Presupuesto": "",
+ "Acepta los terminos para tu cotización": "",
+ "Sucursal": "",
+ "ID Contacto Monte Providencia": "",
+ "Información Adicional": "",
+ "[Número de Teléfono para Atender]": "",
+ "Version del Vehiculo": "POLO",
+ "[Correo_Canalizados]": "",
+ "[Correo_Empresa]": "",
+ "Check Comunicaciones de Marketing": "",
+ "Descripción": "",
+ "[Nombre de la Empresa]": "",
+ "Año del Vehículo": "2019",
+ "[Dirección de la Empresa]": "",
+ "¿Cuándo necesitas el dinero?": "",
+ "Archivos Adicionales": "",
+ "contact_id": "ZHj8ek6lQ6M6EeCIU7Uj",
+ "first_name": "LILIA LISSETH",
+ "last_name": "ZAVALA HEREDIA",
+ "full_name": "LILIA LISSETH ZAVALA HEREDIA",
+ "email": "lilia.zh0209@gmail.com",
+ "phone": "+524361175941",
+ "tags": "sucursal",
+ "country": "MX",
+ "date_created": "2026-05-25T23:59:53.804Z",
+ "full_address": "",
+ "contact_type": "lead",
+ "location": {
+ "name": "85964 - MP - Morelia 1",
+ "address": "Morelia",
+ "city": "Morelia",
+ "state": "Michoacán",
+ "country": "MX",
+ "postalCode": "58855",
+ "fullAddress": "Morelia, Morelia Michoacán 58855",
+ "id": "jE41bVhhnb5T505BFm4F"
+ },
+ "user": {
+ "firstName": "Morelia 1 - 85964",
+ "lastName": "Morelia 1",
+ "email": "ezstore85964@ezcorp.com",
+ "phone": "+524434589152"
+ },
+ "workflow": {
+ "id": "7c92fec9-b858-4a83-b2d9-31891c9b9231",
+ "name": "Sincronizar Contacto Creado V2"
+ },
+ "triggerData": {},
+ "contact": {
+ "attributionSource": {
+ "mediumId": null,
+ "medium": "manual",
+ "sessionSource": "CRM UI"
+ },
+ "lastAttributionSource": {}
+ },
+ "attributionSource": {},
+ "customData": {}
+ },
+ "webhookUrl": "https://webhookn8.consultoriae3.com/webhook/8d574598-d977-4052-823a-26def39c6a64",
+ "executionMode": "production"
+ },
+ "pairedItem": {
+ "item": 0
+ }
+ }
+ ]
+ },
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "activeVersionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "versionCounter": 234,
+ "triggerCount": 1,
+ "shared": [
+ {
+ "updatedAt": "2026-04-20T22:29:00.636Z",
+ "createdAt": "2026-04-20T22:29:00.636Z",
+ "role": "workflow:owner",
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "projectId": "aycNlMpnzsxvXbfG",
+ "project": {
+ "updatedAt": "2025-11-27T04:06:26.313Z",
+ "createdAt": "2025-11-27T03:54:24.410Z",
+ "id": "aycNlMpnzsxvXbfG",
+ "name": "Consultoria E3 ® ",
+ "type": "personal",
+ "icon": null,
+ "description": null,
+ "creatorId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ }
+ ],
+ "tags": [
+ {
+ "updatedAt": "2025-11-27T05:48:12.272Z",
+ "createdAt": "2025-11-27T05:48:12.272Z",
+ "id": "pHkPpq3Httzx4hnb",
+ "name": "Bucefalo"
+ },
+ {
+ "updatedAt": "2025-12-01T22:00:17.627Z",
+ "createdAt": "2025-12-01T22:00:17.627Z",
+ "id": "uIWgqVuJXbqA7m39",
+ "name": "PRUEBAS"
+ }
+ ],
+ "activeVersion": {
+ "updatedAt": "2026-05-30T07:15:08.612Z",
+ "createdAt": "2026-05-30T07:15:08.612Z",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "authors": "Consultoria E3 ®",
+ "name": null,
+ "description": null,
+ "autosaved": false,
+ "workflowPublishHistory": [
+ {
+ "createdAt": "2026-05-30T07:15:09.042Z",
+ "id": 666,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "event": "deactivated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ },
+ {
+ "createdAt": "2026-05-30T07:15:09.069Z",
+ "id": 667,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ },
+ {
+ "createdAt": "2026-05-30T07:15:08.695Z",
+ "id": 664,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "event": "deactivated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ },
+ {
+ "createdAt": "2026-05-30T07:15:08.729Z",
+ "id": 665,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/n8n/backup_fuente_reconcile_ddUEORBEtZLzsQF2_20260530_190108.json b/n8n/backup_fuente_reconcile_ddUEORBEtZLzsQF2_20260530_190108.json
new file mode 100644
index 0000000..0560546
--- /dev/null
+++ b/n8n/backup_fuente_reconcile_ddUEORBEtZLzsQF2_20260530_190108.json
@@ -0,0 +1,1903 @@
+{
+ "updatedAt": "2026-05-30T07:15:08.610Z",
+ "createdAt": "2026-04-20T22:29:00.636Z",
+ "id": "ddUEORBEtZLzsQF2",
+ "name": "[2004][Monte Providencia] Actualizar \"contact.sucursal\", \"contact.tienda\" al crear contacto",
+ "description": null,
+ "active": true,
+ "isArchived": false,
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1",
+ "binaryMode": "separate",
+ "availableInMCP": false
+ },
+ "staticData": null,
+ "meta": {
+ "templateCredsSetupCompleted": true
+ },
+ "pinData": {
+ "Webhook": [
+ {
+ "json": {
+ "headers": {
+ "host": "webhookn8.consultoriae3.com",
+ "user-agent": "axios/1.13.2",
+ "content-length": "1572",
+ "accept": "application/json, text/plain, */*",
+ "accept-encoding": "gzip, compress, deflate, br",
+ "content-type": "application/json",
+ "traceparent": "00-bfdb4ad6378402bf71f61ff3c72d0d02-ee175e0dcbcec88e-01",
+ "x-forwarded-for": "35.253.135.103",
+ "x-forwarded-host": "webhookn8.consultoriae3.com",
+ "x-forwarded-port": "443",
+ "x-forwarded-proto": "https",
+ "x-forwarded-server": "f569f6e85d30",
+ "x-real-ip": "35.253.135.103"
+ },
+ "params": {},
+ "query": {},
+ "body": {
+ "Canal de Origen": "",
+ "¿Qué modalidad prefieres?": "Sin Dejarlo (GPS)",
+ "Fuente de Prospecto": "GALLARDETES",
+ "Marca del Vehiculo": "VW",
+ "[Número de WhatsApp para Atender]": "",
+ "TIENDA": "",
+ "Presupuesto": "",
+ "Acepta los terminos para tu cotización": "",
+ "Sucursal": "",
+ "ID Contacto Monte Providencia": "",
+ "Información Adicional": "",
+ "[Número de Teléfono para Atender]": "",
+ "Version del Vehiculo": "POLO",
+ "[Correo_Canalizados]": "",
+ "[Correo_Empresa]": "",
+ "Check Comunicaciones de Marketing": "",
+ "Descripción": "",
+ "[Nombre de la Empresa]": "",
+ "Año del Vehículo": "2019",
+ "[Dirección de la Empresa]": "",
+ "¿Cuándo necesitas el dinero?": "",
+ "Archivos Adicionales": "",
+ "contact_id": "ZHj8ek6lQ6M6EeCIU7Uj",
+ "first_name": "LILIA LISSETH",
+ "last_name": "ZAVALA HEREDIA",
+ "full_name": "LILIA LISSETH ZAVALA HEREDIA",
+ "email": "lilia.zh0209@gmail.com",
+ "phone": "+524361175941",
+ "tags": "sucursal",
+ "country": "MX",
+ "date_created": "2026-05-25T23:59:53.804Z",
+ "full_address": "",
+ "contact_type": "lead",
+ "location": {
+ "name": "85964 - MP - Morelia 1",
+ "address": "Morelia",
+ "city": "Morelia",
+ "state": "Michoacán",
+ "country": "MX",
+ "postalCode": "58855",
+ "fullAddress": "Morelia, Morelia Michoacán 58855",
+ "id": "jE41bVhhnb5T505BFm4F"
+ },
+ "user": {
+ "firstName": "Morelia 1 - 85964",
+ "lastName": "Morelia 1",
+ "email": "ezstore85964@ezcorp.com",
+ "phone": "+524434589152"
+ },
+ "workflow": {
+ "id": "7c92fec9-b858-4a83-b2d9-31891c9b9231",
+ "name": "Sincronizar Contacto Creado V2"
+ },
+ "triggerData": {},
+ "contact": {
+ "attributionSource": {
+ "mediumId": null,
+ "medium": "manual",
+ "sessionSource": "CRM UI"
+ },
+ "lastAttributionSource": {}
+ },
+ "attributionSource": {},
+ "customData": {}
+ },
+ "webhookUrl": "https://webhookn8.consultoriae3.com/webhook/8d574598-d977-4052-823a-26def39c6a64",
+ "executionMode": "production"
+ },
+ "pairedItem": {
+ "item": 0
+ }
+ }
+ ]
+ },
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "activeVersionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "versionCounter": 234,
+ "triggerCount": 1,
+ "shared": [
+ {
+ "updatedAt": "2026-04-20T22:29:00.636Z",
+ "createdAt": "2026-04-20T22:29:00.636Z",
+ "role": "workflow:owner",
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "projectId": "aycNlMpnzsxvXbfG",
+ "project": {
+ "updatedAt": "2025-11-27T04:06:26.313Z",
+ "createdAt": "2025-11-27T03:54:24.410Z",
+ "id": "aycNlMpnzsxvXbfG",
+ "name": "Consultoria E3 ® ",
+ "type": "personal",
+ "icon": null,
+ "description": null,
+ "creatorId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ }
+ ],
+ "tags": [
+ {
+ "updatedAt": "2025-11-27T05:48:12.272Z",
+ "createdAt": "2025-11-27T05:48:12.272Z",
+ "id": "pHkPpq3Httzx4hnb",
+ "name": "Bucefalo"
+ },
+ {
+ "updatedAt": "2025-12-01T22:00:17.627Z",
+ "createdAt": "2025-12-01T22:00:17.627Z",
+ "id": "uIWgqVuJXbqA7m39",
+ "name": "PRUEBAS"
+ }
+ ],
+ "activeVersion": {
+ "updatedAt": "2026-05-30T07:15:08.612Z",
+ "createdAt": "2026-05-30T07:15:08.612Z",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "authors": "Consultoria E3 ®",
+ "name": null,
+ "description": null,
+ "autosaved": false,
+ "workflowPublishHistory": [
+ {
+ "createdAt": "2026-05-30T07:15:09.042Z",
+ "id": 666,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "event": "deactivated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ },
+ {
+ "createdAt": "2026-05-30T07:15:09.069Z",
+ "id": 667,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ },
+ {
+ "createdAt": "2026-05-30T07:15:08.695Z",
+ "id": 664,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "event": "deactivated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ },
+ {
+ "createdAt": "2026-05-30T07:15:08.729Z",
+ "id": 665,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "11c7184b-0dcd-44ba-9359-e9b83c939348",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/n8n/backup_redes_sociales_ddUEORBEtZLzsQF2_20260530_192327.json b/n8n/backup_redes_sociales_ddUEORBEtZLzsQF2_20260530_192327.json
new file mode 100644
index 0000000..8dbf9f7
--- /dev/null
+++ b/n8n/backup_redes_sociales_ddUEORBEtZLzsQF2_20260530_192327.json
@@ -0,0 +1,2069 @@
+{
+ "updatedAt": "2026-05-31T01:01:08.985Z",
+ "createdAt": "2026-04-20T22:29:00.636Z",
+ "id": "ddUEORBEtZLzsQF2",
+ "name": "[2004][Monte Providencia] Actualizar \"contact.sucursal\", \"contact.tienda\" al crear contacto",
+ "description": null,
+ "active": true,
+ "isArchived": false,
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\nconst fuenteField = findField(\"contact.fuente_de_prospecto\", [\"Fuente de Prospecto\", \"FUENTE DE PROSPECTO\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\n// Valor ACTUAL de \"Fuente de Prospecto\" en el contacto (para reconciliar SOLO si = LEAD DIGITAL).\nconst contactCFs =\n (contactResp && contactResp.contact && contactResp.contact.customFields) ||\n (contactResp && contactResp.customFields) ||\n [];\nlet fuenteActual = null;\nif (fuenteField && fuenteField.id) {\n const hit = contactCFs.find(cf => cf.id === fuenteField.id);\n fuenteActual = hit ? (hit.value != null ? hit.value : (hit.fieldValue != null ? hit.fieldValue : null)) : null;\n}\nconst fuenteEsLeadDigital = String(fuenteActual || \"\").trim().toUpperCase() === \"LEAD DIGITAL\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n fuente: {\n id: fuenteField?.id ?? null,\n name: fuenteField?.name ?? null,\n fieldKey: fuenteField?.fieldKey ?? null,\n picklistOptions: fuenteField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n fuenteActual: fuenteActual,\n fuenteEsLeadDigital: fuenteEsLeadDigital,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "fuente-es-lead-digital",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuenteEsLeadDigital }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 1820,
+ -120
+ ],
+ "name": "Fuente = LEAD DIGITAL (reconciliar)",
+ "id": "e6bc4a7a-9304-4d00-9750-4bb64a76c3d2"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2040,
+ -120
+ ],
+ "name": "PUT Fuente de Prospecto = SUCURSAL",
+ "id": "5ef526d6-4947-4725-a3d5-f85cab931142"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- facebook-ads": {
+ "main": [
+ [
+ {
+ "node": "Fuente = LEAD DIGITAL (reconciliar)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Fuente = LEAD DIGITAL (reconciliar)": {
+ "main": [
+ [
+ {
+ "node": "PUT Fuente de Prospecto = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1",
+ "binaryMode": "separate",
+ "availableInMCP": false
+ },
+ "staticData": null,
+ "meta": {
+ "templateCredsSetupCompleted": true
+ },
+ "pinData": {
+ "Webhook": [
+ {
+ "json": {
+ "headers": {
+ "host": "webhookn8.consultoriae3.com",
+ "user-agent": "axios/1.13.2",
+ "content-length": "1572",
+ "accept": "application/json, text/plain, */*",
+ "accept-encoding": "gzip, compress, deflate, br",
+ "content-type": "application/json",
+ "traceparent": "00-bfdb4ad6378402bf71f61ff3c72d0d02-ee175e0dcbcec88e-01",
+ "x-forwarded-for": "35.253.135.103",
+ "x-forwarded-host": "webhookn8.consultoriae3.com",
+ "x-forwarded-port": "443",
+ "x-forwarded-proto": "https",
+ "x-forwarded-server": "f569f6e85d30",
+ "x-real-ip": "35.253.135.103"
+ },
+ "params": {},
+ "query": {},
+ "body": {
+ "Canal de Origen": "",
+ "¿Qué modalidad prefieres?": "Sin Dejarlo (GPS)",
+ "Fuente de Prospecto": "GALLARDETES",
+ "Marca del Vehiculo": "VW",
+ "[Número de WhatsApp para Atender]": "",
+ "TIENDA": "",
+ "Presupuesto": "",
+ "Acepta los terminos para tu cotización": "",
+ "Sucursal": "",
+ "ID Contacto Monte Providencia": "",
+ "Información Adicional": "",
+ "[Número de Teléfono para Atender]": "",
+ "Version del Vehiculo": "POLO",
+ "[Correo_Canalizados]": "",
+ "[Correo_Empresa]": "",
+ "Check Comunicaciones de Marketing": "",
+ "Descripción": "",
+ "[Nombre de la Empresa]": "",
+ "Año del Vehículo": "2019",
+ "[Dirección de la Empresa]": "",
+ "¿Cuándo necesitas el dinero?": "",
+ "Archivos Adicionales": "",
+ "contact_id": "ZHj8ek6lQ6M6EeCIU7Uj",
+ "first_name": "LILIA LISSETH",
+ "last_name": "ZAVALA HEREDIA",
+ "full_name": "LILIA LISSETH ZAVALA HEREDIA",
+ "email": "lilia.zh0209@gmail.com",
+ "phone": "+524361175941",
+ "tags": "sucursal",
+ "country": "MX",
+ "date_created": "2026-05-25T23:59:53.804Z",
+ "full_address": "",
+ "contact_type": "lead",
+ "location": {
+ "name": "85964 - MP - Morelia 1",
+ "address": "Morelia",
+ "city": "Morelia",
+ "state": "Michoacán",
+ "country": "MX",
+ "postalCode": "58855",
+ "fullAddress": "Morelia, Morelia Michoacán 58855",
+ "id": "jE41bVhhnb5T505BFm4F"
+ },
+ "user": {
+ "firstName": "Morelia 1 - 85964",
+ "lastName": "Morelia 1",
+ "email": "ezstore85964@ezcorp.com",
+ "phone": "+524434589152"
+ },
+ "workflow": {
+ "id": "7c92fec9-b858-4a83-b2d9-31891c9b9231",
+ "name": "Sincronizar Contacto Creado V2"
+ },
+ "triggerData": {},
+ "contact": {
+ "attributionSource": {
+ "mediumId": null,
+ "medium": "manual",
+ "sessionSource": "CRM UI"
+ },
+ "lastAttributionSource": {}
+ },
+ "attributionSource": {},
+ "customData": {}
+ },
+ "webhookUrl": "https://webhookn8.consultoriae3.com/webhook/8d574598-d977-4052-823a-26def39c6a64",
+ "executionMode": "production"
+ },
+ "pairedItem": {
+ "item": 0
+ }
+ }
+ ]
+ },
+ "versionId": "e8f6f33f-a308-4fa6-a7a7-2c344311b69e",
+ "activeVersionId": "e8f6f33f-a308-4fa6-a7a7-2c344311b69e",
+ "versionCounter": 238,
+ "triggerCount": 1,
+ "shared": [
+ {
+ "updatedAt": "2026-04-20T22:29:00.636Z",
+ "createdAt": "2026-04-20T22:29:00.636Z",
+ "role": "workflow:owner",
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "projectId": "aycNlMpnzsxvXbfG",
+ "project": {
+ "updatedAt": "2025-11-27T04:06:26.313Z",
+ "createdAt": "2025-11-27T03:54:24.410Z",
+ "id": "aycNlMpnzsxvXbfG",
+ "name": "Consultoria E3 ® ",
+ "type": "personal",
+ "icon": null,
+ "description": null,
+ "creatorId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ }
+ ],
+ "tags": [
+ {
+ "updatedAt": "2025-11-27T05:48:12.272Z",
+ "createdAt": "2025-11-27T05:48:12.272Z",
+ "id": "pHkPpq3Httzx4hnb",
+ "name": "Bucefalo"
+ },
+ {
+ "updatedAt": "2025-12-01T22:00:17.627Z",
+ "createdAt": "2025-12-01T22:00:17.627Z",
+ "id": "uIWgqVuJXbqA7m39",
+ "name": "PRUEBAS"
+ }
+ ],
+ "activeVersion": {
+ "updatedAt": "2026-05-31T01:01:08.989Z",
+ "createdAt": "2026-05-31T01:01:08.989Z",
+ "versionId": "e8f6f33f-a308-4fa6-a7a7-2c344311b69e",
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\nconst fuenteField = findField(\"contact.fuente_de_prospecto\", [\"Fuente de Prospecto\", \"FUENTE DE PROSPECTO\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\n// Valor ACTUAL de \"Fuente de Prospecto\" en el contacto (para reconciliar SOLO si = LEAD DIGITAL).\nconst contactCFs =\n (contactResp && contactResp.contact && contactResp.contact.customFields) ||\n (contactResp && contactResp.customFields) ||\n [];\nlet fuenteActual = null;\nif (fuenteField && fuenteField.id) {\n const hit = contactCFs.find(cf => cf.id === fuenteField.id);\n fuenteActual = hit ? (hit.value != null ? hit.value : (hit.fieldValue != null ? hit.fieldValue : null)) : null;\n}\nconst fuenteEsLeadDigital = String(fuenteActual || \"\").trim().toUpperCase() === \"LEAD DIGITAL\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n fuente: {\n id: fuenteField?.id ?? null,\n name: fuenteField?.name ?? null,\n fieldKey: fuenteField?.fieldKey ?? null,\n picklistOptions: fuenteField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n fuenteActual: fuenteActual,\n fuenteEsLeadDigital: fuenteEsLeadDigital,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "fuente-es-lead-digital",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuenteEsLeadDigital }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 1820,
+ -120
+ ],
+ "name": "Fuente = LEAD DIGITAL (reconciliar)",
+ "id": "e6bc4a7a-9304-4d00-9750-4bb64a76c3d2"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2040,
+ -120
+ ],
+ "name": "PUT Fuente de Prospecto = SUCURSAL",
+ "id": "5ef526d6-4947-4725-a3d5-f85cab931142"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- facebook-ads": {
+ "main": [
+ [
+ {
+ "node": "Fuente = LEAD DIGITAL (reconciliar)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Fuente = LEAD DIGITAL (reconciliar)": {
+ "main": [
+ [
+ {
+ "node": "PUT Fuente de Prospecto = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "authors": "Consultoria E3 ®",
+ "name": null,
+ "description": null,
+ "autosaved": false,
+ "workflowPublishHistory": [
+ {
+ "createdAt": "2026-05-31T01:01:09.401Z",
+ "id": 681,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "e8f6f33f-a308-4fa6-a7a7-2c344311b69e",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/n8n/backup_redes_sociales_ddUEORBEtZLzsQF2_20260530_192343.json b/n8n/backup_redes_sociales_ddUEORBEtZLzsQF2_20260530_192343.json
new file mode 100644
index 0000000..8dbf9f7
--- /dev/null
+++ b/n8n/backup_redes_sociales_ddUEORBEtZLzsQF2_20260530_192343.json
@@ -0,0 +1,2069 @@
+{
+ "updatedAt": "2026-05-31T01:01:08.985Z",
+ "createdAt": "2026-04-20T22:29:00.636Z",
+ "id": "ddUEORBEtZLzsQF2",
+ "name": "[2004][Monte Providencia] Actualizar \"contact.sucursal\", \"contact.tienda\" al crear contacto",
+ "description": null,
+ "active": true,
+ "isArchived": false,
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\nconst fuenteField = findField(\"contact.fuente_de_prospecto\", [\"Fuente de Prospecto\", \"FUENTE DE PROSPECTO\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\n// Valor ACTUAL de \"Fuente de Prospecto\" en el contacto (para reconciliar SOLO si = LEAD DIGITAL).\nconst contactCFs =\n (contactResp && contactResp.contact && contactResp.contact.customFields) ||\n (contactResp && contactResp.customFields) ||\n [];\nlet fuenteActual = null;\nif (fuenteField && fuenteField.id) {\n const hit = contactCFs.find(cf => cf.id === fuenteField.id);\n fuenteActual = hit ? (hit.value != null ? hit.value : (hit.fieldValue != null ? hit.fieldValue : null)) : null;\n}\nconst fuenteEsLeadDigital = String(fuenteActual || \"\").trim().toUpperCase() === \"LEAD DIGITAL\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n fuente: {\n id: fuenteField?.id ?? null,\n name: fuenteField?.name ?? null,\n fieldKey: fuenteField?.fieldKey ?? null,\n picklistOptions: fuenteField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n fuenteActual: fuenteActual,\n fuenteEsLeadDigital: fuenteEsLeadDigital,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "fuente-es-lead-digital",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuenteEsLeadDigital }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 1820,
+ -120
+ ],
+ "name": "Fuente = LEAD DIGITAL (reconciliar)",
+ "id": "e6bc4a7a-9304-4d00-9750-4bb64a76c3d2"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2040,
+ -120
+ ],
+ "name": "PUT Fuente de Prospecto = SUCURSAL",
+ "id": "5ef526d6-4947-4725-a3d5-f85cab931142"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- facebook-ads": {
+ "main": [
+ [
+ {
+ "node": "Fuente = LEAD DIGITAL (reconciliar)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Fuente = LEAD DIGITAL (reconciliar)": {
+ "main": [
+ [
+ {
+ "node": "PUT Fuente de Prospecto = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1",
+ "binaryMode": "separate",
+ "availableInMCP": false
+ },
+ "staticData": null,
+ "meta": {
+ "templateCredsSetupCompleted": true
+ },
+ "pinData": {
+ "Webhook": [
+ {
+ "json": {
+ "headers": {
+ "host": "webhookn8.consultoriae3.com",
+ "user-agent": "axios/1.13.2",
+ "content-length": "1572",
+ "accept": "application/json, text/plain, */*",
+ "accept-encoding": "gzip, compress, deflate, br",
+ "content-type": "application/json",
+ "traceparent": "00-bfdb4ad6378402bf71f61ff3c72d0d02-ee175e0dcbcec88e-01",
+ "x-forwarded-for": "35.253.135.103",
+ "x-forwarded-host": "webhookn8.consultoriae3.com",
+ "x-forwarded-port": "443",
+ "x-forwarded-proto": "https",
+ "x-forwarded-server": "f569f6e85d30",
+ "x-real-ip": "35.253.135.103"
+ },
+ "params": {},
+ "query": {},
+ "body": {
+ "Canal de Origen": "",
+ "¿Qué modalidad prefieres?": "Sin Dejarlo (GPS)",
+ "Fuente de Prospecto": "GALLARDETES",
+ "Marca del Vehiculo": "VW",
+ "[Número de WhatsApp para Atender]": "",
+ "TIENDA": "",
+ "Presupuesto": "",
+ "Acepta los terminos para tu cotización": "",
+ "Sucursal": "",
+ "ID Contacto Monte Providencia": "",
+ "Información Adicional": "",
+ "[Número de Teléfono para Atender]": "",
+ "Version del Vehiculo": "POLO",
+ "[Correo_Canalizados]": "",
+ "[Correo_Empresa]": "",
+ "Check Comunicaciones de Marketing": "",
+ "Descripción": "",
+ "[Nombre de la Empresa]": "",
+ "Año del Vehículo": "2019",
+ "[Dirección de la Empresa]": "",
+ "¿Cuándo necesitas el dinero?": "",
+ "Archivos Adicionales": "",
+ "contact_id": "ZHj8ek6lQ6M6EeCIU7Uj",
+ "first_name": "LILIA LISSETH",
+ "last_name": "ZAVALA HEREDIA",
+ "full_name": "LILIA LISSETH ZAVALA HEREDIA",
+ "email": "lilia.zh0209@gmail.com",
+ "phone": "+524361175941",
+ "tags": "sucursal",
+ "country": "MX",
+ "date_created": "2026-05-25T23:59:53.804Z",
+ "full_address": "",
+ "contact_type": "lead",
+ "location": {
+ "name": "85964 - MP - Morelia 1",
+ "address": "Morelia",
+ "city": "Morelia",
+ "state": "Michoacán",
+ "country": "MX",
+ "postalCode": "58855",
+ "fullAddress": "Morelia, Morelia Michoacán 58855",
+ "id": "jE41bVhhnb5T505BFm4F"
+ },
+ "user": {
+ "firstName": "Morelia 1 - 85964",
+ "lastName": "Morelia 1",
+ "email": "ezstore85964@ezcorp.com",
+ "phone": "+524434589152"
+ },
+ "workflow": {
+ "id": "7c92fec9-b858-4a83-b2d9-31891c9b9231",
+ "name": "Sincronizar Contacto Creado V2"
+ },
+ "triggerData": {},
+ "contact": {
+ "attributionSource": {
+ "mediumId": null,
+ "medium": "manual",
+ "sessionSource": "CRM UI"
+ },
+ "lastAttributionSource": {}
+ },
+ "attributionSource": {},
+ "customData": {}
+ },
+ "webhookUrl": "https://webhookn8.consultoriae3.com/webhook/8d574598-d977-4052-823a-26def39c6a64",
+ "executionMode": "production"
+ },
+ "pairedItem": {
+ "item": 0
+ }
+ }
+ ]
+ },
+ "versionId": "e8f6f33f-a308-4fa6-a7a7-2c344311b69e",
+ "activeVersionId": "e8f6f33f-a308-4fa6-a7a7-2c344311b69e",
+ "versionCounter": 238,
+ "triggerCount": 1,
+ "shared": [
+ {
+ "updatedAt": "2026-04-20T22:29:00.636Z",
+ "createdAt": "2026-04-20T22:29:00.636Z",
+ "role": "workflow:owner",
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "projectId": "aycNlMpnzsxvXbfG",
+ "project": {
+ "updatedAt": "2025-11-27T04:06:26.313Z",
+ "createdAt": "2025-11-27T03:54:24.410Z",
+ "id": "aycNlMpnzsxvXbfG",
+ "name": "Consultoria E3 ® ",
+ "type": "personal",
+ "icon": null,
+ "description": null,
+ "creatorId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ }
+ ],
+ "tags": [
+ {
+ "updatedAt": "2025-11-27T05:48:12.272Z",
+ "createdAt": "2025-11-27T05:48:12.272Z",
+ "id": "pHkPpq3Httzx4hnb",
+ "name": "Bucefalo"
+ },
+ {
+ "updatedAt": "2025-12-01T22:00:17.627Z",
+ "createdAt": "2025-12-01T22:00:17.627Z",
+ "id": "uIWgqVuJXbqA7m39",
+ "name": "PRUEBAS"
+ }
+ ],
+ "activeVersion": {
+ "updatedAt": "2026-05-31T01:01:08.989Z",
+ "createdAt": "2026-05-31T01:01:08.989Z",
+ "versionId": "e8f6f33f-a308-4fa6-a7a7-2c344311b69e",
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\nconst fuenteField = findField(\"contact.fuente_de_prospecto\", [\"Fuente de Prospecto\", \"FUENTE DE PROSPECTO\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\n// Valor ACTUAL de \"Fuente de Prospecto\" en el contacto (para reconciliar SOLO si = LEAD DIGITAL).\nconst contactCFs =\n (contactResp && contactResp.contact && contactResp.contact.customFields) ||\n (contactResp && contactResp.customFields) ||\n [];\nlet fuenteActual = null;\nif (fuenteField && fuenteField.id) {\n const hit = contactCFs.find(cf => cf.id === fuenteField.id);\n fuenteActual = hit ? (hit.value != null ? hit.value : (hit.fieldValue != null ? hit.fieldValue : null)) : null;\n}\nconst fuenteEsLeadDigital = String(fuenteActual || \"\").trim().toUpperCase() === \"LEAD DIGITAL\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n fuente: {\n id: fuenteField?.id ?? null,\n name: fuenteField?.name ?? null,\n fieldKey: fuenteField?.fieldKey ?? null,\n picklistOptions: fuenteField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n fuenteActual: fuenteActual,\n fuenteEsLeadDigital: fuenteEsLeadDigital,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "fuente-es-lead-digital",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuenteEsLeadDigital }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 1820,
+ -120
+ ],
+ "name": "Fuente = LEAD DIGITAL (reconciliar)",
+ "id": "e6bc4a7a-9304-4d00-9750-4bb64a76c3d2"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2040,
+ -120
+ ],
+ "name": "PUT Fuente de Prospecto = SUCURSAL",
+ "id": "5ef526d6-4947-4725-a3d5-f85cab931142"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- facebook-ads": {
+ "main": [
+ [
+ {
+ "node": "Fuente = LEAD DIGITAL (reconciliar)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Fuente = LEAD DIGITAL (reconciliar)": {
+ "main": [
+ [
+ {
+ "node": "PUT Fuente de Prospecto = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "authors": "Consultoria E3 ®",
+ "name": null,
+ "description": null,
+ "autosaved": false,
+ "workflowPublishHistory": [
+ {
+ "createdAt": "2026-05-31T01:01:09.401Z",
+ "id": 681,
+ "workflowId": "ddUEORBEtZLzsQF2",
+ "versionId": "e8f6f33f-a308-4fa6-a7a7-2c344311b69e",
+ "event": "activated",
+ "userId": "74a7f127-b963-4eb0-aff4-1190428e8409"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/n8n/dryrun_Cfgwp0bOtDW8zuKW_20260530_163623.json b/n8n/dryrun_Cfgwp0bOtDW8zuKW_20260530_163623.json
new file mode 100644
index 0000000..5575b07
--- /dev/null
+++ b/n8n/dryrun_Cfgwp0bOtDW8zuKW_20260530_163623.json
@@ -0,0 +1,2033 @@
+{
+ "name": "Sincronizar Oportunidad - Nodos Nuevos (Create/Update)",
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n\n// ── CONTACT->OPP ENRICH: garantizar Sucursal / TIENDA / Canal de Origen ──\n// Respaldo cuando la opp de sucursal no trae el CF: tomar el valor del CONTACTO\n// (siempre poblado por [1604]/[2004]) y, en ultimo caso, del webhook. El fieldKey\n// canonico (sufijo) es identico en contact y opportunity.\nconst contactResp = $('Obtener Contacto - SUCURSAL').first().json;\nconst contact = (contactResp && contactResp.contact) ? contactResp.contact : (contactResp || {});\nconst webhookBody = ($('Webhook').first().json && $('Webhook').first().json.body) || {};\nconst norm2 = (s) => (s == null ? '' : String(s)).trim();\n\n// Valores del contacto por fieldKey (contacts traen {id, value}).\nconst contactValueByFieldKey = {};\nfor (const cf of (contact.customFields || [])) {\n const fk = fieldMap[cf.id] ? fieldMap[cf.id].fieldKey : null;\n if (fk) contactValueByFieldKey[fk] = cf.value;\n}\n\nconst ENRICH_TARGETS = [\n { oppKey: 'opportunity.sucursal', contactKey: 'contact.sucursal', webhookKey: 'Sucursal' },\n { oppKey: 'opportunity.tienda', contactKey: 'contact.tienda', webhookKey: 'TIENDA' },\n { oppKey: 'opportunity.fuente_de_posible_cliente', contactKey: 'contact.fuente_de_posible_cliente', webhookKey: 'CANAL DE ORIGEN' },\n];\n\nfor (const t of ENRICH_TARGETS) {\n const existing = enrichedCustomFields.find(cf => cf.fieldKey === t.oppKey);\n if (existing && norm2(existing.fieldValue) !== '') continue; // (a) ya viene de la opp\n let value = norm2(contactValueByFieldKey[t.contactKey]); // (b) contacto\n if (value === '') value = norm2(webhookBody[t.webhookKey]); // (c) webhook\n if (value === '') continue;\n if (existing) {\n existing.fieldValue = value;\n } else {\n const def = customFieldsDefs.find(d => d.fieldKey === t.oppKey);\n enrichedCustomFields.push({ id: def ? def.id : null, name: def ? def.name : null, fieldKey: t.oppKey, fieldValue: value });\n }\n}\n// ── fin CONTACT->OPP ENRICH ──\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4208,
+ 1152
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "alwaysOutputData": true,
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6048,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6288,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1750,
+ -32
+ ],
+ "name": "Obtener Contacto - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Trae el contacto de sucursal para derivar Sucursal/TIENDA/Canal de Origen de la opp cuando la opp de origen no los trae. onError=continue para no romper el sync.",
+ "id": "ef9aad0d-3139-4348-9237-9219ed11a2df"
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1"
+ }
+}
\ No newline at end of file
diff --git a/n8n/dryrun_Cfgwp0bOtDW8zuKW_20260530_165900.json b/n8n/dryrun_Cfgwp0bOtDW8zuKW_20260530_165900.json
new file mode 100644
index 0000000..cec2a7c
--- /dev/null
+++ b/n8n/dryrun_Cfgwp0bOtDW8zuKW_20260530_165900.json
@@ -0,0 +1,2041 @@
+{
+ "name": "Sincronizar Oportunidad - Nodos Nuevos (Create/Update)",
+ "nodes": [
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "3eecb45a-e24c-49ac-aef7-99843f485819",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -336,
+ -16
+ ],
+ "id": "dd424583-8295-4013-96ba-c7e29ea944c6",
+ "name": "Webhook",
+ "webhookId": "3eecb45a-e24c-49ac-aef7-99843f485819"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "b02bc821-6121-452d-a042-623fac6e443c",
+ "name": "Oportunidad.opportunity_name",
+ "value": "={{ $json.body.opportunity_name }}",
+ "type": "string"
+ },
+ {
+ "id": "898817a2-7926-4ddf-b785-cac8e28afc58",
+ "name": "Oportunidad.pipleline_stage (new)",
+ "value": "={{ $json.body.pipleline_stage }}",
+ "type": "string"
+ },
+ {
+ "id": "opp-id-sucursal-capture",
+ "name": "Oportunidad.opportunity_id",
+ "value": "={{ $json.body.id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -96,
+ -16
+ ],
+ "id": "2b3ec130-27ce-4988-82db-46e4f12c3f7d",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE SUCURSAL",
+ "height": 352,
+ "width": 1152
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1072,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "19023e33-a9f1-4c60-b87c-957e751e3dc2",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "content": "# OBTENER DATOS DE MARCA",
+ "height": 208,
+ "width": 1188,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2240,
+ -80
+ ],
+ "typeVersion": 1,
+ "id": "3a3d4f18-1a08-4dbc-a00b-7ae6bc4d49d1",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 2480,
+ -32
+ ],
+ "id": "a46df506-6a9a-420d-9cdd-6fc51d1a691e",
+ "name": "DATOS API"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 80,
+ -16
+ ],
+ "id": "25db982f-7bc7-4318-a7b0-e94326abc437",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3952,
+ -32
+ ],
+ "id": "2320b102-816e-4a0c-ae9c-e305d25df6df",
+ "name": "Actualizar Oportunidad - MARCA2",
+ "notes": "El código mapea los custom fields de una oportunidad de una sucursal hacia los IDs equivalentes de una marca. Toma tres fuentes: los metadatos de campos de la sucursal, los valores reales de esos campos en la oportunidad, y los metadatos de campos de la marca. Para cada campo con valor en la oportunidad, primero busca su `fieldKey` en los metadatos de la sucursal usando el `id`, luego usa ese `fieldKey` para encontrar el campo equivalente en la marca, y construye un array con el `id` y `key` de la marca pero con el valor original de la sucursal. Finalmente arma el body de una petición para crear/actualizar una oportunidad en la marca, reutilizando pipeline, nombre, stage y valor monetario de otros nodos, con los custom fields ya traducidos al contexto de la marca."
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1536,
+ -32
+ ],
+ "id": "4e89658b-7ffd-4a3b-b91e-9ed3223a1a73",
+ "name": "Buscar Oportunidad - SUCURSAL",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 528,
+ -32
+ ],
+ "id": "b721a65d-bcbb-44ab-bb7f-8f200b34fcdd",
+ "name": "DATOS API - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ },
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "all"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1136,
+ -32
+ ],
+ "id": "39ef9dcc-ac20-4ba2-b891-2a2baa6ea4f5",
+ "name": "Conseguir Custom Fields - Opportunity - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1712,
+ -32
+ ],
+ "id": "fbd46ae4-792b-451b-b99e-9816dc175d52",
+ "name": "Obtener info de Oportunidad - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "# ACTUALIZAR OPORTUNIDAD - MARCA",
+ "height": 352,
+ "width": 928
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3456,
+ -144
+ ],
+ "typeVersion": 1,
+ "id": "f3ca1cfe-08e2-485b-b238-9240f5753809",
+ "name": "Sticky Note2"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 208,
+ "width": 992,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 2768,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "45066721-8404-48ed-94c1-c88edf48bca5",
+ "name": "Sticky Note5"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 192,
+ "width": 928,
+ "color": 3
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 1104,
+ -64
+ ],
+ "typeVersion": 1,
+ "id": "b1646bb4-8b64-4bf4-b380-189cc7902741",
+ "name": "Sticky Note7"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Webhook').item.json.body.location.name }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 320,
+ -32
+ ],
+ "id": "12088f29-8bb4-475d-ae0e-2cbdf8033138",
+ "name": "API de Sucursal",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "=Monte Providencia"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 2288,
+ -32
+ ],
+ "id": "8c8fa238-6ce4-4adf-8926-b603987a55cf",
+ "name": "API de MARCA",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "jsCode": "const opportunityData = $('Obtener info de Oportunidad - SUCURSAL').first().json;\nconst opportunity = opportunityData.opportunity;\nconst customFieldsDefs = $('Conseguir Custom Fields - Opportunity - SUCURSAL').first().json.customFields;\nconst pipelines = $input.first().json.pipelines;\n\n// Map custom fields: id -> { fieldKey, name }\nconst fieldMap = {};\nfor (const def of customFieldsDefs) {\n fieldMap[def.id] = { fieldKey: def.fieldKey, name: def.name };\n}\n\n// Map pipelines: id -> name, stages: id -> { name, position, stageWinProbability }\nconst pipelineMap = {};\nconst stageMap = {};\nfor (const pipeline of pipelines) {\n pipelineMap[pipeline.id] = pipeline.name;\n for (const stage of pipeline.stages) {\n stageMap[stage.id] = {\n name: stage.name,\n position: stage.position,\n stageWinProbability: stage.stageWinProbability,\n color: stage.color || null\n };\n }\n}\n\n// Enrich custom fields with fieldKey and name\nconst enrichedCustomFields = opportunity.customFields.map(cf => ({\n id: cf.id,\n name: fieldMap[cf.id]?.name || null,\n fieldKey: fieldMap[cf.id]?.fieldKey || null,\n fieldValue: cf.fieldValue\n}));\n\n\n// ── CONTACT->OPP ENRICH: garantizar Sucursal / TIENDA / Canal de Origen ──\n// Respaldo cuando la opp de sucursal no trae el CF: tomar el valor del CONTACTO\n// (siempre poblado por [1604]/[2004]) y, en ultimo caso, del webhook. El fieldKey\n// canonico (sufijo) es identico en contact y opportunity.\nconst contactResp = $('Obtener Contacto - SUCURSAL').first().json;\nconst contact = (contactResp && contactResp.contact) ? contactResp.contact : (contactResp || {});\nconst webhookBody = ($('Webhook').first().json && $('Webhook').first().json.body) || {};\nconst norm2 = (s) => (s == null ? '' : String(s)).trim();\n\n// Valores del contacto por fieldKey (contacts traen {id, value}).\nconst contactValueByFieldKey = {};\nfor (const cf of (contact.customFields || [])) {\n const fk = fieldMap[cf.id] ? fieldMap[cf.id].fieldKey : null;\n if (fk) contactValueByFieldKey[fk] = cf.value;\n}\n\nconst ENRICH_TARGETS = [\n { oppKey: 'opportunity.sucursal', contactKey: 'contact.sucursal', webhookKey: 'Sucursal' },\n { oppKey: 'opportunity.tienda', contactKey: 'contact.tienda', webhookKey: 'TIENDA' },\n { oppKey: 'opportunity.fuente_de_posible_cliente', contactKey: 'contact.fuente_de_posible_cliente', webhookKey: 'CANAL DE ORIGEN' },\n];\n\nfor (const t of ENRICH_TARGETS) {\n const existing = enrichedCustomFields.find(cf => cf.fieldKey === t.oppKey);\n if (existing && norm2(existing.fieldValue) !== '') continue; // (a) ya viene de la opp\n let value = norm2(contactValueByFieldKey[t.contactKey]); // (b) contacto\n if (value === '') value = norm2(webhookBody[t.webhookKey]); // (c) webhook\n if (value === '') continue;\n if (existing) {\n existing.fieldValue = value;\n } else {\n const def = customFieldsDefs.find(d => d.fieldKey === t.oppKey);\n enrichedCustomFields.push({ id: def ? def.id : null, name: def ? def.name : null, fieldKey: t.oppKey, fieldValue: value });\n }\n}\n// ── fin CONTACT->OPP ENRICH ──\n\n// Resolve pipeline and stage info\nconst stageInfo = stageMap[opportunity.pipelineStageId] || {};\n\n// Build enriched opportunity\nconst enrichedOpportunity = {\n ...opportunity,\n pipelineName: pipelineMap[opportunity.pipelineId] || null,\n pipelineStageName: stageInfo.name || null,\n pipelineStagePosition: stageInfo.position ?? null,\n pipelineStageWinProbability: stageInfo.stageWinProbability ?? null,\n pipelineStageColor: stageInfo.color || null,\n customFields: enrichedCustomFields\n};\n\nreturn [{ json: { opportunity: enrichedOpportunity, traceId: opportunityData.traceId } }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 2080,
+ -32
+ ],
+ "id": "d9609dd9-9493-4f3d-b356-99438cedada6",
+ "name": "Mapeo completo oportunidad origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('Webhook').item.json.body.location.id }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de Sucursal').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 1872,
+ -32
+ ],
+ "id": "2d799ae3-b6b1-4e4f-8774-714ebe4f009f",
+ "name": "Obtener Pipelines - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Buscar Oportunidad - MARCA').item.json.opportunities[0].id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3216,
+ -32
+ ],
+ "id": "1eee43d2-c6a8-414b-bebf-4b31d6fb34d7",
+ "name": "Obtener info de Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('API de MARCA').item.json.Location_ID }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('API de MARCA').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "bodyParameters": {
+ "parameters": [
+ {}
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 3424,
+ -32
+ ],
+ "id": "20a1a288-2cd8-471b-9203-5ba88770edb0",
+ "name": "Obtener Pipelines - MARCA"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $json['Location ID'] }}\",\n \"query\": \"{{ $('Datos de Lead').item.json.Oportunidad.opportunity_name }}\",\n \"limit\": 1,\n \"page\": 0\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2800,
+ -32
+ ],
+ "id": "798a7e51-b8ed-4364-947a-7396fab47940",
+ "name": "Buscar Oportunidad - MARCA",
+ "notes": "NECESITA MEJORAS\n\nActualmente solo hace busqueda con base al NOMBRE DE OPORTUNIDAD.\n\nSe puede optimizar la busqueda futura añadiendo más parametros como valor de oportunidad o datos que sean 100% seguros e inmutables."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3008,
+ -32
+ ],
+ "id": "cc37ea9b-0a9f-44ce-8ce2-ee2444822ecf",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ── DATOS MARCA ──────────────────────────────────────────────────────────────\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA').first().json.customFields;\nconst marcaPipelines = $input.first().json.pipelines;\n\n// ── DATOS SUCURSAL (ya enriquecidos) ─────────────────────────────────────────\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\n\n// ── MAP PIPELINES MARCA: name -> { id, stages } ───────────────────────────────\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[pipeline.name.trim()] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[stage.name.trim()] = stage.id;\n }\n}\n\n// ── RESOLVER PIPELINE Y STAGE POR NAME DESDE SUCURSAL ────────────────────────\nconst resolvedPipelineId = marcaPipelineByName[sucursalOpp.pipelineName?.trim()] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[sucursalOpp.pipelineStageName?.trim()] || marcaOpp.pipelineStageId;\n\n// ── MAP CUSTOM FIELDS SUCURSAL: name -> fieldValue ────────────────────────────\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields) {\n if (cf.name) {\n sucursalValueByName[cf.name.trim()] = cf.fieldValue;\n }\n}\n\n// ── CONSTRUIR CUSTOM FIELDS PARA EL BODY ─────────────────────────────────────\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n const nameKey = def.name.trim();\n const sucursalValue = sucursalValueByName[nameKey];\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n const fieldValue = sucursalValue !== undefined ? sucursalValue : (marcaOriginal?.fieldValue ?? null);\n\n if (fieldValue === null) continue;\n\n customFields.push({\n id: def.id,\n key: def.fieldKey,\n field_value: fieldValue\n });\n}\n\n// ── CONSTRUIR BODY VÁLIDO PARA UPDATE OPPORTUNITY ────────────────────────────\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source,\n customFields: customFields\n};\n\nreturn [{ json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body)\n} }];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 3632,
+ -32
+ ],
+ "id": "3b547c2a-a541-4b48-8d97-ea2d5df52010",
+ "name": "Code in JavaScript"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"pageLimit\": 10,\n \"query\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono || $('Datos de Lead').item.json.Cliente.Email }}\"\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3360,
+ 960
+ ],
+ "id": "02cd0fd6-6bb8-4faa-b85f-5d42663fba29",
+ "name": "Buscar Contacto en MARCA",
+ "notes": "Busca contacto en la location de marca por email.\nSi no encuentra, la siguiente IF deriva a creación."
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "exist-contact-check",
+ "leftValue": "={{ $json.contacts ? $json.contacts.length : 0 }}",
+ "rightValue": 0,
+ "operator": {
+ "type": "number",
+ "operation": "gt"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 3600,
+ 960
+ ],
+ "id": "aa2644dc-34b4-4159-8afb-89147b12f5ee",
+ "name": "¿Existe contacto en MARCA?"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/contacts/upsert",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('DATOS API').item.json['Location ID'] }}\",\n \"firstName\": \"{{ $('Datos de Lead').item.json.Cliente.Apellido }}\",\n \"name\": \"{{ $('Datos de Lead').item.json.Cliente['Nombre Completo'] }}\",\n \"email\": \"{{ $('Datos de Lead').item.json.Cliente.Email }}\",\n \"phone\": \"{{ $('Datos de Lead').item.json.Cliente.Telefono }}\",\n \"source\": \"Sincronización Sucursal\",\n \"tags\": [\"sincronizado-sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 3840,
+ 1104
+ ],
+ "id": "f6c75352-3b9e-4fc9-b8e4-063c2792d190",
+ "name": "Crear Contacto en MARCA",
+ "notes": "Crea contacto en la marca solo si no existía.\nIMPORTANTE: revisa el mapeo de Nombre/Apellido, en el workflow original están invertidos."
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "contact-id-resolved",
+ "name": "contactId",
+ "value": "={{ $json.contact ? $json.contact.id : $json.contacts[0].id }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ 4080,
+ 960
+ ],
+ "id": "2a49d01e-6679-4584-9d9b-5778dfc4431e",
+ "name": "Set Contact ID Resuelto",
+ "notes": "Unifica el contactId tanto si vino de la búsqueda (contacts[0].id) como de la creación (contact.id)."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "location_id",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ },
+ {
+ "name": "contact_id",
+ "value": "={{ $('Set Contact ID Resuelto').item.json.contactId }}"
+ },
+ {
+ "name": "limit",
+ "value": "100"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 4320,
+ 960
+ ],
+ "id": "8e25f660-3ed2-4597-9c2a-7480ac7d150f",
+ "name": "Buscar Oportunidades del Contacto - MARCA",
+ "notes": "Busca TODAS las oportunidades del contacto en la marca.\nDespués el Code de decisión elige cuál (o crea nueva)."
+ },
+ {
+ "parameters": {
+ "jsCode": "// DECISION (Create vs Update) con idempotencia GLOBAL via mapeo Baserow (tabla 754).\n// (1) Si el mapeo id_opp_sucursal -> id_opp_marca existe -> UPDATE esa opp de Marca,\n// independiente del contacto resuelto (evita duplicados por contacto ambiguo).\n// (2) Si no hay mapeo, match por CF entre las opps del contacto resuelto.\n// (3) Si nada -> CREATE.\nconst result = $input.first().json;\nconst opportunities = result.opportunities || [];\nconst sucursalOppId = $('Datos de Lead').first().json.Oportunidad.opportunity_id;\n\nlet action = 'CREATE';\nlet opportunityId = null;\nlet matchReason = '';\n\n// (1) Mapeo Baserow global\nlet baserowRows = [];\ntry { baserowRows = $('Buscar Mapeo Opp - Baserow').all().map(i => i.json); } catch (e) { baserowRows = []; }\nconst mapped = baserowRows.find(r =>\n String(r.id_opp_sucursal || '') === String(sucursalOppId) && String(r.id_opp_marca || '').trim()\n);\n\nif (mapped) {\n action = 'UPDATE';\n opportunityId = String(mapped.id_opp_marca).trim();\n matchReason = 'Match por mapeo Baserow (global, tabla 754)';\n} else {\n // (2) match por CF entre las opps del contacto resuelto\n const match = opportunities.find(o =>\n (o.customFields || []).some(cf => {\n const v = cf.fieldValueString ?? cf.fieldValue ?? '';\n return String(v) === String(sucursalOppId);\n })\n );\n if (match) {\n action = 'UPDATE';\n opportunityId = match.id;\n matchReason = 'Match por ID Oportunidad Sucursal (contacto)';\n } else {\n action = 'CREATE';\n matchReason = 'Sin match (Baserow ni contacto) -> CREATE (contacto tiene ' + opportunities.length + ' opps)';\n }\n}\n\nreturn [{\n json: {\n action,\n opportunityId,\n matchReason,\n sucursalOppId,\n contactId: $('Set Contact ID Resuelto').first().json.contactId,\n totalOppsContacto: opportunities.length\n }\n}];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 4560,
+ 960
+ ],
+ "id": "6ca30f13-8503-427f-95ec-b243d30688ec",
+ "name": "Decidir Match (Create vs Update)"
+ },
+ {
+ "parameters": {
+ "rules": {
+ "values": [
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-update",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "UPDATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "UPDATE"
+ },
+ {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "switch-create",
+ "leftValue": "={{ $json.action }}",
+ "rightValue": "CREATE",
+ "operator": {
+ "type": "string",
+ "operation": "equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "renameOutput": true,
+ "outputKey": "CREATE"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.switch",
+ "typeVersion": 3.2,
+ "position": [
+ 4800,
+ 960
+ ],
+ "id": "bff7a5dc-b4af-4033-83ea-c508aa92264a",
+ "name": "Switch UPDATE vs CREATE"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Decidir Match (Create vs Update)').item.json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5040,
+ 816
+ ],
+ "id": "83cd0fd7-1ee9-4896-926e-a0b752e216fe",
+ "name": "Obtener info de Oportunidad - MARCA (v2)",
+ "notes": "Sólo se ejecuta en rama UPDATE.\nReemplaza el nodo original 'Obtener info de Oportunidad - MARCA' que dependía de búsqueda por nombre."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 1104
+ ],
+ "id": "0fb2fdea-cf40-4dfb-abfa-c422282e5d2a",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 1104
+ ],
+ "id": "58114758-f0fb-483a-bd5b-d28188880a02",
+ "name": "Obtener Pipelines - MARCA (CREATE)"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA CREAR OPORTUNIDAD EN MARCA ──────────────────────\n// Mapea custom fields por fieldKey (fallback name) y FIJA el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia futura).\n\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (CREATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (CREATE)').first().json.pipelines || [];\nconst locationId = $('DATOS API').first().json['Location ID'];\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst contactId = decision.contactId;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\n// Map pipelines/stages de la marca por nombre normalizado\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)];\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)];\n\nif (!resolvedPipelineId) {\n throw new Error(`No se encontró pipeline en marca: \"${sucursalOpp.pipelineName}\". Revisa que el nombre coincida.`);\n}\nif (!resolvedStageId) {\n throw new Error(`No se encontró stage en marca: \"${sucursalOpp.pipelineStageName}\". Revisa que el nombre coincida.`);\n}\n\n// Mapear custom fields: preferir fieldKey, fallback a name normalizado\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null || value === '') continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// FIJAR el campo de enlace \"ID Oportunidad Sucursal\" = id de la opp de sucursal\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n locationId: locationId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || 'open',\n contactId: contactId,\n monetaryValue: sucursalOpp.monetaryValue,\n source: sucursalOpp.source || 'Sincronización Sucursal',\n customFields: customFields\n};\n\nreturn [{\n json: {\n body: JSON.stringify(body),\n debug: { resolvedPipelineId, resolvedStageId, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5520,
+ 1104
+ ],
+ "id": "2f9a63e7-277d-49de-8838-a00922c993b2",
+ "name": "Armar Body - CREATE"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5760,
+ 1104
+ ],
+ "id": "fc4b3398-91bb-4dd9-b406-96c8d75a17be",
+ "name": "Crear Oportunidad - MARCA"
+ },
+ {
+ "parameters": {
+ "jsCode": "// ─── ARMAR BODY PARA ACTUALIZAR OPORTUNIDAD EN MARCA (v2) ────────────\n// Mapea CF por fieldKey (fallback name) y reafirma el campo de enlace\n// \"ID Oportunidad Sucursal\" = id de la opp de sucursal (idempotencia).\n\nconst marcaOppData = $('Obtener info de Oportunidad - MARCA (v2)').first().json;\nconst marcaOpp = marcaOppData.opportunity;\nconst marcaCustomFieldsDefs = $('Conseguir Custom Fields - Opportunity - MARCA (UPDATE)').first().json.customFields || [];\nconst marcaPipelines = $('Obtener Pipelines - MARCA (UPDATE)').first().json.pipelines || [];\nconst sucursalOpp = $('Mapeo completo oportunidad origen - SUCURSAL').first().json.opportunity;\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst sucursalOppId = decision.sucursalOppId;\n\nconst norm = (s) => (s || '').toString().trim().toLowerCase();\n\nconst marcaPipelineByName = {};\nconst marcaStageByName = {};\nfor (const pipeline of marcaPipelines) {\n marcaPipelineByName[norm(pipeline.name)] = pipeline.id;\n for (const stage of pipeline.stages) {\n marcaStageByName[norm(stage.name)] = stage.id;\n }\n}\n\nconst resolvedPipelineId = marcaPipelineByName[norm(sucursalOpp.pipelineName)] || marcaOpp.pipelineId;\nconst resolvedStageId = marcaStageByName[norm(sucursalOpp.pipelineStageName)] || marcaOpp.pipelineStageId;\n\nconst sucursalValueByFieldKey = {};\nconst sucursalValueByName = {};\nfor (const cf of sucursalOpp.customFields || []) {\n if (cf.fieldKey) sucursalValueByFieldKey[cf.fieldKey] = cf.fieldValue;\n if (cf.name) sucursalValueByName[norm(cf.name)] = cf.fieldValue;\n}\n\nconst customFields = [];\nfor (const def of marcaCustomFieldsDefs) {\n let value = sucursalValueByFieldKey[def.fieldKey];\n if (value === undefined && def.name) value = sucursalValueByName[norm(def.name)];\n if (value === undefined || value === null) {\n const marcaOriginal = marcaOpp.customFields?.find(cf => cf.id === def.id);\n value = marcaOriginal?.fieldValue;\n }\n if (value === undefined || value === null) continue;\n customFields.push({ id: def.id, key: def.fieldKey, field_value: value });\n}\n\n// Reafirmar el campo de enlace\nconst linkDef = marcaCustomFieldsDefs.find(d =>\n d.fieldKey === 'opportunity.id_oportunidad_sucursal' || norm(d.name) === 'id oportunidad sucursal'\n);\nlet linkFieldFound = false;\nif (linkDef) {\n linkFieldFound = true;\n const idx = customFields.findIndex(c => c.id === linkDef.id);\n const entry = { id: linkDef.id, key: linkDef.fieldKey, field_value: sucursalOppId };\n if (idx >= 0) customFields[idx] = entry; else customFields.push(entry);\n}\n\nconst body = {\n pipelineId: resolvedPipelineId,\n name: sucursalOpp.name,\n pipelineStageId: resolvedStageId,\n status: sucursalOpp.status || marcaOpp.status,\n monetaryValue: sucursalOpp.monetaryValue ?? marcaOpp.monetaryValue,\n source: sucursalOpp.source || marcaOpp.source,\n customFields: customFields\n};\n\nreturn [{\n json: {\n opportunityId: marcaOpp.id,\n body: JSON.stringify(body),\n debug: { matchReason: decision.matchReason, customFieldsCount: customFields.length, sucursalOppId, linkFieldFound }\n }\n}];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 5280,
+ 816
+ ],
+ "id": "969e46cd-bbae-4372-9808-c939f63e3c02",
+ "name": "Armar Body - UPDATE (v2)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $json.opportunityId }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ $json.body }}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5520,
+ 816
+ ],
+ "id": "83929e08-7afd-4670-9c18-be22b8c3656f",
+ "name": "Actualizar Oportunidad - MARCA (v2)"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA UPDATE\n## Oportunidad ya existe en marca → se actualiza",
+ "height": 280,
+ "width": 880,
+ "color": 4
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 720
+ ],
+ "typeVersion": 1,
+ "id": "1c285234-8d90-49ef-8dac-c98cb379299a",
+ "name": "Sticky Update"
+ },
+ {
+ "parameters": {
+ "content": "# RAMA CREATE\n## Oportunidad no existe en marca → se crea desde cero\n### Incluye contacto + custom fields + tag origin-id",
+ "height": 280,
+ "width": 1120,
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 5008,
+ 1024
+ ],
+ "typeVersion": 1,
+ "id": "7e8f350c-9562-485b-8ce5-1b13b4086856",
+ "name": "Sticky Create"
+ },
+ {
+ "parameters": {
+ "content": "# MATCHING ROBUSTO\n## 1. Buscar/crear contacto en marca\n## 2. Buscar oportunidades DEL CONTACTO\n## 3. Decidir match por cantidad + tag origin-id",
+ "height": 320,
+ "width": 1500,
+ "color": 6
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ 3328,
+ 864
+ ],
+ "typeVersion": 1,
+ "id": "8a583e46-41b6-44e0-9313-b70ee085b740",
+ "name": "Sticky Matching"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('DATOS API').item.json['Location ID'] }}/customFields",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "model",
+ "value": "opportunity"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {
+ "maxRedirects": 90
+ }
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 5040,
+ 560
+ ],
+ "id": "45f0a6b0-f44d-4e83-b2ab-cdd3fbfe7911",
+ "name": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "notes": "Necesitamos los custom fields de la marca también en la rama CREATE para mapear los valores que vienen de sucursal."
+ },
+ {
+ "parameters": {
+ "url": "https://services.leadconnectorhq.com/opportunities/pipelines",
+ "sendQuery": true,
+ "queryParameters": {
+ "parameters": [
+ {
+ "name": "locationId",
+ "value": "={{ $('DATOS API').item.json['Location ID'] }}"
+ }
+ ]
+ },
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ 5280,
+ 560
+ ],
+ "id": "5ca962a9-9e56-42d1-af05-ce05d39ed77f",
+ "name": "Obtener Pipelines - MARCA (UPDATE)"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/opportunities/{{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ },
+ {
+ "name": "Content-Type",
+ "value": "application/json"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={{ JSON.stringify({ customFields: [ { id: $('Conseguir Custom Fields - Opportunity - SUCURSAL').item.json.customFields.find(f => f.fieldKey === 'opportunity.id_oportunidad_sucursal')?.id, key: 'opportunity.id_oportunidad_sucursal', field_value: $('Datos de Lead').item.json.Oportunidad.opportunity_id } ] }) }}",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1328,
+ -32
+ ],
+ "id": "a9572dee-ed57-4104-966a-4b22721e75f1",
+ "name": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Auto-mapeo de seguridad: setea 'ID Oportunidad Sucursal' = id nativo de la propia opp de sucursal (del webhook) antes de procesar. onError=continue para no romper el sync si falla."
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 754,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7280,
+ "value": "={{ $('Datos de Lead').item.json.Oportunidad.opportunity_id }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 4208,
+ 1152
+ ],
+ "id": "a64fdffd-ab8f-4ddd-a4d4-4d683a05132d",
+ "name": "Buscar Mapeo Opp - Baserow",
+ "alwaysOutputData": true,
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Idempotencia global: busca en la tabla 754 el mapeo id_opp_sucursal->id_opp_marca. Si existe, 'Decidir Match' hara UPDATE de esa opp aunque el contacto resuelto sea otro. alwaysOutputData + onError para no romper el flujo si no hay match o si Baserow falla."
+ },
+ {
+ "parameters": {
+ "jsCode": "// Prepara el UPSERT del mapeo Baserow (tabla 754) tras CREATE/UPDATE de la opp en Marca.\n// Solo escribe cuando el mapeo NO existe aun:\n// - action CREATE -> la fila no existe (el lookup Baserow fallo) -> crear.\n// - action UPDATE por contacto -> Baserow no la tenia -> crear (idempotencia futura).\n// - action UPDATE por Baserow -> la fila YA existe -> NO escribir (no duplicar).\n// Asi una re-ejecucion del mismo opp encuentra el mapeo y hace UPDATE, no CREATE duplicado.\nconst decision = $('Decidir Match (Create vs Update)').first().json;\nconst action = decision.action;\nconst matchReason = decision.matchReason || '';\nconst sucursalOppId = decision.sucursalOppId;\n\nconst matchedByBaserow = matchReason.indexOf('Baserow') !== -1;\nconst needWrite = (action === 'CREATE') || (action === 'UPDATE' && !matchedByBaserow);\nif (!needWrite) return [];\n\n// id de la opp en Marca segun el camino\nlet marcaOppId = decision.opportunityId;\nif (action === 'CREATE') {\n try {\n const co = $('Crear Oportunidad - MARCA').first().json;\n marcaOppId = (co.opportunity && co.opportunity.id) || co.id || marcaOppId;\n } catch (e) {}\n}\nif (!marcaOppId || !sucursalOppId) return [];\n\nlet locationSucursal = '';\ntry { locationSucursal = $('DATOS API - SUCURSAL').first().json['Location ID'] || ''; } catch (e) {}\n\nreturn [{ json: { sucursalOppId, marcaOppId, locationSucursal } }];\n"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 6048,
+ 960
+ ],
+ "id": "6542723e-f7b2-41de-b371-9e793d48f560",
+ "name": "Preparar Upsert Mapeo",
+ "onError": "continueRegularOutput",
+ "notes": "Decide si escribir el mapeo Baserow tras CREATE/UPDATE. Solo cuando la fila no existe (CREATE o UPDATE-por-contacto). onError continue para no romper la replicacion."
+ },
+ {
+ "parameters": {
+ "operation": "create",
+ "databaseId": 63,
+ "tableId": 754,
+ "fieldsUi": {
+ "fieldValues": [
+ {
+ "fieldId": 7280,
+ "fieldValue": "={{ $json.sucursalOppId }}"
+ },
+ {
+ "fieldId": 7283,
+ "fieldValue": "={{ $json.marcaOppId }}"
+ },
+ {
+ "fieldId": 7284,
+ "fieldValue": "={{ $json.locationSucursal }}"
+ },
+ {
+ "fieldId": 7285,
+ "fieldValue": "={{ $now.toISO() }}"
+ }
+ ]
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ 6288,
+ 960
+ ],
+ "id": "c69036dd-3914-4424-a165-6e0f3b110ebd",
+ "name": "Crear Mapeo - Baserow",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ },
+ "onError": "continueRegularOutput",
+ "notes": "Inserta el mapeo id_opp_sucursal->id_opp_marca en la tabla 754 en tiempo real. Idempotente con el backfill (verifica por id_opp_sucursal)."
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('DATOS API - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1750,
+ -32
+ ],
+ "name": "Obtener Contacto - SUCURSAL",
+ "onError": "continueRegularOutput",
+ "notes": "Trae el contacto de sucursal para derivar Sucursal/TIENDA/Canal de Origen de la opp cuando la opp de origen no los trae. onError=continue para no romper el sync.",
+ "id": "3636d605-1c44-4f2d-b64c-10a5c346cd24"
+ }
+ ],
+ "connections": {
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API": {
+ "main": [
+ [
+ {
+ "node": "Buscar Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "API de Sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "DATOS API - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapear ID Oportunidad Sucursal - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de Sucursal": {
+ "main": [
+ [
+ {
+ "node": "DATOS API - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "API de MARCA": {
+ "main": [
+ [
+ {
+ "node": "DATOS API",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapeo completo oportunidad origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "API de MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Mapeo completo oportunidad origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Code in JavaScript",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Code in JavaScript": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA2",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "¿Existe contacto en MARCA?",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "¿Existe contacto en MARCA?": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Crear Contacto en MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Contacto en MARCA": {
+ "main": [
+ [
+ {
+ "node": "Set Contact ID Resuelto",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Set Contact ID Resuelto": {
+ "main": [
+ [
+ {
+ "node": "Buscar Mapeo Opp - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Oportunidades del Contacto - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Decidir Match (Create vs Update)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Decidir Match (Create vs Update)": {
+ "main": [
+ [
+ {
+ "node": "Switch UPDATE vs CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Switch UPDATE vs CREATE": {
+ "main": [
+ [
+ {
+ "node": "Obtener info de Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener info de Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - UPDATE (v2)": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Oportunidad - MARCA (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (CREATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (CREATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - CREATE",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Armar Body - CREATE": {
+ "main": [
+ [
+ {
+ "node": "Crear Oportunidad - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Fields - Opportunity - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - MARCA (UPDATE)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Pipelines - MARCA (UPDATE)": {
+ "main": [
+ [
+ {
+ "node": "Armar Body - UPDATE (v2)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Mapear ID Oportunidad Sucursal - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidad - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Mapeo Opp - Baserow": {
+ "main": [
+ [
+ {
+ "node": "Buscar Oportunidades del Contacto - MARCA",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Crear Oportunidad - MARCA": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Oportunidad - MARCA (v2)": {
+ "main": [
+ [
+ {
+ "node": "Preparar Upsert Mapeo",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Preparar Upsert Mapeo": {
+ "main": [
+ [
+ {
+ "node": "Crear Mapeo - Baserow",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Pipelines - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1"
+ }
+}
\ No newline at end of file
diff --git a/n8n/dryrun_ddUEORBEtZLzsQF2_20260530_185416.json b/n8n/dryrun_ddUEORBEtZLzsQF2_20260530_185416.json
new file mode 100644
index 0000000..1ca8350
--- /dev/null
+++ b/n8n/dryrun_ddUEORBEtZLzsQF2_20260530_185416.json
@@ -0,0 +1,955 @@
+{
+ "name": "[2004][Monte Providencia] Actualizar \"contact.sucursal\", \"contact.tienda\" al crear contacto",
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\nconst fuenteField = findField(\"contact.fuente_de_prospecto\", [\"Fuente de Prospecto\", \"FUENTE DE PROSPECTO\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\n// Valor ACTUAL de \"Fuente de Prospecto\" en el contacto (para reconciliar SOLO si = LEAD DIGITAL).\nconst contactCFs =\n (contactResp && contactResp.contact && contactResp.contact.customFields) ||\n (contactResp && contactResp.customFields) ||\n [];\nlet fuenteActual = null;\nif (fuenteField && fuenteField.id) {\n const hit = contactCFs.find(cf => cf.id === fuenteField.id);\n fuenteActual = hit ? (hit.value != null ? hit.value : (hit.fieldValue != null ? hit.fieldValue : null)) : null;\n}\nconst fuenteEsLeadDigital = String(fuenteActual || \"\").trim().toUpperCase() === \"LEAD DIGITAL\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n fuente: {\n id: fuenteField?.id ?? null,\n name: fuenteField?.name ?? null,\n fieldKey: fuenteField?.fieldKey ?? null,\n picklistOptions: fuenteField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n fuenteActual: fuenteActual,\n fuenteEsLeadDigital: fuenteEsLeadDigital,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "fuente-es-lead-digital",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuenteEsLeadDigital }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 1820,
+ -120
+ ],
+ "name": "Fuente = LEAD DIGITAL (reconciliar)",
+ "id": "d4ba3c4b-c220-43ab-a9a7-e4f4da407647"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2040,
+ -120
+ ],
+ "name": "PUT Fuente de Prospecto = SUCURSAL",
+ "id": "1eafae90-261d-40d9-aada-01678027d915"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- facebook-ads": {
+ "main": [
+ [
+ {
+ "node": "Fuente = LEAD DIGITAL (reconciliar)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Fuente = LEAD DIGITAL (reconciliar)": {
+ "main": [
+ [
+ {
+ "node": "PUT Fuente de Prospecto = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1"
+ }
+}
\ No newline at end of file
diff --git a/n8n/dryrun_ddUEORBEtZLzsQF2_20260530_192327.json b/n8n/dryrun_ddUEORBEtZLzsQF2_20260530_192327.json
new file mode 100644
index 0000000..a8a7ef5
--- /dev/null
+++ b/n8n/dryrun_ddUEORBEtZLzsQF2_20260530_192327.json
@@ -0,0 +1,1096 @@
+{
+ "name": "[2004][Monte Providencia] Actualizar \"contact.sucursal\", \"contact.tienda\" al crear contacto",
+ "nodes": [
+ {
+ "parameters": {
+ "content": "# De Sucursal a Marca",
+ "color": 5
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -2288,
+ -320
+ ],
+ "typeVersion": 1,
+ "id": "d91325e1-1763-486c-a2c9-8cfffddd57b0",
+ "name": "Sticky Note3"
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 749,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7235,
+ "value": "={{ $('Datos de Lead').item.json.Sucursal['Cuenta Bucéfalo'] }}"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1,
+ "position": [
+ -912,
+ -320
+ ],
+ "id": "50da84c1-c2d3-4a36-91d3-e3745edccdc6",
+ "name": "Obtener Info de cuenta origen - SUCURSAL",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/locations/{{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Location ID'] }}/customFields",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ -224,
+ -320
+ ],
+ "id": "a0c27c4c-0f20-4bab-bf6b-bcdd8281a92b",
+ "name": "Conseguir Custom Cuenta Origen- SUCURSAL"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "strict",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "44d54b9e-d192-4b54-bf0c-156b79afc6e2",
+ "leftValue": "={{ $json.Cliente.Email }}",
+ "rightValue": "@ezcorp.com",
+ "operator": {
+ "type": "string",
+ "operation": "notContains"
+ }
+ },
+ {
+ "id": "64f2add6-506c-4950-8026-c04c9547aeeb",
+ "leftValue": "",
+ "rightValue": "",
+ "operator": {
+ "type": "string",
+ "operation": "equals",
+ "name": "filter.operator.equals"
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ -1392,
+ -304
+ ],
+ "id": "d68558b5-52b8-46b1-a359-fd956c7edc09",
+ "name": "Omitir @ezcorp.com"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "8a998fd4-2de6-4895-ab3d-e052e823d1b8",
+ "name": "Cliente.Fuente Posible Cliente",
+ "value": "={{ $json.body['Fuente de Posible cliente'] }}",
+ "type": "string"
+ },
+ {
+ "id": "938c6fec-ae16-4e7a-ba2a-f450794fa40d",
+ "name": "Cliente.Fecha de creación",
+ "value": "={{ $json.body.date_created }}",
+ "type": "string"
+ },
+ {
+ "id": "b56a1939-2608-47c8-85ad-b60b557d2a27",
+ "name": "Cliente.Sucursal.Sucursal",
+ "value": "={{ $json.body.Sucursal }}",
+ "type": "string"
+ },
+ {
+ "id": "0d07b9c9-4450-497b-ab81-3baa441787fb",
+ "name": "Vehiculo.Versión.Versión",
+ "value": "={{ $json.body['Version del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "75e3f337-00d1-429d-8d5b-85ec18e6c5e4",
+ "name": "Vehiculo.Marca.Marca",
+ "value": "={{ $json.body['Marca del Vehiculo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "cb09c536-fe84-4598-aaae-aa79f2eda61b",
+ "name": "Vehiculo.Marca.fieldKey",
+ "value": "=contact.marca_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "17d36409-4c54-48dd-8100-f7f667fd2415",
+ "name": "Vehiculo.Año.Año",
+ "value": "={{ $json.body['Año del Vehículo'] }}",
+ "type": "string"
+ },
+ {
+ "id": "a1886afc-b0af-4950-9752-f8bfff594896",
+ "name": "Vehiculo.Modalidad.Modalidad",
+ "value": "={{ $json.body['¿Qué modalidad prefieres?'] }}",
+ "type": "string"
+ },
+ {
+ "id": "33b2c28a-1ad3-4c74-917f-3cd718a3a709",
+ "name": "Cliente.Nombre",
+ "value": "={{ $json.body['Información Adicional'] }}",
+ "type": "string"
+ },
+ {
+ "id": "b36131ac-2d88-41f8-8f0f-7640cdb02b57",
+ "name": "Cliente.Apellido",
+ "value": "={{ $json.body.first_name }}",
+ "type": "string"
+ },
+ {
+ "id": "ae252c8f-f0a1-41d9-a21d-04ca949f01c8",
+ "name": "Cliente.Nombre Completo",
+ "value": "={{ $json.body.full_name }}",
+ "type": "string"
+ },
+ {
+ "id": "342a9377-0ded-4f23-b93b-1f76e57c0cbd",
+ "name": "Cliente.Email",
+ "value": "={{ $json.body.email }}",
+ "type": "string"
+ },
+ {
+ "id": "cf1b7058-96c2-4c73-9250-719a88b68673",
+ "name": "Cliente.Telefono",
+ "value": "={{ $json.body.phone }}",
+ "type": "string"
+ },
+ {
+ "id": "0b916193-15e8-4a91-9ff2-0a6f262b3c38",
+ "name": "Cliente.Contact ID",
+ "value": "={{ $json.body.contact_id }}",
+ "type": "string"
+ },
+ {
+ "id": "67eeaa9b-f703-4521-82af-9d2797131edc",
+ "name": "Cliente.Sucursal.fieldKey",
+ "value": "contact.sucursal",
+ "type": "string"
+ },
+ {
+ "id": "b05ea7bb-bbaa-467b-8247-eabb162ff029",
+ "name": "Vehiculo.Versión.fieldKey",
+ "value": "contact.version_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "9891b919-ef4c-46bd-8414-6d916565d896",
+ "name": "Vehiculo.Año.fieldKey",
+ "value": "contact.ano_del_vehiculo",
+ "type": "string"
+ },
+ {
+ "id": "0b6bf582-49c1-41de-9c2e-6ae85c4e41e8",
+ "name": "Vehiculo.Modalidad.fieldKey",
+ "value": "contact.que_modalidad_prefieres",
+ "type": "string"
+ },
+ {
+ "id": "57199999-2d9b-41c7-8269-5a8183ca8132",
+ "name": "Cliente.Cuándo necesitas el dinero",
+ "value": "={{ $json.body[\"¿Cuándo necesitas el dinero?\"] }}",
+ "type": "string"
+ },
+ {
+ "id": "8060d06e-b1da-4a65-8a0a-3c21d237d77e",
+ "name": "Sucursal.Cuenta Bucéfalo",
+ "value": "={{ $json.body.location.name }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -1568,
+ -304
+ ],
+ "id": "d0e455ac-7ccc-4c55-bda2-1cd22092e2d2",
+ "name": "Datos de Lead"
+ },
+ {
+ "parameters": {
+ "assignments": {
+ "assignments": [
+ {
+ "id": "55ff7d12-17b9-4bec-a324-e633020b131d",
+ "name": "Name Location",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Nombre }}",
+ "type": "string"
+ },
+ {
+ "id": "d877c8cd-db32-4c16-96dd-4eeb2dc48efe",
+ "name": "Location ID",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}",
+ "type": "string"
+ },
+ {
+ "id": "7698f395-5db8-415b-919e-3ad61c6566f8",
+ "name": "Token/API",
+ "value": "={{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}",
+ "type": "string"
+ }
+ ]
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.set",
+ "typeVersion": 3.4,
+ "position": [
+ -720,
+ -320
+ ],
+ "id": "f0cff3ec-8464-45d4-9e64-713c36e247c6",
+ "name": "Datos API Cuenta Origen - SUCURSAL",
+ "notes": "Esta en modo prueba forzada para Queretaro"
+ },
+ {
+ "parameters": {
+ "content": "# CUENTA ORIGEN",
+ "height": 240,
+ "width": 1744
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -976,
+ -384
+ ],
+ "typeVersion": 1,
+ "id": "16a74d85-1e6c-4fc7-b854-580a2d3827a0",
+ "name": "Sticky Note"
+ },
+ {
+ "parameters": {
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Webhook').item.json.body.contact_id }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['Token/API'] }}"
+ }
+ ]
+ },
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.4,
+ "position": [
+ -400,
+ -320
+ ],
+ "id": "92f33c6e-ee64-409d-8c60-9fbfe48b3265",
+ "name": "Obtener Contacto Cuenta Origen - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "content": "",
+ "height": 176,
+ "width": 608,
+ "color": 7
+ },
+ "type": "n8n-nodes-base.stickyNote",
+ "position": [
+ -448,
+ -336
+ ],
+ "typeVersion": 1,
+ "id": "768a4001-5109-493f-b12e-e8ba5d30ec2f",
+ "name": "Sticky Note1"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.sucursal.id }}\",\n \"key\": \"contact.sucursal\",\n \"field_value\": \"{{ $json.SUCURSAL }}\"\n },\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.tienda.id }}\",\n \"key\": \"contact.tienda\",\n \"field_value\": \"{{ $json.TIENDA }}\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 512,
+ -320
+ ],
+ "id": "794ce5bb-dea0-4720-958a-1f0940c79e6d",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL"
+ },
+ {
+ "parameters": {
+ "httpMethod": "POST",
+ "path": "8d574598-d977-4052-823a-26def39c6a64",
+ "options": {}
+ },
+ "type": "n8n-nodes-base.webhook",
+ "typeVersion": 2.1,
+ "position": [
+ -1776,
+ -304
+ ],
+ "id": "d4312610-e978-424c-a8a0-426026c4d4f6",
+ "name": "Webhook",
+ "webhookId": "8d574598-d977-4052-823a-26def39c6a64"
+ },
+ {
+ "parameters": {
+ "jsCode": "const customFields = $input.first().json.customFields;\n\nfunction findField(key, names) {\n let f = customFields.find(x => x.fieldKey === key);\n if (!f) {\n const wanted = names.map(n => n.toLowerCase().trim());\n f = customFields.find(x => wanted.includes((x.name || \"\").toLowerCase().trim()));\n }\n return f || null;\n}\n\nconst sucursalField = findField(\"contact.sucursal\", [\"Sucursal\"]);\nconst tiendaField = findField(\"contact.tienda\", [\"TIENDA\", \"Tienda\"]);\nconst canalField = findField(\"contact.fuente_de_posible_cliente\", [\"CANAL DE ORIGEN\", \"Canal de Origen\"]);\nconst fuenteField = findField(\"contact.fuente_de_prospecto\", [\"Fuente de Prospecto\", \"FUENTE DE PROSPECTO\"]);\n\n// createdBy.source SOLO viene del GET individual del contacto.\nconst contactResp = $('Obtener Contacto Cuenta Origen - SUCURSAL').item.json;\nconst createdBySource =\n (contactResp && contactResp.contact && contactResp.contact.createdBy && contactResp.contact.createdBy.source) ||\n (contactResp && contactResp.createdBy && contactResp.createdBy.source) ||\n null;\nconst esUsuario = createdBySource === \"WEB_USER\" || createdBySource === \"MOBILE_USER\";\n\n// Valor ACTUAL de \"Fuente de Prospecto\" en el contacto.\nconst contactCFs =\n (contactResp && contactResp.contact && contactResp.contact.customFields) ||\n (contactResp && contactResp.customFields) ||\n [];\nlet fuenteActual = null;\nif (fuenteField && fuenteField.id) {\n const hit = contactCFs.find(cf => cf.id === fuenteField.id);\n fuenteActual = hit ? (hit.value != null ? hit.value : (hit.fieldValue != null ? hit.fieldValue : null)) : null;\n}\nconst fuenteNorm = String(fuenteActual || \"\").trim().toUpperCase();\nconst fuenteEsLeadDigital = fuenteNorm === \"LEAD DIGITAL\";\nconst fuenteEsRedesSociales = fuenteNorm === \"REDES SOCIALES\";\n\nreturn [\n {\n json: {\n sucursal: {\n id: sucursalField?.id ?? null,\n name: sucursalField?.name ?? null,\n fieldKey: sucursalField?.fieldKey ?? null,\n picklistOptions: sucursalField?.picklistOptions ?? [],\n },\n tienda: {\n id: tiendaField?.id ?? null,\n name: tiendaField?.name ?? null,\n fieldKey: tiendaField?.fieldKey ?? null,\n picklistOptions: tiendaField?.picklistOptions ?? [],\n },\n canal: {\n id: canalField?.id ?? null,\n name: canalField?.name ?? null,\n fieldKey: canalField?.fieldKey ?? null,\n picklistOptions: canalField?.picklistOptions ?? [],\n },\n fuente: {\n id: fuenteField?.id ?? null,\n name: fuenteField?.name ?? null,\n fieldKey: fuenteField?.fieldKey ?? null,\n picklistOptions: fuenteField?.picklistOptions ?? [],\n },\n createdBySource: createdBySource,\n esUsuario: esUsuario,\n fuenteActual: fuenteActual,\n fuenteEsLeadDigital: fuenteEsLeadDigital,\n fuenteEsRedesSociales: fuenteEsRedesSociales,\n },\n },\n];"
+ },
+ "type": "n8n-nodes-base.code",
+ "typeVersion": 2,
+ "position": [
+ 32,
+ -320
+ ],
+ "id": "5a1cfe47-862c-4d28-a4ca-57a9f8c54a7c",
+ "name": "Buscar \"contact.sucursal\" y \"contact.tienda\""
+ },
+ {
+ "parameters": {
+ "databaseId": 63,
+ "tableId": 750,
+ "limit": 1,
+ "additionalOptions": {
+ "filters": {
+ "fields": [
+ {
+ "field": 7247,
+ "value": "={{ $('Datos API Cuenta Origen - SUCURSAL').item.json['Name Location'] }}"
+ },
+ {
+ "field": 7279,
+ "operator": "not_equal",
+ "value": "NO DIGITAL"
+ }
+ ]
+ }
+ }
+ },
+ "type": "n8n-nodes-base.baserow",
+ "typeVersion": 1.1,
+ "position": [
+ 256,
+ -320
+ ],
+ "id": "a912fac3-25d4-492a-9648-8c472098b9ca",
+ "name": "Buscar Sucursal en Verificador de Sucursales",
+ "credentials": {
+ "baserowApi": {
+ "id": "LZztQ3WMpzXjSTIH",
+ "name": "Baserow account"
+ }
+ }
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "https://services.leadconnectorhq.com/opportunities/search",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2023-02-21"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.API_token }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"locationId\": \"{{ $('Obtener Info de cuenta origen - SUCURSAL').item.json.Location_ID }}\",\n \"query\": \"{{ $json.contact.email }}\",\n \"limit\": 20,\n \"page\": 1\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1152,
+ -320
+ ],
+ "id": "4b899380-fe4a-40ad-80bb-21ef504b30ac",
+ "name": "Actualizar Contacto Cuenta Objetivo - SUCURSAL1"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "canal-origen-esusuario",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.esUsuario }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 720,
+ -120
+ ],
+ "name": "Creado por usuario (Canal de Origen)",
+ "id": "49879f5e-7ce8-4ced-b1a6-96df44ac2e0a"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 940,
+ -120
+ ],
+ "name": "PUT Canal de Origen = SUCURSAL",
+ "id": "d0597a9c-aca0-40bb-98d8-bb584d2a2c3e"
+ },
+ {
+ "parameters": {
+ "method": "POST",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"sucursal\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1160,
+ -120
+ ],
+ "name": "Tag+ sucursal",
+ "id": "86bfddcb-c402-413f-9d32-c55050dc470d"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"formulario\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1380,
+ -120
+ ],
+ "name": "Tag- formulario",
+ "onError": "continueRegularOutput",
+ "id": "cbd3cfb2-28d0-44e1-9567-a269382497ae"
+ },
+ {
+ "parameters": {
+ "method": "DELETE",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}/tags",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"tags\": [\"facebook-ads\"]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1600,
+ -120
+ ],
+ "name": "Tag- facebook-ads",
+ "onError": "continueRegularOutput",
+ "id": "19bdc2b2-9345-4294-8e59-7f35963f261d"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "fuente-es-lead-digital",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuenteEsLeadDigital }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 1820,
+ -120
+ ],
+ "name": "Fuente = LEAD DIGITAL (reconciliar)",
+ "id": "e6bc4a7a-9304-4d00-9750-4bb64a76c3d2"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.fieldKey }}\",\n \"field_value\": \"SUCURSAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 2040,
+ -120
+ ],
+ "name": "PUT Fuente de Prospecto = SUCURSAL",
+ "id": "5ef526d6-4947-4725-a3d5-f85cab931142"
+ },
+ {
+ "parameters": {
+ "conditions": {
+ "options": {
+ "caseSensitive": true,
+ "leftValue": "",
+ "typeValidation": "loose",
+ "version": 3
+ },
+ "conditions": [
+ {
+ "id": "fuente-es-redes-sociales",
+ "leftValue": "={{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuenteEsRedesSociales }}",
+ "rightValue": "",
+ "operator": {
+ "type": "boolean",
+ "operation": "true",
+ "singleValue": true
+ }
+ }
+ ],
+ "combinator": "and"
+ },
+ "options": {}
+ },
+ "type": "n8n-nodes-base.if",
+ "typeVersion": 2.3,
+ "position": [
+ 820,
+ -320
+ ],
+ "name": "Fuente es REDES SOCIALES",
+ "id": "215a1570-a538-4b2a-97e7-afc0c4dfae93"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.canal.fieldKey }}\",\n \"field_value\": \"FACEBOOK\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1040,
+ -320
+ ],
+ "name": "PUT Canal de Origen = FACEBOOK",
+ "id": "0d27dc59-52b0-49cf-871b-605b24b04f3f"
+ },
+ {
+ "parameters": {
+ "method": "PUT",
+ "url": "=https://services.leadconnectorhq.com/contacts/{{ $('Datos de Lead').item.json.Cliente['Contact ID'] }}",
+ "sendHeaders": true,
+ "headerParameters": {
+ "parameters": [
+ {
+ "name": "Accept",
+ "value": "application/json"
+ },
+ {
+ "name": "Version",
+ "value": "2021-07-28"
+ },
+ {
+ "name": "Authorization",
+ "value": "=Bearer {{ $('Buscar Sucursal en Verificador de Sucursales').item.json['SC TOKEN BUCEFALO'] }}"
+ }
+ ]
+ },
+ "sendBody": true,
+ "specifyBody": "json",
+ "jsonBody": "={\n \"customFields\": [\n {\n \"id\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.id }}\",\n \"key\": \"{{ $('Buscar \"contact.sucursal\" y \"contact.tienda\"').item.json.fuente.fieldKey }}\",\n \"field_value\": \"LEAD DIGITAL\"\n }\n ]\n}",
+ "options": {
+ "redirect": {
+ "redirect": {}
+ }
+ }
+ },
+ "type": "n8n-nodes-base.httpRequest",
+ "typeVersion": 4.2,
+ "position": [
+ 1260,
+ -320
+ ],
+ "name": "PUT Fuente de Prospecto = LEAD DIGITAL",
+ "id": "834217ba-07ed-47cb-b771-1cd5e99bf11e"
+ }
+ ],
+ "connections": {
+ "Obtener Info de cuenta origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Datos API Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Conseguir Custom Cuenta Origen- SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Buscar \"contact.sucursal\" y \"contact.tienda\"",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Omitir @ezcorp.com": {
+ "main": [
+ [
+ {
+ "node": "Obtener Info de cuenta origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos de Lead": {
+ "main": [
+ [
+ {
+ "node": "Omitir @ezcorp.com",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Datos API Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Obtener Contacto Cuenta Origen - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Obtener Contacto Cuenta Origen - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Conseguir Custom Cuenta Origen- SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Webhook": {
+ "main": [
+ [
+ {
+ "node": "Datos de Lead",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar Sucursal en Verificador de Sucursales": {
+ "main": [
+ [
+ {
+ "node": "Actualizar Contacto Cuenta Objetivo - SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Buscar \"contact.sucursal\" y \"contact.tienda\"": {
+ "main": [
+ [
+ {
+ "node": "Buscar Sucursal en Verificador de Sucursales",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Actualizar Contacto Cuenta Objetivo - SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Creado por usuario (Canal de Origen)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Creado por usuario (Canal de Origen)": {
+ "main": [
+ [
+ {
+ "node": "Fuente es REDES SOCIALES",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = SUCURSAL": {
+ "main": [
+ [
+ {
+ "node": "Tag+ sucursal",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag+ sucursal": {
+ "main": [
+ [
+ {
+ "node": "Tag- formulario",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- formulario": {
+ "main": [
+ [
+ {
+ "node": "Tag- facebook-ads",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Tag- facebook-ads": {
+ "main": [
+ [
+ {
+ "node": "Fuente = LEAD DIGITAL (reconciliar)",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Fuente = LEAD DIGITAL (reconciliar)": {
+ "main": [
+ [
+ {
+ "node": "PUT Fuente de Prospecto = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "Fuente es REDES SOCIALES": {
+ "main": [
+ [
+ {
+ "node": "PUT Canal de Origen = FACEBOOK",
+ "type": "main",
+ "index": 0
+ }
+ ],
+ [
+ {
+ "node": "PUT Canal de Origen = SUCURSAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ },
+ "PUT Canal de Origen = FACEBOOK": {
+ "main": [
+ [
+ {
+ "node": "PUT Fuente de Prospecto = LEAD DIGITAL",
+ "type": "main",
+ "index": 0
+ }
+ ]
+ ]
+ }
+ },
+ "settings": {
+ "executionOrder": "v1"
+ }
+}
\ No newline at end of file
diff --git a/scripts/_investigate_erika.py b/scripts/_investigate_erika.py
new file mode 100644
index 0000000..337eff6
--- /dev/null
+++ b/scripts/_investigate_erika.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""Investigacion read-only: opp de Marca hNPaauyuqM1Epycwj0wj (ERIKA RUBI CONCHA).
+Imprime CF resueltos, contactId, link a sucursal y busca el contacto en sucursales."""
+import os, sys
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if ROOT_DIR not in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+import sync_engine
+from scripts import common
+
+gc = sync_engine.ghl_client
+BRAND = common.BRAND_LOCATION_ID
+OPP_ID = "hNPaauyuqM1Epycwj0wj"
+
+accounts = {a["location_id"]: a for a in common.load_accounts()}
+brand_token = accounts[BRAND]["token"]
+
+
+def keymap(token, loc, obj):
+ fields = gc.get_object_schema_fields(token, loc, obj)
+ return {f["id"]: f.get("fieldKey") for f in fields if f.get("id")}
+
+
+def cfval(cf):
+ for k in ("fieldValue", "fieldValueString", "value"):
+ if cf.get(k) is not None:
+ return cf[k]
+ return None
+
+
+opp = (gc.get_opportunity(brand_token, OPP_ID) or {}).get("opportunity") or {}
+print("=== OPP MARCA ===")
+print("name:", opp.get("name"))
+print("status:", opp.get("status"), "value:", opp.get("monetaryValue"))
+print("contactId:", opp.get("contactId") or (opp.get("contact") or {}).get("id"))
+id2key = keymap(brand_token, BRAND, "opportunity")
+print("--- customFields (opp Marca) ---")
+link = None
+for cf in opp.get("customFields") or []:
+ k = id2key.get(cf.get("id"))
+ v = cfval(cf)
+ print(f" {k} = {v!r}")
+ if k == "opportunity.id_oportunidad_sucursal":
+ link = v
+print("LINK id_oportunidad_sucursal:", link)
+
+# contacto de Marca
+cid = opp.get("contactId") or (opp.get("contact") or {}).get("id")
+if cid:
+ c = (gc._request("GET", f"/contacts/{cid}", brand_token) or {}).get("contact") or {}
+ print("\n=== CONTACTO MARCA ===")
+ print("name:", c.get("contactName") or f"{c.get('firstName')} {c.get('lastName')}")
+ print("phone:", c.get("phone"), "email:", c.get("email"))
+ ck = keymap(brand_token, BRAND, "contact")
+ for cf in c.get("customFields") or []:
+ k = ck.get(cf.get("id"))
+ if k in ("contact.id_contacto_sucursal", "contact.sucursal", "contact.tienda",
+ "contact.fuente_de_posible_cliente", "contact.fuente_de_prospecto"):
+ print(f" {k} = {cf.get('value')!r}")
+
+# buscar la opp link en cada sucursal para identificar la sucursal de origen
+if link:
+ print("\n=== BUSCANDO opp", link, "EN SUCURSALES ===")
+ for loc, acc in accounts.items():
+ if loc == BRAND or acc.get("type") == "brand":
+ continue
+ try:
+ bo = (gc.get_opportunity(acc["token"], link) or {}).get("opportunity") or {}
+ except Exception:
+ bo = {}
+ if bo:
+ print(f" ENCONTRADA en {acc['nombre']} ({loc})")
+ bk = keymap(acc["token"], loc, "opportunity")
+ for cf in bo.get("customFields") or []:
+ k = bk.get(cf.get("id"))
+ if k in ("opportunity.sucursal", "opportunity.tienda",
+ "opportunity.fuente_de_posible_cliente", "opportunity.fuente_de_prospecto"):
+ print(f" {k} = {cfval(cf)!r}")
+ break
+ else:
+ print(" No encontrada por GET directo en ninguna sucursal.")
diff --git a/scripts/audit_origen_fuente_incoherencia.py b/scripts/audit_origen_fuente_incoherencia.py
new file mode 100644
index 0000000..6d3b552
--- /dev/null
+++ b/scripts/audit_origen_fuente_incoherencia.py
@@ -0,0 +1,137 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""Read-only: clasifica la incoherencia Canal de Origen / Fuente de Prospecto.
+
+Detecta en SUCURSALES los dos patrones incoherentes y, para cada contacto,
+lee ``createdBy.source`` EN VIVO (solo viene en el GET individual) para decidir
+la verdad del lead:
+
+ Patron A: Canal=SUCURSAL & Fuente=LEAD DIGITAL (viola AGENTS Cap.3)
+ - createdBy in {WEB_USER, MOBILE_USER} -> manual sucursal -> arreglar FUENTE (->SUCURSAL)
+ - otro (INTEGRATION/form/etc.) -> lead digital -> arreglar CANAL (->FORMULARIO/FACEBOOK)
+ Patron B: Fuente=REDES SOCIALES -> lead digital -> Canal=FACEBOOK + Fuente=LEAD DIGITAL
+
+No escribe nada. Imprime la particion y el plan por contacto.
+"""
+
+import argparse
+import json
+import os
+import sqlite3
+import sys
+from collections import Counter
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if ROOT_DIR not in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+import paths # noqa: E402
+from tag_canal_origen_workflow import ( # noqa: E402
+ MAIN_LOCATION_ID,
+ contact_display_name,
+ ghl_request,
+ load_locations,
+)
+from canal_origen_resolver import classify_source # noqa: E402
+
+USER_SOURCES = {"WEB_USER", "MOBILE_USER"}
+
+
+def cfval(custom_fields, fid):
+ for f in custom_fields or []:
+ if f.get("id") == fid:
+ for k in ("value", "fieldValue", "fieldValueString"):
+ if f.get(k) is not None:
+ return f[k]
+ return None
+
+
+def field_maps(conn, location_id):
+ m = {}
+ for r in conn.execute(
+ "select field_id, field_name from object_schemas where location_id=? and object_key='contact'",
+ (location_id,),
+ ):
+ m[r[1].strip().lower()] = r[0]
+ return m
+
+
+def incoherent_from_cache(conn, location_id):
+ """Devuelve [(contact_id, patron, canal, fuente)] desde la cache."""
+ fm = field_maps(conn, location_id)
+ canal_id = fm.get("canal de origen")
+ fuente_id = fm.get("fuente de prospecto")
+ out = []
+ for r in conn.execute(
+ "select id, custom_fields_json from contacts where location_id=?",
+ (location_id,),
+ ):
+ cf = json.loads(r[1] or "[]")
+ canal = cfval(cf, canal_id)
+ fuente = cfval(cf, fuente_id)
+ if canal == "SUCURSAL" and fuente == "LEAD DIGITAL":
+ out.append((r[0], "A", canal, fuente))
+ elif fuente == "REDES SOCIALES":
+ out.append((r[0], "B", canal, fuente))
+ return out
+
+
+def get_contact_full(contact_id, token):
+ data = ghl_request("GET", f"/contacts/{contact_id}", token)
+ inner = data.get("contact")
+ return inner if isinstance(inner, dict) else data
+
+
+def main():
+ if hasattr(sys.stdout, "reconfigure"):
+ sys.stdout.reconfigure(encoding="utf-8")
+ parser = argparse.ArgumentParser(description="Audit read-only de incoherencia origen/fuente")
+ parser.add_argument("--all", action="store_true", help="Todas las sucursales productivas")
+ parser.add_argument("--location", help="Una location especifica")
+ args = parser.parse_args()
+
+ accounts = load_locations(include_main=False)
+ accounts = [a for a in accounts if a["location_id"] != MAIN_LOCATION_ID]
+ if args.location:
+ accounts = [a for a in accounts if a["location_id"] == args.location]
+ elif not args.all:
+ raise SystemExit("Usa --all o --location ")
+
+ conn = sqlite3.connect(paths.DB_PATH)
+
+ grand = Counter()
+ for acc in accounts:
+ loc = acc["location_id"]
+ token = acc["token"]
+ targets = incoherent_from_cache(conn, loc)
+ if not targets:
+ continue
+ print(f"\n{'='*70}\n{acc['nombre']} ({loc}) - {len(targets)} incoherentes\n{'='*70}")
+ for cid, patron, canal, fuente in targets:
+ full = get_contact_full(cid, token)
+ created = (full.get("createdBy") or {}).get("source")
+ src = full.get("source")
+ name = contact_display_name(full)
+ if patron == "B":
+ plan = "Canal->FACEBOOK + Fuente->LEAD DIGITAL"
+ bucket = "B_redes->digital"
+ else:
+ if created in USER_SOURCES:
+ plan = "Fuente->SUCURSAL (manual sucursal)"
+ bucket = "A_manual->fuente"
+ else:
+ # createdBy no-usuario => digital; canal segun source
+ src_tag = classify_source(src)
+ canal_target = "FACEBOOK" if src_tag == "facebook-ads" else "FORMULARIO"
+ plan = f"Canal->{canal_target} (digital)"
+ bucket = f"A_digital->canal({canal_target})"
+ grand[bucket] += 1
+ print(f" {name:35.35} | createdBy={created or '-':12} source={src or '-':12} | {plan}")
+
+ print(f"\n{'='*70}\nRESUMEN GLOBAL (plan)\n{'='*70}")
+ for k, v in grand.most_common():
+ print(f" {v:4} {k}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/backfill_brand_opp_cf_from_source.py b/scripts/backfill_brand_opp_cf_from_source.py
new file mode 100644
index 0000000..f49155f
--- /dev/null
+++ b/scripts/backfill_brand_opp_cf_from_source.py
@@ -0,0 +1,178 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""Backfill de custom fields descriptivos en una opp de MARCA que quedó "solo
+enlace" (solo `opportunity.id_oportunidad_sucursal`), tomando los valores de la
+opp de sucursal enlazada y, como respaldo, del CONTACTO de sucursal.
+
+Caso de origen: la opp de Marca `8HITkGkOn3gN23Tl8LBr` (Miguel Temixco) quedó sin
+Sucursal / TIENDA / Canal de Origen / Vehículo. El nodo de réplica las copia por
+`fieldKey`, pero esta opp se creó fuera del flujo normal. Mismo `fieldKey`
+canónico (sufijo) en contact y opportunity.
+
+Prioridad por campo: (a) valor en la opp de sucursal → (b) valor en el contacto
+de sucursal. Solo rellena campos que estén VACÍOS en la opp de Marca (no
+sobreescribe). dry-run por defecto; snapshot + script_audit para rollback.
+
+Uso:
+ python scripts/backfill_brand_opp_cf_from_source.py \\
+ --brand-opp-id 8HITkGkOn3gN23Tl8LBr --branch-location-id yjqKxoO02rsdwdJZSPmD
+ # añade --apply para escribir en Bucéfalo
+"""
+
+import argparse
+import datetime
+import json
+import os
+import sys
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if ROOT_DIR not in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+import script_audit # noqa: E402
+import sync_engine # noqa: E402
+from scripts import common # noqa: E402
+from paths import MIGRATIONS_DIR # noqa: E402
+
+gc = sync_engine.ghl_client
+BRAND_LOCATION_ID = common.BRAND_LOCATION_ID
+LINK_KEY = "opportunity.id_oportunidad_sucursal"
+
+# (opp fieldKey canónico, contact fieldKey de respaldo o None).
+TARGETS = [
+ ("opportunity.sucursal", "contact.sucursal"),
+ ("opportunity.tienda", "contact.tienda"),
+ ("opportunity.fuente_de_posible_cliente", "contact.fuente_de_posible_cliente"), # CANAL DE ORIGEN
+ ("opportunity.fuente_de_prospecto", "contact.fuente_de_prospecto"),
+ ("opportunity.vehiculo", None), # el contacto guarda marca/versión/año por separado
+]
+
+
+def clean(v):
+ return "" if v is None else str(v).strip()
+
+
+def opp_cf_value(cf):
+ for k in ("fieldValue", "fieldValueString", "value"):
+ if cf.get(k) is not None:
+ return cf[k]
+ return None
+
+
+def schema_key_by_id(token, location_id, object_key):
+ """id -> fieldKey usando el schema dinámico de la location."""
+ fields = gc.get_object_schema_fields(token, location_id, object_key)
+ return {f["id"]: f.get("fieldKey") for f in fields if f.get("id")}, \
+ {f.get("fieldKey"): f for f in fields if f.get("fieldKey")}
+
+
+def main():
+ ap = argparse.ArgumentParser(description="Backfill CF descriptivos en opp de Marca desde la opp/contacto de sucursal.")
+ ap.add_argument("--brand-opp-id", required=True)
+ ap.add_argument("--branch-location-id", required=True)
+ ap.add_argument("--brand-location-id", default=BRAND_LOCATION_ID)
+ ap.add_argument("--apply", action="store_true")
+ ap.add_argument("--run-id", default=None)
+ args = ap.parse_args()
+
+ accounts = {a["location_id"]: a for a in common.load_accounts()}
+ brand = accounts.get(args.brand_location_id)
+ branch = accounts.get(args.branch_location_id)
+ if not brand or not branch:
+ raise SystemExit("No se encontró el token de la location de Marca o sucursal en el CSV.")
+ brand_token, branch_token = brand["token"], branch["token"]
+
+ # 1. Opp de Marca (estado actual).
+ brand_opp = (gc.get_opportunity(brand_token, args.brand_opp_id) or {}).get("opportunity") or {}
+ if not brand_opp:
+ raise SystemExit(f"No se pudo leer la opp de Marca {args.brand_opp_id}.")
+ brand_id2key, brand_key2def = schema_key_by_id(brand_token, args.brand_location_id, "opportunity")
+ brand_val_by_key = {}
+ for cf in brand_opp.get("customFields") or []:
+ k = brand_id2key.get(cf.get("id"))
+ if k:
+ brand_val_by_key[k] = opp_cf_value(cf)
+
+ # 2. Resolver la opp de sucursal enlazada (del CF link de Marca).
+ branch_opp_id = clean(brand_val_by_key.get(LINK_KEY))
+ if not branch_opp_id:
+ raise SystemExit(f"La opp de Marca no tiene {LINK_KEY}; no se puede resolver el origen.")
+ branch_opp = (gc.get_opportunity(branch_token, branch_opp_id) or {}).get("opportunity") or {}
+ if not branch_opp:
+ raise SystemExit(f"No se pudo leer la opp de sucursal {branch_opp_id}.")
+ branch_id2key, _ = schema_key_by_id(branch_token, args.branch_location_id, "opportunity")
+ branch_opp_val_by_key = {}
+ for cf in branch_opp.get("customFields") or []:
+ k = branch_id2key.get(cf.get("id"))
+ if k:
+ branch_opp_val_by_key[k] = opp_cf_value(cf)
+
+ # 3. Contacto de sucursal (respaldo).
+ branch_contact_val_by_key = {}
+ cid = branch_opp.get("contactId") or branch_opp.get("contact", {}).get("id")
+ if cid:
+ contact = (gc._request("GET", f"/contacts/{cid}", branch_token) or {}).get("contact") or {}
+ c_id2key, _ = schema_key_by_id(branch_token, args.branch_location_id, "contact")
+ for cf in contact.get("customFields") or []:
+ k = c_id2key.get(cf.get("id"))
+ if k:
+ branch_contact_val_by_key[k] = cf.get("value")
+
+ # 4. Calcular el backfill (solo campos vacíos en Marca).
+ run_id = args.run_id or f"backfill-opp-cf-{datetime.datetime.now().strftime('%Y%m%d-%H%M%S')}"
+ plan = []
+ for opp_key, contact_key in TARGETS:
+ if clean(brand_val_by_key.get(opp_key)) != "":
+ continue # ya tiene valor, no sobreescribir
+ value = clean(branch_opp_val_by_key.get(opp_key))
+ source = "opp_sucursal"
+ if value == "" and contact_key:
+ value = clean(branch_contact_val_by_key.get(contact_key))
+ source = "contacto_sucursal"
+ if value == "":
+ continue
+ bdef = brand_key2def.get(opp_key)
+ if not bdef:
+ print(f" WARN: Marca no tiene el campo {opp_key}; se omite.")
+ continue
+ plan.append({"opp_key": opp_key, "field_id": bdef["id"], "name": bdef.get("name"),
+ "value": value, "source": source})
+
+ print(f"Opp Marca: {args.brand_opp_id} <- opp sucursal: {branch_opp_id} (contacto {cid})")
+ if not plan:
+ print("Nada que rellenar (todos los campos objetivo ya tienen valor o no hay fuente).")
+ return
+ print(f"Campos a rellenar ({len(plan)}):")
+ for p in plan:
+ print(f" {p['name']:20} [{p['opp_key']}] = {p['value']!r} (fuente: {p['source']})")
+
+ if not args.apply:
+ print("\nDRY-RUN. Vuelve a correr con --apply para escribir en Bucéfalo.")
+ return
+
+ # 5. Snapshot + audit + PUT.
+ os.makedirs(MIGRATIONS_DIR, exist_ok=True)
+ snap_path = os.path.join(MIGRATIONS_DIR, f"backfill_opp_cf_{args.brand_opp_id}_{run_id}.json")
+ with open(snap_path, "w", encoding="utf-8") as fh:
+ json.dump({"run_id": run_id, "brand_opp_id": args.brand_opp_id, "before": brand_opp, "plan": plan},
+ fh, ensure_ascii=False, indent=2)
+ print(f" snapshot -> {snap_path}")
+
+ script_audit.create_run(run_id, "backfill_brand_opp_cf_from_source", arguments=" ".join(sys.argv[1:]),
+ locations=[args.brand_location_id])
+ change_ids = []
+ for p in plan:
+ cidc = script_audit.record_change(run_id, args.brand_location_id, "opportunity", args.brand_opp_id,
+ p["field_id"], p["name"], None, p["value"])
+ change_ids.append(cidc)
+
+ payload = {"customFields": [{"id": p["field_id"], "key": p["opp_key"], "field_value": p["value"]} for p in plan]}
+ gc.update_opportunity(brand_token, args.brand_opp_id, payload)
+ for cidc in change_ids:
+ script_audit.mark_change(cidc, "applied")
+ script_audit.update_run_status(run_id, "success")
+ print(f" PUT aplicado. run_id={run_id} (reversible desde el dashboard).")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/fix_origen_fuente_incoherencia.py b/scripts/fix_origen_fuente_incoherencia.py
new file mode 100644
index 0000000..209450a
--- /dev/null
+++ b/scripts/fix_origen_fuente_incoherencia.py
@@ -0,0 +1,242 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""Corrige la incoherencia Canal de Origen / Fuente de Prospecto en contactos
+y propaga a TODAS sus oportunidades asociadas.
+
+Detecta por el estado ACTUAL de los campos (idempotente) dos patrones:
+
+ Patron A Canal de Origen = SUCURSAL & Fuente de Prospecto = LEAD DIGITAL
+ (viola AGENTS Cap.3: si Canal=SUCURSAL, Fuente no puede ser LEAD DIGITAL)
+ -> Contacto: Fuente de Prospecto = SUCURSAL (Canal se conserva)
+ -> Opps: Canal de Origen de la Oportunidad = Sucursal, Fuente = SUCURSAL
+
+ Patron B Fuente de Prospecto = REDES SOCIALES
+ (REDES SOCIALES es un canal digital mal clasificado como sucursal)
+ -> Contacto: Canal de Origen = FACEBOOK, Fuente de Prospecto = LEAD DIGITAL
+ -> Opps: Canal de Origen de la Oportunidad = Facebook,
+ Tipo de Lead = Lead digital, Fuente de Prospecto = LEAD DIGITAL
+
+Decision validada con el usuario el 2026-05-30 (createdBy.source en vivo confirmo
+que los 28 del Patron A son captura manual de sucursal -> WEB_USER/MOBILE_USER).
+
+Dry-run por defecto. Con --apply --run-id registra cada cambio en script_audit
+(reversible desde el dashboard). Resuelve los IDs de campo dinamicamente por nombre
+(FIELD_ALIASES), nunca hardcodea. Sirve igual para sucursales y para Marca: como
+la deteccion es por estado, correrlo en Marca arregla el panel directamente sin
+depender de la replicacion.
+"""
+
+import argparse
+import os
+import sys
+from collections import Counter
+
+ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if ROOT_DIR not in sys.path:
+ sys.path.insert(0, ROOT_DIR)
+
+import script_audit # noqa: E402
+import sync_engine # noqa: E402
+import common # noqa: E402
+
+from tag_canal_origen_workflow import ( # noqa: E402
+ contact_display_name,
+ get_all_contacts,
+ get_all_opportunities_for_contact,
+ get_custom_field_value,
+ get_opportunity,
+ get_schemas,
+ load_locations,
+ resolve_opp_field_ids,
+ safe_update_contact_field,
+ safe_update_opportunity_field,
+)
+
+SCRIPT_NAME = "fix_origen_fuente_incoherencia.py"
+
+# Plan de correccion por patron (alineado a TAG_TO_OPP_UPDATES del workflow canonico).
+PLAN = {
+ "A": {
+ "contact": {"Fuente de Prospecto": "SUCURSAL"},
+ "opp": {
+ "Canal de Origen de la Oportunidad": "Sucursal",
+ "Fuente de Prospecto": "SUCURSAL",
+ },
+ },
+ "B": {
+ "contact": {"Canal de Origen": "FACEBOOK", "Fuente de Prospecto": "LEAD DIGITAL"},
+ "opp": {
+ "Canal de Origen de la Oportunidad": "Facebook",
+ "Tipo de Lead": "Lead digital",
+ "Fuente de Prospecto": "LEAD DIGITAL",
+ },
+ },
+}
+
+# Mapeo display-name de opp -> alias key de common.FIELD_ALIASES (tolerante a variantes).
+OPP_FIELD_ALIAS_KEY = {
+ "Canal de Origen de la Oportunidad": "canal_origen",
+ "Tipo de Lead": "tipo_lead",
+ "Fuente de Prospecto": "fuente_prospecto",
+}
+
+
+def resolve_contact_field_id(contact_schema, display_name):
+ """contact_schema es {name: id}. Resuelve por FIELD_ALIASES, tolerante a mayusculas."""
+ alias_key = {
+ "Canal de Origen": "canal_origen",
+ "Fuente de Prospecto": "fuente_prospecto",
+ }.get(display_name, display_name)
+ candidates = common.FIELD_ALIASES.get(alias_key, [display_name])
+ norm_to_id = {common.normalize_name(n): i for n, i in (contact_schema or {}).items()}
+ for cand in candidates:
+ fid = norm_to_id.get(common.normalize_name(cand))
+ if fid:
+ return fid
+ return None
+
+
+def resolve_opp_field_ids_alias(opp_fields_list, display_name):
+ alias_key = OPP_FIELD_ALIAS_KEY.get(display_name, display_name)
+ candidates = common.FIELD_ALIASES.get(alias_key, [display_name])
+ target_norm = {common.normalize_name(n) for n in candidates}
+ return [
+ f["id"]
+ for f in (opp_fields_list or [])
+ if f.get("name") and f.get("id") and common.normalize_name(f["name"]) in target_norm
+ ]
+
+
+def classify_patron(canal, fuente):
+ if canal == "SUCURSAL" and fuente == "LEAD DIGITAL":
+ return "A"
+ if fuente == "REDES SOCIALES":
+ return "B"
+ return None
+
+
+def process_location(account, *, dry_run, run_id):
+ location_id = account["location_id"]
+ token = account["token"]
+ name = account["nombre"]
+ local = Counter()
+
+ contact_schema = get_schemas(location_id, token, "contact")["contact"]
+ canal_id = resolve_contact_field_id(contact_schema, "Canal de Origen")
+ fuente_id = resolve_contact_field_id(contact_schema, "Fuente de Prospecto")
+ if not canal_id or not fuente_id:
+ print(f" SKIP {name}: faltan campos de contacto (Canal={bool(canal_id)}, Fuente={bool(fuente_id)})")
+ return local
+
+ opp_fields_list = sync_engine.ghl_client.get_object_schema_fields(token, location_id, "opportunity")
+
+ contacts = get_all_contacts(location_id, token)
+ targets = []
+ for c in contacts:
+ canal = get_custom_field_value(c, canal_id)
+ fuente = get_custom_field_value(c, fuente_id)
+ patron = classify_patron(canal, fuente)
+ if patron:
+ targets.append((c, patron))
+
+ if not targets:
+ return local
+
+ print(f"\n{'='*70}\n{name} ({location_id}) - {len(targets)} contactos a corregir\n{'='*70}")
+
+ for contact, patron in targets:
+ if not script_audit.wait_if_paused_or_stopped(run_id):
+ print("\n Detencion segura solicitada. Saliendo antes del siguiente contacto.")
+ break
+ cid = contact["id"]
+ display = contact_display_name(contact)
+ local[f"patron_{patron}"] += 1
+
+ # --- Contacto ---
+ for field_name, value in PLAN[patron]["contact"].items():
+ fid = canal_id if field_name == "Canal de Origen" else fuente_id
+ if safe_update_contact_field(run_id, location_id, contact, fid, field_name, value, token, dry_run):
+ local["contact_fields"] += 1
+ print(f" [contacto {patron}] {display} | {field_name} -> {value}")
+
+ # --- Oportunidades asociadas (todas) ---
+ for opp_summary in get_all_opportunities_for_contact(location_id, cid, token):
+ opp_id = opp_summary.get("id")
+ if not opp_id:
+ continue
+ opp = get_opportunity(location_id, opp_id, token) or opp_summary
+ opp_touched = False
+ for field_name, value in PLAN[patron]["opp"].items():
+ for fid in resolve_opp_field_ids_alias(opp_fields_list, field_name) or resolve_opp_field_ids(opp_fields_list, field_name):
+ if safe_update_opportunity_field(run_id, location_id, opp_id, opp, fid, field_name, value, token, dry_run):
+ opp_touched = True
+ if opp_touched:
+ local["opps"] += 1
+ print(f" [opp {patron}] {opp_id} | {opp.get('name') or display}")
+
+ print(f" -> {name}: A={local['patron_A']} B={local['patron_B']} | "
+ f"campos contacto={local['contact_fields']}, opps={local['opps']}")
+ return local
+
+
+def select_locations(args):
+ accounts = load_locations(include_main=True)
+ if args.location:
+ m = [a for a in accounts if a["location_id"] == args.location]
+ if not m:
+ raise SystemExit(f"Location {args.location} no esta en el CSV")
+ return m
+ if args.all:
+ return accounts
+ raise SystemExit("Especifica --location o --all. Sin --apply corre en dry-run.")
+
+
+def main():
+ if hasattr(sys.stdout, "reconfigure"):
+ sys.stdout.reconfigure(encoding="utf-8")
+ parser = argparse.ArgumentParser(description="Corrige incoherencia Canal/Fuente + propaga a opps")
+ parser.add_argument("--location", help="Location ID especifico (sucursal o Marca)")
+ parser.add_argument("--all", action="store_true", help="Todas las cuentas del CSV (sucursales + Marca)")
+ parser.add_argument("--apply", action="store_true", help="Aplica en el CRM. Sin este flag corre en dry-run.")
+ parser.add_argument("--run-id", help="ID de auditoria (lo da el dashboard; en CLI se crea si se aplica)")
+ args = parser.parse_args()
+
+ dry_run = not args.apply
+ run_id = args.run_id
+ accounts = select_locations(args)
+
+ print("=" * 70)
+ print("FIX INCOHERENCIA ORIGEN / FUENTE (+ propagacion a oportunidades)")
+ print("=" * 70)
+ print(f"Modo: {'DRY-RUN (sin cambios)' if dry_run else 'APPLY (escribe en el CRM)'}")
+ print(f"Cuentas objetivo: {len(accounts)}")
+
+ if not dry_run and run_id:
+ script_audit.create_run(run_id, SCRIPT_NAME, arguments=" ".join(sys.argv[1:]),
+ locations=[a["location_id"] for a in accounts])
+
+ grand = Counter()
+ errors = 0
+ for account in accounts:
+ try:
+ for k, v in process_location(account, dry_run=dry_run, run_id=run_id).items():
+ grand[k] += v
+ except Exception as exc: # noqa: BLE001
+ errors += 1
+ print(f"\nERROR en {account['nombre']}: {exc}")
+
+ print("\n" + "=" * 70)
+ print(f"RESUMEN: Patron A={grand['patron_A']}, Patron B={grand['patron_B']}, "
+ f"campos de contacto={grand['contact_fields']}, opps tocadas={grand['opps']}, errores={errors}")
+ if dry_run:
+ print("Dry-run terminado. Revisa el plan y vuelve a correr con --apply --run-id .")
+
+ if not dry_run and run_id:
+ script_audit.update_run_status(run_id, "failed" if errors else "success",
+ f"{errors} errores" if errors else None)
+ if errors:
+ raise SystemExit(1)
+
+
+if __name__ == "__main__":
+ main()