/ 9 Min. Lesezeit / Nico Döhrn
Praxisbericht · Buchhaltungs-Automatisierung

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.

GestiXi · API
# eine Tabelle pro Request. keine JOINs.
POST /query
[{ "recordType": "contact", "id": 40244 }]
# 50+ vernetzte Tabellen,
# Doku: bescheiden.

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. 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. 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. 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.

DATEV-Buchungsstapel · Auszug
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.

2
Standorte, eine Logik
OPOS
Auszifferung läuft automatisch
0
Abstimmung im Jahresabschluss

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