{
  "name": "Rutinra | Ajánlatkérések tisztítása | helyi demó",
  "nodes": [
    {
      "parameters": {},
      "id": "folyamat-manual",
      "name": "Kézi indítás",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "return [\n  {\n    \"submissionId\": \"minta-001\",\n    \"name\": \"Minta Műhely\",\n    \"email\": \"  hello@example.test \",\n    \"service\": \"weboldal\",\n    \"message\": \"Ötoldalas bemutatkozó oldalra kérek ajánlatot.\"\n  },\n  {\n    \"submissionId\": \"minta-002\",\n    \"name\": \"Példa Stúdió\",\n    \"email\": \"studio@example.test\",\n    \"service\": \"automatizalas\",\n    \"message\": \"Az ajánlatkéréseimet szeretném rendezni.\"\n  },\n  {\n    \"submissionId\": \"minta-001\",\n    \"name\": \"Minta Műhely\",\n    \"email\": \"hello@example.test\",\n    \"service\": \"weboldal\",\n    \"message\": \"Ötoldalas bemutatkozó oldalra kérek ajánlatot.\"\n  },\n  {\n    \"submissionId\": \"minta-003\",\n    \"name\": \"Hiányos Minta\",\n    \"email\": \"nem-email\",\n    \"service\": \"weboldal\",\n    \"message\": \"Hiányzó elérhetőség.\"\n  },\n  {\n    \"submissionId\": \"minta-004\",\n    \"name\": \"Minta Műhely\",\n    \"email\": \"hello@example.test\",\n    \"service\": \"automatizalas\",\n    \"message\": \"Külön megrendelésként automatizálást is szeretnék.\"\n  }\n].map(json => ({ json }));"
      },
      "id": "folyamat-samples",
      "name": "Kizárólag mintaadat",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "function processLeads(rows, known = {}) {\n  if (\n    !Array.isArray(rows) ||\n    !known ||\n    typeof known !== \"object\" ||\n    Array.isArray(known)\n  )\n    throw new Error(\"Érvénytelen bemenet.\");\n  const seen = new Map(Object.entries(known));\n  const accepted = [];\n  const duplicates = [];\n  const rejected = [];\n  for (const [index, raw] of rows.entries()) {\n    const value = raw && typeof raw === \"object\" ? raw : {};\n    const lead = Object.fromEntries(\n      [\"submissionId\", \"name\", \"email\", \"service\", \"message\"].map((key) => [\n        key,\n        typeof value[key] === \"string\" ? value[key].trim() : \"\",\n      ]),\n    );\n    lead.email = lead.email.toLowerCase();\n    const reasons = [];\n    if (!/^[a-zA-Z0-9_-]{1,80}$/.test(lead.submissionId))\n      reasons.push(\"submission_id\");\n    if (!lead.name || lead.name.length > 120) reasons.push(\"name\");\n    if (\n      !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(lead.email) ||\n      lead.email.length > 254\n    )\n      reasons.push(\"email\");\n    if (![\"weboldal\", \"automatizalas\", \"egyeb\"].includes(lead.service))\n      reasons.push(\"service\");\n    if (!lead.message || lead.message.length > 3000) reasons.push(\"message\");\n    if (reasons.length) {\n      rejected.push({\n        row: index + 1,\n        submissionId: lead.submissionId || null,\n        reasons,\n      });\n      continue;\n    }\n    const fingerprint = JSON.stringify(lead);\n    if (seen.has(lead.submissionId)) {\n      if (seen.get(lead.submissionId) !== fingerprint)\n        rejected.push({\n          row: index + 1,\n          submissionId: lead.submissionId,\n          reasons: [\"id_conflict\"],\n        });\n      else duplicates.push(lead.submissionId);\n      continue;\n    }\n    seen.set(lead.submissionId, fingerprint);\n    accepted.push({\n      ...lead,\n      nextAction:\n        \"Személyes átnézés és ajánlat-előkészítés; nincs automatikus kiküldés.\",\n    });\n  }\n  return {\n    accepted,\n    duplicates,\n    rejected,\n    state: Object.fromEntries(seen),\n    summary: {\n      input: rows.length,\n      accepted: accepted.length,\n      duplicates: duplicates.length,\n      rejected: rejected.length,\n    },\n  };\n}\nconst result = processLeads($input.all().map(item => item.json));\nreturn [{ json: result }];"
      },
      "id": "folyamat-clean",
      "name": "Ellenőrzés és duplikációszűrés",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        500,
        0
      ]
    },
    {
      "parameters": {
        "jsCode": "const result = $input.first().json; return [{ json: { demo: true, summary: result.summary, nextStep: \"Nézd át az accepted és rejected listát az előző node kimenetében. Nincs külső kapcsolat vagy levélküldés.\", limitation: \"Ez a sablon egy futáson belüli duplikációszűrést mutat be. Éles használathoz tartós tárolás és egyedi kulcs szükséges.\" } }];"
      },
      "id": "folyamat-summary",
      "name": "Ellenőrizhető összesítő",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        0
      ]
    }
  ],
  "connections": {
    "Kézi indítás": {
      "main": [
        [
          {
            "node": "Kizárólag mintaadat",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Kizárólag mintaadat": {
      "main": [
        [
          {
            "node": "Ellenőrzés és duplikációszűrés",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Ellenőrzés és duplikációszűrés": {
      "main": [
        [
          {
            "node": "Ellenőrizhető összesítő",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "timezone": "Europe/Budapest"
  },
  "active": false,
  "pinData": {},
  "tags": []
}
