Zahlzeit: Wie ich meine EÜR nach 15 Jahren Excel selbst programmiert habe
23. Jul 2026
15 Jahre lang habe ich meine Einnahmenüberschussrechnung als Freiberufler in zwei Excel-Tabellen geführt, die mir mein Steuerberater einmal als Vorlage gegeben hat. Weil mir das zunehmend unkomfortabel wurde, habe ich eine eigene Web-Anwendung namens Zahlzeit gebaut – inklusive E-Rechnungs-Import, KI-gestützter Belegzuordnung und Anbindung an Paperless-ngx.
Der Ausgangspunkt: zwei Excel-Tabellen
Als Freiberufler ist die Einnahmenüberschussrechnung (EÜR) die einfachste Form der Gewinnermittlung – keine Bilanz, keine doppelte Buchführung, nur eine Gegenüberstellung von Einnahmen und Ausgaben. Mein Steuerberater hat mir dafür vor Jahren zwei Excel-Dateien mitgegeben: eine für Einnahmen, eine für Ausgaben. Beide mit festen Spalten – Datum, Rechnungsnummer, Kunde oder Dienstleister, Zweck, Betrag, Kontenart, Steuersatz.
Diese Tabellen habe ich 15 Jahre lang gepflegt, jede Rechnung und jede Ausgabe von Hand eingetragen. Es hat funktioniert, war aber nie wirklich angenehm: kein Dashboard, keine Automatisierung, kein Zugriff von unterwegs, und jede Änderung an der Struktur musste in beiden Dateien synchron gehalten werden.
Warum eine eigene Lösung
Bevor ich angefangen habe zu programmieren, habe ich mich kurz umgesehen, was es an fertigen Lösungen für Freiberufler-Buchhaltung gibt. Richtig überzeugt hat mich nichts – vieles ist auf Kleinunternehmer oder komplette Buchhaltungen zugeschnitten, nicht auf die schlanke EÜR-Struktur, an die ich mich über 15 Jahre gewöhnt hatte. Und ehrlich gesagt wollte ich auch einfach mal wieder etwas Eigenes bauen und ausprobieren, statt mich in ein fremdes System einzuarbeiten, das doch nicht ganz passt.
Also habe ich mich an genau den Spalten orientiert, die ich aus den Excel-Tabellen kannte: Dienstleister und Rechnungsnummer bei Ausgaben, Zweck der Buchung, Zuordnung zu einem Konto nach Kontenart, dazu bei Einnahmen der jeweilige Kunde. Das war die Grundlage – kein völlig neues Datenmodell, sondern die vertraute Struktur, nur eben als richtige Anwendung statt als Tabelle.
Die technische Basis
Zahlzeit besteht aus einer API und einem Frontend, beide containerisiert und bei meinem Hosting-Partner Mittwald betrieben.
Die API ist mit dem Node.js-Framework Ts.ED und TypeScript gebaut, als Datenbankzugriff kommt Prisma zum Einsatz. Die Oberfläche ist eine React-19-Anwendung mit MUI als Komponentenbibliothek, für Diagramme im Dashboard sorgt Recharts. Die Anmeldung läuft über OpenID Connect gegen einen eigenen zentralen Auth-Service.
In meinen Projekten ist ein sauber getrennter Aufbau aus API und Frontend Standard, auch wenn – wie hier – zunächst nur ich selbst die Anwendung nutze. Das hat sich schon mehrfach ausgezahlt, etwa als ich später den MCP-Server als dritten, unabhängigen Client hinzugefügt habe, ohne an der API etwas ändern zu müssen.
Vom Excel-Ersatz zur vollständigen Buchhaltung
Die erste Version von Zahlzeit war bewusst simpel: im Grunde die Excel-Tabellen als App nachgebaut, mit denselben Feldern und derselben Logik. Von dort aus habe ich sukzessive erweitert. Für meinen Steuerberater kann ich weiterhin Excel-Dateien exportieren, die genauso aussehen wie die, die er all die Jahre bekommen hat – er merkt vom Wechsel im Zweifel gar nichts. Alternativ könnte ich ihm auch direkten Zugriff auf die Anwendung selbst geben.
Damit die Dateneingabe nicht mehr komplett manuell passieren muss, habe ich mehrere Importer geschrieben:
- Banking-Import: Ich nutze MoneyMoney auf dem Mac für mein Banking. Die Kontoumsätze lassen sich dort als Excel-Datei exportieren und direkt in Zahlzeit als Ausgaben importieren.
- E-Rechnungs-Import: Da ich selbst nur noch E-Rechnungen im ZUGFeRD/Factur-X- oder XRechnung-Format verschicke, liest ein Importer diese Formate aus und legt daraus automatisch die passenden Einnahmen an.
E-Rechnungen automatisch einlesen
Beim Import einer E-Rechnung prüft ein Validierungsdienst zunächst, ob es sich überhaupt um eine gültige ZUGFeRD/Factur-X-PDF oder XRechnung-XML handelt. Nur wenn die Datei valide ist, werden Rechnungsnummer, Rechnungsdatum, Kunde sowie Brutto-, Netto- und Steuerbetrag übernommen. Existiert bereits eine Einnahme mit derselben Rechnungsnummer, bricht der Import kontrolliert ab, statt Duplikate anzulegen.
Schreibe ich selbst eine Rechnung mit gemischten Steuersätzen – etwa einem Anteil zu 19 % und einem zu 7 % –, werden daraus automatisch zwei getrennte Einnahmebuchungen mit dem jeweils passenden Steuersatz. Für die spätere Umsatzsteuervoranmeldung ist das wichtig, weil Elster genau diese Aufschlüsselung nach Steuersätzen verlangt.
KI räumt die Bankimporte auf
Beim Import von Ausgaben aus der Banking-Software blieb ein Problem: Überweisungsbetreffe sind oft kryptisch und enthalten weder eine saubere Bezeichnung noch verlässlich die Rechnungsnummer. Also habe ich für jede importierte Zeile einen KI-Button eingebaut.
Ein Klick genügt, und ein Sprachmodell (ich nutze dafür GPT-4o mini über die OpenAI-API) gleicht die Buchung mit bereits vorhandenen Datenbankeinträgen ab, extrahiert – sofern vorhanden – die Rechnungsnummer direkt aus dem Betreff und bereitet den Eintrag entsprechend auf. Dabei wird auch der Steuersatz korrekt gesetzt, je nachdem ob es sich um 19 %, 7 % oder einen nicht steuerbaren Vorgang handelt. Netto- und Vorsteuerbeträge werden serverseitig aus Brutto und Steuersatz neu berechnet, damit die KI-Antwort nicht versehentlich inkonsistente Zahlen liefert.
Belege automatisch mit Paperless verknüpfen
Meine Eingangsrechnungen landen ohnehin automatisch in Paperless-ngx, meinem Dokumentenarchiv. Da die Rechnungsnummer bereits in der importierten Ausgabenzeile steckt, gibt es in Zahlzeit einen Button, der genau danach in Paperless sucht.
Die Suche ist mehrstufig aufgebaut, damit sie weder zu unpräzise noch zu streng ist: Zuerst wird nach Dokumenttyp „Eingangsrechnung" und – wenn auflösbar – nach dem passenden Korrespondenten gefiltert, wobei Firmenbestandteile wie „GmbH" oder „KG" beim Namensabgleich ignoriert werden. Liefert das keinen Treffer, wird die Suche ohne den Korrespondenten-Filter wiederholt, der Dokumenttyp bleibt aber als Sicherheitsnetz bestehen. Bei genau einem Treffer wird das Dokument automatisch mit der Ausgabe verknüpft; bei mehreren oder keinem Treffer bekomme ich das transparent angezeigt, statt dass etwas falsch verlinkt wird. So muss ich in Zahlzeit selbst keine PDF- oder XML-Dateien mehr vorhalten, sondern verweise direkt auf das Original in Paperless.
Zahlzeit per KI befragen: der MCP-Server
Der letzte Baustein ist ein eigener MCP-Server (Model Context Protocol) für Zahlzeit. Er stellt rund 40 Werkzeuge bereit, mit denen sich Einnahmen, Ausgaben, Konten, Steuersätze und Dashboard-Auswertungen über ein KI-Modell abfragen und pflegen lassen – nutzbar zum Beispiel in Claude Desktop.
Damit kann ich Fragen stellen wie „Wie viele Einnahmen hatte ich mit einem bestimmten Kunden?" oder „Wie viele Ausgaben sind bei einem bestimmten Dienstleister angefallen?" – die Antwort kommt direkt über die Zahlzeit-API, ganz ohne die Anwendung selbst zu öffnen. Die Anmeldung läuft dabei über denselben OIDC-Login wie im Frontend, inklusive automatischer Token-Erneuerung, sodass ich mich nicht bei jeder Sitzung neu einloggen muss.
Fazit
Aus zwei Excel-Tabellen ist über die Zeit eine vollständige, auf meine Bedürfnisse zugeschnittene Buchhaltungs-Software geworden – mit automatisiertem Import von Bank- und Rechnungsdaten, KI-gestützter Aufbereitung kryptischer Buchungstexte, automatischer Belegverknüpfung und einem eigenen KI-Zugang über MCP. Der Aufwand, das selbst zu bauen, war deutlich größer als eine fertige Lösung zu kaufen. Er hat sich für mich trotzdem gelohnt, weil ich damit genau die Struktur behalten konnte, mit der ich seit 15 Jahren arbeite, und weil ich an jeder Stelle selbst entscheiden kann, wie viel Automatisierung ich haben möchte.
Dieser Text wurde mit KI-Unterstützung erzeugt.
