Automatisierte Nachverfolgung von Rechnungszahlungen basierend auf OCR, Claude AI, Slack und Notion DB

Experte

Dies ist ein AI Summarization, Multimodal AI-Bereich Automatisierungsworkflow mit 92 Nodes. Hauptsächlich werden If, Code, Wait, Slack, Notion und andere Nodes verwendet. Automatisierte Nachverfolgung von Rechnungszahlungen auf Basis von OCR, Claude AI, Slack und Notion DB

Voraussetzungen
  • Slack Bot Token oder Webhook URL
  • Notion API Key
  • Möglicherweise sind Ziel-API-Anmeldedaten erforderlich
  • Anthropic API Key
Workflow-Vorschau
Visualisierung der Node-Verbindungen, mit Zoom und Pan
Workflow exportieren
Kopieren Sie die folgende JSON-Konfiguration und importieren Sie sie in n8n
{
  "meta": {
    "instanceId": "c8523726fb538ba356528013ec3b00a89ffd0cddf2d31a7bcce94063a36b7fec",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "909b0322-55e4-4c3d-a5a9-9392d5bbf745",
      "name": "Format Check",
      "type": "n8n-nodes-base.code",
      "position": [
        -5808,
        1744
      ],
      "parameters": {
        "jsCode": "const files = $('Slack Trigger').first().json.files || [];\nconst results = [];\n\nfor (const file of files) {\n  const mimetype = file.mimetype || \"\";\n  const fileType = mimetype.split('/').pop().toLowerCase();\n  const fileName = file.name || file.title || \"unknown\";\n\n  const isImage = ['jpg', 'jpeg', 'png', 'webp'].includes(fileType);\n  const isDocument = ['pdf', 'doc', 'docx', 'txt', 'rtf', 'eml'].includes(fileType);\n  const isEmail = fileType === 'eml' || fileName.endsWith('.eml');\n\n  results.push({\n    json: {\n      ...file, // keep Slack file data like url_private_download\n      fileType,\n      mimetype,\n      isImage,\n      isDocument,\n      isEmail,\n    }\n  });\n}\n\nreturn results;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "ca8559e4-b29b-4a1a-b113-e70bba47f23a",
      "name": "Check Format",
      "type": "n8n-nodes-base.switch",
      "position": [
        -5584,
        1744
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Image",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "f5d6e124-c68e-42bb-a9bb-c97d54b09143",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.isImage }}",
                    "rightValue": "true"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Document",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "87759194-16d1-4593-8c9b-016aa7be4e03",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.isDocument }}",
                    "rightValue": "true"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "allMatchingOutputs": true
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "6543e986-8860-457d-a8de-bb052718e9c6",
      "name": "Take Binary Files for Document",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -5360,
        1840
      ],
      "parameters": {
        "url": "={{ $json.url_private_download }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        },
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "slackApi"
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "af88d22a-5a2d-4471-9ac9-b1cb9531bd35",
      "name": "OCR Space Parse1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -5136,
        1840
      ],
      "parameters": {
        "url": "https://api.ocr.space/parse/image",
        "method": "POST",
        "options": {
          "timeout": 100000
        },
        "sendBody": true,
        "contentType": "multipart-form-data",
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "filetype",
              "value": "PDF"
            },
            {
              "name": "file",
              "parameterType": "formBinaryData",
              "inputDataFieldName": "data"
            },
            {
              "name": "scale",
              "value": "true"
            },
            {
              "name": "OCREngine",
              "value": "2"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "dkJjl1msBNIeIT5u",
          "name": "OCR Space"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.2,
      "waitBetweenTries": 5000
    },
    {
      "id": "ecb68486-32af-41e3-a9a7-86c763205061",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        -4688,
        1936
      ],
      "parameters": {
        "jsCode": "// $input.all() gives you the 3 separate OCR result items\nconst inputItems = $input.all();\n\nreturn inputItems.map((item, index) => {\n  const parsedResults = item.json.ParsedResults || [];\n\n  // Join all ParsedText per result into one string\n  const mergedText = parsedResults\n    .map(p => p.ParsedText || \"\")\n    .join(\"\\n\\n\")\n    .trim();\n\n  return {\n    json: {\n      index: index + 1,\n      mergedParsedText: mergedText\n    }\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "acb3e33c-59de-4cf3-a008-a47af9673abb",
      "name": "Check parsing Error3",
      "type": "n8n-nodes-base.if",
      "position": [
        -4912,
        1840
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ddbbbfbb-e05b-4ca9-b607-65ad8ac748bb",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $('OCR Space Parse1').item.json.IsErroredOnProcessing }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "96e61695-6dfd-4cf4-8064-aea9d80284f0",
      "name": "Basic LLM Kette",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        -4240,
        1888
      ],
      "parameters": {
        "text": "=Extract the invoice fields from this OCR text and populate the EXACT schema.\n\nTARGET SCHEMA:\n{\n  \"invoice_no\": \"\",\n  \"vendor\": \"\",\n  \"issue_date\": \"YYYY-MM-DD\",\n  \"due_date\": \"YYYY-MM-DD\",\n  \"currency\": \"\",\n  \"subtotal\": 0,\n  \"tax_total\": 0,\n  \"discount_total\": 0,\n  \"discount_percent\": 0,\n  \"amount_total\": 0,\n\n  \"amount_due\": 0,          // if shown (a.k.a. Balance Due); else 0\n  \"paid_amount\": 0,         // if shown or implied; else 0\n  \"paid_date\": \"\",          // if shown; else \"\"\n  \"receipt_no\": \"\",         // if shown; else \"\"\n  \"payment_method\": \"\",     // if shown; else \"\"\n\n  \"destination_account\": \"\",\n  \"payment_ref\": \"\",\n  \"doc_says_paid\": false,\n  \"status\": \"\",\n  \"notes\": \"\",\n  \"source_file_id\": \"\",\n  \"source_file_name\": \"\",\n  \"source_file_url\": \"\",\n  \"ingestion_batch\": \"\",\n  \"line_items\": [],\n  \"attachments\": []\n}\n\nOCR TEXT:\n{{ $json.OCRResult }}\n",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "=You are an extraction engine for US invoices. Output EXACTLY the JSON fields of the target schema—no extra keys, no comments, no markdown. Do not invent values.\n\nGeneral rules\n- Locale: US. Normalize dates to YYYY-MM-DD.\n- Numbers: plain decimals (no symbols/commas).\n- currency: infer from symbol/labels when present (“$” ⇒ “USD”), else \"\".\n- If a field is unavailable: use \"\" for strings, 0 for numbers, false for booleans, [] for arrays.\n\nDiscount fields\n- If the doc shows a percent (e.g., “Discount 49%”), set discount_percent to the decimal (0.49) and discount_total to 0 unless a currency discount is also printed.\n- If the doc shows a currency discount (e.g., “Discount $60.27”), set discount_total to that amount; discount_percent is 0 unless the percent is explicitly printed too.\n- If both forms are printed, fill both.\n\nTotals\n- amount_total: prefer the document’s explicit “Amount due/Total/Total amount/Grand total”.\n- If not printed but subtotal, discount_* and tax_total are present, compute:\n  amount_total = subtotal − (discount_total OR subtotal × discount_percent) + tax_total.\n- Otherwise leave amount_total = 0.\n\nPartial payments\n- If the doc shows Amount due / Balance due:\n  • Set amount_due to that value.\n  • If amount_total is known and amount_due < amount_total, set paid_amount = amount_total − amount_due (≥ 0).\n- If the doc shows Amount paid / Payment history:\n  • Sum payments and set paid_amount.\n  • If amount_due is not shown but amount_total is known, set amount_due = max(amount_total − paid_amount, 0).\n- If a paid date, receipt number, or payment method is explicitly shown, set paid_date, receipt_no, payment_method; otherwise leave them empty.\n- Clamp impossible values (no negatives; when amount_total is known, neither paid_amount nor amount_due may exceed it).\n\nDocument-based status\n- If amount_due == 0 AND the document states PAID (or shows “Amount due $0.00”): status = \"Paid (Unverified)\".\n- Else if paid_amount > 0 AND amount_due > 0: status = \"Partially Paid\".\n- Else: status = \"Unpaid\".\n- Set doc_says_paid = true only if the document itself explicitly says “PAID” or shows “Amount due $0.00”; otherwise false.\n\nLine items\n- line_items: include when clearly listed, as\n  [{\"description\": string, \"qty\": number, \"unit_price\": number, \"amount\": number}], else [].\n\nAttachments\n- attachments: [] unless explicit links are present.\n\nReturn ONLY the JSON object matching the target schema.\n"
            }
          ]
        },
        "promptType": "define"
      },
      "retryOnFail": false,
      "typeVersion": 1.7
    },
    {
      "id": "0aaa9bdf-05b2-4dc1-ad6d-4de8926ef9f1",
      "name": "Anthropic-Chat-Modell4",
      "type": "@n8n/n8n-nodes-langchain.lmChatAnthropic",
      "position": [
        -4240,
        2048
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "claude-3-5-haiku-20241022",
          "cachedResultName": "Claude Haiku 3.5"
        },
        "options": {}
      },
      "credentials": {
        "anthropicApi": {
          "id": "UBlNqbwvx1EotIn7",
          "name": "Anthropic account"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "54187b60-dabd-42a7-b5c9-d46199dbed73",
      "name": "Cleans AI Response",
      "type": "n8n-nodes-base.code",
      "position": [
        -3888,
        1888
      ],
      "parameters": {
        "jsCode": "// n8n Code node — Run Once for All Items\n// Repair + Enforce schema + attach Slack file info\n// Adds discount_percent support + derives discount_amount & stable amount_total\n// + Partial payment normalization (amount_due, paid_amount, paid_date, receipt_no, payment_method)\n\nfunction stripCodeFences(s) {\n  return String(s || \"\")\n    .replace(/```(?:json)?/gi, \"\")\n    .replace(/```/g, \"\")\n    .trim();\n}\n\nfunction findTopLevelJson(s) {\n  const str = String(s || \"\");\n  let start = -1, depth = 0;\n  for (let i = 0; i < str.length; i++) {\n    const ch = str[i];\n    if (start === -1) {\n      if (ch === \"{\" || ch === \"[\") { start = i; depth = 1; }\n    } else {\n      if (ch === \"{\" || ch === \"[\") depth++;\n      if (ch === \"}\" || ch === \"]\") depth--;\n      if (depth === 0) return str.slice(start, i + 1);\n    }\n  }\n  return null;\n}\n\nfunction safeParseAny(x) {\n  if (Array.isArray(x)) return x;\n  if (x && typeof x === \"object\" && (x.invoice_no || x.vendor || x.line_items)) return x;\n\n  let txt = \"\";\n  if (typeof x === \"string\") txt = x;\n  else if (typeof x?.text === \"string\") txt = x.text;\n  else if (typeof x?.output === \"string\") txt = x.output;\n  else if (typeof x?.response === \"string\") txt = x.response;\n  else if (typeof x?.content === \"string\") txt = x.content;\n  else if (typeof x?.message === \"string\") txt = x.message;\n  else txt = JSON.stringify(x ?? \"\");\n\n  txt = stripCodeFences(txt);\n\n  try { return JSON.parse(txt); } catch {}\n  const block = findTopLevelJson(txt);\n  if (!block) throw new Error(\"No JSON found in LLM output\");\n  return JSON.parse(block);\n}\n\n// coercers\nfunction num(v) {\n  if (v === \"\" || v == null || (typeof v === \"number\" && !isFinite(v))) return 0;\n  if (typeof v === \"number\") return v;\n  let s = String(v).trim();\n  if (!s) return 0;\n  // keep digits , . -\n  s = s.replace(/[^\\d,.\\-]/g, \"\");\n  if (s.includes(\",\") && s.includes(\".\")) s = s.replace(/,/g, \"\");\n  else if (s.includes(\",\") && !s.includes(\".\")) {\n    if ((s.match(/,/g) || []).length === 1 && /\\d,\\d{1,2}$/.test(s)) s = s.replace(\",\", \".\");\n    else s = s.replace(/,/g, \"\");\n  }\n  const n = Number(s);\n  return isFinite(n) ? n : 0;\n}\nconst str = (v) => (v == null ? \"\" : String(v).trim());\nconst bool = (v) => v === true;\nconst two = (n) => Math.round((Number(n) || 0) * 100) / 100;\n\n// parse percent from \"49%\", \"49\", 0.49, etc. → 0..1\nfunction pct(v) {\n  if (v == null || v === \"\") return 0;\n  if (typeof v === \"string\" && v.includes(\"%\")) return Math.min(Math.max(num(v) / 100, 0), 1);\n  let n = num(v);\n  if (n > 1) n = n / 100;\n  if (n < 0) n = 0;\n  if (n > 1) n = 1;\n  return n;\n}\n\nfunction normalizeOne(obj, fileUrl) {\n  const line_items = Array.isArray(obj?.line_items)\n    ? obj.line_items.map(x => ({\n        description: str(x?.description),\n        qty: num(x?.qty),\n        unit_price: num(x?.unit_price),\n        amount: num(x?.amount)\n      }))\n    : [];\n\n  // base fields from LLM\n  const base = {\n    invoice_no: str(obj?.invoice_no),\n    vendor: str(obj?.vendor),\n    issue_date: str(obj?.issue_date),\n    due_date: str(obj?.due_date),\n    currency: str(obj?.currency),\n    subtotal: num(obj?.subtotal),\n    tax_total: num(obj?.tax_total),\n\n    // discounts (raw)\n    discount_total: num(obj?.discount_total),      // fixed amount if present\n    discount_percent: pct(obj?.discount_percent),  // normalized 0..1\n\n    amount_total: num(obj?.amount_total),\n\n    // payment/receipt extras (raw; normalized below)\n    amount_due: num(obj?.amount_due),\n    paid_amount: num(obj?.paid_amount),\n    paid_date: str(obj?.paid_date),\n    receipt_no: str(obj?.receipt_no),\n    payment_method: str(obj?.payment_method),\n\n    destination_account: str(obj?.destination_account),\n    payment_ref: str(obj?.payment_ref),\n    doc_says_paid: bool(obj?.doc_says_paid),\n    status: str(obj?.status),\n    notes: str(obj?.notes),\n    source_file_id: str(obj?.source_file_id),\n    source_file_name: str(obj?.source_file_name),\n    source_file_url: str(obj?.source_file_url),\n    ingestion_batch: str(obj?.ingestion_batch),\n    line_items,\n    attachments: Array.isArray(obj?.attachments) ? obj.attachments.map(str) : []\n  };\n\n  // ---- discount math ----\n  const discount_amount =\n    base.discount_total > 0\n      ? two(base.discount_total)\n      : two(base.subtotal * (base.discount_percent || 0));\n\n  // compute fallback amount_total\n  const calc_total = two(base.subtotal - discount_amount + base.tax_total);\n\n  // choose stable amount_total for pipeline (prefer LLM if sane; else calc)\n  const provided = base.amount_total;\n  const useProvided =\n    provided > 0 && Math.abs(provided - calc_total) <= Math.max(0.01, calc_total * 0.01);\n  base.amount_total = useProvided ? two(provided) : calc_total;\n\n  // Notion percent wants 0..1\n  base.discount_percent_for_notion = +(base.discount_percent || 0).toFixed(4);\n  base.discount_amount = discount_amount; // handy for dedup & debug\n  base._amount_total_source = useProvided ? \"provided\" : \"calculated\";\n\n  // ---- partial / payment normalization ----\n  const at = Number(base.amount_total || 0);\n  let due  = Number(base.amount_due || 0);\n  let paid = Number(base.paid_amount || 0);\n\n  // Derive missing pieces when amount_total is known\n  if (at > 0) {\n    if (paid > 0 && due <= 0) due = Math.max(0, two(at - paid));\n    if (due > 0 && paid <= 0) paid = Math.max(0, two(at - due));\n    // If doc says PAID and due is zero but paid missing, assume fully paid\n    if (base.doc_says_paid && due === 0 && paid <= 0) paid = at;\n    // Clamp impossible values\n    if (paid < 0) paid = 0;\n    if (due < 0) due = 0;\n    if (paid > at) paid = at;\n    if (due > at) due = at;\n    if (paid + due > at) due = Math.max(0, two(at - paid));\n  } else {\n    // amount_total unknown — still clamp non-negatives\n    if (paid < 0) paid = 0;\n    if (due  < 0) due  = 0;\n  }\n\n  base.paid_amount = two(paid);\n  base.amount_due  = two(due);\n\n  // Receipt hints payload for later routing/Notion Receipt DB\n  base.receipt_hints = {\n    paid_amount: base.paid_amount,\n    paid_date: base.paid_date,\n    receipt_no: base.receipt_no,\n    payment_method: base.payment_method\n  };\n\n  // Nudge status if inconsistent with amounts\n  if (at > 0) {\n    if (base.amount_due === 0 && (base.doc_says_paid || base.paid_amount >= at - 0.01)) {\n      base.status = \"Paid (Unverified)\";\n    } else if (base.paid_amount > 0 && base.amount_due > 0) {\n      base.status = \"Partially Paid\";\n    } else if (base.paid_amount === 0 && base.amount_due >= at - 0.01) {\n      base.status = \"Unpaid\";\n    }\n  }\n\n  // ---- Attach Slack file URL (if available) ----\n  if (fileUrl) {\n    let fileName = \"\", fileId = \"\";\n    try {\n      const u = new URL(fileUrl);\n      const seg = u.pathname.split(\"/\").filter(Boolean);\n      fileName = decodeURIComponent(seg[seg.length - 1] || \"\");\n      const m = u.pathname.match(/-(F[A-Z0-9]+)\\//i);\n      if (m) fileId = m[1];\n    } catch {\n      const m1 = fileUrl.match(/\\/download\\/([^?\\/#]+)($|\\?)/i);\n      if (m1) fileName = decodeURIComponent(m1[1]);\n      const m2 = fileUrl.match(/-(F[A-Z0-9]+)\\//i);\n      if (m2) fileId = m2[1];\n    }\n\n    base.source_file_url = fileUrl;\n    if (!base.source_file_name) base.source_file_name = fileName;\n    if (!base.source_file_id) base.source_file_id = fileId;\n\n    const atSet = new Set(base.attachments.map(String));\n    atSet.add(fileUrl);\n    base.attachments = Array.from(atSet);\n  }\n\n  // Guard status values\n  const allowedStatus = new Set([\n    \"Unpaid\",\"Paid (Unverified)\",\"Paid (Verified)\",\n    \"Partially Paid\",\"Overdue\",\"Void/Cancelled\",\"Duplicate\"\n  ]);\n  if (!allowedStatus.has(base.status)) base.status = \"Unpaid\";\n\n  // Basic date sanity\n  const dateOk = (s) => /^(\\d{4})-(\\d{2})-(\\d{2})$/.test(s);\n  if (base.issue_date && !dateOk(base.issue_date)) base.issue_date = \"\";\n  if (base.due_date && !dateOk(base.due_date)) base.due_date = \"\";\n\n  return base;\n}\n\n// --- Collect Slack file URLs from either node (PDF or Image lanes) ---\nfunction collectSlackUrls(nodeName) {\n  try {\n    return $(nodeName).all()\n      .map(it =>\n        String(\n          it.json?.url_private_download ||\n          it.json?.file?.url_private_download || // some Slack nodes nest under file\n          \"\"\n        )\n      )\n      .filter(Boolean);\n  } catch {\n    return [];\n  }\n}\n\nconst urlsDoc = collectSlackUrls('Take Binary Files for Document'); // PDF lane\nconst urlsImg = collectSlackUrls('Take Binary Files');              // Image lane\n\n// Pick a URL for item index i; prefer same index, then first available\nfunction pickFileUrl(i) {\n  return urlsDoc[i] || urlsImg[i] || urlsDoc[0] || urlsImg[0] || \"\";\n}\n\n// --- Process ALL incoming items; each may yield one or many outputs ---\nconst outputs = [];\n\nfor (const [idx, item] of $input.all().entries()) {\n  let parsed = safeParseAny(item.json);\n\n  if (parsed && !Array.isArray(parsed) && typeof parsed === \"object\") {\n    const maybeArr = parsed.data || parsed.items || parsed.result || parsed.invoices;\n    if (Array.isArray(maybeArr)) parsed = maybeArr;\n  }\n  if (!Array.isArray(parsed)) parsed = [parsed];\n\n  const fileUrlForThisItem = pickFileUrl(idx);\n\n  for (const obj of parsed) {\n    const out = normalizeOne(obj, fileUrlForThisItem);\n    outputs.push({ json: out });\n  }\n}\n\nreturn outputs;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "0e729384-88a1-4ee3-9bd1-ccc218462dbc",
      "name": "Internal Check Duplicate Invoice",
      "type": "n8n-nodes-base.code",
      "position": [
        -3664,
        1888
      ],
      "parameters": {
        "jsCode": "// Input: many cleaned invoices (each item.json is like your sample)\n// Output: clusters of duplicates; each cluster picks one \"keep\" and lists \"drop\"\n\nconst input = $input.all().map(i => i.json);\n\n// --- Helpers ---\nconst canonVendor = (v) => {\n  if (!v) return \"\";\n  return String(v)\n    .toLowerCase()\n    .replace(/[.,'’\"]/g, \" \")\n    .replace(/\\b(pt|tbk|cv|inc|ltd|llc|llp|plc|corp|co|gmbh|sarl|bv)\\b/g, \"\")\n    .replace(/\\s+/g, \" \")\n    .trim();\n};\nconst canonInv = (s) => {\n  if (!s) return \"\";\n  return String(s)\n    .toUpperCase()\n    .replace(/\\s+/g, \"\")\n    .replace(/[–—]/g, \"-\")\n    .replace(/[^A-Z0-9\\/\\-\\.]/g, \"\")\n    .replace(/-+/g, \"-\")\n    .trim();\n};\nconst round2 = (n) => Math.round(Number(n || 0) * 100) / 100;\n\n// --- NEW: scoring helpers so PAID wins ---\nfunction parseYmd(s) {\n  // \"YYYY-MM-DD\" -> epoch ms; invalid -> 0\n  const m = String(s || \"\").match(/^(\\d{4})-(\\d{2})-(\\d{2})/);\n  if (!m) return 0;\n  return Date.UTC(+m[1], +m[2] - 1, +m[3]);\n}\n\nfunction statusRank(status, docPaid) {\n  const s = String(status || \"\").toLowerCase();\n  if (docPaid === true || /paid\\s*\\(verified\\)/i.test(status)) return 4;\n  if (/paid/i.test(s)) return 3;              // Paid (Unverified)\n  if (/partially/i.test(s)) return 2;         // Partially Paid\n  if (/overdue/i.test(s)) return 1;           // Overdue still beats Unpaid\n  return 0;                                   // Unpaid / others\n}\n\nfunction richness(o) {\n  let r = 0;\n  if (Array.isArray(o.attachments) && o.attachments.length) r += 2;\n  if (o.source_file_id) r += 1;\n  if (o.notes) r += 0.5;\n  if (Array.isArray(o.line_items)) r += Math.min(2, o.line_items.length * 0.1);\n  return r;\n}\n\n// choose one representative to keep\nfunction chooseMaster(arr) {\n  let best = null, bestScore = -Infinity, bestWhy = \"\";\n  for (const o of arr) {\n    const paidRank = statusRank(o.status, o.doc_says_paid); // 0..4\n    const newestDate = Math.max(parseYmd(o.due_date), parseYmd(o.issue_date));\n    const rich = richness(o);\n\n    // Weights: paidness >>> recency > richness\n    const score =\n      paidRank * 100 +               // ensure any \"Paid\" beats \"Unpaid\"\n      (newestDate / 8.64e7) * 0.1 +  // days since epoch * 0.1\n      rich;                          // small tie-break\n\n    const why = `paidRank=${paidRank} doc_says_paid=${!!o.doc_says_paid} status=${o.status || \"\"} newest=${newestDate ? new Date(newestDate).toISOString().slice(0,10) : \"-\"} richness=${rich}`;\n\n    if (score > bestScore) {\n      best = o; bestScore = score; bestWhy = why;\n    }\n  }\n  best._keep_reason_debug = bestWhy;\n  best._keep_score_debug = bestScore;\n  return best || arr[0];\n}\n\n// --- Build clusters ---\nconst clustersMap = new Map(); // key -> { reason, list: [] }\n\nfor (const o of input) {\n  const vendor_canon = canonVendor(o.vendor);\n  const invoice_no_canon = canonInv(o.invoice_no);\n  const currency = (o.currency || \"\").toUpperCase().trim();\n  const amt = round2(o.amount_total);\n  const due = (o.due_date || o.issue_date || \"\").slice(0, 10);\n\n  let key, reason;\n  if (invoice_no_canon) {\n    key = `INV#${vendor_canon}|${invoice_no_canon}`;\n    reason = \"SAME_VENDOR + INVOICE_NO\";\n  } else {\n    key = `FALLBACK#${vendor_canon}|${currency}|${amt}|${due}`;\n    reason = \"NO_INVOICE_NO → SAME_VENDOR + CURRENCY + AMOUNT + DATE\";\n  }\n\n  if (!clustersMap.has(key)) clustersMap.set(key, { reason, list: [] });\n  clustersMap.get(key).list.push({\n    ...o,\n    _vendor_canon: vendor_canon,\n    _invoice_no_canon: invoice_no_canon,\n    _fallback_key: !invoice_no_canon\n  });\n}\n\n// --- Emit only duplicate clusters (>1) ---\nconst results = [];\nfor (const [key, { reason, list }] of clustersMap.entries()) {\n  if (list.length <= 1) continue;\n\n  const amountSet = Array.from(new Set(list.map(x => round2(x.amount_total))));\n  const currencySet = Array.from(new Set(list.map(x => (x.currency || \"\").toUpperCase().trim())));\n\n  // annotate if amounts differ\n  let reasonDetailed = reason;\n  if (reason.startsWith(\"SAME_VENDOR\") && amountSet.length > 1) {\n    reasonDetailed += \" (amount differs across copies)\";\n  }\n\n  // --- NEW: count paid vs unpaid; prefer paid in keep\n  const paidCount = list.filter(x => x.doc_says_paid || /^paid/i.test(String(x.status || \"\"))).length;\n  if (paidCount > 0) reasonDetailed += \" | keep prefers PAID copy\";\n\n  const keep = chooseMaster(list);\n  const drop = list.filter(x => x !== keep);\n\n  results.push({\n    json: {\n      isDuplicate: true,\n      cluster_key: key,\n      reason: reasonDetailed,\n      count: list.length,\n      amounts: amountSet,\n      currencies: currencySet,\n      paid_count: paidCount,                 // debug/metrics\n      keep,                                  // should now be one of C/D (paid)\n      drop,\n      entries: list\n    }\n  });\n}\n\n// No duplicates? Emit a simple flag.\nif (results.length === 0) {\n  return [{ json: { isDuplicate: false, info: \"No duplicate invoices found.\" } }];\n}\n\nreturn results;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "dbcea768-1818-4a07-932c-3161e06342b5",
      "name": "Slack-Trigger",
      "type": "n8n-nodes-base.slackTrigger",
      "position": [
        -6032,
        1744
      ],
      "webhookId": "d13d3a70-faed-40f9-99fd-00a219c3af7c",
      "parameters": {
        "options": {},
        "trigger": [
          "message"
        ],
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09701BLY2Z",
          "cachedResultName": "expenses"
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0202318a-016b-4130-930c-bd092f18c492",
      "name": "Zusammenführen with Original Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -3440,
        1888
      ],
      "parameters": {
        "jsCode": "// n8n Code node — Merge originals with dedup clusters and tag each original\n// Upstream nodes:\n//   - \"Cleans AI Response\"  -> contains ORIGINAL parsed items (A, B, C)\n//   - Input to this node    -> contains cluster objects from \"Internal Check Duplicate Invoice\"\n// Output: one item per original, with dedup_* fields added\n\n// ---- helpers ----\nfunction canonVendor(v) {\n  return String(v || '')\n    .toLowerCase()\n    .replace(/[^a-z0-9\\s]/g, ' ')     // strip punctuation (ASCII-safe)\n    .replace(/\\b(pt|tbk|inc|ltd|llc)\\b/g, '')\n    .replace(/\\s+/g, ' ')\n    .trim();\n}\nfunction canonInvoiceNo(inv) {\n  return String(inv || '')\n    .toUpperCase()\n    .replace(/\\s+/g, '')\n    .replace(/[^A-Z0-9\\/\\-.]/g, '');\n}\nfunction clusterKeyFromItem(it) {\n  const vendor = canonVendor(it.vendor);\n  const inv = canonInvoiceNo(it.invoice_no);\n  if (inv) return `INV#${vendor}|${inv}`;\n  const currency = String(it.currency || '').toUpperCase();\n  const amt = Number(it.amount_total || it.subtotal || 0) || 0;\n  const date = String(it.due_date || it.issue_date || '');\n  return `FALLBACK#${vendor}|${currency}|${amt}|${date}`;\n}\n// Stable-ish signature to match items across steps\nfunction sig(o) {\n  return [\n    o.source_file_id || '',\n    o.source_file_url || '',\n    String(o.vendor || '').trim(),\n    String(o.invoice_no || '').trim(),\n    String(o.issue_date || '').trim(),\n    String(o.due_date || '').trim(),\n    String(o.currency || '').trim().toUpperCase(),\n    String(Number(o.amount_total ?? o.subtotal ?? 0) || 0)\n  ].join('||');\n}\n\n// ---- 1) load originals (A, B, C) ----\nconst originals = $('Cleans AI Response').all().map(i => i.json);\n\n// ---- 2) load and normalize clusters from THIS node input ----\nconst rawIn = $input.all().map(i => i.json);\nconst clusters = [];\nfor (const x of rawIn) {\n  if (Array.isArray(x)) {\n    for (const c of x) if (c && c.cluster_key) clusters.push(c);\n  } else if (x && x.cluster_key) {\n    clusters.push(x);\n  }\n}\n// If your duplicate checker sometimes emits {clusters:[...]}, support that too\nfor (const x of rawIn) {\n  if (x && Array.isArray(x.clusters)) {\n    for (const c of x.clusters) if (c && c.cluster_key) clusters.push(c);\n  }\n}\n\n// ---- 3) index clusters (by cluster_key) ----\nconst clusterIndex = new Map();  // cluster_key -> { meta, keepSig, dropSigSet, keepUsed }\nfor (const c of clusters) {\n  const meta = {\n    cluster_key: c.cluster_key,\n    reason: c.reason || '',\n    count: Number(c.count || (c.entries ? c.entries.length : 1)) || 1,\n    amounts: c.amounts || [],\n    currencies: c.currencies || []\n  };\n  const keepSig = c.keep ? sig(c.keep) : null;\n  const dropSigSet = new Set((c.drop || []).map(sig));\n  clusterIndex.set(c.cluster_key, { meta, keepSig, dropSigSet, keepUsed: false });\n}\n\n// Try to find matching cluster for an original item\nfunction findClusterForOriginal(item) {\n  const s = sig(item);\n  for (const [ck, rec] of clusterIndex) {\n    if ((rec.keepSig && rec.keepSig === s) || rec.dropSigSet.has(s)) return [ck, rec];\n  }\n  const ck = clusterKeyFromItem(item);\n  return [ck, clusterIndex.get(ck) || null];\n}\n\n// ---- 4) merge labels onto originals ----\nconst out = [];\n\nfor (const item of originals) {\n  const [ck, rec] = findClusterForOriginal(item);\n\n  if (!rec) {\n    out.push({\n      json: {\n        ...item,\n        dedup_cluster_key: ck || '',\n        dedup_role: 'unique',\n        dedup_count: 1,\n        dedup_reason: 'no_cluster_match'\n      }\n    });\n    continue;\n  }\n\n  const { meta, keepSig, dropSigSet } = rec;\n  const s = sig(item);\n  let role;\n\n  if (meta.count <= 1) {\n    role = 'unique';\n  } else if (keepSig && s === keepSig && !rec.keepUsed) {\n    role = 'keep';           // first original that matches the keepSig\n    rec.keepUsed = true;     // ensure only one \"keep\" per cluster\n  } else {\n    role = 'drop';           // everything else in that cluster is a duplicate\n  }\n\n  out.push({\n    json: {\n      ...item,\n      dedup_cluster_key: meta.cluster_key,\n      dedup_role: role,                 // \"keep\" | \"drop\" | \"unique\"\n      dedup_count: meta.count,\n      dedup_reason: meta.reason,\n      dedup_amounts: meta.amounts,\n      dedup_currencies: meta.currencies\n    }\n  });\n}\n\nreturn out;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "123fc9c7-f6d3-4be5-b02a-d6c65faa5bc9",
      "name": "Zusammenführen Data Value into One Key",
      "type": "n8n-nodes-base.code",
      "position": [
        -4464,
        1888
      ],
      "parameters": {
        "jsCode": "// Code node — Run once for all items\n// Preceded by a Merge (Wait for all) so ALL items from both paths arrive here.\n\nconst out = [];\n\nfunction get(v) {\n  return typeof v === 'string' ? v.trim() : '';\n}\n\nfor (const it of $input.all()) {\n  const j = it.json || {};\n\n  // Your two possible sources per item\n  const fromPdf   = get(j.mergedParsedText);                 // Error3 (PDF path)\n  const fromImage = get(j?.ParsedResults?.[0]?.ParsedText);  // Error2 (image path)\n\n  const OCRResult = fromPdf || fromImage || '';\n  const OCRSource = fromPdf\n    ? 'Error3.mergedParsedText'\n    : fromImage\n    ? 'Error2.ParsedResults[0].ParsedText'\n    : 'none';\n\n  // Keep any file metadata you already have on the item\n  out.push({\n    json: {\n      ...j,\n      OCRResult,\n      OCRSource\n    }\n  });\n}\n\nreturn out;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "88aae252-885b-4433-af13-88fea42ad24e",
      "name": "Decide Fate for Data",
      "type": "n8n-nodes-base.if",
      "position": [
        -3216,
        1888
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9cb0bdab-37f9-4536-8b75-de7e3bdd4a76",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.dedup_role }}",
              "rightValue": "drop"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c3b08864-40e6-4c71-b0ad-f46231351a92",
      "name": "Create Query for DB",
      "type": "n8n-nodes-base.code",
      "position": [
        -2992,
        1312
      ],
      "parameters": {
        "jsCode": "// Run ONCE FOR ALL ITEMS\nconst out = [];\n\nfunction windowDates(anchor) {\n  if (!anchor) return null;\n  const d = new Date(anchor + \"T00:00:00Z\");\n  if (isNaN(d)) return null;\n  const s = new Date(d); s.setUTCDate(s.getUTCDate() - 30);\n  const e = new Date(d); e.setUTCDate(e.getUTCDate() + 30);\n  return [s.toISOString().slice(0,10), e.toISOString().slice(0,10)];\n}\n\nfor (const { json: j } of $input.all()) {\n  const haveInvoiceNo = !!j?.invoice_no;\n\n  // Anchor date:\n  // - If we know the invoice number, anchor to invoice-level dates\n  // - Otherwise, paid_date is acceptable for finding the invoice by heuristics\n  const anchor = haveInvoiceNo\n    ? (j?.issue_date || j?.due_date || \"\")\n    : (j?.receipt_hints?.paid_date || j?.issue_date || j?.due_date || \"\");\n  const dates = windowDates(anchor);\n\n  const and = [];\n\n  if (haveInvoiceNo) {\n    // Prefer canon properties if your DB has them; else fall back to title field\n    if (j.invoice_no_canon) {\n      and.push({ property: \"Invoice No (Canon)\", rich_text: { equals: String(j.invoice_no_canon) } });\n      if (j.vendor_canon) {\n        and.push({ property: \"Vendor (Canon)\", rich_text: { equals: String(j.vendor_canon) } });\n      }\n    } else {\n      and.push({ property: \"Invoice No\", title: { equals: String(j.invoice_no) } });\n    }\n    if (j.currency) {\n      and.push({ property: \"Currency\", select: { equals: String(j.currency) } });\n    }\n\n    // IMPORTANT: no Amount Total filter when Invoice No is present\n    // (If you want a belt-and-suspenders check, you can add a WIDE band on amount_total instead,\n    // but never use the receipt paid amount.)\n\n  } else {\n    // Fallback: vendor + currency + invoice total band + date\n    if (j.vendor_canon) {\n      and.push({ property: \"Vendor (Canon)\", rich_text: { equals: String(j.vendor_canon) } });\n    } else if (j.vendor) {\n      and.push({ property: \"Vendor\", rich_text: { equals: String(j.vendor) } });\n    }\n    if (j.currency) {\n      and.push({ property: \"Currency\", select: { equals: String(j.currency) } });\n    }\n    const total = Number(j?.amount_total);\n    if (!Number.isNaN(total) && total > 0) {\n      const eps = Math.max(5, total * 0.03); // ± $5 or 3%\n      and.push(\n        { property: \"Amount Total\", number: { greater_than_or_equal_to: +(total - eps).toFixed(2) } },\n        { property: \"Amount Total\", number: { less_than_or_equal_to:   +(total + eps).toFixed(2) } },\n      );\n    }\n  }\n\n  if (dates) {\n    const [start, end] = dates;\n    and.push({\n      or: [\n        { property: \"Issue Date\", date: { on_or_after: start, on_or_before: end } },\n        { property: \"Due Date\",   date: { on_or_after: start, on_or_before: end } },\n      ]\n    });\n  }\n\n  const queryBody = { filter: { and }, page_size: haveInvoiceNo ? 10 : 5 };\n  out.push({ json: { ...j, queryBody } });\n}\n\nreturn out;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "de2b4a0f-eaba-4d8c-ac76-220f14725f10",
      "name": "Check DB Invoice",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -2768,
        1312
      ],
      "parameters": {
        "url": "https://api.notion.com/v1/databases/24df7557957380739611da8371404254/query",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json.queryBody }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Notion-Version",
              "value": "2022-06-28"
            }
          ]
        },
        "nodeCredentialType": "notionApi"
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "067db3c6-fc83-46a2-8ad4-0b8cec9ab83e",
      "name": "Zusammenführen Items Invoice",
      "type": "n8n-nodes-base.code",
      "position": [
        -2544,
        1312
      ],
      "parameters": {
        "jsCode": "// After \"Check DB Invoice\" (HTTP). Mode: Run once for all items. Single output.\n\n// Originals aligned by index (from your query-prep node)\nconst originals = $('Create Query for DB').all().map(i => i.json);\n\n// Toggle if you want partial flows to auto-route (true) or go to manual_review (false)\nconst ENABLE_PARTIAL = true;\n\n// ---------- Notion helpers ----------\nconst getTitle  = (p, name) => (p?.properties?.[name]?.title || [])\n  .map(t => t.plain_text || '').join('');\nconst getRich   = (p, name) => (p?.properties?.[name]?.rich_text || [])\n  .map(t => t.plain_text || '').join('');\nconst getSelect = (p, name) => p?.properties?.[name]?.select?.name || '';\nconst getNumber = (p, name) => (\n  typeof p?.properties?.[name]?.number === 'number'\n    ? p.properties[name].number\n    : null\n);\nconst getDate   = (p, name) => p?.properties?.[name]?.date?.start || '';\n\nconst isPaidName = (s) => /^paid/i.test(String(s || ''));\n\n// quick equality for “no-change/dup” check\nfunction coreSame(src, db) {\n  const eq = (x,y)=> String(x||'') === String(y||'');\n  const numEq=(x,y)=> {\n    const nx=Number(x??NaN), ny=Number(y??NaN);\n    if (Number.isNaN(nx) && Number.isNaN(ny)) return true;\n    return Math.abs(nx - ny) < 0.001;\n  };\n  return (\n    eq(src.vendor, db.vendor) &&\n    eq(src.invoice_no, db.invoice_no) &&\n    eq(src.currency, db.currency) &&\n    numEq(src.amount_total, db.amount_total) &&\n    eq(src.issue_date, db.issue_date) &&\n    eq(src.due_date, db.due_date)\n  );\n}\n\nconst out = [];\nconst tolAbs = 0.01;   // absolute amount tolerance\nconst tolPct = 0.01;   // 1% relative tolerance\n\n$input.all().forEach((it, idx) => {\n  const src   = originals[idx] || {};\n  const http  = it.json || {};\n  const pages = Array.isArray(http.results) ? http.results : [];\n  const manyMatches = pages.length > 1;\n  const page  = pages[0] || null;\n\n  // ---------- DB snapshot ----------\n  const db = page ? {\n    page_id:     page.id,\n    invoice_no:  getTitle(page, 'Invoice No'),\n    vendor:      getRich(page,  'Vendor'),\n    currency:    getSelect(page,'Currency'),\n    amount_total:getNumber(page,'Amount Total'),\n    issue_date:  getDate(page,  'Issue Date'),\n    due_date:    getDate(page,  'Due Date'),\n    status:      getSelect(page,'Status'),\n  } : null;\n  const dbPaid = db ? isPaidName(db.status) : false;\n\n  // ---------- mismatches ----------\n  const vendorMismatch   = !!(db && db.vendor && src.vendor && db.vendor !== src.vendor);\n  const currencyMismatch = !!(db && db.currency && src.currency && db.currency !== src.currency);\n\n  const inAmt = Number(src.amount_total ?? NaN);\n  const dbAmt = Number(db?.amount_total ?? NaN);\n  const amountMismatch =\n    db && Number.isFinite(inAmt) && Number.isFinite(dbAmt) &&\n    (Math.abs(inAmt - dbAmt) > tolAbs) &&\n    (Math.abs(inAmt - dbAmt) / Math.max(1, dbAmt) > tolPct);\n\n  const fallbackAmbiguous = !src.invoice_no && manyMatches;\n\n  // ---------- derive payment signals from AMOUNTS (ignore labels) ----------\n  const statusStr = String(src.status || '');\n  const totalIn   = Number(src.amount_total ?? NaN);\n  const paidAmtIn = Number(\n    (src?.receipt_hints?.paid_amount ?? src.paid_amount) ?? NaN\n  );\n  const dueIn     = Number(src.amount_due ?? NaN);\n\n  // some payment if: positive paid OR “partial” in status OR doc_says_paid flag\n  let hasSomePayment =\n    (Number.isFinite(paidAmtIn) && paidAmtIn > tolAbs) ||\n    /partial/i.test(statusStr) ||\n    src.doc_says_paid === true;\n\n  // full payment primarily by amounts; labels only if amounts missing\n  let isFullPayment =\n    (Number.isFinite(dueIn)   && dueIn <= tolAbs) ||\n    (Number.isFinite(totalIn) && Number.isFinite(paidAmtIn) && (paidAmtIn >= totalIn - tolAbs));\n\n  // if due is positive, it cannot be full—even if the doc says “PAID”\n  if (Number.isFinite(dueIn) && dueIn > tolAbs) isFullPayment = false;\n\n  // keep compatibility names used later in logic\n  const incomingPaid    = hasSomePayment;\n  const partialDetected = hasSomePayment && !isFullPayment;\n\n  // ---------- decide route ----------\n  let next_action = 'archive';\n  let reason = '';\n\n  if (!page) {\n    // No DB page found → choose create_* route\n    if (hasSomePayment) {\n      if (isFullPayment) {\n        next_action = 'create_paid';\n        reason = 'no_db_match_paid';\n      } else {\n        next_action = ENABLE_PARTIAL ? 'create_partial' : 'manual_review';\n        reason = ENABLE_PARTIAL ? 'no_db_match_partial_payment' : 'partial_needs_review';\n      }\n    } else {\n      next_action = 'create_unpaid';\n      reason = 'no_db_match_unpaid';\n    }\n  } else {\n    // Have a DB page\n    if (manyMatches || vendorMismatch || currencyMismatch || fallbackAmbiguous) {\n      next_action = 'manual_review';\n      reason = manyMatches\n        ? 'multiple_db_matches'\n        : vendorMismatch\n          ? 'vendor_mismatch'\n          : currencyMismatch\n            ? 'currency_mismatch'\n            : 'fallback_ambiguous';\n    } else if (hasSomePayment) {\n      // There is some payment in the incoming doc\n      if (isFullPayment) {\n        // mark paid if DB not yet paid; else archive duplicate payment\n        if (!dbPaid) {\n          next_action = 'update_mark_paid';\n          reason = 'mark_paid';\n        } else {\n          next_action = 'archive';\n          reason = 'duplicate_payment_already_paid';\n        }\n      } else {\n        // partial payment path\n        if (ENABLE_PARTIAL) {\n          next_action = 'update_partial';\n          reason = 'partial_payment_detected';\n        } else {\n          next_action = 'manual_review';\n          reason = 'partial_needs_review';\n        }\n      }\n    } else if (amountMismatch) {\n      next_action = 'manual_review';\n      reason = 'amount_mismatch';\n    } else {\n      // no payment transition\n      const same = coreSame(src, db);\n      next_action = 'archive';\n      reason = same ? 'duplicate_no_change' : 'no_payment_transition';\n    }\n  }\n\n  out.push({\n    json: {\n      ...src,\n      db_found:  !!page,\n      db_page_id: db?.page_id || '',\n      db_status:  db?.status   || '',\n      next_action,\n      reason,\n      _checks: {\n        manyMatches,\n        vendorMismatch,\n        currencyMismatch,\n        amountMismatch,\n        fallbackAmbiguous,\n        hasSomePayment,\n        isFullPayment,\n        dbPaid\n      }\n    }\n  });\n});\n\nreturn out;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "1e7efdbb-f58c-4cfa-9a74-22cda80b58c7",
      "name": "Send to Source File Invoice 1",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1872,
        736
      ],
      "parameters": {
        "title": "={{ $json.source_file_id }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-8062-b50d-fe9db34ec410",
          "cachedResultUrl": "https://www.notion.so/238f755795738062b50dfe9db34ec410",
          "cachedResultName": "Source File"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "File ID|title",
              "title": "={{ $json.source_file_id }}"
            },
            {
              "key": "Filename|rich_text",
              "textContent": "={{ $json.source_file_name }}"
            },
            {
              "key": "File URL|url",
              "urlValue": "={{ $json.source_file_url }}"
            },
            {
              "key": "Summary|rich_text",
              "text": {
                "text": [
                  {
                    "text": "={{ $json.line_items_rich_text[0].text.content }}",
                    "annotationUi": {}
                  }
                ]
              },
              "richText": true
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "3b8e7c65-8d40-4636-bfb0-8091365e584e",
      "name": "Prepare Line Items before send",
      "type": "n8n-nodes-base.code",
      "position": [
        -2320,
        1312
      ],
      "parameters": {
        "jsCode": "// n8n Code node — prepare line items + compute ONE field for Notion (\"Paid Amount\")\nconst out = [];\n\nfunction two(n){ return Math.round((Number(n)||0)*100)/100; }\nfunction chunk(str, size=1800){ const a=[]; for(let i=0;i<str.length;i+=size)a.push(str.slice(i,i+size)); return a; }\nfunction num(x){ if(x===null||x===undefined||x===\"\") return NaN; const n=Number(String(x).replace(/[^0-9.-]/g,\"\")); return isNaN(n)?NaN:n; }\nfunction clamp(n,min,max){ return Math.max(min, Math.min(max, n)); }\nfunction approxEq(a,b,eps=0.01){ return Math.abs(a-b)<=eps; }\n\nfor (const item of $input.all()) {\n  const j = item.json || {};\n  const ccy = (j.currency || '').toUpperCase();\n  const items = Array.isArray(j.line_items) ? j.line_items : [];\n\n  // Build line-items text (unchanged)\n  const lines = items.map(li => {\n    const desc=(li?.description||'').trim();\n    const qty = two(li?.qty);\n    const up  = two(li?.unit_price);\n    const amt = two(li?.amount || qty*up);\n    const tail = ccy ? ` ${ccy}` : '';\n    return `${qty} × ${desc} @ ${up}${tail} = ${amt}${tail}`;\n  });\n  const text = lines.join('\\n') || '';\n  const rich = chunk(text).map(s => ({ type:'text', text:{ content:s }}));\n\n  // Minimal compute for Paid Amount\n  const total = num(j.amount_total);\n  const due   = num(j.amount_due);\n  const delta = num(j?.receipt_hints?.paid_amount ?? j.paid_amount);       // new receipt (e.g., 200)\n  const prev  = num(j.db_paid_amount_prev ?? j.invoice?.paid_amount ?? 0); // previous paid if you pass it\n\n  // Prefer set-to from doc (Total - Due); fallback to prev + delta\n  let newPaid = Number.isFinite(total) && Number.isFinite(due)\n    ? two(clamp(total - due, 0, total))\n    : (Number.isFinite(delta) ? two(clamp(prev + delta, 0, Number.isFinite(total)? total : Infinity)) : NaN);\n\n  // If still NaN, don't emit the field to avoid bad writes\n  const outJson = {\n    ...j,\n    line_items_text: text,\n    line_items_rich_text: rich,\n  };\n  if (Number.isFinite(newPaid)) outJson.notion_paid_amount = newPaid;\n\n  // (Optional tiny extra: status, only if you want it — safe to ignore)\n  if (Number.isFinite(total) && Number.isFinite(newPaid)) {\n    outJson.notion_status =\n      approxEq(newPaid, 0)      ? \"Unpaid\" :\n      approxEq(newPaid, total)  ? \"Paid (Verified)\" :\n                                  \"Partially Paid\";\n  }\n\n  out.push({ json: outJson });\n}\n\nreturn out;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "fa73399a-c133-48b3-87fe-922961f4d448",
      "name": "Decide Fate",
      "type": "n8n-nodes-base.switch",
      "position": [
        -2096,
        1232
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Create Unpaid",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "18f4cc4b-ad0f-4782-a59d-a66dbffc6475",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.next_action }}",
                    "rightValue": "create_unpaid"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Create Paid",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "d8bb0418-0798-428a-b379-8cf8accf5ea9",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.next_action }}",
                    "rightValue": "create_paid"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Update to Paid",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "4009916c-000e-435d-ada3-6a7d1fbc595c",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.next_action }}",
                    "rightValue": "update_mark_paid"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Archive",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "172dad2a-7a92-493d-977d-56c568d5c360",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.next_action }}",
                    "rightValue": "archive"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "New Create Partial",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "a14d6d5c-6eac-49e8-8380-f85cf565a542",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.next_action }}",
                    "rightValue": "create_partial"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Update Partial Payment",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "b9d0f364-e7a4-48b8-94fc-6053b51f6e14",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.next_action }}",
                    "rightValue": "update_partial"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Manual Review",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "4d8986d1-3896-42bf-9d6f-9adb48ac3987",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.next_action }}",
                    "rightValue": "manual_review"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "f90f09ea-6016-429b-915f-1565bcff1d97",
      "name": "Create new Invoice Unpaid",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1648,
        736
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "24df7557-9573-8073-9611-da8371404254",
          "cachedResultUrl": "https://www.notion.so/24df7557957380739611da8371404254",
          "cachedResultName": "Clearflow Invoice (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Attachments|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.attachments[0] }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Decide Fate').item.json.currency }}"
            },
            {
              "key": "Destination Account|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.destination_account }}"
            },
            {
              "key": "Discount Percent|number",
              "numberValue": "={{ $('Decide Fate').item.json.discount_percent_for_notion }}"
            },
            {
              "key": "Due Date|date",
              "date": "={{ $('Decide Fate').item.json.due_date }}"
            },
            {
              "key": "Invoice No|title",
              "title": "={{ $('Decide Fate').item.json.invoice_no }}"
            },
            {
              "key": "Issue Date|date",
              "date": "={{ $('Decide Fate').item.json.issue_date }}"
            },
            {
              "key": "Line Items|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.line_items_rich_text[0].text.content }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.notes }}"
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Decide Fate').item.json.paid_amount }}"
            },
            {
              "key": "Payment Ref|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.payment_ref }}"
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.destination_account }}"
            },
            {
              "key": "Status|select",
              "selectValue": "={{ $('Decide Fate').item.json.status }}"
            },
            {
              "key": "Subtotal|number",
              "numberValue": "={{ $('Decide Fate').item.json.subtotal }}"
            },
            {
              "key": "Tax Total|number",
              "numberValue": "={{ $('Decide Fate').item.json.tax_total }}"
            },
            {
              "key": "Vendor|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.vendor }}"
            },
            {
              "key": "=Source File|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8f25494a-6b7c-45e5-99fc-7ab5e2e0d085",
      "name": "Add Receipt into Cashflow",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1872,
        1312
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-80a2-96c8-e638a56411d2",
          "cachedResultUrl": "https://www.notion.so/238f7557957380a296c8e638a56411d2",
          "cachedResultName": "Cashflow (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Cashflow ID|title",
              "title": "={{ $json.receipt_no || 'cf_' + Date.now() + '_' + Math.floor(Math.random() * 1000) }}"
            },
            {
              "key": "Amount (Net)|number",
              "numberValue": "={{ $json.paid_amount }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $json.currency }}"
            },
            {
              "key": "Fee|number",
              "numberValue": "={{ $json.tax_total }}"
            },
            {
              "key": "Gross Amount|number",
              "numberValue": "={{ $json.paid_amount }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $json.notes }}"
            },
            {
              "key": "Timestamp|date",
              "date": "={{ $json.paid_date }}"
            },
            {
              "key": "Timestamp (ISO)|rich_text",
              "textContent": "={{ $json.paid_date }}"
            },
            {
              "key": "Type|select",
              "selectValue": "=Expense"
            },
            {
              "key": "Vendor / Recipient|rich_text",
              "textContent": "={{ $json.vendor }}"
            },
            {
              "key": "Vendor Ref ID|rich_text",
              "textContent": "={{ $json.invoice_no }}"
            },
            {
              "key": "Source File|relation",
              "relationValue": [
                "={{ $json.db_page_id }}"
              ]
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $json.vendor }}"
            },
            {
              "key": "Source Account|rich_text",
              "textContent": "={{ $json.payment_method }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $json.line_items_rich_text[0].text.content }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "35db92f5-faf6-4ecd-a148-7bbf09bf620b",
      "name": "Update Invoice to Paid Fully",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1648,
        1312
      ],
      "parameters": {
        "pageId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Prepare Line Items before send').item.json.db_page_id }}"
        },
        "options": {},
        "resource": "databasePage",
        "operation": "update",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Receipt|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.paid_amount }}"
            },
            {
              "key": "Status|select",
              "selectValue": "Paid"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5487835c-5655-476b-bbad-f368653150d1",
      "name": "Send to Source File Invoice 2",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1872,
        928
      ],
      "parameters": {
        "title": "={{ $json.source_file_id }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-8062-b50d-fe9db34ec410",
          "cachedResultUrl": "https://www.notion.so/238f755795738062b50dfe9db34ec410",
          "cachedResultName": "Source File"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "File ID|title",
              "title": "={{ $json.source_file_id }}"
            },
            {
              "key": "Filename|rich_text",
              "textContent": "={{ $json.source_file_name }}"
            },
            {
              "key": "File URL|url",
              "urlValue": "={{ $json.source_file_url }}"
            },
            {
              "key": "Summary|rich_text",
              "text": {
                "text": [
                  {
                    "text": "={{ $json.line_items_rich_text[0].text.content }}",
                    "annotationUi": {}
                  }
                ]
              },
              "richText": true
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a09de3d7-f79a-4027-ab49-a4e2376d3f82",
      "name": "Add Receipt into Cashflow Paid 1",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1648,
        928
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-80a2-96c8-e638a56411d2",
          "cachedResultUrl": "https://www.notion.so/238f7557957380a296c8e638a56411d2",
          "cachedResultName": "Cashflow (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Cashflow ID|title",
              "title": "={{ $('Prepare Line Items before send').item.json.receipt_no || 'cf_' + Date.now() + '_' + Math.floor(Math.random() * 1000) }}"
            },
            {
              "key": "Amount (Net)|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.paid_amount }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Prepare Line Items before send').item.json.currency }}"
            },
            {
              "key": "Fee|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.tax_total }}"
            },
            {
              "key": "Gross Amount|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.paid_amount }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.notes }}"
            },
            {
              "key": "Timestamp|date",
              "date": "={{ $('Prepare Line Items before send').item.json.paid_date }}"
            },
            {
              "key": "Timestamp (ISO)|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.paid_date }}"
            },
            {
              "key": "Type|select",
              "selectValue": "=Expense"
            },
            {
              "key": "Vendor / Recipient|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.vendor }}"
            },
            {
              "key": "Vendor Ref ID|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.receipt_no }}"
            },
            {
              "key": "Source File|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.vendor }}"
            },
            {
              "key": "Source Account|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.payment_method }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "54b5f427-4c28-4b83-a04d-40bc14df309d",
      "name": "Create new Invoice Paid Full",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1424,
        928
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "24df7557-9573-8073-9611-da8371404254",
          "cachedResultUrl": "https://www.notion.so/24df7557957380739611da8371404254",
          "cachedResultName": "Clearflow Invoice (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Attachments|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.attachments[0] }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Decide Fate').item.json.currency }}"
            },
            {
              "key": "Destination Account|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.destination_account }}"
            },
            {
              "key": "Discount Percent|number",
              "numberValue": "={{ $('Decide Fate').item.json.discount_percent_for_notion }}"
            },
            {
              "key": "Due Date|date",
              "date": "={{ $('Decide Fate').item.json.due_date }}"
            },
            {
              "key": "Invoice No|title",
              "title": "={{ $('Decide Fate').item.json.invoice_no }}"
            },
            {
              "key": "Issue Date|date",
              "date": "={{ $('Decide Fate').item.json.issue_date }}"
            },
            {
              "key": "Line Items|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.line_items_rich_text[0].text.content }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.notes }}"
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Decide Fate').item.json.paid_amount }}"
            },
            {
              "key": "Payment Ref|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.payment_ref }}"
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.destination_account }}"
            },
            {
              "key": "Status|select",
              "selectValue": "={{ $('Decide Fate').item.json.status }}"
            },
            {
              "key": "Subtotal|number",
              "numberValue": "={{ $('Decide Fate').item.json.subtotal }}"
            },
            {
              "key": "Tax Total|number",
              "numberValue": "={{ $('Decide Fate').item.json.tax_total }}"
            },
            {
              "key": "Vendor|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.vendor }}"
            },
            {
              "key": "=Source File|relation",
              "relationValue": [
                "={{ $('Send to Source File Invoice 2').item.json.id }}"
              ]
            },
            {
              "key": "Source Account|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.payment_method }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "48bc9ab1-03bb-40a6-844d-a4fff203fcd5",
      "name": "Send to Archive Source File Invoice",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1872,
        1120
      ],
      "parameters": {
        "title": "={{ $json.source_file_id }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "239f7557-9573-80d6-a8fb-fc710833e5db",
          "cachedResultUrl": "https://www.notion.so/239f7557957380d6a8fbfc710833e5db",
          "cachedResultName": "Archived Source File (Duplicate)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "File ID|title",
              "title": "={{ $json.source_file_id }}"
            },
            {
              "key": "Filename|rich_text",
              "textContent": "={{ $json.source_file_name }}"
            },
            {
              "key": "FILE URL|url",
              "urlValue": "={{ $json.source_file_url }}"
            },
            {
              "key": "Summary|rich_text",
              "text": {
                "text": [
                  {
                    "text": "={{ $json.line_items_rich_text[0].text.content }}",
                    "annotationUi": {}
                  }
                ]
              },
              "richText": true
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "d165164c-bcf8-4ef3-b434-9416865c6b26",
      "name": "Archive Invoice",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1648,
        1120
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "254f7557-9573-8012-b9b3-e7811bfac12c",
          "cachedResultUrl": "https://www.notion.so/254f755795738012b9b3e7811bfac12c",
          "cachedResultName": "Archived Clearflow Invoice (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Attachments|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.attachments[0] }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Decide Fate').item.json.currency }}"
            },
            {
              "key": "Destination Account|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.destination_account }}"
            },
            {
              "key": "Discount Percent|number",
              "numberValue": "={{ $('Decide Fate').item.json.discount_percent_for_notion }}"
            },
            {
              "key": "Due Date|date",
              "date": "={{ $('Decide Fate').item.json.due_date }}"
            },
            {
              "key": "Invoice No|title",
              "title": "={{ $('Decide Fate').item.json.invoice_no }}"
            },
            {
              "key": "Issue Date|date",
              "date": "={{ $('Decide Fate').item.json.issue_date }}"
            },
            {
              "key": "Line Items|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.line_items_rich_text[0].text.content }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.notes }}"
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Decide Fate').item.json.paid_amount }}"
            },
            {
              "key": "Payment Ref|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.payment_ref }}"
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.destination_account }}"
            },
            {
              "key": "Status|select",
              "selectValue": "={{ $('Decide Fate').item.json.status }}"
            },
            {
              "key": "Subtotal|number",
              "numberValue": "={{ $('Decide Fate').item.json.subtotal }}"
            },
            {
              "key": "Tax Total|number",
              "numberValue": "={{ $('Decide Fate').item.json.tax_total }}"
            },
            {
              "key": "Vendor|rich_text",
              "textContent": "={{ $('Decide Fate').item.json.vendor }}"
            },
            {
              "key": "=Source File|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4157135a-0645-4f12-9315-c6b2299520b6",
      "name": "Warten",
      "type": "n8n-nodes-base.wait",
      "position": [
        -1600,
        2544
      ],
      "webhookId": "9d0e00b6-5ee8-45c9-8597-34db73f701ae",
      "parameters": {
        "resume": "webhook",
        "options": {},
        "resumeUnit": "days",
        "resumeAmount": 2,
        "limitWaitTime": true
      },
      "typeVersion": 1.1
    },
    {
      "id": "da9cdafe-01c8-49c8-afaa-29cb46f67aef",
      "name": "Send a message",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1824,
        2544
      ],
      "webhookId": "2df2d5da-990f-4499-9131-0bbf3595e9bc",
      "parameters": {
        "text": "Test Text",
        "select": "channel",
        "blocksUi": "={\n\t\"blocks\": [\n\t\t{\n\t\t\t\"type\": \"section\",\n\t\t\t\"text\": {\n\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\"text\": \"You have a new invoice to review:\\n*{{ $('Prepare Line Items before send').item.json.invoice_no || '—' }}*\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"type\": \"section\",\n\t\t\t\"fields\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Type:*\\nInvoice\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*When:*\\n{{ $('Prepare Line Items before send').item.json.issue_date || '—' }} → {{ $('Prepare Line Items before send').item.json.due_date || '—' }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Vendor:*\\n{{ $('Prepare Line Items before send').item.json.vendor || '—' }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Currency:*\\n{{ $('Prepare Line Items before send').item.json.currency || '—' }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Invoice No:*\\n{{ $('Prepare Line Items before send').item.json.invoice_no || '—' }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Status (detected):*\\n{{ $('Prepare Line Items before send').item.json.status || '—' }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Amount Total:*\\n{{ $('Prepare Line Items before send').item.json.amount_total || 0 }} {{ $('Prepare Line Items before send').item.json.currency || '' }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Paid / Due:*\\n{{ $('Prepare Line Items before send').item.json.paid_amount || 0 }} / {{ $('Prepare Line Items before send').item.json.amount_due || 0 }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Payment Method:*\\n{{ $('Prepare Line Items before send').item.json.payment_method || '—' }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mrkdwn\",\n\t\t\t\t\t\"text\": \"*Reason:*\\n{{ $('Prepare Line Items before send').item.json.reason || '—' }}\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"type\": \"image\",\n\t\t\t\"title\": {\n\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\"text\": \"image1\",\n\t\t\t\t\"emoji\": true\n\t\t\t},\n\t\t\t\"image_url\": \"{{ $json.source_file_url }}\",\n\t\t\t\"alt_text\": \"image1\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"divider\"\n\t\t},\n\t\t{\n\t\t\t\"type\": \"actions\",\n\t\t\t\"block_id\": \"review_actions\",\n\t\t\t\"elements\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"button\",\n\t\t\t\t\t\"action_id\": \"approve\",\n\t\t\t\t\t\"text\": {\n\t\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\t\"text\": \"✅ Approve Paid\"\n\t\t\t\t\t},\n\t\t\t\t\t\"style\": \"primary\",\n\t\t\t\t\t\"url\": \"{{ $execution.resumeUrl }}?choice=approve&inv={{ encodeURIComponent($('Prepare Line Items before send').item.json.invoice_no || '') }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"button\",\n\t\t\t\t\t\"action_id\": \"unpaid\",\n\t\t\t\t\t\"text\": {\n\t\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\t\"text\": \"📝 Approve Unpaid\"\n\t\t\t\t\t},\n\t\t\t\t\t\"style\": \"danger\",\n\t\t\t\t\t\"url\": \"{{ $execution.resumeUrl }}?choice=unpaid&inv={{ encodeURIComponent($('Prepare Line Items before send').item.json.invoice_no || '') }}\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"button\",\n\t\t\t\t\t\"action_id\": \"archive\",\n\t\t\t\t\t\"text\": {\n\t\t\t\t\t\t\"type\": \"plain_text\",\n\t\t\t\t\t\t\"text\": \"❌ Archive\"\n\t\t\t\t\t},\n\t\t\t\t\t\"url\": \"{{ $execution.resumeUrl }}?choice=archive&inv={{ encodeURIComponent($('Prepare Line Items before send').item.json.invoice_no || '') }}\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09B5P66Q4A",
          "cachedResultName": "required-invoice-review"
        },
        "messageType": "block",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "e2179126-0881-4701-9d4a-62d335a74abd",
      "name": "Send to Archive Source File Invoice Duplicate",
      "type": "n8n-nodes-base.notion",
      "position": [
        -2768,
        2032
      ],
      "parameters": {
        "title": "={{ $json.source_file_id }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "239f7557-9573-80d6-a8fb-fc710833e5db",
          "cachedResultUrl": "https://www.notion.so/239f7557957380d6a8fbfc710833e5db",
          "cachedResultName": "Archived Source File (Duplicate)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "File ID|title",
              "title": "={{ $json.source_file_id }}"
            },
            {
              "key": "Filename|rich_text",
              "textContent": "={{ $json.source_file_name }}"
            },
            {
              "key": "FILE URL|url",
              "urlValue": "={{ $json.source_file_url }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "cca27d76-da70-42fc-b6b2-5c5330490d2b",
      "name": "Archive Invoice Duplicate",
      "type": "n8n-nodes-base.notion",
      "position": [
        -2544,
        2032
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "254f7557-9573-8012-b9b3-e7811bfac12c",
          "cachedResultUrl": "https://www.notion.so/254f755795738012b9b3e7811bfac12c",
          "cachedResultName": "Archived Clearflow Invoice (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Attachments|rich_text",
              "textContent": "={{ $('Prepare Archive Duplicate Items').item.json.attachments[0] }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Prepare Archive Duplicate Items').item.json.currency }}"
            },
            {
              "key": "Destination Account|rich_text",
              "textContent": "={{ $('Prepare Archive Duplicate Items').item.json.destination_account }}"
            },
            {
              "key": "Discount Percent|number",
              "numberValue": "={{ $('Prepare Archive Duplicate Items').item.json.discount_percent_for_notion }}"
            },
            {
              "key": "Due Date|date",
              "date": "={{ $('Prepare Archive Duplicate Items').item.json.due_date }}"
            },
            {
              "key": "Invoice No|title",
              "title": "={{ $('Prepare Archive Duplicate Items').item.json.invoice_no }}"
            },
            {
              "key": "Issue Date|date",
              "date": "={{ $('Prepare Archive Duplicate Items').item.json.issue_date }}"
            },
            {
              "key": "Line Items|rich_text",
              "textContent": "={{ $('Prepare Archive Duplicate Items').item.json.line_items_text }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Prepare Archive Duplicate Items').item.json.notes }}"
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Prepare Archive Duplicate Items').item.json.paid_amount }}"
            },
            {
              "key": "Payment Ref|rich_text",
              "textContent": "={{ $('Prepare Archive Duplicate Items').item.json.payment_ref }}"
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Prepare Archive Duplicate Items').item.json.destination_account }}"
            },
            {
              "key": "Status|select",
              "selectValue": "={{ $('Prepare Archive Duplicate Items').item.json.status }}"
            },
            {
              "key": "Subtotal|number",
              "numberValue": "={{ $('Prepare Archive Duplicate Items').item.json.subtotal }}"
            },
            {
              "key": "Tax Total|number",
              "numberValue": "={{ $('Prepare Archive Duplicate Items').item.json.tax_total }}"
            },
            {
              "key": "Vendor|rich_text",
              "textContent": "={{ $('Prepare Archive Duplicate Items').item.json.vendor }}"
            },
            {
              "key": "=Source File|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e4d849f2-4c10-4e93-9133-b78e861687f2",
      "name": "Prepare Archive Duplicate Items",
      "type": "n8n-nodes-base.code",
      "position": [
        -2992,
        2032
      ],
      "parameters": {
        "jsCode": "// Build \"summary items\" text from line_items (one output per input)\n\nfunction toNum(v) {\n  const n = Number(v);\n  return Number.isFinite(n) ? n : 0;\n}\nfunction clean(s) {\n  return String(s ?? \"\").trim();\n}\nfunction fmt(n) {\n  // 2dp but strip trailing .00 if integer\n  const f = (Math.round(n * 100) / 100).toFixed(2);\n  return f.endsWith(\".00\") ? String(Math.round(n)) : f;\n}\n\nconst out = [];\n\nfor (const { json: rec } of $input.all()) {\n  const currency = clean(rec.currency).toUpperCase(); // e.g., \"USD\"\n  const lis = Array.isArray(rec.line_items) ? rec.line_items : [];\n\n  // Group by description + unit_price to collapse duplicates\n  const groups = new Map();\n  for (const li of lis) {\n    const desc = clean(li?.description) || \"Item\";\n    const unit = toNum(li?.unit_price);\n    const qty  = toNum(li?.qty);\n    const amt  = toNum(li?.amount) || qty * unit;\n\n    const key = `${desc}||${unit}`;\n    if (!groups.has(key)) groups.set(key, { desc, unit, qty: 0, amount: 0 });\n    const g = groups.get(key);\n    g.qty += qty;\n    g.amount += amt;\n  }\n\n  // Render lines\n  const lines = [];\n  const rich = [];\n  for (const g of groups.values()) {\n    const qtyS  = fmt(g.qty);\n    const unitS = fmt(g.unit);\n    const amtS  = fmt(g.amount);\n    const curS  = currency ? ` ${currency}` : \"\";\n    const line  = `${qtyS} × ${g.desc} @ ${unitS}${curS} = ${amtS}${curS}`;\n    lines.push(line);\n    rich.push({ type: \"text\", text: { content: line } });\n  }\n\n  const summary = lines.join(\"\\n\");\n\n  out.push({\n    json: {\n      ...rec,\n      summary_items: summary,              // <-- your \"Summary Items\" field\n      line_items_text: summary,            // keep old name if you need it\n      line_items_rich_text: rich           // Notion rich_text-friendly\n    }\n  });\n}\n\nreturn out;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "237841d5-2268-4efe-9ae2-25e904dbd48a",
      "name": "Send to Source File Invoice 3",
      "type": "n8n-nodes-base.notion",
      "position": [
        -704,
        2288
      ],
      "parameters": {
        "title": "={{ $json.source_file_id }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-8062-b50d-fe9db34ec410",
          "cachedResultUrl": "https://www.notion.so/238f755795738062b50dfe9db34ec410",
          "cachedResultName": "Source File"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "File ID|title",
              "title": "={{ $json.source_file_id }}"
            },
            {
              "key": "Filename|rich_text",
              "textContent": "={{ $json.source_file_name }}"
            },
            {
              "key": "File URL|url",
              "urlValue": "={{ $json.source_file_url }}"
            },
            {
              "key": "Summary|rich_text",
              "text": {
                "text": [
                  {
                    "text": "={{ $json.line_items_rich_text[0].text.content }}",
                    "annotationUi": {}
                  }
                ]
              },
              "richText": true
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "010957b9-c7a4-4432-ac02-6ea1400f0418",
      "name": "Add Receipt into Cashflow Paid 2",
      "type": "n8n-nodes-base.notion",
      "position": [
        -480,
        2288
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-80a2-96c8-e638a56411d2",
          "cachedResultUrl": "https://www.notion.so/238f7557957380a296c8e638a56411d2",
          "cachedResultName": "Cashflow (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Cashflow ID|title",
              "title": "={{ $('Take Invoice Details 1').item.json.receipt_no || 'cf_' + Date.now() + '_' + Math.floor(Math.random() * 1000) }}"
            },
            {
              "key": "Amount (Net)|number",
              "numberValue": "={{ $('Take Invoice Details 1').item.json.paid_amount }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Take Invoice Details 1').item.json.currency }}"
            },
            {
              "key": "Fee|number",
              "numberValue": "={{ $('Take Invoice Details 1').item.json.tax_total }}"
            },
            {
              "key": "Gross Amount|number",
              "numberValue": "={{ $('Take Invoice Details 1').item.json.paid_amount }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.notes }}"
            },
            {
              "key": "Timestamp|date",
              "date": "={{ $('Take Invoice Details 1').item.json.paid_date }}"
            },
            {
              "key": "Timestamp (ISO)|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.paid_date }}"
            },
            {
              "key": "Type|select",
              "selectValue": "=Expense"
            },
            {
              "key": "Vendor / Recipient|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.vendor }}"
            },
            {
              "key": "Vendor Ref ID|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.receipt_no }}"
            },
            {
              "key": "Source File|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.vendor }}"
            },
            {
              "key": "Source Account|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.payment_method }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5b13d0d1-28a9-47df-82a2-5b83d338c413",
      "name": "Approval Check",
      "type": "n8n-nodes-base.switch",
      "position": [
        -1376,
        2528
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Paid",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "cf7a1e2d-9984-4052-9c1f-691f7a0ea50c",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.query.choice }}",
                    "rightValue": "approve"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Unpaid",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "78953ded-6256-4f3a-86c5-1189b02b20e7",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.query.choice }}",
                    "rightValue": "unpaid"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "Archive",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "3f329867-45ba-4287-b5f7-632c52567c79",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.query.choice }}",
                    "rightValue": "archive"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "0163f077-3850-4609-9def-1483cd5f720b",
      "name": "Add Receipt into Cashflow1",
      "type": "n8n-nodes-base.notion",
      "position": [
        -704,
        2096
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-80a2-96c8-e638a56411d2",
          "cachedResultUrl": "https://www.notion.so/238f7557957380a296c8e638a56411d2",
          "cachedResultName": "Cashflow (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Cashflow ID|title",
              "title": "={{ $json.receipt_no || 'cf_' + Date.now() + '_' + Math.floor(Math.random() * 1000) }}"
            },
            {
              "key": "Amount (Net)|number",
              "numberValue": "={{ $json.paid_amount }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $json.currency }}"
            },
            {
              "key": "Fee|number",
              "numberValue": "={{ $json.tax_total }}"
            },
            {
              "key": "Gross Amount|number",
              "numberValue": "={{ $json.paid_amount }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $json.notes }}"
            },
            {
              "key": "Timestamp|date",
              "date": "={{ $json.paid_date }}"
            },
            {
              "key": "Timestamp (ISO)|rich_text",
              "textContent": "={{ $json.paid_date }}"
            },
            {
              "key": "Type|select",
              "selectValue": "=Expense"
            },
            {
              "key": "Vendor / Recipient|rich_text",
              "textContent": "={{ $json.vendor }}"
            },
            {
              "key": "Vendor Ref ID|rich_text",
              "textContent": "={{ $json.invoice_no }}"
            },
            {
              "key": "Source File|relation",
              "relationValue": [
                "={{ $json.db_page_id }}"
              ]
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $json.vendor }}"
            },
            {
              "key": "Source Account|rich_text",
              "textContent": "={{ $json.payment_method }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $json.line_items_rich_text[0].text.content }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "557a172b-f58a-4f82-a8b8-ddc3865bbe20",
      "name": "Update Invoice to Paid Fully 1",
      "type": "n8n-nodes-base.notion",
      "position": [
        -480,
        2096
      ],
      "parameters": {
        "pageId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Take Invoice Details 1').item.json.db_page_id }}"
        },
        "options": {},
        "resource": "databasePage",
        "operation": "update",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Receipt|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Take Invoice Details 1').item.json.paid_amount }}"
            },
            {
              "key": "Status|select",
              "selectValue": "Paid"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5e962f4f-f35a-46f6-a80f-bdd66553c3ed",
      "name": "Create new Invoice Paid 3",
      "type": "n8n-nodes-base.notion",
      "position": [
        -256,
        2288
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "24df7557-9573-8073-9611-da8371404254",
          "cachedResultUrl": "https://www.notion.so/24df7557957380739611da8371404254",
          "cachedResultName": "Clearflow Invoice (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Attachments|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.attachments[0] }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Take Invoice Details 1').item.json.currency }}"
            },
            {
              "key": "Destination Account|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.destination_account }}"
            },
            {
              "key": "Discount Percent|number",
              "numberValue": "={{ $('Take Invoice Details 1').item.json.discount_percent_for_notion }}"
            },
            {
              "key": "Due Date|date",
              "date": "={{ $('Take Invoice Details 1').item.json.due_date }}"
            },
            {
              "key": "Invoice No|title",
              "title": "={{ $('Take Invoice Details 1').item.json.invoice_no }}"
            },
            {
              "key": "Issue Date|date",
              "date": "={{ $('Take Invoice Details 1').item.json.issue_date }}"
            },
            {
              "key": "Line Items|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.line_items_rich_text[0].text.content }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.notes }}"
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Take Invoice Details 1').item.json.paid_amount }}"
            },
            {
              "key": "Payment Ref|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.payment_ref }}"
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.destination_account }}"
            },
            {
              "key": "Status|select",
              "selectValue": "={{ $('Take Invoice Details 1').item.json.status }}"
            },
            {
              "key": "Subtotal|number",
              "numberValue": "={{ $('Take Invoice Details 1').item.json.subtotal }}"
            },
            {
              "key": "Tax Total|number",
              "numberValue": "={{ $('Take Invoice Details 1').item.json.tax_total }}"
            },
            {
              "key": "Vendor|rich_text",
              "textContent": "={{ $('Take Invoice Details 1').item.json.vendor }}"
            },
            {
              "key": "=Source File|relation",
              "relationValue": [
                "={{ $('Send to Source File Invoice 3').item.json.id }}"
              ]
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5fcebb58-8279-4d89-981f-27d34f2c2747",
      "name": "Take Invoice Details 2",
      "type": "n8n-nodes-base.code",
      "position": [
        -1152,
        2576
      ],
      "parameters": {
        "jsCode": "// Code node: Pick Reviewed Invoice\n// Input: the Wait node callback (has query.choice, query.inv)\n// Also reads items from \"Prepare Line Items before send\"\n// Output: ONE item = the picked invoice + review info\n\nconst choice = $json?.query?.choice || '';              // approve | unpaid | archive\nconst invRaw = $json?.query?.inv || '';\nconst inv = String(invRaw).trim();\n\nconst prepared = $('Prepare Line Items before send').all().map(i => i.json);\nif (!prepared.length) {\n  throw new Error('No items found in \"Prepare Line Items before send\".');\n}\n\n// try exact invoice_no match first\nlet picked = inv\n  ? prepared.find(x => String(x.invoice_no || '').trim() === inv)\n  : undefined;\n\n// soft fallback(s)\nif (!picked) {\n  if (prepared.length === 1) {\n    picked = prepared[0];\n  } else {\n    const canon = s => String(s || '').toLowerCase().replace(/\\s+/g, '').trim();\n    const invC = canon(inv);\n    picked = prepared.find(x => canon(x.invoice_no) === invC) || prepared[0];\n  }\n}\n\n// annotate with the review decision so the next Switch can route\nconst out = {\n  ...picked,\n  review: {\n    choice,            // approve | unpaid | archive\n    inv,               // invoice_no from the button\n    source: 'slack_button'\n  }\n};\n\nreturn [{ json: out }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d6375c43-4c99-41fe-9215-eec2ba228e17",
      "name": "Take Invoice Details 1",
      "type": "n8n-nodes-base.code",
      "position": [
        -1152,
        2192
      ],
      "parameters": {
        "jsCode": "// Code node: Pick Reviewed Invoice\n// Input: the Wait node callback (has query.choice, query.inv)\n// Also reads items from \"Prepare Line Items before send\"\n// Output: ONE item = the picked invoice + review info\n\nconst choice = $json?.query?.choice || '';              // approve | unpaid | archive\nconst invRaw = $json?.query?.inv || '';\nconst inv = String(invRaw).trim();\n\nconst prepared = $('Prepare Line Items before send').all().map(i => i.json);\nif (!prepared.length) {\n  throw new Error('No items found in \"Prepare Line Items before send\".');\n}\n\n// try exact invoice_no match first\nlet picked = inv\n  ? prepared.find(x => String(x.invoice_no || '').trim() === inv)\n  : undefined;\n\n// soft fallback(s)\nif (!picked) {\n  if (prepared.length === 1) {\n    picked = prepared[0];\n  } else {\n    const canon = s => String(s || '').toLowerCase().replace(/\\s+/g, '').trim();\n    const invC = canon(inv);\n    picked = prepared.find(x => canon(x.invoice_no) === invC) || prepared[0];\n  }\n}\n\n// annotate with the review decision so the next Switch can route\nconst out = {\n  ...picked,\n  review: {\n    choice,            // approve | unpaid | archive\n    inv,               // invoice_no from the button\n    source: 'slack_button'\n  }\n};\n\nreturn [{ json: out }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "a9a19c40-4875-4c02-9c2b-3f65124ebdec",
      "name": "Update Invoice to Paid Fully ",
      "type": "n8n-nodes-base.notion",
      "position": [
        -704,
        2480
      ],
      "parameters": {
        "pageId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Take Invoice Details 2').item.json.db_page_id }}"
        },
        "options": {},
        "resource": "databasePage",
        "operation": "update",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Take Invoice Details 2').item.json.paid_amount }}"
            },
            {
              "key": "Status|select",
              "selectValue": "=Unpaid"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0af156a4-3324-4a1f-9f63-7a181adb4485",
      "name": "Send to Source File Invoice ",
      "type": "n8n-nodes-base.notion",
      "position": [
        -704,
        2672
      ],
      "parameters": {
        "title": "={{ $json.source_file_id }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-8062-b50d-fe9db34ec410",
          "cachedResultUrl": "https://www.notion.so/238f755795738062b50dfe9db34ec410",
          "cachedResultName": "Source File"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "File ID|title",
              "title": "={{ $json.source_file_id }}"
            },
            {
              "key": "Filename|rich_text",
              "textContent": "={{ $json.source_file_name }}"
            },
            {
              "key": "File URL|url",
              "urlValue": "={{ $json.source_file_url }}"
            },
            {
              "key": "Summary|rich_text",
              "text": {
                "text": [
                  {
                    "text": "={{ $json.line_items_rich_text[0].text.content }}",
                    "annotationUi": {}
                  }
                ]
              },
              "richText": true
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a1eaf719-3843-424f-b758-b58b32cdc30c",
      "name": "Create new Invoice Paid ",
      "type": "n8n-nodes-base.notion",
      "position": [
        -480,
        2672
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "24df7557-9573-8073-9611-da8371404254",
          "cachedResultUrl": "https://www.notion.so/24df7557957380739611da8371404254",
          "cachedResultName": "Clearflow Invoice (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Attachments|rich_text",
              "textContent": "={{ $('Take Invoice Details 2').item.json.attachments[0] }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Take Invoice Details 2').item.json.currency }}"
            },
            {
              "key": "Destination Account|rich_text",
              "textContent": "={{ $('Take Invoice Details 2').item.json.destination_account }}"
            },
            {
              "key": "Discount Percent|number",
              "numberValue": "={{ $('Take Invoice Details 2').item.json.discount_percent_for_notion }}"
            },
            {
              "key": "Due Date|date",
              "date": "={{ $('Take Invoice Details 2').item.json.due_date }}"
            },
            {
              "key": "Invoice No|title",
              "title": "={{ $('Take Invoice Details 2').item.json.invoice_no }}"
            },
            {
              "key": "Issue Date|date",
              "date": "={{ $('Take Invoice Details 2').item.json.issue_date }}"
            },
            {
              "key": "Line Items|rich_text",
              "textContent": "={{ $('Take Invoice Details 2').item.json.line_items_rich_text[0].text.content }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Take Invoice Details 2').item.json.notes }}"
            },
            {
              "key": "Payment Ref|rich_text",
              "textContent": "={{ $('Take Invoice Details 2').item.json.payment_ref }}"
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Take Invoice Details 2').item.json.destination_account }}"
            },
            {
              "key": "Status|select",
              "selectValue": "={{ $('Take Invoice Details 2').item.json.status }}"
            },
            {
              "key": "Subtotal|number",
              "numberValue": "={{ $('Take Invoice Details 2').item.json.subtotal }}"
            },
            {
              "key": "Tax Total|number",
              "numberValue": "={{ $('Take Invoice Details 2').item.json.tax_total }}"
            },
            {
              "key": "Vendor|rich_text",
              "textContent": "={{ $('Take Invoice Details 2').item.json.vendor }}"
            },
            {
              "key": "=Source File|relation",
              "relationValue": [
                "={{ $('Send to Source File Invoice ').item.json.id }}"
              ]
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Take Invoice Details 2').item.json.paid_amount }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2d7330e7-e3b9-4afc-9217-9dcbdbd4a3e9",
      "name": "Archive Invoice 1",
      "type": "n8n-nodes-base.notion",
      "position": [
        -704,
        2864
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "254f7557-9573-8012-b9b3-e7811bfac12c",
          "cachedResultUrl": "https://www.notion.so/254f755795738012b9b3e7811bfac12c",
          "cachedResultName": "Archived Clearflow Invoice (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Attachments|rich_text",
              "textContent": "={{ $('Take Invoice Details 3').item.json.attachments[0] }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Take Invoice Details 3').item.json.currency }}"
            },
            {
              "key": "Destination Account|rich_text",
              "textContent": "={{ $('Take Invoice Details 3').item.json.destination_account }}"
            },
            {
              "key": "Discount Percent|number",
              "numberValue": "={{ $('Take Invoice Details 3').item.json.discount_percent_for_notion }}"
            },
            {
              "key": "Due Date|date",
              "date": "={{ $('Take Invoice Details 3').item.json.due_date }}"
            },
            {
              "key": "Invoice No|title",
              "title": "={{ $('Take Invoice Details 3').item.json.invoice_no }}"
            },
            {
              "key": "Issue Date|date",
              "date": "={{ $('Take Invoice Details 3').item.json.issue_date }}"
            },
            {
              "key": "Line Items|rich_text",
              "textContent": "={{ $('Take Invoice Details 3').item.json.line_items_rich_text[0].text.content }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Take Invoice Details 3').item.json.notes || $('Take Invoice Details 3').item.json.reason}}"
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Take Invoice Details 3').item.json.paid_amount }}"
            },
            {
              "key": "Payment Ref|rich_text",
              "textContent": "={{ $('Take Invoice Details 3').item.json.payment_ref }}"
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Take Invoice Details 3').item.json.destination_account }}"
            },
            {
              "key": "Status|select",
              "selectValue": "={{ $('Take Invoice Details 3').item.json.status }}"
            },
            {
              "key": "Subtotal|number",
              "numberValue": "={{ $('Take Invoice Details 3').item.json.subtotal }}"
            },
            {
              "key": "Tax Total|number",
              "numberValue": "={{ $('Take Invoice Details 3').item.json.tax_total }}"
            },
            {
              "key": "Vendor|rich_text",
              "textContent": "={{ $('Take Invoice Details 3').item.json.vendor }}"
            },
            {
              "key": "=Source File|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6342d55e-4e82-4755-8826-3d4e5b7f9be7",
      "name": "Take Invoice Details 3",
      "type": "n8n-nodes-base.code",
      "position": [
        -1152,
        2864
      ],
      "parameters": {
        "jsCode": "// Code node: Pick Reviewed Invoice\n// Input: the Wait node callback (has query.choice, query.inv)\n// Also reads items from \"Prepare Line Items before send\"\n// Output: ONE item = the picked invoice + review info\n\nconst choice = $json?.query?.choice || '';              // approve | unpaid | archive\nconst invRaw = $json?.query?.inv || '';\nconst inv = String(invRaw).trim();\n\nconst prepared = $('Prepare Line Items before send').all().map(i => i.json);\nif (!prepared.length) {\n  throw new Error('No items found in \"Prepare Line Items before send\".');\n}\n\n// try exact invoice_no match first\nlet picked = inv\n  ? prepared.find(x => String(x.invoice_no || '').trim() === inv)\n  : undefined;\n\n// soft fallback(s)\nif (!picked) {\n  if (prepared.length === 1) {\n    picked = prepared[0];\n  } else {\n    const canon = s => String(s || '').toLowerCase().replace(/\\s+/g, '').trim();\n    const invC = canon(inv);\n    picked = prepared.find(x => canon(x.invoice_no) === invC) || prepared[0];\n  }\n}\n\n// annotate with the review decision so the next Switch can route\nconst out = {\n  ...picked,\n  review: {\n    choice,            // approve | unpaid | archive\n    inv,               // invoice_no from the button\n    source: 'slack_button'\n  }\n};\n\nreturn [{ json: out }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c6f37078-96cb-4e97-b678-ebb688afb413",
      "name": "Check DB Exist 1",
      "type": "n8n-nodes-base.if",
      "position": [
        -928,
        2192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "95b89f55-ca6f-46ce-bc0c-8ea48b18c013",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.db_found }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2b1a1c57-bad7-4629-a969-aced98962828",
      "name": "Check DB Exist 2",
      "type": "n8n-nodes-base.if",
      "position": [
        -928,
        2576
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "95b89f55-ca6f-46ce-bc0c-8ea48b18c013",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.db_found }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ed421b2f-4a7e-4098-9d09-96965813f3e4",
      "name": "Send to Source File Invoice 4",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1872,
        1504
      ],
      "parameters": {
        "title": "={{ $json.source_file_id }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-8062-b50d-fe9db34ec410",
          "cachedResultUrl": "https://www.notion.so/238f755795738062b50dfe9db34ec410",
          "cachedResultName": "Source File"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "File ID|title",
              "title": "={{ $json.source_file_id }}"
            },
            {
              "key": "Filename|rich_text",
              "textContent": "={{ $json.source_file_name }}"
            },
            {
              "key": "File URL|url",
              "urlValue": "={{ $json.source_file_url }}"
            },
            {
              "key": "Summary|rich_text",
              "text": {
                "text": [
                  {
                    "text": "={{ $json.line_items_rich_text[0].text.content }}",
                    "annotationUi": {}
                  }
                ]
              },
              "richText": true
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "3f33a49f-f4d5-4483-b01b-ab7b05f1edef",
      "name": "Add Receipt into Cashflow Paid Partially",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1648,
        1504
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-80a2-96c8-e638a56411d2",
          "cachedResultUrl": "https://www.notion.so/238f7557957380a296c8e638a56411d2",
          "cachedResultName": "Cashflow (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Cashflow ID|title",
              "title": "={{ $('Prepare Line Items before send').item.json.receipt_no || 'cf_' + Date.now() + '_' + Math.floor(Math.random() * 1000) }}"
            },
            {
              "key": "Amount (Net)|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.paid_amount }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Prepare Line Items before send').item.json.currency }}"
            },
            {
              "key": "Fee|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.tax_total }}"
            },
            {
              "key": "Gross Amount|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.paid_amount }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.notes || \"Partial Paid\" }}"
            },
            {
              "key": "Timestamp|date",
              "date": "={{ $('Prepare Line Items before send').item.json.paid_date }}"
            },
            {
              "key": "Timestamp (ISO)|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.paid_date }}"
            },
            {
              "key": "Type|select",
              "selectValue": "=Expense"
            },
            {
              "key": "Vendor / Recipient|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.vendor }}"
            },
            {
              "key": "Vendor Ref ID|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.receipt_no }}"
            },
            {
              "key": "Source File|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.vendor }}"
            },
            {
              "key": "Source Account|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.payment_method }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a988e2c7-ad51-4df3-b4d6-9d5cd6e123af",
      "name": "Create new Invoice Paid Partially",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1424,
        1504
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "24df7557-9573-8073-9611-da8371404254",
          "cachedResultUrl": "https://www.notion.so/24df7557957380739611da8371404254",
          "cachedResultName": "Clearflow Invoice (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Attachments|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.attachments[0] }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $('Prepare Line Items before send').item.json.currency }}"
            },
            {
              "key": "Destination Account|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.destination_account }}"
            },
            {
              "key": "Discount Percent|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.discount_percent_for_notion }}"
            },
            {
              "key": "Due Date|date",
              "date": "={{ $('Prepare Line Items before send').item.json.due_date }}"
            },
            {
              "key": "Invoice No|title",
              "title": "={{ $('Prepare Line Items before send').item.json.invoice_no }}"
            },
            {
              "key": "Issue Date|date",
              "date": "={{ $('Prepare Line Items before send').item.json.issue_date }}"
            },
            {
              "key": "Line Items|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.line_items_rich_text[0].text.content }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.notes }}"
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.paid_amount }}"
            },
            {
              "key": "Payment Ref|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.payment_ref }}"
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.destination_account }}"
            },
            {
              "key": "Status|select",
              "selectValue": "={{ $('Prepare Line Items before send').item.json.status }}"
            },
            {
              "key": "Subtotal|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.subtotal }}"
            },
            {
              "key": "Tax Total|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.tax_total }}"
            },
            {
              "key": "Vendor|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.vendor }}"
            },
            {
              "key": "=Source File|relation",
              "relationValue": [
                "={{ $('Send to Source File Invoice 4').item.json.id }}"
              ]
            },
            {
              "key": "Source Account|rich_text",
              "textContent": "={{ $('Prepare Line Items before send').item.json.payment_method }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8e8ac821-5cd5-4bd2-b78d-203fd5cf57fb",
      "name": "Add Receipt into Cashflow2",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1872,
        1696
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "238f7557-9573-80a2-96c8-e638a56411d2",
          "cachedResultUrl": "https://www.notion.so/238f7557957380a296c8e638a56411d2",
          "cachedResultName": "Cashflow (Ledger)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Cashflow ID|title",
              "title": "={{ $json.receipt_no || 'cf_' + Date.now() + '_' + Math.floor(Math.random() * 1000) }}"
            },
            {
              "key": "Amount (Net)|number",
              "numberValue": "={{ $json.paid_amount }}"
            },
            {
              "key": "Currency|select",
              "selectValue": "={{ $json.currency }}"
            },
            {
              "key": "Fee|number",
              "numberValue": "={{ $json.tax_total }}"
            },
            {
              "key": "Gross Amount|number",
              "numberValue": "={{ $json.paid_amount }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $json.notes }}"
            },
            {
              "key": "Timestamp|date",
              "date": "={{ $json.paid_date }}"
            },
            {
              "key": "Timestamp (ISO)|rich_text",
              "textContent": "={{ $json.paid_date }}"
            },
            {
              "key": "Type|select",
              "selectValue": "=Expense"
            },
            {
              "key": "Vendor / Recipient|rich_text",
              "textContent": "={{ $json.vendor }}"
            },
            {
              "key": "Vendor Ref ID|rich_text",
              "textContent": "={{ $json.invoice_no }}"
            },
            {
              "key": "Source File|relation",
              "relationValue": [
                "={{ $json.db_page_id }}"
              ]
            },
            {
              "key": "Recipient Account|rich_text",
              "textContent": "={{ $json.vendor }}"
            },
            {
              "key": "Source Account|rich_text",
              "textContent": "={{ $json.payment_method }}"
            },
            {
              "key": "Notes|rich_text",
              "textContent": "={{ $json.line_items_rich_text[0].text.content }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "25951d6e-c27d-48b0-8bef-1b06bb931c30",
      "name": "Update Invoice to Paid Partial or Fully",
      "type": "n8n-nodes-base.notion",
      "position": [
        -1648,
        1696
      ],
      "parameters": {
        "pageId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Prepare Line Items before send').item.json.db_page_id }}"
        },
        "options": {},
        "resource": "databasePage",
        "operation": "update",
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Receipt|relation",
              "relationValue": [
                "={{ $json.id }}"
              ]
            },
            {
              "key": "Paid Amount|number",
              "numberValue": "={{ $('Prepare Line Items before send').item.json.notion_paid_amount }}"
            },
            {
              "key": "Status|select",
              "selectValue": "={{ $('Prepare Line Items before send').item.json.notion_status }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "1ed7bced-88d4-4210-b323-c64bf1c1fece",
      "name": "Check parsing Error2",
      "type": "n8n-nodes-base.if",
      "position": [
        -4688,
        1552
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ddbbbfbb-e05b-4ca9-b607-65ad8ac748bb",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.IsErroredOnProcessing }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "1c81ef35-2d9b-435b-90ae-979dbebe8ace",
      "name": "OCR Space Parse",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -4912,
        1552
      ],
      "parameters": {
        "url": "https://api.ocr.space/parse/image",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "multipart-form-data",
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "filetype",
              "value": "jpg"
            },
            {
              "name": "file",
              "parameterType": "formBinaryData",
              "inputDataFieldName": "data"
            },
            {
              "name": "scale",
              "value": "true"
            },
            {
              "name": "OCREngine",
              "value": "2"
            }
          ]
        },
        "genericAuthType": "httpHeaderAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "dkJjl1msBNIeIT5u",
          "name": "OCR Space"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.2
    },
    {
      "id": "7dde97e8-b6cd-4527-a948-36d62ca9d235",
      "name": "Take Binary Files",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -5136,
        1552
      ],
      "parameters": {
        "url": "={{ $json.url_private_download }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        },
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "slackApi"
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "d2da0e22-0a2f-4a66-8651-7a0bd73f3452",
      "name": "Stoppen und Fehler",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        -4464,
        1504
      ],
      "parameters": {
        "errorMessage": "=OCR Server Parsing Failed Reason:{{ $json.ErrorMessage[0] }}"
      },
      "typeVersion": 1
    },
    {
      "id": "6376b9b6-40c7-4f01-8a11-8f5bee34dfd4",
      "name": "Stoppen und Fehler1",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        -4688,
        1744
      ],
      "parameters": {
        "errorMessage": "=OCR Server Parsing Failed Reason:{{ $json.ErrorMessage[0] }}"
      },
      "typeVersion": 1
    },
    {
      "id": "17f5f3e0-7aa0-45c2-9c84-d840321ef94a",
      "name": "Aggregieren1",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -2320,
        2032
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "d707c4fc-d2a5-496d-9d6b-8c71f627ad21",
      "name": "Send Duplicate Notification",
      "type": "n8n-nodes-base.slack",
      "position": [
        -2096,
        2032
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟥 Internal Duplicate Found:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0971ANKZM1",
          "cachedResultName": "duplicate-alert"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "548ea7e3-8e51-4a56-891e-1db51e466b2d",
      "name": "Aggregieren",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1424,
        736
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "893731ba-84cd-4189-9c3d-c1a73c158979",
      "name": "Aggregieren2",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1200,
        928
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "2d9bf727-1b2f-4a1e-bc54-61c686f63d01",
      "name": "Notify New Invoice with Receipt",
      "type": "n8n-nodes-base.slack",
      "position": [
        -976,
        928
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟩 Paid Invoice Created:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "cb2e3474-2c42-4804-a1a0-aea65c45aece",
      "name": "Notify New Invoice",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1200,
        736
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟨 Invoice Created:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "6db4ac23-65d8-4e5a-b1ae-84777f7c6a0b",
      "name": "Aggregieren3",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1424,
        1312
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "7766fd88-d419-47ee-b545-e6d6d574045f",
      "name": "Notify Update Invoice",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1200,
        1312
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟩 Invoice Updated to Paid:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "ec4398cb-c999-43bb-9d71-76a9ec6e2747",
      "name": "Aggregieren4",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1424,
        1120
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "8976661d-c12c-4b3b-92c9-337fb7b3be3f",
      "name": "Aggregieren5",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1200,
        1504
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "20260742-e05b-4ce1-b2ca-40db32c1e66b",
      "name": "Aggregieren6",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1424,
        1696
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "75d16382-b71a-413c-abb7-5f6ee529b268",
      "name": "Notify Update Invoice Partial Paid",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1200,
        1696
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟡 Updated Invoice Partial Paid:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "be11d35c-a96d-432d-bf60-747e9242b8b0",
      "name": "Notify Create Invoice Partial Paid",
      "type": "n8n-nodes-base.slack",
      "position": [
        -976,
        1504
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟡 Created New Invoice Partial Paid:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "cb059bc5-42c4-4eee-a4c5-f70013b81d1f",
      "name": "Notify Invoice Archived",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1200,
        1120
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟥 Database Duplicate Found:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "29cc18f8-253c-4763-a2ae-e9f2668b4e8c",
      "name": "Aggregieren8",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -480,
        2864
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "852ca201-dfe6-4d5b-bf6d-9d06954f0604",
      "name": "Notify Invoice Archived2",
      "type": "n8n-nodes-base.slack",
      "position": [
        -256,
        2864
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟥 Manual Review Archived:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "2e9ab2da-f324-4864-8617-4ebf6d6873ab",
      "name": "Send to Archive Source File Invoice ",
      "type": "n8n-nodes-base.notion",
      "position": [
        -928,
        2864
      ],
      "parameters": {
        "title": "={{ $json.source_file_id }}",
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "239f7557-9573-80d6-a8fb-fc710833e5db",
          "cachedResultUrl": "https://www.notion.so/239f7557957380d6a8fbfc710833e5db",
          "cachedResultName": "Archived Source File (Duplicate)"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "File ID|title",
              "title": "={{ $json.source_file_id }}"
            },
            {
              "key": "Filename|rich_text",
              "textContent": "={{ $json.source_file_name }}"
            },
            {
              "key": "FILE URL|url",
              "urlValue": "={{ $json.source_file_url }}"
            },
            {
              "key": "Summary|rich_text",
              "text": {
                "text": [
                  {
                    "text": "={{ $json.line_items_rich_text[0].text.content }}",
                    "annotationUi": {}
                  }
                ]
              },
              "richText": true
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ff53fb86-f773-4690-b874-be81d77259ab",
      "name": "Aggregieren7",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -256,
        2672
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "38fd6b37-35cd-43f4-a6a1-caf4c20f0848",
      "name": "Notify New Invoice1",
      "type": "n8n-nodes-base.slack",
      "position": [
        -32,
        2672
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟨 Manual Review Invoice Created Unpaid:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "30d801f2-7ae0-4f43-882d-2df58867102e",
      "name": "Aggregieren9",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -480,
        2480
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "3fbead5e-2aa0-4222-a2ff-2a03901ffbe0",
      "name": "Notify New Invoice2",
      "type": "n8n-nodes-base.slack",
      "position": [
        -256,
        2480
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟨 Manual Review Invoice Updated Unpaid:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "9706d716-8bfc-433e-9d09-8a3a479a5ecc",
      "name": "Aggregieren10",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -32,
        2288
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "2731b665-b116-459e-9a90-1d28d63d1c85",
      "name": "Notify New Invoice with Receipt1",
      "type": "n8n-nodes-base.slack",
      "position": [
        192,
        2288
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟩 Manual Review Invoice Created Paid:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "ffec1ef1-51d6-4870-b4e6-86af6c95ed87",
      "name": "Aggregieren11",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -256,
        2096
      ],
      "parameters": {
        "include": "specifiedFields",
        "options": {},
        "aggregate": "aggregateAllItemData",
        "fieldsToInclude": "name, url"
      },
      "typeVersion": 1
    },
    {
      "id": "b206f8e8-74f5-4502-8dc1-ef154867890f",
      "name": "Notify New Invoice with Receipt2",
      "type": "n8n-nodes-base.slack",
      "position": [
        -32,
        2096
      ],
      "webhookId": "f6b10e04-64be-4474-9ffd-2c8f511c9020",
      "parameters": {
        "text": "=🟩 Manual Review Invoice Updated Paid:\n{{ ($json.data || []).map(i => `*<${i.url}|${i.name}>*\\n`).join('') }}\n────────────────────────",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0976KA2QTC",
          "cachedResultName": "notification"
        },
        "otherOptions": {
          "includeLinkToWorkflow": false
        }
      },
      "credentials": {
        "slackApi": {
          "id": "muT22qcO4YUdHAGU",
          "name": "Slack account"
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "b4ea52bb-acc9-42d9-a61b-0f89bcfabba0",
      "name": "Haftnotiz",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -6112,
        1440
      ],
      "parameters": {
        "width": 672,
        "height": 704,
        "content": "# 🔤 Input & Detect Format"
      },
      "typeVersion": 1
    },
    {
      "id": "4a5b2a7d-80d5-4897-884c-00d0451daee0",
      "name": "Haftnotiz1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -5376,
        1440
      ],
      "parameters": {
        "color": 2,
        "width": 1056,
        "height": 704,
        "content": "# 👨‍💻 Parse Data\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c3f62378-ecf0-4bd2-88d1-63e5268ef615",
      "name": "Haftnotiz2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -4272,
        1440
      ],
      "parameters": {
        "color": 3,
        "width": 1200,
        "height": 704,
        "content": "# 🤖 AI Format & Detect Duplicate\n"
      },
      "typeVersion": 1
    },
    {
      "id": "3f9110e8-9778-48e4-ab48-286bdfefc291",
      "name": "Haftnotiz3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3040,
        1888
      ],
      "parameters": {
        "color": 7,
        "width": 1120,
        "height": 384,
        "content": "# ❌ Archive Duplicates\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f32354a7-d05f-49e3-b60d-5d48c7f02126",
      "name": "Haftnotiz4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3024,
        1200
      ],
      "parameters": {
        "color": 6,
        "width": 1040,
        "height": 384,
        "content": "# 🟢 Check Invoice on DB\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4996b730-0f80-4a37-a702-fc8588934ece",
      "name": "Haftnotiz5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1936,
        672
      ],
      "parameters": {
        "color": 4,
        "width": 1136,
        "height": 1200,
        "content": "# 🟢 Sends Data & Notify\n"
      },
      "typeVersion": 1
    },
    {
      "id": "49782403-dd3c-4457-97ca-bf49c393c395",
      "name": "Haftnotiz7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1888,
        2016
      ],
      "parameters": {
        "color": 5,
        "width": 2384,
        "height": 1072,
        "content": "# 👤 Manual Review & Sends Data"
      },
      "typeVersion": 1
    },
    {
      "id": "ff8438b9-5804-473b-bd6b-c9840be62317",
      "name": "Fehler-Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        -6048,
        2192
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "fdaacf56-2efe-4272-80fc-365951cd7d48",
      "name": "Create a database page",
      "type": "n8n-nodes-base.notion",
      "position": [
        -5840,
        2192
      ],
      "parameters": {
        "options": {},
        "resource": "databasePage",
        "databaseId": {
          "__rl": true,
          "mode": "list",
          "value": "258f7557-9573-8013-bb51-d528ba507e68",
          "cachedResultUrl": "https://www.notion.so/258f755795738013bb51d528ba507e68",
          "cachedResultName": "ERROR CHECK"
        },
        "propertiesUi": {
          "propertyValues": [
            {
              "key": "Message|rich_text",
              "textContent": "={{ $json.execution.error.message }}"
            },
            {
              "key": "Workflow|title",
              "title": "={{ $json.workflow.name }}"
            }
          ]
        }
      },
      "credentials": {
        "notionApi": {
          "id": "FRdXwx5ANpHG8ZPX",
          "name": "Notion account"
        }
      },
      "typeVersion": 2.2
    }
  ],
  "pinData": {},
  "connections": {
    "ecb68486-32af-41e3-a9a7-86c763205061": {
      "main": [
        [
          {
            "node": "Merge Data Value into One Key",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait": {
      "main": [
        [
          {
            "node": "5b13d0d1-28a9-47df-82a2-5b83d338c413",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "cb2e3474-2c42-4804-a1a0-aea65c45aece",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate1": {
      "main": [
        [
          {
            "node": "d707c4fc-d2a5-496d-9d6b-8c71f627ad21",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate2": {
      "main": [
        [
          {
            "node": "2d9bf727-1b2f-4a1e-bc54-61c686f63d01",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate3": {
      "main": [
        [
          {
            "node": "7766fd88-d419-47ee-b545-e6d6d574045f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate4": {
      "main": [
        [
          {
            "node": "cb059bc5-42c4-4eee-a4c5-f70013b81d1f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate5": {
      "main": [
        [
          {
            "node": "be11d35c-a96d-432d-bf60-747e9242b8b0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate6": {
      "main": [
        [
          {
            "node": "75d16382-b71a-413c-abb7-5f6ee529b268",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate7": {
      "main": [
        [
          {
            "node": "38fd6b37-35cd-43f4-a6a1-caf4c20f0848",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate8": {
      "main": [
        [
          {
            "node": "852ca201-dfe6-4d5b-bf6d-9d06954f0604",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate9": {
      "main": [
        [
          {
            "node": "3fbead5e-2aa0-4222-a2ff-2a03901ffbe0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate10": {
      "main": [
        [
          {
            "node": "2731b665-b116-459e-9a90-1d28d63d1c85",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate11": {
      "main": [
        [
          {
            "node": "b206f8e8-74f5-4502-8dc1-ef154867890f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fa73399a-c133-48b3-87fe-922961f4d448": {
      "main": [
        [
          {
            "node": "1e7efdbb-f58c-4cfa-9a74-22cda80b58c7",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "5487835c-5655-476b-bbad-f368653150d1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "8f25494a-6b7c-45e5-99fc-7ab5e2e0d085",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "48bc9ab1-03bb-40a6-844d-a4fff203fcd5",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ed421b2f-4a7e-4098-9d09-96965813f3e4",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "8e8ac821-5cd5-4bd2-b78d-203fd5cf57fb",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "da9cdafe-01c8-49c8-afaa-29cb46f67aef",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ca8559e4-b29b-4a1a-b113-e70bba47f23a": {
      "main": [
        [
          {
            "node": "7dde97e8-b6cd-4527-a948-36d62ca9d235",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "6543e986-8860-457d-a8de-bb052718e9c6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "909b0322-55e4-4c3d-a5a9-9392d5bbf745": {
      "main": [
        [
          {
            "node": "ca8559e4-b29b-4a1a-b113-e70bba47f23a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Error Trigger": {
      "main": [
        [
          {
            "node": "fdaacf56-2efe-4272-80fc-365951cd7d48",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Trigger": {
      "main": [
        [
          {
            "node": "909b0322-55e4-4c3d-a5a9-9392d5bbf745",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5b13d0d1-28a9-47df-82a2-5b83d338c413": {
      "main": [
        [
          {
            "node": "d6375c43-4c99-41fe-9215-eec2ba228e17",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "5fcebb58-8279-4d89-981f-27d34f2c2747",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "6342d55e-4e82-4755-8826-3d4e5b7f9be7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "da9cdafe-01c8-49c8-afaa-29cb46f67aef": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d165164c-bcf8-4ef3-b434-9416865c6b26": {
      "main": [
        [
          {
            "node": "Aggregate4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Basic LLM Chain": {
      "main": [
        [
          {
            "node": "54187b60-dabd-42a7-b5c9-d46199dbed73",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1c81ef35-2d9b-435b-90ae-979dbebe8ace": {
      "main": [
        [
          {
            "node": "1ed7bced-88d4-4210-b323-c64bf1c1fece",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c6f37078-96cb-4e97-b678-ebb688afb413": {
      "main": [
        [
          {
            "node": "0163f077-3850-4609-9def-1483cd5f720b",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "237841d5-2268-4efe-9ae2-25e904dbd48a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2b1a1c57-bad7-4629-a969-aced98962828": {
      "main": [
        [
          {
            "node": "a9a19c40-4875-4c02-9c2b-3f65124ebdec",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "0af156a4-3324-4a1f-9f63-7a181adb4485",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "de2b4a0f-eaba-4d8c-ac76-220f14725f10": {
      "main": [
        [
          {
            "node": "Merge Items Invoice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "af88d22a-5a2d-4471-9ac9-b1cb9531bd35": {
      "main": [
        [
          {
            "node": "acb3e33c-59de-4cf3-a008-a47af9673abb",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2d7330e7-e3b9-4afc-9217-9dcbdbd4a3e9": {
      "main": [
        [
          {
            "node": "Aggregate8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7dde97e8-b6cd-4527-a948-36d62ca9d235": {
      "main": [
        [
          {
            "node": "1c81ef35-2d9b-435b-90ae-979dbebe8ace",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "54187b60-dabd-42a7-b5c9-d46199dbed73": {
      "main": [
        [
          {
            "node": "0e729384-88a1-4ee3-9bd1-ccc218462dbc",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c3b08864-40e6-4c71-b0ad-f46231351a92": {
      "main": [
        [
          {
            "node": "de2b4a0f-eaba-4d8c-ac76-220f14725f10",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Items Invoice": {
      "main": [
        [
          {
            "node": "3b8e7c65-8d40-4636-bfb0-8091365e584e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1ed7bced-88d4-4210-b323-c64bf1c1fece": {
      "main": [
        [
          {
            "node": "Stop and Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Merge Data Value into One Key",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "acb3e33c-59de-4cf3-a008-a47af9673abb": {
      "main": [
        [
          {
            "node": "Stop and Error1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ecb68486-32af-41e3-a9a7-86c763205061",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "88aae252-885b-4433-af13-88fea42ad24e": {
      "main": [
        [
          {
            "node": "c3b08864-40e6-4c71-b0ad-f46231351a92",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "e4d849f2-4c10-4e93-9133-b78e861687f2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Anthropic Chat Model4": {
      "ai_languageModel": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "d6375c43-4c99-41fe-9215-eec2ba228e17": {
      "main": [
        [
          {
            "node": "c6f37078-96cb-4e97-b678-ebb688afb413",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5fcebb58-8279-4d89-981f-27d34f2c2747": {
      "main": [
        [
          {
            "node": "2b1a1c57-bad7-4629-a969-aced98962828",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6342d55e-4e82-4755-8826-3d4e5b7f9be7": {
      "main": [
        [
          {
            "node": "2e9ab2da-f324-4864-8617-4ebf6d6873ab",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a1eaf719-3843-424f-b758-b58b32cdc30c": {
      "main": [
        [
          {
            "node": "Aggregate7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge with Original Data": {
      "main": [
        [
          {
            "node": "88aae252-885b-4433-af13-88fea42ad24e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8f25494a-6b7c-45e5-99fc-7ab5e2e0d085": {
      "main": [
        [
          {
            "node": "35db92f5-faf6-4ecd-a148-7bbf09bf620b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "cca27d76-da70-42fc-b6b2-5c5330490d2b": {
      "main": [
        [
          {
            "node": "Aggregate1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5e962f4f-f35a-46f6-a80f-bdd66553c3ed": {
      "main": [
        [
          {
            "node": "Aggregate10",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f90f09ea-6016-429b-915f-1565bcff1d97": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0163f077-3850-4609-9def-1483cd5f720b": {
      "main": [
        [
          {
            "node": "557a172b-f58a-4f82-a8b8-ddc3865bbe20",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8e8ac821-5cd5-4bd2-b78d-203fd5cf57fb": {
      "main": [
        [
          {
            "node": "25951d6e-c27d-48b0-8bef-1b06bb931c30",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "54b5f427-4c28-4b83-a04d-40bc14df309d": {
      "main": [
        [
          {
            "node": "Aggregate2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0af156a4-3324-4a1f-9f63-7a181adb4485": {
      "main": [
        [
          {
            "node": "a1eaf719-3843-424f-b758-b58b32cdc30c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "35db92f5-faf6-4ecd-a148-7bbf09bf620b": {
      "main": [
        [
          {
            "node": "Aggregate3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Data Value into One Key": {
      "main": [
        [
          {
            "node": "Basic LLM Chain",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1e7efdbb-f58c-4cfa-9a74-22cda80b58c7": {
      "main": [
        [
          {
            "node": "f90f09ea-6016-429b-915f-1565bcff1d97",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5487835c-5655-476b-bbad-f368653150d1": {
      "main": [
        [
          {
            "node": "a09de3d7-f79a-4027-ab49-a4e2376d3f82",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "237841d5-2268-4efe-9ae2-25e904dbd48a": {
      "main": [
        [
          {
            "node": "010957b9-c7a4-4432-ac02-6ea1400f0418",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ed421b2f-4a7e-4098-9d09-96965813f3e4": {
      "main": [
        [
          {
            "node": "3f33a49f-f4d5-4483-b01b-ab7b05f1edef",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a9a19c40-4875-4c02-9c2b-3f65124ebdec": {
      "main": [
        [
          {
            "node": "Aggregate9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3b8e7c65-8d40-4636-bfb0-8091365e584e": {
      "main": [
        [
          {
            "node": "fa73399a-c133-48b3-87fe-922961f4d448",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6543e986-8860-457d-a8de-bb052718e9c6": {
      "main": [
        [
          {
            "node": "af88d22a-5a2d-4471-9ac9-b1cb9531bd35",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "557a172b-f58a-4f82-a8b8-ddc3865bbe20": {
      "main": [
        [
          {
            "node": "Aggregate11",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e4d849f2-4c10-4e93-9133-b78e861687f2": {
      "main": [
        [
          {
            "node": "e2179126-0881-4701-9d4a-62d335a74abd",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a09de3d7-f79a-4027-ab49-a4e2376d3f82": {
      "main": [
        [
          {
            "node": "54b5f427-4c28-4b83-a04d-40bc14df309d",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "010957b9-c7a4-4432-ac02-6ea1400f0418": {
      "main": [
        [
          {
            "node": "5e962f4f-f35a-46f6-a80f-bdd66553c3ed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0e729384-88a1-4ee3-9bd1-ccc218462dbc": {
      "main": [
        [
          {
            "node": "Merge with Original Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a988e2c7-ad51-4df3-b4d6-9d5cd6e123af": {
      "main": [
        [
          {
            "node": "Aggregate5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "48bc9ab1-03bb-40a6-844d-a4fff203fcd5": {
      "main": [
        [
          {
            "node": "d165164c-bcf8-4ef3-b434-9416865c6b26",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2e9ab2da-f324-4864-8617-4ebf6d6873ab": {
      "main": [
        [
          {
            "node": "2d7330e7-e3b9-4afc-9217-9dcbdbd4a3e9",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "25951d6e-c27d-48b0-8bef-1b06bb931c30": {
      "main": [
        [
          {
            "node": "Aggregate6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3f33a49f-f4d5-4483-b01b-ab7b05f1edef": {
      "main": [
        [
          {
            "node": "a988e2c7-ad51-4df3-b4d6-9d5cd6e123af",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e2179126-0881-4701-9d4a-62d335a74abd": {
      "main": [
        [
          {
            "node": "cca27d76-da70-42fc-b6b2-5c5330490d2b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Häufig gestellte Fragen

Wie verwende ich diesen Workflow?

Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.

Für welche Szenarien ist dieser Workflow geeignet?

Experte - KI-Zusammenfassung, Multimodales KI

Ist es kostenpflichtig?

Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.

Workflow-Informationen
Schwierigkeitsgrad
Experte
Anzahl der Nodes92
Kategorie2
Node-Typen14
Schwierigkeitsbeschreibung

Für fortgeschrittene Benutzer, komplexe Workflows mit 16+ Nodes

Externe Links
Auf n8n.io ansehen

Diesen Workflow teilen

Kategorien

Kategorien: 34