{
  "name": "ezGPT - Stop Invalid Batch",
  "active": false,
  "nodes": [
    {
      "id": "trigger",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        240,
        300
      ],
      "parameters": {}
    },
    {
      "id": "sample",
      "name": "Sample Batch",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const orders = [\n  {\n    \"order_id\": \"O1\",\n    \"client\": \"Анна\",\n    \"amount_minor\": 150000\n  },\n  {\n    \"order_id\": \"O2\",\n    \"client\": \"Борис\",\n    \"amount_minor\": 0\n  },\n  {\n    \"order_id\": \"O3\",\n    \"client\": \"Альфа\",\n    \"amount_minor\": 49900\n  }\n];\nreturn [{ json: { orders } }];"
      }
    },
    {
      "id": "validate",
      "name": "Check Batch",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nconst errors = [];\nconst add = (row, code) => errors.push({ row, code });\nconst orders = items.length === 1 ? items[0].json.orders : undefined;\nconst ids = new Set();\nlet total = 0;\nif (!Array.isArray(orders)) add(0, 'orders_array_required');\nelse if (!orders.length) add(0, 'orders_empty');\nelse for (let i = 0; i < orders.length; i++) {\n  const row = orders[i];\n  if (!row || typeof row !== 'object' || Array.isArray(row)) {\n    add(i + 1, 'order_object_required');\n    continue;\n  }\n  if (typeof row.order_id !== 'string' || !row.order_id.trim() || ids.has(row.order_id)) {\n    add(i + 1, 'order_id_missing_or_duplicate');\n  } else ids.add(row.order_id);\n  if (typeof row.client !== 'string' || !row.client.trim()) add(i + 1, 'client_required');\n  if (!Number.isSafeInteger(row.amount_minor) || row.amount_minor < 0) {\n    add(i + 1, 'amount_minor_invalid');\n  } else {\n    total += row.amount_minor;\n    if (!Number.isSafeInteger(total)) add(i + 1, 'total_out_of_range');\n  }\n}\nconst valid = errors.length === 0;\nreturn [{ json: {\n  valid,\n  errors,\n  orders: valid ? orders.map(({ order_id, client, amount_minor }) => ({ order_id, client, amount_minor })) : [],\n  count: Array.isArray(orders) ? orders.length : 0,\n  total_amount_minor: valid ? total : null,\n  error_message: valid ? '' : 'batch_invalid: ' + errors.map(e => 'row ' + e.row + ' ' + e.code).join('; '),\n} }];"
      }
    },
    {
      "id": "if",
      "name": "Batch OK",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        900,
        300
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "valid",
              "leftValue": "={{ $json.valid }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "preview",
      "name": "Preview Ready",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        180
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1) throw new Error('preview_requires_valid_batch');\nconst row = items[0].json;\nif (row.valid !== true || !Array.isArray(row.errors) || row.errors.length ||\n    !Array.isArray(row.orders) || !row.orders.length || row.count !== row.orders.length) {\n  throw new Error('preview_requires_valid_batch');\n}\nreturn [{ json: {\n  status: 'ready_for_review',\n  count: row.count,\n  order_ids: row.orders.map(order => order.order_id),\n  total_amount_minor: row.total_amount_minor,\n  action_performed: false,\n} }];"
      }
    },
    {
      "id": "stop",
      "name": "Stop Invalid Batch",
      "type": "n8n-nodes-base.stopAndError",
      "typeVersion": 1,
      "position": [
        1120,
        420
      ],
      "parameters": {
        "errorType": "errorMessage",
        "errorMessage": "={{ $json.error_message }}"
      }
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Sample Batch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sample Batch": {
      "main": [
        [
          {
            "node": "Check Batch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Batch": {
      "main": [
        [
          {
            "node": "Batch OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Batch OK": {
      "main": [
        [
          {
            "node": "Preview Ready",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Stop Invalid Batch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveDataSuccessExecution": "all",
    "saveDataErrorExecution": "all"
  },
  "pinData": {}
}
