Задача и предварительные условия

Сравните сумму заявки с индивидуальным лимитом её подразделения, а не общей константой для всех.

В примере используются демонстрационные данные и настройки. Проверьте ожидаемый результат в своей среде до подключения рабочих получателей. Идентификаторы demo_* условны: выберите собственные учебные подключения или источники в редакторе. JSON ниже показывает структуру блоков и связей, а не готовый архив потока для переноса.

Учебные входные данные

requests.csv

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

limits.csv

Dept;Limit
IT;1000
HR;500

Блоки, связи и точные настройки

Поясняющая схемаУвеличить ↗11. Маршрутизация по справочнику лимитов. Схема примера 11: 7 блоков, 6 связей. Идентификаторы узлов и порты настроенной схемы сохранены.
Схема потока 11

Схема примера 11: блоков — 7, связей — 6. Идентификаторы узлов и порты настроенной схемы сохранены.

Схема: requests и limits → соединение по Dept → проверка обязательного лимита → маршрутизация Amount > Limit → два результата. Используйте левое соединение с many_to_one, чтобы повторные строки справочника не размножали заявки. Поля соединения имеют префиксы r. и 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"
    }
  ]
}

Ожидаемый результат

over_limit.csv содержит R2 (600 > 500) и R3 (1200 > 1000). within_limit.csv содержит R1 (900 ≤ 1000). Результат включает присоединённый лимит; поля заявки имеют префикс r., справочника — l.

Запуск и проверка

  1. Зарегистрируйте оба CSV и обеспечьте один лимит на Dept.
  2. Постройте схему JSON; выберите requests основным входом соединения, limits — левым соединением по Dept.
  3. Проверьте l.Limit и правило ошибки отсутствующих лимитов.
  4. Проверьте три заявки: R1 в пределах лимита, R2 и R3 превышают.
  5. Добавьте Dept=FIN без лимита: проверка качества должна остановиться до экспорта.

Устранение неполадок

  • Используйте точные имена после соединения: r.Amount и l.Limit.
  • Повторные Dept нарушают many_to_one; исправьте справочник.
  • Не заменяйте отсутствующий лимит нулём без бизнес-правила.
  • Маршрутизация сравнивает поля текущей строки; прежний вход справочника не нужен.