{
  "name": "ezGPT - Import CSV Orders",
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1",
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "all"
  },
  "nodes": [
    {
      "id": "d803525e-0258-4517-b495-eb40c8c7c175",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "parameters": {},
      "position": [
        0,
        0
      ]
    },
    {
      "id": "617d50f6-6983-453a-bd48-b47fd4bd48f9",
      "name": "Download CSV",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "parameters": {
        "method": "GET",
        "url": "https://ezgpt.ru/storage/article-files/n8n-csv-import-orders.csv",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file",
              "outputPropertyName": "data"
            }
          },
          "timeout": 15000
        }
      },
      "position": [
        240,
        0
      ]
    },
    {
      "id": "bd450c20-99b3-41e5-9b85-9022acdee6c5",
      "name": "Read CSV",
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "parameters": {
        "operation": "csv",
        "binaryPropertyName": "data",
        "options": {
          "headerRow": true,
          "delimiter": ",",
          "encoding": "utf8",
          "enableBOM": true,
          "includeEmptyCells": true,
          "relaxQuotes": false
        }
      },
      "position": [
        480,
        0
      ],
      "alwaysOutputData": true
    },
    {
      "id": "a407e42e-4de0-4cae-9037-eb951efae525",
      "name": "Check Rows",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const fields = ['order_id', 'client', 'amount_minor', 'currency', 'note'];\nconst items = $input.all();\nif (!items.length || items.some(item =>\n  Object.keys(item.json).length !== fields.length\n  || fields.some(key => typeof item.json[key] !== 'string')))\n  throw new Error('csv_columns_mismatch_or_empty');\nconst rows = items.map(item => item.json);\nif (rows.some(row => fields.some(key => row[key].includes('\\uFFFD'))))\n  throw new Error('csv_text_encoding_invalid');\nconst clean = value => value.trim().replace(/\\s+/g, ' ');\nconst ids = rows.map(row => clean(row.order_id));\nif (ids.some(id => !id) || new Set(ids).size !== ids.length)\n  throw new Error('csv_id_missing_or_duplicate');\nreturn rows.map((row, index) => {\n  const raw = row.amount_minor.trim();\n  const amount = /^\\d+$/.test(raw) ? Number(raw) : NaN;\n  const errors = [];\n  if (!clean(row.client)) errors.push('client_required');\n  if (clean(row.currency).toUpperCase() !== 'RUB')\n    errors.push('currency_must_be_RUB');\n  if (!Number.isSafeInteger(amount) || amount < 0)\n    errors.push('amount_minor_invalid');\n  return {\n    json: {\n      order_id: ids[index], client: clean(row.client),\n      currency: clean(row.currency).toUpperCase(), note: row.note.trim(),\n      amount_minor: errors.length ? null : amount,\n      status: errors.length ? 'needs_review' : 'ready', errors,\n    },\n    pairedItem: { item: index },\n  };\n});"
      },
      "position": [
        720,
        0
      ]
    },
    {
      "id": "5d13f3d7-5266-4bcc-b402-cb35f85d25d3",
      "name": "Import Summary",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const rows = $input.all().map(item => item.json);\nconst ready = rows.filter(row => row.status === 'ready');\nlet total = 0;\nfor (const row of ready) {\n  total += row.amount_minor;\n  if (!Number.isSafeInteger(total))\n    throw new Error('csv_ready_sum_out_of_range');\n}\nreturn [{ json: {\n  rows: rows.length, ready: ready.length,\n  needs_review: rows.length - ready.length,\n  ready_amount_minor: total, ready_amount_rub: total / 100,\n  ready_ids: ready.map(row => row.order_id),\n  review_ids: rows.filter(row => row.status !== 'ready').map(row => row.order_id),\n  action_performed: false,\n}}];"
      },
      "position": [
        960,
        0
      ]
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Download CSV",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download CSV": {
      "main": [
        [
          {
            "node": "Read CSV",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read CSV": {
      "main": [
        [
          {
            "node": "Check Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Rows": {
      "main": [
        [
          {
            "node": "Import Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
