Módulo 2: Branching y Decisiones Avanzadas

Condiciones AND/OR Complejas

Descripción de la cápsula

En G1-M07-02 viste cómo combinar 2 condiciones con AND u OR. La realidad de negocio rara vez es así de simple. Casos típicos: "(USA o Canadá) y plan enterprise y consentimiento dado y email corporativo". Esto requiere anidar AND/OR con paréntesis correctos.

n8n soporta esto de 2 maneras: con grupos de condiciones dentro del IF (visual) o con expressions JavaScript dentro de un solo condition. Saber cuándo usar cada uno y cómo estructurar la lógica para que sea legible es la habilidad clave de esta cápsula.


Lo que vas a aprender

Al terminar esta cápsula serás capaz de:

  • Construir grupos de condiciones AND/OR en el IF node
  • Usar expressions para lógica booleana compleja
  • Decidir entre grupos visuales vs expression según el caso
  • Aplicar De Morgan's law para simplificar negaciones
  • Validar la lógica con casos de prueba antes de productivizar

Operadores booleanos: refresher

Lo básico:

OperadorJSSignificado
AND&&Ambas deben ser true
OR||Al menos una debe ser true
NOT!Niega (true → false)

Precedencia (importante): AND se evalúa antes que OR. Con paréntesis cambias el orden.

Ejemplo:

  • A && B || C = (A && B) || C (AND primero)
  • A && (B || C) = paréntesis cambia: AND con el resultado de OR

Método 1: Grupos de condiciones en el IF (visual)

En versiones recientes de n8n, el IF node soporta grupos. Visualmente:

[IF]
├─ Group 1: (regla A AND regla B)
│
└─ Group 2: (regla C) — combinado con OR del Group 1

Esto traduce a: (A AND B) OR C.

Cómo configurarlo

  1. Abre el IF
  2. Configura primera condición (Group 1)
  3. Click Add condition dentro del mismo grupo → segunda condición AND
  4. Click Add group → segundo grupo (combinado con OR del primero por default)
  5. Configura las condiciones del segundo grupo

Ventajas

  • Visual — quien lo abre ve la estructura clara
  • No necesita conocer JavaScript booleano
  • Combinadores AND/OR son explícitos

Limitaciones

  • No anida más de 2 niveles en algunas versiones — para lógica muy compleja, usar Método 2
  • Si la regla es ((A AND B) OR (C AND D)) AND E — eso es 3 niveles, puede ser limitante

Método 2: Expression booleana en una sola condición

En lugar de grupos visuales, escribes una expression que devuelve true/false:

{{
  ($json.country === "USA" || $json.country === "Canada") &&
  $json.plan === "enterprise" &&
  $json.consent === true
}}

Y la usas como condición: expression is true.

Ventajas

  • Cualquier complejidad soportada
  • Anida tanto como necesites con paréntesis
  • Familiar si sabes algo de JavaScript

Limitaciones

  • Menos visual — leer una expression larga es menos amigable
  • Errores de paréntesis difíciles de detectar
  • Para tu yo de 6 meses o un colega, expression complejas son menos mantenibles

Decisión: ¿Cuándo cada uno?

CasoRecomendado
2-3 condiciones simplesGrupos visuales
Lógica con 1 nivel de paréntesis ((A OR B) AND C)Grupos visuales
2+ niveles de paréntesisExpression
Quieres usar métodos string/array (.includes, .length)Expression
Workflows mantenibles por non-devsGrupos visuales

Regla general: empezar con grupos. Si te encuentras peleando con el editor visual, pasa a expression.


Pattern: De Morgan's law (simplificar negaciones)

Si te encuentras con condiciones como:

!(A && B)

Es equivalente a:

!A || !B

Y !(A || B) es equivalente a !A && !B.

Por qué importa

Negaciones de grupos son difíciles de leer. Aplicar De Morgan distribuye la negación y a veces queda más claro.

Ejemplo:

// Confuso
!($json.plan === "free" || $json.plan === "trial")

// Más claro con De Morgan
$json.plan !== "free" && $json.plan !== "trial"

Estructura recomendada: tabla de verdad

Para condiciones complejas, dibuja una tabla de verdad antes de implementar:

Pregunta: "¿Cuándo procesar este lead?"

PaísPlanConsentimiento¿Procesar?
USAenterprisetrue✅ Sí
USAtrialtrue❌ No (no es enterprise)
Canadaenterprisetrue✅ Sí
Argentinaenterprisetrue❌ No (no es USA/Canada)
USAenterprisefalse❌ No (sin consentimiento)

De acá derivas la condición:

  • Procesar si: (country === "USA" OR country === "Canada") AND plan === "enterprise" AND consent === true

Beneficio

  • Cubres casos que olvidarías de otra forma
  • Detectas inconsistencias en los requirements
  • Documentación natural de qué hace tu workflow

Casos típicos: 5 ejemplos

Ejemplo 1: Solo procesar VIPs en mercados clave

{{
  ($json.country === "USA" || $json.country === "Canada" || $json.country === "United Kingdom") &&
  $json.amount > 5000 &&
  $json.consent === true
}}

Ejemplo 2: Detectar emails sospechosos

{{
  $json.email.includes('@') &&
  !$json.email.endsWith('tempmail.com') &&
  !$json.email.endsWith('10minutemail.com') &&
  !$json.email.endsWith('guerrillamail.com') &&
  $json.name.length > 1
}}

Ejemplo 3: Routing por hora del día

{{
  DateTime.now().setZone('America/Mexico_City').hour >= 9 &&
  DateTime.now().setZone('America/Mexico_City').hour < 18 &&
  [1,2,3,4,5].includes(DateTime.now().setZone('America/Mexico_City').weekday)
}}

Devuelve true si estamos en horas de oficina (9am-6pm, lunes-viernes).

Ejemplo 4: Distintos tiers de pago con descuento

{{
  ($json.plan === "annual" && $json.amount > 0) ||
  ($json.plan === "monthly" && $json.amount > 100) ||
  ($json.promo_code === "FRIENDS50")
}}

Procesar si: plan anual con monto positivo, o plan mensual con monto >$100, o tiene código FRIENDS50.

Ejemplo 5: Validar form completo

{{
  !!$json.name &&
  $json.name.length >= 2 &&
  $json.name.length <= 100 &&
  !!$json.email &&
  /^[^@]+@[^@]+\.[^@]+$/.test($json.email) &&
  $json.consent === true
}}

(El /^[^@]+@[^@]+\.[^@]+$/ es regex para validar formato email.)


Patrón: descomponer en Booleans intermedios

Para expressions muy complejas, descomponerlas ayuda a la legibilidad.

Antes (todo en una expression)

{{
  ($json.country === "USA" || $json.country === "Canada") &&
  $json.plan === "enterprise" &&
  $json.amount > 5000 &&
  $json.consent === true &&
  !$json.email.endsWith('tempmail.com')
}}

Después (Set con Booleans intermedios + IF simple)

[Set: descomponer]
  - is_key_market: {{ ["USA", "Canada"].includes($json.country) }}
  - is_enterprise: {{ $json.plan === "enterprise" && $json.amount > 5000 }}
  - gave_consent: {{ $json.consent === true }}
  - email_valid: {{ !$json.email.endsWith('tempmail.com') }}
  - meets_all: {{
      $json.is_key_market &&
      $json.is_enterprise &&
      $json.gave_consent &&
      $json.email_valid
    }}

[IF: meets_all is true]

Ventajas:

  • Cada Boolean es debuggeable individualmente
  • Si falla, inspeccionas Set output y ves exactamente qué condición no cumple
  • Más fácil de mantener al cambiar requirements

(Pattern profundizado en cápsula 04.)


Validar con casos de prueba

Antes de productivizar lógica compleja, prueba con casos representativos.

Cómo

  1. Crea variantes de tu input pineado (cápsula 6.05 de G1)
  2. Para cada uno, mentalmente decide qué debería resultar
  3. Ejecuta el workflow con cada variante
  4. Verifica que el resultado coincide

Tabla mínima de casos

Para tu condición compleja, ten al menos:

  • 1 caso que pasa todas las condiciones (TRUE puro)
  • 1 caso que falla cada condición individual (uno por cada AND)
  • 1 caso que cumple una rama OR pero no otra (verifica OR)
  • 1 caso edge (valores límite, nulls, strings vacíos)

Pasar estos 4 casos no garantiza correctitud completa pero atrapa los errores más comunes.


Trampas comunes

Trampa 1: Paréntesis mal puestos

Qué pasa:

A && B || C

Tú lo querías como A && (B || C). Pero por precedencia, JS evalúa como (A && B) || C. Bug.

Cómo evitar: siempre usar paréntesis explícitos para grupos OR dentro de AND.


Trampa 2: Strings comparados con == en vez de ===

Qué pasa:

$json.consent == "true"

== hace coerción de tipo. "true" == true da true y "" == false da true. Resultados inconsistentes.

Cómo evitar: usar siempre === para igualdad estricta.


Trampa 3: Acceso a propiedad de null/undefined

Qué pasa:

$json.user.email.includes('@')

Si user es null, error. Si user.email es null, error.

Cómo evitar: optional chaining:

$json.user?.email?.includes('@')

(?. evita el error si la cadena es null/undefined, devuelve undefined.)


Trampa 4: Lógica que cambia entre items

Qué pasa: Tu expression funciona para un item pero falla en otro porque la estructura es ligeramente distinta (un campo presente vs ausente).

Cómo evitar:

  • Inspeccionar varios items del input antes de escribir la condición
  • Usar fallbacks: ($json.company || '').includes('Acme')

Trampa 5: Olvidar testear el lado FALSE

Qué pasa: Pruebas con datos que cumplen, ves que TRUE funciona. Activates en producción. Llegan datos que deberían ir a FALSE y van a TRUE por un bug.

Cómo evitar: siempre probar al menos un caso por rama (TRUE y FALSE), no solo el happy path.


Ejercicio: estructurar condición de validación

Objetivo: practicar el patrón de descomposición.

Tu tarea

Te dan los siguientes requirements para validar un registro:

  • Email tiene @ y no termina en .local, .test, .example
  • Nombre tiene entre 2 y 100 caracteres
  • O es enterprise (plan = enterprise) O es starter con código de descuento válido (plan = starter AND discount_code IS NOT empty)
  • Consentimiento es true

Escribe:

  1. Una versión "todo en una expression"
  2. Una versión "descomposición con Booleans intermedios"

Discusión

¿Cuál te parece más mantenible? La descompuesta. ¿Cuál es más rápido de escribir cuando ya sabes? La expression única.

Producción: descompuesta. Workflow temporal de 1 vez: lo que prefieras.


Resumen y siguiente paso

  • 2 métodos para condiciones complejas: grupos visuales (IF) y expressions booleanas
  • Grupos: mejor para non-devs y lógica simple
  • Expressions: mejor para lógica muy anidada o que usa métodos string/array
  • De Morgan's law simplifica negaciones (!(A && B) = !A || !B)
  • Tabla de verdad antes de implementar = detectar casos olvidados
  • Descomponer en Booleans intermedios con Set = más debuggeable
  • Validar con casos por rama (no solo happy path)
  • 5 trampas: paréntesis, == vs ===, optional chaining, varianza entre items, no testear FALSE

Antes de avanzar deberías poder:

  • Construir condiciones con AND/OR de 3+ niveles
  • Decidir entre grupos visuales y expression según caso
  • Descomponer una condición compleja en Booleans intermedios

Lo que sigue (cápsula 03):

IF maneja 2 caminos. Switch con 4+ ramas es para casos donde las categorías son muchas. Vas a aprender cómo estructurar Switch grandes sin que se vuelvan caóticos, incluyendo cuándo extraer cada rama a un sub-workflow.


Recursos adicionales

  1. Boolean Logic Reference (MDN) - Operadores en JS.
  2. De Morgan's Laws - Reglas para simplificar lógica.
  3. Optional Chaining - El operador ?..

Creado: Mayo 11, 2026 Versión: 1.0