{
  "name": "ezGPT - Edit Fields Leads",
  "active": false,
  "nodes": [
    {
      "id": "trigger",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        240,
        300
      ],
      "parameters": {}
    },
    {
      "id": "sample",
      "name": "Sample Leads",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const leads = [\n  {\n    \"id\": \"L1\",\n    \"name\": \" Анна \",\n    \"email\": \" ANNA@EXAMPLE.INVALID \",\n    \"budget\": \"150000\",\n    \"consent\": \"true\",\n    \"internal_note\": \"Учебная пометка A\"\n  },\n  {\n    \"id\": \"L2\",\n    \"name\": \"Борис\",\n    \"email\": \"BORIS@example.invalid\",\n    \"budget\": \"0\",\n    \"consent\": \"false\",\n    \"internal_note\": \"Учебная пометка B\"\n  },\n  {\n    \"id\": \"L3\",\n    \"name\": \"Альфа\",\n    \"email\": \"team@example.invalid\",\n    \"budget\": \" 49900 \",\n    \"consent\": \"true\",\n    \"internal_note\": \"Учебная пометка C\"\n  }\n];\nif (!leads.length) throw new Error(\"leads_empty\");\nreturn leads.map(json => ({ json }));"
      }
    },
    {
      "id": "validate",
      "name": "Validate Leads",
      "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.id !== 'string' || !row.id.trim() || ids.has(row.id)) {\n    throw new Error('id_missing_or_duplicate');\n  }\n  if (typeof row.name !== 'string' || !row.name.trim()) throw new Error('name_required');\n  if (typeof row.email !== 'string' || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(row.email.trim())) {\n    throw new Error('email_invalid');\n  }\n  if (typeof row.budget !== 'string' || !/^\\d+$/.test(row.budget.trim()) ||\n      !Number.isSafeInteger(Number(row.budget.trim()))) throw new Error('budget_invalid');\n  if (!['true', 'false'].includes(row.consent)) throw new Error('consent_invalid');\n  ids.add(row.id);\n}\nreturn items;"
      }
    },
    {
      "id": "set",
      "name": "Prepare Payload",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        900,
        300
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "field-0",
              "name": "request_id",
              "type": "string",
              "value": "={{ $json.id }}"
            },
            {
              "id": "field-1",
              "name": "contact.name",
              "type": "string",
              "value": "={{ $json.name.trim() }}"
            },
            {
              "id": "field-2",
              "name": "contact.email",
              "type": "string",
              "value": "={{ $json.email.trim().toLowerCase() }}"
            },
            {
              "id": "field-3",
              "name": "budget_minor",
              "type": "number",
              "value": "={{ Number($json.budget.trim()) }}"
            },
            {
              "id": "field-4",
              "name": "consent",
              "type": "boolean",
              "value": "={{ $json.consent === 'true' }}"
            },
            {
              "id": "field-5",
              "name": "source",
              "type": "string",
              "value": "website"
            }
          ]
        },
        "includeOtherFields": false,
        "options": {
          "dotNotation": true,
          "ignoreConversionErrors": false
        }
      }
    },
    {
      "id": "check",
      "name": "Check Payload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const items = $input.all();\nconst source = $('Validate Leads').all().map(item => item.json);\nconst keys = value => Object.keys(value).sort().join('|');\nif (items.length !== source.length) throw new Error('payload_count_mismatch');\nreturn items.map((item, i) => {\n  const row = item.json;\n  const input = source[i];\n  if (keys(row) !== 'budget_minor|consent|contact|request_id|source' ||\n      !row.contact || typeof row.contact !== 'object' || Array.isArray(row.contact) ||\n      keys(row.contact) !== 'email|name') throw new Error('payload_fields_mismatch');\n  if (row.request_id !== input.id || row.contact.name !== input.name.trim() ||\n      row.contact.email !== input.email.trim().toLowerCase() ||\n      row.budget_minor !== Number(input.budget.trim()) ||\n      row.consent !== (input.consent === 'true') || row.source !== 'website') {\n    throw new Error('payload_value_mismatch');\n  }\n  return { json: { payload: row, action_performed: false }, pairedItem: { item: i } };\n});"
      }
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Sample Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sample Leads": {
      "main": [
        [
          {
            "node": "Validate Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Leads": {
      "main": [
        [
          {
            "node": "Prepare Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Payload": {
      "main": [
        [
          {
            "node": "Check Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveDataSuccessExecution": "all",
    "saveDataErrorExecution": "all"
  },
  "pinData": {}
}
