GUTEX Schweiz · Rechnungsverarbeitung und ERP
Die Rechnungsverarbeitung für die Schweiz neu aufgesetzt, auf Parität gebracht und ohne Ausfall live geschaltet.
GUTEX wandelt deutsche und französische Rechnungen in Schweizer Belege und ERP-Buchungen um. Ich baue an diesen Systemen seit 2025 mit, habe jede Abweichung gegen das Altsystem geprüft und im August live geschaltet. Seit Herbst läuft auch Frankreich darüber.
- Kunde
- GUTEX Schweiz
- Zeitraum
- seit 2025
- Technik
- Python, FastAPI, HTMX, MySQL, PostgreSQL, AWS, LlamaParse, abas, Abacus
Ausgangslage
GUTEX stellt Holzfaser-Dämmstoffe im Schwarzwald her und verkauft vor allem in Deutschland, der Schweiz und Frankreich. Jede Rechnung aus Deutschland muss für die Schweiz neu aufbereitet werden: eigene PDFs für Kunden und Intercompany, eigene Nummernkreise, Buchungen in zwei ERP-Systemen, E-Mails an die richtigen Postfächer.
An der Schweizer Lösung arbeite ich seit 2025, gemeinsam mit AM Software. Es ist nicht eine App, sondern mehrere Systeme, die zusammenspielen müssen.
Was ich hier baue
Inventur vor dem ersten Commit
Am 18. Juni habe ich einen Agenten alle Repos und die Cloud-Umgebung lesend durchgehen lassen. Ergebnis war eine Landkarte aller Systeme: ein Dokumenten-Management mit OCR für die Buchhaltung, die Schweizer Interimslösung, ihr Nachfolger und ein System für Avis-Rechnungen. Pro Anwendung ein Absatz, was sie tut, wo sie läuft, welche Datenbank und welche externen Dienste dranhängen. Die wichtigste Erkenntnis kam aus der Datenbank: In der Interimslösung waren am selben Tag 64 neue Belege entstanden. Das war kein Altlast-Thema, sondern Tagesgeschäft.
Alles an einen Ort
Für einen Teil gab es kein gepflegtes Repository. Ich habe den laufenden Stand gesichert, bereinigt und in ein eigenes Repo überführt. Alles Betriebliche liegt seitdem in einem zentralen Ops-Repo mit Doku, Systemlandkarte und Wiederherstellungsdaten.
Erst verstehen, dann fixen
Die erste Meldung betraf hängende Uploads. Statt zu raten, habe ich zuerst das Logging so ausgebaut, dass jeder Schritt nachvollziehbar ist, dann Tests geschrieben, die das Verhalten nachstellen, und erst danach den Fehler behoben. Dazu kam Idempotenz beim Versand, damit nichts doppelt ans ERP geht.
Parität mit dem Altsystem
Das ERP hat nur ein Produktivsystem. Ein Fehler landet direkt in der Buchhaltung. Das neue System musste deshalb exakt dieselben Belege erzeugen wie das alte, “nicht nur ein bisschen”. Ich habe alte Exporte aus der Datenbank des Altsystems reproduziert und gegen ein Review-Paket mit 192 Belegen verglichen. Rückmeldungen der Buchhaltung, etwa zu Texten auf Abholbelegen, habe ich als Code-Änderung umgesetzt und den Export danach neu erzeugt, damit der Vergleich eindeutig bleibt. Später kamen Details wie Vorzeichen bei Gutschriften in Abacus dazu, jeweils geprüft gegen das, was das Altsystem gemacht hatte.
Neue Oberfläche und eine Warteschlange, die hält
Am liebsten hätte ich alles in Rails neu gebaut. Ich habe den bestehenden Python-Code trotzdem behalten, weil Parität wichtiger war als mein Lieblings-Stack. Neu sind eine schlanke Bedienoberfläche mit FastAPI und HTMX, eine Warteschlange mit Wiederholungen und eine Audit-Spur für jeden Versand an E-Mail, Abacus und abas. Ein Testmodus simuliert alle Sendungen und sagt das auf Deutsch. Mehrere PDFs lassen sich gesammelt hochladen, Proformas gehen auf Wunsch automatisch raus. Unterbrochene Sendungen werden nicht blind wiederholt, sondern landen zur Prüfung beim Menschen.
Go-live und der langsame Nachmittag
Am 18. August begann GUTEX mit Tests. Ein Agent hat Logs und Datenbank im 30-Minuten-Takt geprüft, nicht nur den Health-Check. Mittags habe ich das System geleert und scharf geschaltet. Die erste echte Rechnung ging um 13:40 Uhr raus: zwei E-Mails, zwei Buchungen in Abacus, eine in abas, alles in elf Sekunden.
Nachmittags hieß es, die Umwandlung sei morgens schnell gewesen und jetzt langsam. Die Spur führte zum PDF-Parser: Standardeinstellungen, keine feste Version, im Schnitt 44 Sekunden pro Beleg, im schlimmsten Fall fast vier Minuten. Ich habe nicht auf Verdacht umgestellt, sondern 24 Belege aus allen drei Belegarten mit beiden Modi parsen lassen und die extrahierten Felder verglichen. 24 von 24 identisch, der neue Modus rund viermal schneller. Pull Request, Tests, Deployment, alles am selben Tag. Danach wurde die Parallelität konfigurierbar, und das Benchmark-Skript liegt im Repo, damit jeder die Zahlen nachrechnen kann.
Frankreich
Im September kam die französische Gesellschaft dazu: andere Konten, eigener Nummernkreis, Gutschriften und Nullrechnungen. Ich habe das Länderverhalten hinter Profile und Feature-Flags gezogen und eine getrennte Testumgebung für Frankreich aufgesetzt. Bei jedem Schritt liefen die französischen Beispielbelege und aktuelle Schweizer Belege durch, damit die Schweiz nichts davon merkt. Fragen an GUTEX habe ich vorher gegen die Spezifikation geprüft, damit wir nichts fragen, was längst geklärt war. Als die Schnittstellen-Doku für das französische abas kam, habe ich sie Feld für Feld mit dem Schweizer Adapter verglichen, statt “ist identisch” einfach zu glauben. Ergebnis: gleiche Basis, aber einige Felder und Datentypen anders.
Die anderen Systeme
Auch das System für Avis-Rechnungen gehört dazu. Dort habe ich die Datenbank auf eine aktuelle PostgreSQL-Version gebracht, erst lokal mit einer Kopie getestet, dann mit verifizierter Verschlüsselung umgestellt. Eine ungenutzte Staging-Umgebung habe ich gesichert und pausiert. Seitdem prüft ein täglicher Check, ob die Anwendung gesund ist und Jobs durchlaufen.
Wie ich arbeite
Agenten lesen bei GUTEX standardmäßig nur. Schreibende Schritte in Produktion sind einzeln benannt und freigegeben. Deployments laufen über Staging: Dasselbe Image, das dort getestet wurde, wird in Produktion befördert, sonst nichts. Für neue Beispielbelege gibt es einen Verifikations-Skill, der Umwandlung und fertiges PDF gegen die Erwartung prüft. Meldet GUTEX einen Fall, etwa eine doppelt hochgeladene Abholrechnung, kommt zuerst ein Test, der ihn nachstellt, dann der Fix, dann eine kurze Antwort auf Deutsch.
Was dabei rauskam
Das Rechnungssystem läuft seit dem 18. August produktiv. Am ersten vollen Tag liefen 44 Belege durch, ohne Fehler und ohne Lücken in den Nummernkreisen. Seit Ende Juli habe ich über 60 Pull Requests in dieses Repo gemergt, von der Oberfläche bis zur Frankreich-Kontierung. Frankreich läuft im selben System, mit Konten, die die Buchhaltung selbst pflegt. Was vorher verstreut und undokumentiert war, liegt jetzt an einem Ort, mit Tests, Runbooks und Monitoring.
Bei gewachsenen Systemen ist die erste Aufgabe nicht Code, sondern Inventur. Und am Go-live-Tag zählt nur, was die Datenbank sagt.
Ein ähnliches Problem? Schreib mir.