Primer commit
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Tercer fix del path cascada del workflow Marca->Sucursal V2 (4UMRwxJdHFfOGHBp).
|
||||
|
||||
Tras arreglar el token y el locationId del 'Buscar Contacto Objetivo - SUCURSAL(mail)',
|
||||
el endpoint responde correctamente con {contacts:[], total:0} cuando no encuentra
|
||||
por email. Pero el IF siguiente `Si hay mas de un resultado` no maneja el caso
|
||||
0 resultados:
|
||||
|
||||
condiciones actuales: contacts[1] exists AND total > 0 (AND)
|
||||
true -> Retry telefono
|
||||
false -> Obtener Contacto Cuenta objetivo - SUCURSAL (BUG: con id undefined)
|
||||
|
||||
Cuando total=0, ambas condiciones son false, va a [false] -> `Obtener Contacto`
|
||||
con `$json.contacts[0].id` = undefined, lo que dispara 403 y termina en CREATE
|
||||
fallido (si hay duplicate phone) o CREATE exitoso (si es contacto nuevo).
|
||||
|
||||
Fix: alinear con la logica del IF `Si hay mas de un resultado1` (el siguiente
|
||||
en la cadena), que ya tiene la condicion correcta:
|
||||
|
||||
condiciones correctas: contacts[1] exists OR total equals 0 (OR)
|
||||
true (2+ resultados o 0 resultados) -> Retry telefono
|
||||
false (exactamente 1 resultado) -> Obtener Contacto
|
||||
|
||||
Cambio neto: 2 expressions (operator y combinator) en un solo IF. Total nodos
|
||||
sin cambios.
|
||||
"""
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from scripts.n8n_workflow_lib import load_credentials, N8NClient
|
||||
|
||||
WID = "4UMRwxJdHFfOGHBp"
|
||||
TARGET_NODE = "Si hay más de un resultado"
|
||||
REFERENCE_NODE = "Si hay más de un resultado1" # ya tiene la logica correcta
|
||||
|
||||
|
||||
def parse_args():
|
||||
ap = argparse.ArgumentParser()
|
||||
ap.add_argument("--apply", action="store_true",
|
||||
help="Aplicar PUT real (default: dry-run a n8n/dryrun_*.json)")
|
||||
return ap.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
api_key, base_url = load_credentials()
|
||||
client = N8NClient(api_key, base_url)
|
||||
|
||||
print(f"[1/6] GET workflow {WID}")
|
||||
wf = client.get_workflow(WID)
|
||||
prev_version = wf.get("versionId")
|
||||
print(f" versionId previo: {prev_version}")
|
||||
print(f" total nodos : {len(wf.get('nodes') or [])}")
|
||||
|
||||
target = next((n for n in wf["nodes"] if n.get("name") == TARGET_NODE), None)
|
||||
ref = next((n for n in wf["nodes"] if n.get("name") == REFERENCE_NODE), None)
|
||||
if not target or not ref:
|
||||
print(f"\nERROR: nodos requeridos no existen. Abortando.")
|
||||
sys.exit(2)
|
||||
|
||||
target_conds = target["parameters"]["conditions"]
|
||||
ref_conds = ref["parameters"]["conditions"]
|
||||
|
||||
print(f"\n[2/6] Diagnostico")
|
||||
print(f" Target combinator: {target_conds.get('combinator')}")
|
||||
print(f" Ref combinator: {ref_conds.get('combinator')}")
|
||||
for i, (tc, rc) in enumerate(zip(target_conds["conditions"], ref_conds["conditions"])):
|
||||
t_op = tc.get("operator", {}).get("operation")
|
||||
r_op = rc.get("operator", {}).get("operation")
|
||||
print(f" cond[{i}]: target.op={t_op} ref.op={r_op}")
|
||||
|
||||
# Aplicar misma estructura del ref al target (preservando los ids existentes)
|
||||
if target_conds.get("combinator") == "or":
|
||||
is_total_eq_zero = any(
|
||||
c.get("operator", {}).get("operation") == "equals" and c.get("leftValue", "").endswith("total }}")
|
||||
for c in target_conds["conditions"]
|
||||
)
|
||||
if is_total_eq_zero:
|
||||
print(f"\n [SKIP] Target ya esta arreglado.")
|
||||
return
|
||||
|
||||
print(f"\n[3/6] Backup fresco")
|
||||
_, bpath = client.backup_workflow(WID, label="pre_fix_cascada_if_zero_results")
|
||||
print(f" backup -> {bpath}")
|
||||
|
||||
print(f"\n[4/6] Aplicar cambio en memoria")
|
||||
# Forzar combinator OR
|
||||
target_conds["combinator"] = "or"
|
||||
# Cambiar la segunda condicion (total > 0) a (total equals 0)
|
||||
second = target_conds["conditions"][1]
|
||||
second["operator"]["operation"] = "equals"
|
||||
# rightValue ya era 0 (number), se queda igual
|
||||
print(f" nuevo combinator: {target_conds['combinator']}")
|
||||
print(f" nuevo cond[1].op: {second['operator']['operation']}")
|
||||
|
||||
print(f"\n[5/6] {'APPLY' if args.apply else 'DRY-RUN'} put_workflow")
|
||||
result = client.put_workflow(WID, wf, dry_run=not args.apply)
|
||||
if not args.apply:
|
||||
print(f" dry-run dump -> {result}")
|
||||
print("\nLISTO. Revisa el JSON. Si todo bien, corre con --apply.")
|
||||
return
|
||||
|
||||
print(f"\n[6/6] Verificar y reactivar")
|
||||
new_wf = client.verify_post(WID, prev_version_id=prev_version)
|
||||
target_post = next((n for n in new_wf["nodes"] if n.get("name") == TARGET_NODE), None)
|
||||
conds_post = target_post["parameters"]["conditions"]
|
||||
print(f" versionId nuevo : {new_wf.get('versionId')}")
|
||||
print(f" total nodos : {len(new_wf.get('nodes') or [])}")
|
||||
print(f" combinator post : {conds_post.get('combinator')}")
|
||||
print(f" cond[1].op post : {conds_post['conditions'][1]['operator']['operation']}")
|
||||
if not new_wf.get("active"):
|
||||
print(" workflow inactivo; reactivando...")
|
||||
client.activate(WID)
|
||||
new_wf = client.get_workflow(WID)
|
||||
print(f" active final : {new_wf.get('active')}")
|
||||
print("\nOK.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user