Keine JOINs, 50 Tabellen, eine französische Software – und am Ende bucht die Fibu sich selbst
Zwei Kletterhallen, ein Kassensystem ohne brauchbare Exporte, eine API ohne JOINs. Wie aus diesem Chaos eine vollautomatische Buchhaltung mit PRAP, Mehrzweckgutscheinen und automatischer OPOS-Auszifferung wurde – ein Praxisbericht.
Dieses Projekt ist ein gutes Beispiel dafür, warum es selten reicht, „nur" programmieren oder „nur" buchen zu können. Wer die API rückwärts versteht, aber nicht weiß, was eine passive Rechnungsabgrenzung ist, baut die Daten falsch zusammen. Wer die Buchhaltung beherrscht, aber kein Datenbankschema lesen kann, kommt an die Daten gar nicht erst heran. Hier traf beides auf eine Person – das ist der eigentliche Hebel.
Die Ausgangslage
Zwei Kletterhallen an unterschiedlichen Standorten, ein gemeinsames Kassen- und Verwaltungssystem: GestiXi, eine französische Software. Die Buchhaltung lief bis dahin über Excel-Listen mit Umsatzwerten – und genau da fing das Problem an. Pro Rechnung gab es nur eine Zeile, in der aber mehrere Steuersätze und völlig unterschiedliche Sachverhalte stecken konnten.
Was buchhalterisch sauber abgebildet werden musste:
- ·Kostenstellenrechnung über zwei Standorte und Produktkategorien
- ·Diverse Zahlungsarten: Bar, Kasse, PayPal, Kreditkarte (Mollie), EC
- ·Mehrzweckgutscheine und Kundenguthaben (frei einlösbar)
- ·Abgrenzung schwebender Geschäfte gegen erhaltene Anzahlungen – Termine werden in die Zukunft gebucht
- ·10er-Abo-Karten: Umsatz erst bei anteiliger Einlösung → passive Rechnungsabgrenzung
Die Sackgassen
Echte Projekte verlaufen selten geradlinig. Bevor die Lösung stand, gab es drei Umwege – und jeder hat etwas darüber verraten, wie dieses System tickt.
- 1
Die Excel-Exporte reichen nicht
Eine Zeile pro Rechnung, aber mehrere Steuersätze und Sachverhalte darin – damit lässt sich keine korrekte Buchung erzeugen. Schon bei der Bestandsaufnahme war klar: Die vorhandenen Listen sind eine Sackgasse.
- 2
Zugang ins System, Exporte kombinieren – Fehlanzeige
Also vom Kunden einen direkten Zugang besorgt und geprüft, ob sich verschiedene Exporte zu den benötigten Daten zusammenführen lassen. Ergebnis: nicht das Gewünschte. Auch der (französische) Support konnte keine individuellen Exporte liefern – „aber es gibt eine API".
- 3
Die API kann keine JOINs
Die Doku war bescheiden, also musste die Abfragesprache selbst rekonstruiert werden. Die Anwendung besteht aus über 50 vernetzten Tabellen – abgefragt werden kann aber nur eine Tabelle pro Request. Keine JOINs. Die Daten lagen vor, nur eben verstreut und unverbunden.
Der Wendepunkt: eine eigene Datenbank
Wenn das Quellsystem die Daten nicht verbinden kann, muss man es selbst tun. Ich habe mich tief in das Datenbankdesign von GestiXi eingearbeitet, ein eigenes, normalisiertes Schema aufgesetzt und die benötigten Datensätze Tabelle für Tabelle abgerufen und lokal zusammengeführt.
Der entscheidende Schritt: Sind die Daten erst einmal normalisiert in der eigenen Datenbank, ist mehr als die halbe Miete gewonnen. Ab hier arbeitet man nicht mehr gegen ein fremdes System, sondern mit einer sauberen Grundlage, die genau die Verknüpfungen kennt, die die Buchhaltung braucht.
Wo Buchhaltung und Code zusammenkommen
Auf der normalisierten Datenbasis entsteht zum Monatsanfang vollautomatisch der komplette Buchungsstapel. Die eigentliche Kunst liegt nicht im Datenabruf, sondern in der buchhalterisch korrekten Verarbeitung jedes Sonderfalls:
Umsatz, Zahlung und Abgrenzung in einem Durchlauf
Umsätze werden debitorisch verbucht, Zahlungen direkt anhand der Datenbank mit den Umsätzen verknüpft. So lässt sich pro Rechnungsposition prüfen, ob der Leistungszeitraum erst in einem Folgemonat beginnt – und ob es sich um ein schwebendes Geschäft oder eine erhaltene Anzahlung handelt. Die nötigen Umbuchungen laufen automatisch.
Mollie: nur der echte Auszahlungsbetrag bleibt offen
Mollie-Abrechnungen gleichen die Debitoren direkt aus und buchen sämtliche Gebühren automatisch (per Lerndatei). Auf dem Forderungskonto bleibt am Ende nur der Betrag stehen, der tatsächlich über die Bank eingeht – ohne manuelle Auszifferung.
Abo-Karten als PRAP – anteilig aufgelöst
Der Verkauf einer 10er-Karte wird als passive Rechnungsabgrenzung gebucht. Über Datenbankabfragen wird ermittelt, wie oft die Karte im Monat eingelöst wurde; der PRAP wird entsprechend anteilig aufgelöst. Ist die Karte vollständig eingelöst, ziffert sich der Posten von selbst aus.
Gutscheine & Kundenguthaben: Selbstauszifferung über die Auftragsnummer
Gutscheine werden gegen das Gutscheinkonto gebucht – selbst wenn zwei Gutscheine in einer Rechnungsposition stecken, entstehen daraus zwei getrennte Buchungen. Der Trick: In der DATEV-Spalte Auftragsnummer steht die Gutschein-ID. Über das OPOS-Ausziffern gleicht sich der Posten automatisch aus, sobald der Gutschein eingelöst wird. Kundenguthaben funktioniert analog über die Kontakt-ID als erhaltene Anzahlung.
Soll Haben Betrag Auftragsnr. 1718 10000 25,00 GUT-88431 # Gutschein verkauft 10000 1718 25,00 GUT-88431 # später eingelöst → ziffert sich aus 1718 10000 40,00 ANZ-40244 # Kundenguthaben (Kontakt-ID)
Rabattkategorien & Kostenstellen sauber getrennt
Gewährte Rabatte werden nicht nur erfasst, sondern nach Kategorie differenziert – etwa Bonuskarten oder Kooperationen auf jeweils eigene Konten. Dazu Kostenstellen nach Standort und Produktkategorie.
Das Kontroll-Layer: die Fibu prüft sich selbst
Neben den eigentlichen Buchungen entsteht automatisch eine Übersicht, welche Salden auf welchem Konto stehen sollten. Bewusst „sollten": Diese Erwartung wird nicht aus der Buchungslogik abgeleitet, sondern unabhängig davon „von oben" berechnet.
Beispiel: Liegen bezahlte Rechnungen über 1.000 € vor, deren Leistungszeitraum erst im Folgemonat beginnt, dann erwarte ich auf dem Konto „erhaltene Anzahlungen" exakt diese 1.000 €. Stimmt der tatsächliche Saldo nicht, fällt der Fehler sofort auf.
Über eine Detailansicht ist tabellarisch sichtbar, welche Positionen einen Saldo bilden – „diese Gutscheine mit den IDs X, Y und Z ergeben den Kontostand". Das Ergebnis: keine Abstimmungsarbeiten mehr im Jahresabschluss.
Warum das kein klassischer Dienstleister löst
Ein Entwickler hätte die Daten zusammengebaut – aber falsch
PRAP, schwebende Geschäfte, erhaltene Anzahlungen, OPOS-Ausziffern: Das sind keine technischen, sondern buchhalterische Konzepte. Ohne sie wird aus sauber abgerufenen Daten eine sauber falsche Buchhaltung.
Ein Steuerberater wäre an der API gescheitert
Eine undokumentierte Abfragesprache rekonstruieren, ein normalisiertes Schema entwerfen, 50 Tabellen verknüpfen – das passiert nicht im Standard-Werkzeugkasten einer Kanzlei.
Der Wert entsteht genau an der Schnittstelle
Die Auftragsnummer als OPOS-Schlüssel zu missbrauchen, damit sich Gutscheine selbst ausziffern, ist nur denkbar, wenn man DATEV und Datenmodell gleichzeitig im Kopf hat.
Das Ergebnis
Zum Anfang jedes Monats ruft die Lösung selbstständig alle benötigten Daten ab und erzeugt den vollständigen Buchungsstapel. Manuell bleibt nur ein Schritt: die Stapel einspielen.
Ein Vorsystem, das nicht mitspielt?
Fremde Software, fehlende Schnittstellen, Sachverhalte, die sich im Standard nicht abbilden lassen? Genau dafür lohnt sich der Blick von jemandem, der Buchhaltung und Programmierung gleichzeitig denkt.
Prozess-Audit vereinbaren