Primer commit

This commit is contained in:
2026-05-30 14:31:19 -06:00
commit a35d26fac0
277 changed files with 265240 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
"""Agrega al workflow n8n de oportunidades un nodo HTTP PUT que, antes de
'Buscar Oportunidad - SUCURSAL', setea el campo 'ID Oportunidad Sucursal' de la
opp de sucursal = su propio id nativo (del webhook). Reordena la rama sucursal
para que 'Conseguir Custom Fields - Opportunity - SUCURSAL' vaya antes (necesario
para resolver el field_id, que varia por sucursal). Hace backup y verifica.
"""
import requests, json, datetime, uuid
api_key = base = None
with open('n8n/n8n credencials.txt', encoding='utf-8') as f:
for line in f:
if line.startswith('API:'): api_key = line.split('API:', 1)[1].strip()
if line.startswith('URL:'): base = line.split('URL:', 1)[1].strip().rstrip('/')
H = {'X-N8N-API-KEY': api_key, 'Accept': 'application/json', 'Content-Type': 'application/json'}
WID = 'Cfgwp0bOtDW8zuKW'
wf = requests.get(f'{base}/api/v1/workflows/{WID}', headers=H, timeout=30).json()
print('versionId previo:', wf.get('versionId'))
ts = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
bpath = f'n8n/backup_workflow_pre_automap_{ts}.json'
open(bpath, 'w', encoding='utf-8').write(json.dumps(wf, ensure_ascii=False, indent=2))
print('backup:', bpath)
nodes = wf['nodes']; conns = wf['connections']
NEW_NAME = 'Mapear ID Oportunidad Sucursal - SUCURSAL'
if any(n.get('name') == NEW_NAME for n in nodes):
print('El nodo ya existe; abortando para no duplicar.'); raise SystemExit
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 } ] }) }}")
new_node = {
"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": jsonBody,
"options": {},
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [1448, 176],
"id": str(uuid.uuid4()),
"name": NEW_NAME,
"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."),
}
nodes.append(new_node)
def setconn(src, dst):
conns[src] = {'main': [[{'node': dst, 'type': 'main', 'index': 0}]]}
# Rama sucursal reordenada: DATOS API - SUCURSAL -> Conseguir CF -> [PUT] -> Buscar Opp -> Obtener info
setconn('DATOS API - SUCURSAL', 'Conseguir Custom Fields - Opportunity - SUCURSAL')
setconn('Conseguir Custom Fields - Opportunity - SUCURSAL', NEW_NAME)
setconn(NEW_NAME, 'Buscar Oportunidad - SUCURSAL')
setconn('Buscar Oportunidad - SUCURSAL', 'Obtener info de Oportunidad - SUCURSAL')
ALLOWED = {'saveExecutionProgress', 'saveManualExecutions', 'saveDataErrorExecution',
'saveDataSuccessExecution', 'executionTimeout', 'errorWorkflow', 'timezone', 'executionOrder'}
settings = {k: v for k, v in (wf.get('settings') or {}).items() if k in ALLOWED}
payload = {'name': wf['name'], 'nodes': nodes, 'connections': conns, 'settings': settings}
r = requests.put(f'{base}/api/v1/workflows/{WID}', headers=H, data=json.dumps(payload), timeout=60)
print('PUT status:', r.status_code)
if r.status_code != 200:
print(r.text[:600]); raise SystemExit('PUT fallo')
wf2 = requests.get(f'{base}/api/v1/workflows/{WID}', headers=H, timeout=30).json()
print('versionId nuevo:', wf2.get('versionId'))
print('active:', wf2.get('active'))
print('total nodos:', len(wf2['nodes']))
print('nodo agregado:', any(n.get('name') == NEW_NAME for n in wf2['nodes']))
c = wf2['connections']
def tgt(s): return [x['node'] for o in c.get(s, {}).get('main', []) for x in (o or [])]
print('DATOS API - SUCURSAL ->', tgt('DATOS API - SUCURSAL'))
print('Conseguir CF SUCURSAL ->', tgt('Conseguir Custom Fields - Opportunity - SUCURSAL'))
print(NEW_NAME, '->', tgt(NEW_NAME))
print('Buscar Oportunidad - SUCURSAL ->', tgt('Buscar Oportunidad - SUCURSAL'))