Objectif et prérequis

Comparez le montant d’une demande au plafond propre à son service plutôt qu’à une constante unique pour tous.

Cet exemple utilise des données et paramètres de démonstration. Validez le résultat attendu dans votre propre environnement avant de connecter des destinations de production. Les identifiants demo_* sont illustratifs : sélectionnez vos propres connexions ou sources pédagogiques dans l’éditeur. Le JSON ci-dessous présente la structure des blocs et connexions, pas une archive de flux prête à transférer.

Données d’entrée pédagogiques

requests.csv

Request;Dept;Amount
R1;IT;900
R2;HR;600
R3;IT;1200

limits.csv

Dept;Limit
IT;1000
HR;500

Blocs, connexions et paramètres exacts

Schéma explicatifAgrandir ↗11. Orienter à partir d’un référentiel de plafonds. Topologie de l’exemple 11 : 7 blocs, 6 connexions. Les identifiants de nœuds et les ports du graphe configuré sont conservés.
Schéma du flux 11

Topologie de l’exemple 11 : 7 blocs, 6 connexions. Les identifiants de nœuds et les ports du graphe configuré sont conservés.

Graphe : requests et limits → Jointure par Dept → validation du plafond obligatoire → routage Amount > Limit → deux résultats. Utilisez une jointure gauche avec many_to_one pour empêcher les doublons du référentiel de multiplier les demandes. Les champs de jointure ont les préfixes r. et l.

{
  "version": 3,
  "nodes": [
    {
      "id": "requests",
      "type": "file",
      "label": "Requests",
      "config": {
        "role": "source",
        "source_id": "demo_requests",
        "options": {
          "sheet": "CSV",
          "range": "A1:C4",
          "header": true,
          "delimiter": ";"
        }
      }
    },
    {
      "id": "limits",
      "type": "file",
      "label": "Limits",
      "config": {
        "role": "source",
        "source_id": "demo_limits",
        "options": {
          "sheet": "CSV",
          "range": "A1:B3",
          "header": true,
          "delimiter": ";"
        }
      }
    },
    {
      "id": "join",
      "type": "join",
      "label": "Department limit",
      "config": {
        "inputs": [
          {
            "id": "requests",
            "alias": "r"
          },
          {
            "id": "limits",
            "alias": "l",
            "how": "left",
            "keys": [
              {
                "left": "r.Dept",
                "right": "Dept"
              }
            ],
            "cardinality": "many_to_one"
          }
        ]
      }
    },
    {
      "id": "quality",
      "type": "quality",
      "label": "Limit required",
      "config": {
        "rules": [
          {
            "fields": [
              "l.Limit"
            ],
            "condition": "empty",
            "action": "error"
          }
        ]
      }
    },
    {
      "id": "router",
      "type": "router",
      "label": "Limit check",
      "config": {
        "route_type": "conditions",
        "mode": "first",
        "default_route": true,
        "routes": [
          {
            "id": "over",
            "label": "Over limit",
            "predicates": [
              {
                "column": "r.Amount",
                "op": "gt",
                "numeric": true,
                "value_mode": "field",
                "value_field": "l.Limit"
              }
            ]
          }
        ]
      }
    },
    {
      "id": "over_out",
      "type": "export",
      "label": "Over limit",
      "config": {
        "format": "csv",
        "filename": "over_limit",
        "destination": "download",
        "delimiter": ";",
        "timezone": "Europe/Kyiv"
      }
    },
    {
      "id": "within_out",
      "type": "export",
      "label": "Within limit",
      "config": {
        "format": "csv",
        "filename": "within_limit",
        "destination": "download",
        "delimiter": ";",
        "timezone": "Europe/Kyiv"
      }
    }
  ],
  "edges": [
    {
      "source": "requests",
      "target": "join",
      "source_port": "out",
      "target_port": "requests"
    },
    {
      "source": "limits",
      "target": "join",
      "source_port": "out",
      "target_port": "limits"
    },
    {
      "source": "join",
      "target": "quality",
      "source_port": "out",
      "target_port": "in"
    },
    {
      "source": "quality",
      "target": "router",
      "source_port": "out",
      "target_port": "in"
    },
    {
      "source": "router",
      "target": "over_out",
      "source_port": "over",
      "target_port": "in"
    },
    {
      "source": "router",
      "target": "within_out",
      "source_port": "else",
      "target_port": "in"
    }
  ]
}

Résultat attendu

over_limit.csv contient R2 (600 > 500) et R3 (1200 > 1000). within_limit.csv contient R1 (900 ≤ 1000). Le résultat inclut le plafond joint ; les champs de demande ont le préfixe r. et ceux du référentiel le préfixe l.

Exécuter et vérifier

  1. Enregistrez les deux CSV et assurez un seul plafond par Dept.
  2. Construisez le graphe JSON ; sélectionnez requests comme entrée principale de Jointure et limits comme jointure gauche par Dept.
  3. Examinez l.Limit et la règle d’erreur pour les plafonds manquants.
  4. Vérifiez les trois demandes : R1 respecte le plafond, R2 et R3 le dépassent.
  5. Ajoutez Dept=FIN sans plafond : le contrôle de qualité doit arrêter avant l’export.

Dépannage

  • Utilisez les noms exacts après Jointure, r.Amount et l.Limit.
  • Des valeurs Dept répétées enfreignent many_to_one ; corrigez le référentiel.
  • Ne remplacez pas un plafond manquant par zéro sans règle métier.
  • Le routage compare les champs de la ligne actuelle ; aucune ancienne entrée de référence n’est nécessaire.