{
  "name": "Finance: Rechnung per E-Mail → KI extrahiert IBAN, Betrag & Datum → Buchhaltung",
  "nodes": [
    {
      "id": "trigger-1",
      "name": "Rechnungs-E-Mail empfangen",
      "type": "n8n-nodes-base.emailReadImap",
      "typeVersion": 2.1,
      "position": [250, 300],
      "parameters": {
        "mailbox": "INBOX",
        "postProcessAction": "read",
        "format": "simple",
        "downloadAttachments": true
      },
      "credentials": {
        "imap": {
          "id": "",
          "name": "Rechnungs-Postfach IMAP"
        }
      },
      "notes": "Überwacht das Rechnungspostfach (z.B. rechnungen@firma.de). Lädt PDF-Anhänge automatisch herunter. Tipp: Richte eine Mailregel ein, die nur Rechnungs-Mails in einen speziellen Ordner verschiebt, und überwache diesen."
    },
    {
      "id": "check-attachment",
      "name": "Hat PDF-Anhang?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [500, 300],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "has-binary",
              "leftValue": "={{ Object.keys($binary).length }}",
              "rightValue": 0,
              "operator": {
                "type": "number",
                "operation": "gt"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "notes": "Prüft ob die E-Mail einen Anhang hat. E-Mails ohne Anhang werden separat behandelt (KI versucht, Rechnungsdaten aus dem E-Mail-Body zu lesen)."
    },
    {
      "id": "extract-pdf",
      "name": "PDF-Text extrahieren",
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [750, 200],
      "parameters": {
        "operation": "pdf",
        "binaryPropertyName": "attachment_0",
        "options": {
          "joinPages": true
        }
      },
      "notes": "Extrahiert den Text aus dem PDF-Rechnungsanhang. Bei gescannten PDFs (Bilder) funktioniert dies nicht — aktiviere dann den alternativen Vision-Pfad."
    },
    {
      "id": "email-body-fallback",
      "name": "E-Mail-Body verwenden",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [750, 450],
      "parameters": {
        "jsCode": "// Fallback: Use email body when no PDF attachment\nconst emailData = $('Rechnungs-E-Mail empfangen').first().json;\n\nreturn [{\n  json: {\n    data: emailData.textPlain || emailData.text || emailData.html?.replace(/<[^>]+>/g, ' ').replace(/\\s+/g, ' ') || 'Kein Inhalt gefunden',\n    quelle: 'E-Mail-Body (kein PDF-Anhang)',\n    betreff: emailData.subject || '',\n    absender: emailData.from?.text || emailData.from || ''\n  }\n}];"
      },
      "notes": "Falls kein PDF angehängt war, wird der E-Mail-Body als Rechnungstext verwendet (z.B. bei Rechnungen direkt im E-Mail-Text)."
    },
    {
      "id": "merge-sources",
      "name": "Quellen zusammenführen",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3.1,
      "position": [1000, 300],
      "parameters": {
        "mode": "passThrough",
        "output": "input1"
      },
      "notes": "Führt beide Pfade (PDF-Text oder E-Mail-Body) wieder zusammen."
    },
    {
      "id": "ai-extract",
      "name": "KI extrahiert Rechnungsdaten",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 2.1,
      "position": [1250, 300],
      "parameters": {
        "resource": "text",
        "operation": "message",
        "modelId": {
          "__rl": true,
          "mode": "id",
          "value": "gpt-4o-mini"
        },
        "messages": {
          "values": [
            {
              "content": "=Du bist ein spezialisierter Buchhaltungs-Assistent für die Rechnungsverarbeitung. Analysiere den folgenden Rechnungstext und extrahiere ALLE relevanten Daten.\n\n## Extrahiere diese Felder:\n\n1. **rechnungsnummer** – Rechnungs-/Belegnummer\n2. **rechnungsdatum** – Datum der Rechnung (Format: YYYY-MM-DD)\n3. **faelligkeitsdatum** – Fälligkeitsdatum/Zahlungsziel (Format: YYYY-MM-DD, berechne aus Zahlungsziel falls nötig)\n4. **lieferant_name** – Name des Rechnungsstellers / Lieferanten\n5. **lieferant_adresse** – Vollständige Adresse des Lieferanten\n6. **lieferant_steuernummer** – USt-IdNr. oder Steuernummer\n7. **iban** – IBAN des Zahlungsempfängers\n8. **bic** – BIC/SWIFT (falls vorhanden)\n9. **bank** – Name der Bank (falls vorhanden)\n10. **nettobetrag** – Nettobetrag in EUR (nur Zahl, Punkt als Dezimaltrenner)\n11. **mwst_satz** – Mehrwertsteuersatz in % (z.B. 19 oder 7)\n12. **mwst_betrag** – MwSt-Betrag in EUR\n13. **bruttobetrag** – Bruttobetrag / Gesamtbetrag in EUR\n14. **waehrung** – Währung (Standard: EUR)\n15. **verwendungszweck** – Verwendungszweck / Referenz für die Überweisung\n16. **positionen** – Array der Rechnungspositionen [{\"beschreibung\": \"\", \"menge\": 0, \"einzelpreis\": 0, \"gesamt\": 0}]\n17. **kategorie** – Geschätzte Buchungskategorie (z.B. \"Büromaterial\", \"IT & Software\", \"Beratung\", \"Reisekosten\", \"Miete\", \"Versicherung\", \"Telekommunikation\", \"Marketing\", \"Sonstiges\")\n18. **skonto** – Skonto-Information falls vorhanden (z.B. \"2% bei Zahlung innerhalb 10 Tagen\")\n19. **notizen** – Besonderheiten oder Hinweise\n\n## Regeln:\n- Beträge IMMER als Zahl mit Punkt als Dezimaltrenner (z.B. 1234.56)\n- Datumsangaben IMMER im Format YYYY-MM-DD\n- Falls ein Feld nicht erkennbar ist: leeren String setzen\n- Falls IBAN vorhanden: Validiere das Format (DE + 20 Ziffern für deutsche IBANs)\n- Berechne fehlende Beträge wenn möglich (Netto + MwSt = Brutto)\n\n## Antwortformat (STRIKT als JSON):\n{\n  \"rechnungsnummer\": \"\",\n  \"rechnungsdatum\": \"\",\n  \"faelligkeitsdatum\": \"\",\n  \"lieferant_name\": \"\",\n  \"lieferant_adresse\": \"\",\n  \"lieferant_steuernummer\": \"\",\n  \"iban\": \"\",\n  \"bic\": \"\",\n  \"bank\": \"\",\n  \"nettobetrag\": 0,\n  \"mwst_satz\": 0,\n  \"mwst_betrag\": 0,\n  \"bruttobetrag\": 0,\n  \"waehrung\": \"EUR\",\n  \"verwendungszweck\": \"\",\n  \"positionen\": [],\n  \"kategorie\": \"\",\n  \"skonto\": \"\",\n  \"notizen\": \"\"\n}\n\nRechnungstext:\n{{ $json.data }}"
            }
          ]
        },
        "options": {
          "temperature": 0.1,
          "maxTokens": 2000
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "",
          "name": "OpenAI API"
        }
      },
      "notes": "GPT-4o-mini extrahiert alle Rechnungsfelder inkl. IBAN-Validierung, Betragsberechnung und automatischer Buchungskategorie. Temperatur bewusst niedrig (0.1) für maximale Präzision."
    },
    {
      "id": "parse-validate",
      "name": "Parsen & Validieren",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1500, 300],
      "parameters": {
        "jsCode": "const aiResponse = $input.first().json.message.content;\nconst emailData = $('Rechnungs-E-Mail empfangen').first().json;\n\ntry {\n  let jsonStr = aiResponse;\n  const jsonMatch = aiResponse.match(/\\{[\\s\\S]*\\}/);\n  if (jsonMatch) jsonStr = jsonMatch[0];\n  \n  const inv = JSON.parse(jsonStr);\n  \n  // === VALIDIERUNGEN ===\n  const warnungen = [];\n  \n  // IBAN-Validierung (deutsches Format)\n  if (inv.iban) {\n    const cleanIban = inv.iban.replace(/\\s/g, '');\n    if (cleanIban.startsWith('DE') && cleanIban.length !== 22) {\n      warnungen.push(`IBAN-Länge ungültig: ${cleanIban.length} statt 22 Zeichen`);\n    }\n    if (!/^[A-Z]{2}[0-9]{2}[A-Z0-9]+$/.test(cleanIban)) {\n      warnungen.push('IBAN-Format ungültig');\n    }\n    inv.iban = cleanIban;\n  } else {\n    warnungen.push('Keine IBAN erkannt');\n  }\n  \n  // Betrags-Validierung\n  const netto = parseFloat(inv.nettobetrag) || 0;\n  const mwst = parseFloat(inv.mwst_betrag) || 0;\n  const brutto = parseFloat(inv.bruttobetrag) || 0;\n  \n  if (netto > 0 && mwst > 0 && brutto > 0) {\n    const berechneterBrutto = Math.round((netto + mwst) * 100) / 100;\n    if (Math.abs(berechneterBrutto - brutto) > 0.02) {\n      warnungen.push(`Betragsabweichung: Netto (${netto}) + MwSt (${mwst}) = ${berechneterBrutto}, aber Brutto = ${brutto}`);\n    }\n  }\n  \n  if (brutto <= 0) {\n    warnungen.push('Kein Bruttobetrag erkannt');\n  }\n  \n  // Datums-Validierung\n  if (!inv.rechnungsdatum || !/^\\d{4}-\\d{2}-\\d{2}$/.test(inv.rechnungsdatum)) {\n    warnungen.push('Rechnungsdatum fehlt oder ungültiges Format');\n  }\n  \n  // Pflichtfeld-Check\n  if (!inv.lieferant_name) warnungen.push('Lieferantenname fehlt');\n  if (!inv.rechnungsnummer) warnungen.push('Rechnungsnummer fehlt');\n  \n  // Konfidenz-Score berechnen\n  const pflichtfelder = ['iban', 'bruttobetrag', 'rechnungsdatum', 'lieferant_name', 'rechnungsnummer'];\n  const gefuellt = pflichtfelder.filter(f => inv[f] && inv[f] !== '' && inv[f] !== 0).length;\n  const konfidenz = Math.round((gefuellt / pflichtfelder.length) * 100);\n  \n  // Freigabe-Status bestimmen\n  let freigabe_status = 'auto_freigabe';\n  if (konfidenz < 60) freigabe_status = 'manuelle_pruefung';\n  else if (warnungen.length > 0) freigabe_status = 'pruefung_empfohlen';\n  if (brutto > 5000) freigabe_status = 'management_freigabe';\n  \n  return [{\n    json: {\n      // Rechnungsdaten\n      rechnungsnummer: inv.rechnungsnummer || '',\n      rechnungsdatum: inv.rechnungsdatum || '',\n      faelligkeitsdatum: inv.faelligkeitsdatum || '',\n      lieferant_name: inv.lieferant_name || '',\n      lieferant_adresse: inv.lieferant_adresse || '',\n      lieferant_steuernummer: inv.lieferant_steuernummer || '',\n      iban: inv.iban || '',\n      bic: inv.bic || '',\n      bank: inv.bank || '',\n      nettobetrag: netto,\n      mwst_satz: parseFloat(inv.mwst_satz) || 0,\n      mwst_betrag: mwst,\n      bruttobetrag: brutto,\n      waehrung: inv.waehrung || 'EUR',\n      verwendungszweck: inv.verwendungszweck || '',\n      positionen: JSON.stringify(inv.positionen || []),\n      kategorie: inv.kategorie || 'Sonstiges',\n      skonto: inv.skonto || '',\n      \n      // Metadaten\n      email_betreff: emailData.subject || '',\n      email_absender: emailData.from?.text || emailData.from || '',\n      email_datum: emailData.date || '',\n      \n      // Validierung\n      konfidenz_prozent: konfidenz,\n      freigabe_status: freigabe_status,\n      warnungen: warnungen.join(' | ') || 'Keine',\n      anzahl_warnungen: warnungen.length,\n      erfasst_am: new Date().toISOString().split('T')[0]\n    }\n  }];\n} catch (e) {\n  return [{\n    json: {\n      error: true,\n      message: 'Rechnung konnte nicht verarbeitet werden: ' + e.message,\n      raw_response: aiResponse,\n      email_betreff: emailData.subject || '',\n      email_absender: emailData.from?.text || ''\n    }\n  }];\n}"
      },
      "notes": "Validiert IBAN-Format, prüft Betrags-Konsistenz (Netto + MwSt = Brutto), berechnet einen Konfidenz-Score und entscheidet über den Freigabe-Status: auto_freigabe (>60% + keine Warnungen), pruefung_empfohlen (Warnungen), manuelle_pruefung (<60%), management_freigabe (>5000€)."
    },
    {
      "id": "route-status",
      "name": "Freigabe-Routing",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [1750, 300],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "auto",
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.freigabe_status }}",
                    "rightValue": "auto_freigabe",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            },
            {
              "outputKey": "pruefung",
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.freigabe_status }}",
                    "rightValue": "pruefung_empfohlen",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            },
            {
              "outputKey": "manuell",
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.freigabe_status }}",
                    "rightValue": "manuelle_pruefung",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            },
            {
              "outputKey": "management",
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.freigabe_status }}",
                    "rightValue": "management_freigabe",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "notes": "Routet die Rechnung basierend auf Konfidenz und Betrag:\n- auto_freigabe: Direkt ins Buchhaltungstool\n- pruefung_empfohlen: Ins Tool + Warnung an Buchhaltung\n- manuelle_pruefung: Nur Warnung, kein Auto-Eintrag\n- management_freigabe: Hoher Betrag, braucht Freigabe"
    },
    {
      "id": "sheets-rechnungen",
      "name": "Rechnungs-Register (Google Sheets)",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [2050, 150],
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": "GOOGLE_SHEET_URL_HIER_EINFUEGEN"
        },
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Eingangsrechnungen"
        },
        "columns": {
          "mappingMode": "autoMapInputData"
        },
        "options": {}
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "",
          "name": "Google Sheets OAuth2"
        }
      },
      "notes": "Schreibt die extrahierten Rechnungsdaten in das Eingangsrechnungen-Register. Dieses Sheet dient als zentrale Übersicht und Grundlage für den Export in DATEV/lexoffice/sevDesk."
    },
    {
      "id": "xero-invoice",
      "name": "Xero: Rechnungsentwurf",
      "type": "n8n-nodes-base.xero",
      "typeVersion": 1,
      "position": [2050, 0],
      "parameters": {
        "resource": "invoice",
        "operation": "create",
        "organizationId": "XERO_ORG_ID",
        "type": "ACCPAY",
        "contactId": "={{ $json.lieferant_name }}",
        "additionalFields": {
          "date": "={{ $json.rechnungsdatum }}",
          "dueDate": "={{ $json.faelligkeitsdatum }}",
          "invoiceNumber": "={{ $json.rechnungsnummer }}",
          "reference": "={{ $json.verwendungszweck }}",
          "status": "DRAFT",
          "currencyCode": "={{ $json.waehrung }}",
          "lineItemsUi": {
            "lineItemsValues": [
              {
                "description": "={{ $json.kategorie }}: Rechnung {{ $json.rechnungsnummer }}",
                "quantity": 1,
                "unitAmount": "={{ $json.nettobetrag }}",
                "taxAmount": "={{ $json.mwst_betrag }}"
              }
            ]
          }
        }
      },
      "credentials": {
        "xeroOAuth2Api": {
          "id": "",
          "name": "Xero OAuth2"
        }
      },
      "disabled": true,
      "notes": "OPTIONAL: Erstellt einen Rechnungsentwurf (DRAFT) in Xero als Eingangsrechnung (ACCPAY). Aktiviere diesen Node wenn du Xero nutzt. Status ist bewusst 'DRAFT' — die finale Freigabe erfolgt manuell in Xero."
    },
    {
      "id": "http-lexoffice",
      "name": "lexoffice: Beleg anlegen (API)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [2050, -150],
      "parameters": {
        "method": "POST",
        "url": "https://api.lexoffice.io/v1/vouchers",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"type\": \"purchaseinvoice\",\n  \"voucherNumber\": \"{{ $json.rechnungsnummer }}\",\n  \"voucherDate\": \"{{ $json.rechnungsdatum }}\",\n  \"dueDate\": \"{{ $json.faelligkeitsdatum }}\",\n  \"totalGrossAmount\": {{ $json.bruttobetrag }},\n  \"totalTaxAmount\": {{ $json.mwst_betrag }},\n  \"taxType\": \"gross\",\n  \"useCollectiveContact\": true,\n  \"remark\": \"Automatisch erfasst aus E-Mail von {{ $json.lieferant_name }}. Konfidenz: {{ $json.konfidenz_prozent }}%\",\n  \"voucherItems\": [\n    {\n      \"amount\": {{ $json.bruttobetrag }},\n      \"taxAmount\": {{ $json.mwst_betrag }},\n      \"taxRatePercent\": {{ $json.mwst_satz }},\n      \"categoryId\": \"{{ $json.kategorie }}\"\n    }\n  ]\n}",
        "options": {}
      },
      "credentials": {
        "httpHeaderAuth": {
          "id": "",
          "name": "lexoffice API Key"
        }
      },
      "disabled": true,
      "notes": "OPTIONAL: Erstellt einen Beleg in lexoffice. Aktiviere diesen Node wenn du lexoffice nutzt. API-Key als Header-Auth hinterlegen (Name: 'Authorization', Value: 'Bearer DEIN_API_KEY'). Die categoryId muss ggf. auf deine Kontenrahmen angepasst werden."
    },
    {
      "id": "http-sevdesk",
      "name": "sevDesk: Beleg anlegen (API)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [2050, -300],
      "parameters": {
        "method": "POST",
        "url": "https://my.sevdesk.de/api/v1/Voucher/Factory/saveVoucher",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpQueryAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"voucher\": {\n    \"objectName\": \"Voucher\",\n    \"mapAll\": true,\n    \"voucherDate\": \"{{ $json.rechnungsdatum }}\",\n    \"description\": \"Rechnung {{ $json.rechnungsnummer }} von {{ $json.lieferant_name }}\",\n    \"payDate\": \"{{ $json.faelligkeitsdatum }}\",\n    \"status\": 50,\n    \"taxType\": \"default\",\n    \"creditDebit\": \"D\",\n    \"voucherType\": \"VOU\",\n    \"currency\": \"{{ $json.waehrung }}\"\n  },\n  \"voucherPosSave\": [\n    {\n      \"objectName\": \"VoucherPos\",\n      \"mapAll\": true,\n      \"taxRate\": {{ $json.mwst_satz }},\n      \"sum\": {{ $json.nettobetrag }},\n      \"net\": true,\n      \"comment\": \"{{ $json.kategorie }}\"\n    }\n  ]\n}",
        "options": {}
      },
      "credentials": {
        "httpQueryAuth": {
          "id": "",
          "name": "sevDesk API Token"
        }
      },
      "disabled": true,
      "notes": "OPTIONAL: Erstellt einen Beleg in sevDesk. Aktiviere diesen Node wenn du sevDesk nutzt. API-Token als Query-Auth hinterlegen (Name: 'token', Value: 'DEIN_API_TOKEN')."
    },
    {
      "id": "slack-auto",
      "name": "Bestätigung senden",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [2350, 150],
      "parameters": {
        "resource": "message",
        "operation": "post",
        "channel": {
          "__rl": true,
          "mode": "name",
          "value": "#buchhaltung"
        },
        "text": "=:white_check_mark: *Rechnung automatisch erfasst*\n\n:page_facing_up: *{{ $json.rechnungsnummer }}* von *{{ $json.lieferant_name }}*\n:euro: Brutto: {{ $json.bruttobetrag }} {{ $json.waehrung }} (Netto: {{ $json.nettobetrag }} + {{ $json.mwst_satz }}% MwSt)\n:calendar: Datum: {{ $json.rechnungsdatum }} | Fällig: {{ $json.faelligkeitsdatum || 'k.A.' }}\n:bank: IBAN: `{{ $json.iban || 'Nicht erkannt' }}`\n:file_folder: Kategorie: {{ $json.kategorie }}\n{{ $json.skonto ? ':moneybag: Skonto: ' + $json.skonto : '' }}\n\n:chart_with_upwards_trend: Konfidenz: {{ $json.konfidenz_prozent }}% | Status: {{ $json.freigabe_status }}\n{{ $json.warnungen !== 'Keine' ? ':warning: Warnungen: ' + $json.warnungen : '' }}",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "",
          "name": "Slack API"
        }
      },
      "notes": "Benachrichtigt die Buchhaltung in Slack mit allen extrahierten Rechnungsdaten, Konfidenz-Score und Warnungen."
    },
    {
      "id": "slack-pruefung",
      "name": "Prüfung anfordern",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [2350, 350],
      "parameters": {
        "resource": "message",
        "operation": "post",
        "channel": {
          "__rl": true,
          "mode": "name",
          "value": "#buchhaltung"
        },
        "text": "=:eyes: *Rechnung erfasst — Prüfung empfohlen*\n\n:page_facing_up: *{{ $json.rechnungsnummer }}* von *{{ $json.lieferant_name }}*\n:euro: Brutto: {{ $json.bruttobetrag }} {{ $json.waehrung }}\n:calendar: Datum: {{ $json.rechnungsdatum }}\n:bank: IBAN: `{{ $json.iban || 'FEHLT' }}`\n\n:warning: *Warnungen:* {{ $json.warnungen }}\n:chart_with_upwards_trend: Konfidenz: {{ $json.konfidenz_prozent }}%\n\nBitte im Rechnungs-Register prüfen und ggf. korrigieren.",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "",
          "name": "Slack API"
        }
      },
      "notes": "Wird gesendet wenn Warnungen vorliegen (z.B. IBAN-Format ungültig, Betragsabweichung)."
    },
    {
      "id": "slack-manuell",
      "name": "Manuelle Erfassung nötig",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [2050, 450],
      "parameters": {
        "resource": "message",
        "operation": "post",
        "channel": {
          "__rl": true,
          "mode": "name",
          "value": "#buchhaltung"
        },
        "text": "=:x: *Rechnung konnte nicht automatisch erfasst werden*\n\n:email: Betreff: {{ $json.email_betreff }}\n:bust_in_silhouette: Absender: {{ $json.email_absender }}\n:chart_with_upwards_trend: Konfidenz: nur {{ $json.konfidenz_prozent }}%\n\n{{ $json.error ? ':bug: Fehler: ' + $json.message : ':warning: Warnungen: ' + $json.warnungen }}\n\nBitte manuell erfassen.",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "",
          "name": "Slack API"
        }
      },
      "notes": "Wird gesendet wenn die automatische Erkennung zu unsicher ist (<60% Konfidenz) oder ein Fehler auftrat."
    },
    {
      "id": "slack-management",
      "name": "Management-Freigabe anfordern",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [2050, 600],
      "parameters": {
        "resource": "message",
        "operation": "post",
        "channel": {
          "__rl": true,
          "mode": "name",
          "value": "#buchhaltung"
        },
        "text": "=:rotating_light: *Hohe Rechnung — Management-Freigabe erforderlich*\n\n:page_facing_up: *{{ $json.rechnungsnummer }}* von *{{ $json.lieferant_name }}*\n:euro: *Brutto: {{ $json.bruttobetrag }} {{ $json.waehrung }}*\n:calendar: Datum: {{ $json.rechnungsdatum }} | Fällig: {{ $json.faelligkeitsdatum || 'k.A.' }}\n:bank: IBAN: `{{ $json.iban }}`\n:file_folder: Kategorie: {{ $json.kategorie }}\n{{ $json.skonto ? ':moneybag: Skonto: ' + $json.skonto : '' }}\n\n:chart_with_upwards_trend: Konfidenz: {{ $json.konfidenz_prozent }}%\n\n:point_right: Betrag über 5.000 € — bitte Freigabe erteilen.",
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "",
          "name": "Slack API"
        }
      },
      "notes": "Wird gesendet wenn der Bruttobetrag über 5.000€ liegt. Erfordert eine separate Freigabe durch das Management."
    }
  ],
  "connections": {
    "Rechnungs-E-Mail empfangen": {
      "main": [
        [
          {
            "node": "Hat PDF-Anhang?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hat PDF-Anhang?": {
      "main": [
        [
          {
            "node": "PDF-Text extrahieren",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "E-Mail-Body verwenden",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "PDF-Text extrahieren": {
      "main": [
        [
          {
            "node": "Quellen zusammenführen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "E-Mail-Body verwenden": {
      "main": [
        [
          {
            "node": "Quellen zusammenführen",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Quellen zusammenführen": {
      "main": [
        [
          {
            "node": "KI extrahiert Rechnungsdaten",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "KI extrahiert Rechnungsdaten": {
      "main": [
        [
          {
            "node": "Parsen & Validieren",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parsen & Validieren": {
      "main": [
        [
          {
            "node": "Freigabe-Routing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Freigabe-Routing": {
      "main": [
        [
          {
            "node": "Rechnungs-Register (Google Sheets)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Rechnungs-Register (Google Sheets)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Manuelle Erfassung nötig",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Rechnungs-Register (Google Sheets)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Rechnungs-Register (Google Sheets)": {
      "main": [
        [
          {
            "node": "Bestätigung senden",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prüfung anfordern",
            "type": "main",
            "index": 0
          },
          {
            "node": "Management-Freigabe anfordern",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": false,
  "tags": [
    {
      "name": "Finance"
    },
    {
      "name": "Buchhaltung"
    },
    {
      "name": "Automatisierung"
    }
  ]
}
