{
  "name": "killBottleneck — nová reklamace",
  "nodes": [
    {
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "SEM_ID_TABULKY",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Reklamace"
        },
        "event": "rowAdded",
        "options": {}
      },
      "id": "11111111-1111-4111-8111-111111111111",
      "name": "Nový řádek v tabulce",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "typeVersion": 1,
      "position": [0, 0],
      "credentials": {
        "googleSheetsTriggerOAuth2Api": {
          "id": "SEM_ID_PRIHLASENI",
          "name": "Google Sheets"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// ⚙️ VYPLŇTE ČTYŘI ŘÁDKY -----------------------------------------\nconst KB_ADRESA = 'https://vasefirma.killbottleneck.com'; // bez lomítka na konci\nconst KB_KLIC   = 'kb_user_sem_vlozte_svuj_klic';         // API klíč s právem zápisu\nconst KB_MAPA   = 'sem_vlozte_id_mapy';                   // z adresy /mapa/xxxxx\nconst KB_VETEV  = 'Nové reklamace';                       // pod co se reklamace věší\n// ---------------------------------------------------------------\n\n// Tip pro pokročilé: klíč nemusí být v kódu. Když si ho vložíte do proměnné\n// prostředí n8n, nahraďte řádek výše za:  const KB_KLIC = $env.KB_KLIC;\n\nconst hlavicky = { Authorization: 'Bearer ' + KB_KLIC };\n\n/** Projde strom mapy a najde uzel podle názvu. */\nfunction najdiPodleNazvu(uzly, nazev) {\n  for (const u of uzly || []) {\n    if (u.title === nazev) return u;\n    const hlubsi = najdiPodleNazvu(u.children, nazev);\n    if (hlubsi) return hlubsi;\n  }\n  return null;\n}\n\n/** Z chyby vytáhne HTTP kód, ať už ho n8n schová kamkoli. */\nfunction kodChyby(e) {\n  return Number(e.httpCode || e.statusCode || (e.response && (e.response.status || e.response.statusCode)) || 0);\n}\n\nconst vysledky = [];\n\nfor (const polozka of $input.all()) {\n  const radek = polozka.json;\n  const nazev = 'Reklamace ' + (radek['Číslo reklamace'] || '?') + ' — ' + (radek['Zákazník'] || '');\n  const popis = String(radek['Popis problému'] || '');\n\n  let uzelId = null;\n  let posledniChyba = '';\n\n  // Až čtyři pokusy. killBottleneck u každého zápisu chce vědět, jakou verzi mapy\n  // jsme viděli (base_updated). Když ji někdo mezitím změnil, odpoví 409 a chce,\n  // ať si mapu načteme znovu — je to pojistka proti přepsání cizí práce.\n  for (let pokus = 1; pokus <= 4 && !uzelId; pokus++) {\n    const mapa = await this.helpers.httpRequest({\n      method: 'GET',\n      url: KB_ADRESA + '/api/kb/v1/maps/' + KB_MAPA,\n      headers: hlavicky,\n      json: true,\n    });\n\n    const vetev = najdiPodleNazvu(mapa.tree, KB_VETEV);\n    if (!vetev) throw new Error('V mapě chybí větev „' + KB_VETEV + '\".');\n\n    try {\n      const odpoved = await this.helpers.httpRequest({\n        method: 'POST',\n        url: KB_ADRESA + '/api/kb/v1/maps/' + KB_MAPA + '/nodes',\n        headers: hlavicky,\n        body: {\n          base_updated: mapa.updated,\n          parent_id: vetev.id,\n          items: [{ title: nazev, description: popis }],\n        },\n        json: true,\n      });\n      uzelId = odpoved.added_ids[0];\n    } catch (e) {\n      const kod = kodChyby(e);\n      posledniChyba = kod + ' ' + e.message;\n      if (kod === 401) throw new Error('Neplatný API klíč — zkontrolujte KB_KLIC.');\n      if (kod === 404) throw new Error('Mapa nenalezena — zkontrolujte KB_MAPA.');\n      if (kod !== 409 && kod !== 429) throw e;\n      await new Promise((r) => setTimeout(r, 700 * pokus)); // někdo mapu změnil, zkusíme znovu\n    }\n  }\n\n  if (!uzelId) throw new Error('Uzel se nepodařilo založit: ' + posledniChyba);\n\n  vysledky.push({ json: Object.assign({}, radek, { killBottleneck: uzelId, kb_nazev: nazev }) });\n}\n\nreturn vysledky;"
      },
      "id": "22222222-2222-4222-8222-222222222222",
      "name": "Založ reklamaci v mapě",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [220, 0]
    },
    {
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "SEM_ID_TABULKY",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Reklamace"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "matchingColumns": ["Číslo reklamace"],
          "value": {}
        },
        "options": {}
      },
      "id": "33333333-3333-4333-8333-333333333333",
      "name": "Zapiš id zpět do tabulky",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [440, 0],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "SEM_ID_PRIHLASENI",
          "name": "Google Sheets"
        }
      }
    }
  ],
  "connections": {
    "Nový řádek v tabulce": {
      "main": [[{ "node": "Založ reklamaci v mapě", "type": "main", "index": 0 }]]
    },
    "Založ reklamaci v mapě": {
      "main": [[{ "node": "Zapiš id zpět do tabulky", "type": "main", "index": 0 }]]
    }
  },
  "settings": { "executionOrder": "v1" }
}
