{
  "name": "ezGPT - Aggregate Orders",
  "active": false,
  "nodes": [
    {
      "id": "manual-trigger",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        240,
        300
      ],
      "parameters": {}
    },
    {
      "id": "sample-orders",
      "name": "Sample Orders",
      "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    \"note\": \"Доставка утром\",\n    \"internal_note\": \"Учебная служебная пометка A\"\n  },\n  {\n    \"order_id\": \"O2\",\n    \"client\": \"Борис\",\n    \"amount_minor\": 0,\n    \"note\": null,\n    \"internal_note\": \"Учебная служебная пометка B\"\n  },\n  {\n    \"order_id\": \"O3\",\n    \"client\": \"Альфа\",\n    \"amount_minor\": 49900,\n    \"internal_note\": \"Учебная служебная пометка C\"\n  }\n];\nif (!orders.length) throw new Error('orders_empty');\nreturn orders.map(json => ({ json }));"
      }
    },
    {
      "id": "validate-orders",
      "name": "Validate Orders",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nconst ids = new Set();\nfor (const { json: row } of items) {\n  if (typeof row.order_id !== 'string' || !row.order_id.trim() || ids.has(row.order_id)) {\n    throw new Error('order_id_missing_or_duplicate');\n  }\n  if (typeof row.client !== 'string' || !row.client.trim()) throw new Error('client_required');\n  if (!Number.isSafeInteger(row.amount_minor) || row.amount_minor < 0) {\n    throw new Error('amount_minor_invalid');\n  }\n  if (row.note !== undefined && row.note !== null && typeof row.note !== 'string') {\n    throw new Error('note_invalid');\n  }\n  ids.add(row.order_id);\n}\nreturn items;"
      }
    },
    {
      "id": "aggregate-orders",
      "name": "Aggregate Orders",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        900,
        300
      ],
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "orders",
        "include": "specifiedFields",
        "fieldsToInclude": "order_id, client, amount_minor, note",
        "options": {
          "includeBinaries": false
        }
      }
    },
    {
      "id": "check-payload",
      "name": "Check Payload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nif (items.length !== 1 || !Array.isArray(items[0].json.orders)) {\n  throw new Error('payload_structure_invalid');\n}\nconst orders = items[0].json.orders;\nconst source = $('Validate Orders').all().map(item => item.json);\nconst allowed = ['order_id', 'client', 'amount_minor', 'note'];\nif (orders.length !== source.length) throw new Error('payload_count_mismatch');\nlet total = 0;\nfor (let i = 0; i < orders.length; i++) {\n  const row = orders[i];\n  const expectedKeys = Object.keys(source[i]).filter(key => allowed.includes(key)).sort();\n  if (Object.keys(row).sort().join('|') !== expectedKeys.join('|')) {\n    throw new Error('payload_fields_mismatch');\n  }\n  for (const key of expectedKeys) {\n    if (!Object.is(row[key], source[i][key])) throw new Error('payload_value_mismatch');\n  }\n  total += row.amount_minor;\n  if (!Number.isSafeInteger(total)) throw new Error('payload_total_out_of_range');\n}\nreturn [{ json: {\n  orders,\n  count: orders.length,\n  total_amount_minor: total,\n  total_amount_rub: total / 100,\n  action_performed: false,\n} }];"
      }
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Sample Orders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sample Orders": {
      "main": [
        [
          {
            "node": "Validate Orders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Orders": {
      "main": [
        [
          {
            "node": "Aggregate Orders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Orders": {
      "main": [
        [
          {
            "node": "Check Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveDataSuccessExecution": "all",
    "saveDataErrorExecution": "all"
  },
  "pinData": {}
}
