{
  "name": "Belege des Monats für die Steuerberatung bündeln",
  "nodes": [
    {
      "id": "ecc8caa4-e0d9-4197-ab22-bfb13362f429",
      "name": "Notiz 1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -60,
        -520
      ],
      "parameters": {
        "content": "## So richtest du den Ablauf ein\n1. Er baut auf dem Ablauf **Rechnungsbelege automatisch ablegen** auf: Belege liegen dort als Datum_Lieferant_Nummer_Betrag.pdf in einem Ordner.\n2. In **Zeitraum: Vormonat** und im Knoten **Testdaten: 4 Belege** oben denselben Ordner eintragen.\n3. Mit **Test: Start per Klick** ausprobieren: Vier erfundene Belege werden angelegt, drei davon aus dem Vormonat landen im Paket.\n4. **An die Steuerberatung senden** mit SMTP-Daten und der Adresse deiner Steuerberatung einrichten und einschalten.\n5. Läuft nur, wenn du n8n selbst betreibst (Dateien auf der Festplatte). Belege mit PRUEFEN_ kommen nicht ins Paket.",
        "height": 320,
        "width": 560,
        "color": 4
      }
    },
    {
      "id": "26e3c394-7478-4be2-a69f-ed1c11c98053",
      "name": "Test: Start per Klick",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        200
      ],
      "parameters": {},
      "notes": "Startet den Ablauf von Hand, zum Testen mit den Beispieldaten."
    },
    {
      "id": "f49d3bff-a6fd-4edc-ab18-1b8893a7605f",
      "name": "Am 1. jedes Monats um 7 Uhr",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "months",
              "monthsInterval": 1,
              "triggerAtDayOfMonth": 1,
              "triggerAtHour": 7
            }
          ]
        }
      },
      "notes": "Startet einmal im Monat."
    },
    {
      "id": "146fb31c-835b-404c-a661-5d78fba48255",
      "name": "Testdaten: 4 Belege",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        200
      ],
      "parameters": {
        "jsCode": "// Vier erfundene Belege im Namensschema des Ablaufs \"Rechnungsbelege ablegen\", drei aus dem Vormonat, einer aus diesem Monat.\nconst ORDNER = '/home/node/.n8n-files/belege';\nconst jetzt = new Date();\nconst vormonat = new Date(jetzt.getFullYear(), jetzt.getMonth() - 1, 1);\nconst ym = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;\nconst pdf = (text) => {\n  const inhalt = `BT /F1 11 Tf 50 780 Td (${text}) Tj ET`;\n  const objekte = ['<< /Type /Catalog /Pages 2 0 R >>', '<< /Type /Pages /Kids [3 0 R] /Count 1 >>', '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >>', '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>', `<< /Length ${inhalt.length} >>\\nstream\\n${inhalt}\\nendstream`];\n  let aus = '%PDF-1.4\\n';\n  const stellen = [];\n  objekte.forEach((o, i) => {\n    stellen.push(aus.length);\n    aus += `${i + 1} 0 obj\\n${o}\\nendobj\\n`;\n  });\n  const xref = aus.length;\n  aus += `xref\\n0 ${objekte.length + 1}\\n0000000000 65535 f \\n${stellen.map((s) => `${String(s).padStart(10, '0')} 00000 n \\n`).join('')}trailer\\n<< /Size ${objekte.length + 1} /Root 1 0 R >>\\nstartxref\\n${xref}\\n%%EOF`;\n  return Buffer.from(aus, 'latin1').toString('base64');\n};\nconst namen = [\n  `${ym(vormonat)}-03_Muster-Hosting-GmbH_RE-2026-1042_23,80EUR.pdf`,\n  `${ym(vormonat)}-14_Buerobedarf-Beispiel-KG_88123_1234,56EUR.pdf`,\n  `${ym(vormonat)}-28_Telefon-Beispiel-AG_T-7781_39,99EUR.pdf`,\n  `${ym(jetzt)}-02_Muster-Hosting-GmbH_RE-2026-1101_23,80EUR.pdf`,\n];\nreturn namen.map((name) => ({\n  json: { pfad: `${ORDNER}/${name}` },\n  binary: { data: { data: pdf(name), mimeType: 'application/pdf', fileName: name, fileExtension: 'pdf' } },\n}));\n"
      },
      "notes": "Vier erfundene Belege, drei aus dem Vormonat."
    },
    {
      "id": "c2021023-c070-4a91-af28-9e791c368c2f",
      "name": "Testbelege in den Ordner legen",
      "type": "n8n-nodes-base.readWriteFile",
      "typeVersion": 1,
      "position": [
        480,
        200
      ],
      "parameters": {
        "operation": "write",
        "fileName": "={{ $json.pfad }}",
        "dataPropertyName": "data",
        "options": {}
      },
      "notes": "Nur für den Test: legt die Beispielbelege in den Belege-Ordner."
    },
    {
      "id": "7a8e65d1-be20-4bbe-a239-ced39bc81c66",
      "name": "Zeitraum: Vormonat",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        80
      ],
      "parameters": {
        "jsCode": "// ===== Deine Angaben =====\nconst ORDNER = '/home/node/.n8n-files/belege'; // derselbe Ordner wie im Ablauf \"Rechnungsbelege ablegen\"\n// ==========================\nconst jetzt = new Date();\nconst vormonat = new Date(jetzt.getFullYear(), jetzt.getMonth() - 1, 1);\nconst monat = `${vormonat.getFullYear()}-${String(vormonat.getMonth() + 1).padStart(2, '0')}`;\n// Ein einziger Eintrag, egal wie viele vorher ankommen: Der nächste Schritt liest dann genau einmal.\nreturn [{ json: { monat, muster: `${ORDNER}/${monat}-*.pdf`, zipPfad: `${ORDNER}/Belege_${monat}.zip` } }];\n"
      },
      "notes": "Bestimmt den Vormonat und das Suchmuster für die Dateien, z. B. 2026-10-*.pdf."
    },
    {
      "id": "3e04c89b-31c4-445e-ad1b-5cd2f7e59a14",
      "name": "Belege des Vormonats lesen",
      "type": "n8n-nodes-base.readWriteFile",
      "typeVersion": 1,
      "position": [
        960,
        80
      ],
      "parameters": {
        "operation": "read",
        "fileSelector": "={{ $json.muster }}",
        "options": {}
      },
      "notes": "Liest alle PDF-Belege, deren Name mit dem Vormonat beginnt."
    },
    {
      "id": "e419098f-2581-4c41-a35f-fedc21283953",
      "name": "Paket und Übersicht bauen",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        80
      ],
      "parameters": {
        "jsCode": "// Alle Belege in einen Eintrag, dazu eine Übersicht als CSV (Datum;Lieferant;Nummer;Betrag;Datei)\nconst items = $input.all();\nconst monat = $('Zeitraum: Vormonat').first().json.monat;\nconst binary = {};\nconst zeilen = ['\"Datum\";\"Lieferant\";\"Nummer\";\"Betrag EUR\";\"Datei\"'];\nlet summe = 0;\nitems.forEach((item, i) => {\n  const datei = item.binary.data;\n  binary[`beleg_${i + 1}`] = datei;\n  const name = datei.fileName ?? '';\n  const [datum, lieferant, nummer, betragTeil] = name.replace(/\\.pdf$/i, '').split('_');\n  const betrag = Number(String(betragTeil ?? '').replace(/EUR$/, '').replace(',', '.')) || 0;\n  summe += betrag;\n  zeilen.push([datum, (lieferant ?? '').replace(/-/g, ' '), nummer, betrag.toFixed(2).replace('.', ','), name].map((w) => `\"${w ?? ''}\"`).join(';'));\n});\nzeilen.push(`\"Summe\";\"\";\"\";\"${summe.toFixed(2).replace('.', ',')}\";\"${items.length} Belege\"`);\nbinary.uebersicht = { data: Buffer.from(`${zeilen.join('\\n')}\\n`, 'utf8').toString('base64'), mimeType: 'text/csv', fileName: `Uebersicht_${monat}.csv`, fileExtension: 'csv' };\nreturn [{ json: { monat, anzahl: items.length, summe: Math.round(summe * 100) / 100, dateien: items.map((x) => x.binary.data.fileName), zipPfad: $('Zeitraum: Vormonat').first().json.zipPfad }, binary }];\n"
      },
      "notes": "Sammelt alle Belege in einem Eintrag und schreibt eine Übersicht mit Summe."
    },
    {
      "id": "8cff8a37-254e-4160-a065-fd7896f23bc4",
      "name": "Als ZIP packen",
      "type": "n8n-nodes-base.compression",
      "typeVersion": 1.1,
      "position": [
        1440,
        80
      ],
      "parameters": {
        "operation": "compress",
        "binaryPropertyName": "={{ Object.keys($binary).join(\",\") }}",
        "outputFormat": "zip",
        "fileName": "={{ \"Belege_\" + $json.monat + \".zip\" }}",
        "binaryPropertyOutput": "data"
      },
      "notes": "Packt Belege und Übersicht in eine ZIP-Datei."
    },
    {
      "id": "1c3dba34-0360-42e7-af79-65a5640f5442",
      "name": "ZIP ablegen",
      "type": "n8n-nodes-base.readWriteFile",
      "typeVersion": 1,
      "position": [
        1680,
        0
      ],
      "parameters": {
        "operation": "write",
        "fileName": "={{ $json.zipPfad }}",
        "dataPropertyName": "data",
        "options": {}
      },
      "notes": "Legt eine Kopie des Pakets im Belege-Ordner ab."
    },
    {
      "id": "f513bea3-d4f9-45ff-ac2f-110baf7540b4",
      "name": "An die Steuerberatung senden",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        1680,
        160
      ],
      "disabled": true,
      "parameters": {
        "fromEmail": "Ihr Name <deine-adresse@example.com>",
        "toEmail": "steuerberatung@example.com",
        "subject": "={{ 'Belege ' + $json.monat }}",
        "emailFormat": "text",
        "text": "=Guten Tag,\n\nanbei die Belege für {{ $json.monat }}: {{ $json.anzahl }} Belege, zusammen {{ $json.summe.toLocaleString('de-DE') }} EUR. Die Übersicht liegt als CSV im Paket.\n\nViele Grüße",
        "options": {
          "appendAttribution": false,
          "attachments": "data"
        }
      },
      "notes": "Schickt das Paket an deine Steuerberatung. Beim Import ausgeschaltet."
    }
  ],
  "connections": {
    "Test: Start per Klick": {
      "main": [
        [
          {
            "node": "Testdaten: 4 Belege",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Testdaten: 4 Belege": {
      "main": [
        [
          {
            "node": "Testbelege in den Ordner legen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Testbelege in den Ordner legen": {
      "main": [
        [
          {
            "node": "Zeitraum: Vormonat",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Am 1. jedes Monats um 7 Uhr": {
      "main": [
        [
          {
            "node": "Zeitraum: Vormonat",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Zeitraum: Vormonat": {
      "main": [
        [
          {
            "node": "Belege des Vormonats lesen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Belege des Vormonats lesen": {
      "main": [
        [
          {
            "node": "Paket und Übersicht bauen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Paket und Übersicht bauen": {
      "main": [
        [
          {
            "node": "Als ZIP packen",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Als ZIP packen": {
      "main": [
        [
          {
            "node": "ZIP ablegen",
            "type": "main",
            "index": 0
          },
          {
            "node": "An die Steuerberatung senden",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "timezone": "Europe/Berlin"
  },
  "pinData": {}
}
