Sein Fund: "an der storno verweist du auf die alte rechnung, muss aber
lauten neu zu und neue rechnungs nummer. heisst kette ist so: rechnung
storniert weist auf die storno nummer, storno verweist auf neue rechnung.
wer soll denn sonst wissen wo er suchen muss."
Er hat recht: eine Zeile, die nur zurueckzeigt, laesst den Leser stehen.
Jetzt sagt jede Zeile, wo es WEITERGEHT:
Rechnung -> "storniert mit 2026-901"
Storno -> "neue Rechnung 2026-902" (Fall A)
-> "neu abgerechnet mit 2026-343" (Fall B, Doppelung)
-> "Storno zu 2026-900" (Fall C / alte Belege ohne Angabe)
neue R. -> "Neuausstellung"
Dafuer wandert die Folgenummer aus den PDF-Kenndaten bis ins Journal:
Buchung.folge_nummer + folge_art (neu | vorhanden | ""), gelesen aus
korrektur_nummer/ersatz_vorhanden/nur_storno, zwei neue DB-Spalten, alte
Journale bauen sich wie gehabt selbst um.
An seinen ECHTEN Belegen geprueft: Storno 2026-455 -> folge 2026-369
(vorhanden), 2026-456 -> 2026-343 (vorhanden). Die Angabe steht in den
Kenndaten schon drin, sie wurde bisher nur nicht gelesen.
Fenster und Blatt zeigen dieselben Worte. Erklaerungs-PDF um eine
Kettentabelle ergaenzt. Pruefkette gruen (storno_verrechnet inkl.
September-Blatt, doppelte_leistung, nur_storno).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
|
||
|---|---|---|
| .gitignore | ||
| ablage.py | ||
| api.py | ||
| app.py | ||
| Beherbergungssteuer starten.bat | ||
| Beherbergungssteuer.exe | ||
| bericht_pdf.py | ||
| db.py | ||
| doku_aenderungen_pdf.py | ||
| einzelinstanz.py | ||
| firma.py | ||
| gemeinsam.py | ||
| gui_monat.py | ||
| modell.py | ||
| ordnerwahl.py | ||
| pdf_parser.py | ||
| pruef_berichtigung.py | ||
| pruef_doppelte.py | ||
| pruef_einzelinstanz.py | ||
| pruef_storno_journal.py | ||
| pruef_storno_verrechnet.py | ||
| pruef_wache.py | ||
| README.md | ||
| xlsx_io.py | ||
| zeig_stornos.py | ||
Beherbergungssteuer – Campinghof Bartl
Ersetzt die Excel-Mappe Beherbergungsteuer.xlsx.
Quelle der Wahrheit sind die Rechnungs-PDFs aus dem Rechnungstool. Das Programm liest den Rechnungs-Ordner ein, führt daraus das Steuerjournal und schreibt auf Knopfdruck die Excel-Mappe fürs Amt.
Starten
- Doppelklick auf
Beherbergungssteuer starten.bat - oder im Terminal:
python app.py
Bedienung
- Rechnungs-Ordner… → den Ordner wählen, in dem das Rechnungstool die PDFs ablegt
(Standard:
Dokumente\Campinghof Rechnungen). Danach wird sofort eingelesen; bei jedem Start passiert das automatisch. - Rechnungen einlesen (oder F5) holt neue Rechnungen nach. Bereits gelesene PDFs werden übersprungen (Vergleich über Pfad, Änderungszeit und Größe) – das geht auch bei tausend Rechnungen schnell.
- Monats-Reiter zeigen die Buchungen mit Summenzeile, unten rechts steht die Jahressumme.
- PDF fürs Amt schreibt den Monatsbericht des offenen Reiters als PDF im
Campinghof-Layout (gleicher Briefkopf wie die Rechnungen) nach
berichte/: Tabelle aller Rechnungen, Summenblock mit der Steuer, Unterschriftszeile. Über das Menü gibt es zusätzlich den Jahresbericht. Gedruckt wird aus dem PDF-Programm heraus.
Im Journal wird nichts von Hand geändert (seit v1.4): weder anlegen noch bearbeiten. Jede Zeile gehört zu einer Rechnung aus dem Rechnungstool – auch die Barzahlung. Wer hier Betrag oder Nummer verstellte, meldete dem Amt etwas anderes, als auf dem Beleg steht; beim nächsten Einlesen käme die Änderung ohnehin zurück. Stimmt eine Rechnung nicht, wird sie im Rechnungstool storniert oder berichtigt.
Löschen bleibt: Entf oder die Haken-Spalte mit dem Papierkorb. Das entfernt nur die Zeile aus dem Zwischenspeicher – die PDF bleibt liegen und wird beim nächsten Einlesen wieder gefunden.
Der Briefkopf des Berichts (Firma, Logo, Bankzeile) wird aus der config.json des
Rechnungstools gelesen – also nur an einer Stelle gepflegt.
Was aus der PDF gelesen wird
| Spalte | Herkunft in der Rechnung |
|---|---|
| Datum | Rechnungsdatum: |
| Rechnung | Rechnungsnummer: (z.B. 2026-238) |
| Nachname | erste Zeile unter Rechnung an: |
| Übernachtungen | Zeitraum: 3 Nächte (ersatzweise An-/Abreise) |
| Gezahlt | Zwischensumme: – das ist die Basis der Steuer |
| Steuer | zzgl. Beherbergungssteuer (5 %): |
Weicht der in der PDF ausgewiesene Steuerbetrag von der eigenen Rechnung ab,
steht das als Warnung in beherbergungssteuer.log.
Doppelt vergebene Rechnungsnummern
Jede Rechnungsnummer darf es nur einmal geben (§ 14 Abs. 4 Nr. 4 UStG). Kommt eine Nummer trotzdem zweimal vor, zeigt das Journal sie an, statt eine der beiden verschwinden zu lassen:
- die betroffenen Zeilen stehen rot und tragen ein ⚠ vor der Nummer,
- der Monatsreiter bekommt ebenfalls ein ⚠ – auch dann, wenn die zweite Rechnung in einem anderen Monat liegt (gerechnet wird über das ganze Jahr),
- unter der Jahressumme steht eine rote Zeile mit dem Knopf „Doppelte Rechnungen anzeigen…": dort stehen alle Belege mit Datum, Gast, Betrag und Dateiname.
Die Beträge bleiben in allen Summen und im Bericht fürs Amt – es wird nichts stillschweigend weggerechnet. Zwei Zeilen zur selben Rechnung (z. B. einmal aus dem Excel-Altbestand und einmal aus der PDF) melden die Übernachtung doppelt ans Amt; zwei verschiedene Gäste unter einer Nummer sind ein Fehler im Rechnungstool. Was zu tun ist, entscheidet der Wirt – das Programm ändert von allein nichts.
Bis Version 1.2 war die Rechnungsnummer der Schlüssel der Datenbank: die zweite Rechnung hat die erste still überschrieben und fehlte danach in der Meldung ans Amt. Seit v1.3 ist der Schlüssel die PDF-Datei, seit v1.4 sieht man den Fall auch.
Nur ein Fenster
Das Programm lässt sich nicht zweimal öffnen. Ein zweiter Doppelklick holt das
offene Fenster nach vorn. Grund: beide Fenster würden denselben Rechnungsordner in
dieselbe journal.sqlite3 einlesen und danach verschiedene Stände zeigen – wer im
älteren Fenster auf „PDF fürs Amt" drückt, meldet einen Stand, den es nicht mehr gibt.
Excel einlesen
Datei → Excel-Tabelle einlesen… zieht die bisherige Beherbergungsteuer.xlsx ins
Journal – sowohl den Altbestand aus der Zeit vor dem Rechnungstool als auch jede
spätere Fassung, die noch in Excel gepflegt wurde. Zeilen ohne PDF sind in der
Tabelle grau dargestellt. Rechnungsnummern werden dabei vereinheitlicht
(001, 13, 2026-17 → 2026-013), sonst entstünden doppelte Buchungen.
Dateien
| Datei | Zweck |
|---|---|
app.py |
Fenster, Menü, Aktionen |
gui_monat.py |
ein Monatsblatt (Tabelle + Summenzeile) |
pdf_parser.py |
Rechnungs-PDF → Buchung |
bericht_pdf.py |
Monats-/Jahresbericht fürs Amt (reportlab) |
firma.py |
Briefkopf aus der config.json des Rechnungstools |
db.py |
Journal (SQLite) + PDF-Scan mit Cache |
xlsx_io.py |
Excel-Import |
modell.py |
Datenmodell + Steuerrechnung + doppelte Nummern (die einzige Rechenstelle) |
ablage.py |
wo der Datenordner liegt (neben der EXE oder in LOCALAPPDATA) |
einzelinstanz.py |
Sperre gegen ein zweites Fenster |
pruef_doppelte.py |
Prüfstand: werden doppelte Nummern angezeigt? |
pruef_einzelinstanz.py |
Prüfstand: geht das Programm wirklich nur einmal auf? |
pruef_berichtigung.py |
Prüfstand: Storno/Berichtigung überschreiben nichts |
journal.sqlite3 |
die Daten (wird beim 1. Start angelegt) |
berichte/ |
die erzeugten Amts-PDFs |
Voraussetzungen
Python 3.10+, pypdf, openpyxl und reportlab (pip install pypdf openpyxl reportlab).