Aufraeumrunde nach der Pruefkette. Fuer den Nutzer sichtbar ist ein Punkt:
der Wechsel von einem Menuetitel zum anderen braucht nur noch EINEN Klick.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Die Runde vom 07.09.2026 hat neben den zwei echten Fehlern eine Reihe
Wiederholungen und stumme Stellen gemeldet. Abgearbeitet in Etappen, jede fuer
sich pruefbar - nach jeder liefen beide Pruefketten gruen.
* Menueleiste: der Wechsel von einem Titel zum anderen brauchte ZWEI Klicks.
Der grab_set der offenen Liste schluckt den ersten, die <Button-1>-Bindung
des Titels feuert gar nicht. Das native tk.Menu, das diese Leiste ersetzt
hat, wechselte schon beim blossen Ueberfahren - zwei Klicks waren also eine
Verschlechterung gegenueber dem, was vorher da war. Die Klappliste wird
ausserdem jetzt wie jede andere Position ueber theme.auf_bildschirm()
begrenzt; am unteren Fensterrand lief sie vorher hinaus.
Neu: pruef_menueleiste.py misst beides ueber echte Klickereignisse.
* %LOCALAPPDATA%/ravokk wurde an drei Stellen einzeln ausgerechnet. Jetzt
fragen alle gemeinsam.standard_ordner(). Laufen die je auseinander, fuehren
die beiden Programme zwei Nummernbuecher - und das faellt erst auf, wenn
eine Rechnungsnummer zum zweiten Mal vergeben ist (§ 14 Abs. 4 Nr. 4 UStG).
* pruefe() stand 35-mal im Quelltext, in sechs Fassungen -> pruefhelfer.py.
Die zwei Ausreisser sind mitgezogen: pruef_storno_verrechnet.py zaehlte in
einer Zahl und konnte am Ende nicht sagen, WAS fehlschlug, pruef_bilder.py
im Rechnungstool schrieb ein eigenes Format.
* dlg_darstellung() und die drei Handgriffe des Umschaltens standen in beiden
app.py fast wortgleich -> ThemeMixin in theme.py. Beide trugen inzwischen
denselben langen Kommentar zu demselben Fehler; das war der Beweis, dass es
eine Sache ist. Programmspezifisch bleiben der Hinweistext im Dialog (R31)
und die Frage, ob die Einstellungen ausdruecklich gespeichert werden muessen.
* pruef_gemeinsam_automatisch.py sagte im Text "genau ein Buch" und prueft
">= 1" mit einem any() - eine Pruefung, die nicht rot werden kann. Jetzt
== 1, und der Dateiname wird mitgeprueft.
Dazu neu: die neun Dateien, die im Kopf zusagen, sie laegen in beiden
Programmen gleich, werden byteweise verglichen. Bei hinweis.py stimmte die
Zusage seit dem 06.09. nicht mehr - gleicher Inhalt, CRLF gegen LF.
* .gitattributes, damit die Zeilenenden nicht von der Maschine abhaengen.
Ohne das meldet genau diese Pruefung nach einem frischen Checkout einen
Unterschied, den es im Repository gar nicht gibt.
* Die stummen "except OSError" in api.py, updater.py und einzelinstanz.py
sagen jetzt, warum sie schweigen duerfen. Die stummen tk.TclError bleiben:
dort wird ein Widget angefasst, das gerade zerstoert wurde, und eine Meldung
waere Rauschen.
* Tote Parameter und Variablen aus dem Umbau des Vortags: symbol_setzen(dunkel=),
kachel(grund=, radius=), mit_trennlinie, sechs x/y-Berechnungen, die von
theme.mittig() sofort ueberschrieben wurden, vier lokale "import ctypes".
39 Pruefstaende, 0 rot.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
## 1. Der Temp-Schutz war geschrieben, aber nicht angeschlossen
_ist_temp() stand seit heute Vormittag in ablage.py, ausfuehrlich begruendet
("Ein Merkzettel, der dorthin zeigt, wird deshalb verworfen") - und wurde von
NIEMANDEM gerufen. Der Schutz war ein Kommentar, keine Massnahme.
Zwei Pruefagenten haben das unabhaengig voneinander gefunden, einer mit
Messung: das Journal landete weiterhin im Temp-Ordner. Windows raeumt den von
selbst auf; es geht um aufbewahrungspflichtige Aufzeichnungen (§ 147 AO).
⚠️ Das ist die schlimmste Sorte Fehler - ein Kommentar, der eine
Schutzmassnahme zusichert, die es nicht gibt. Wer die Datei liest, haelt die
Falle fuer geschlossen. Und ich hatte sie dem Auftraggeber als behoben
gemeldet.
Behoben: _gemerkter_ordner() prueft jetzt wirklich.
pruef_temp_merkzettel.py sichert es ab - er prueft nicht, ob die FUNKTION
existiert, sondern ob sie WIRKT. Dazu die Gegenprobe, dass ein GUELTIGER
Merkzettel weiter befolgt wird: sonst haette der Schutz jemandem sein
Netzlaufwerk weggenommen.
⚠️ Im ersten Anlauf war dieser Pruefstand rot - weil ich seine Spielwiese mit
tempfile.mkdtemp() angelegt hatte und die selbst im Temp liegt. Wer das
Verhalten IM Temp-Ordner prueft, darf seine Spielwiese nicht dort aufbauen.
## 2. Der Darstellungsdialog zerstoerte sich beim ersten Klick selbst
Gleiche Ursache und gleiche Behebung wie im Rechnungstool: _oberflaeche_neu()
loeschte alle Kinder des Hauptfensters, und ein tk.Toplevel ist eines.
pruef_darstellung drueckt jetzt den Radioknopf statt cfg von Hand zu setzen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
War das Programm vorher installiert, ist es danach wieder installiert. Beim
ersten Lauf war es das NICHT - danach stand ein deinstalliertes Programm da,
und der naechste Schritt (den Updater starten lassen) lief ins Leere.
Ein Pruefstand, der aufraeumt, muss auch sich selbst aufraeumen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Sein Befund: "hast du bei dem windows icon das gleich farbige wie im
programm, wo als wasserzeichen gilt, gemacht - weil das schaut blau aus".
Er hatte recht: auf der Kachel stand das ROHE Logo mit seinem Petrol
#004860, waehrend im Programm (Kopfzeile, Wasserzeichen) laengst die
umgefaerbte Fassung laeuft. Zwei Farben fuer dasselbe Zeichen.
Jetzt geht das Logo auch fuers Symbol durch _umfaerben() - dieselbe
Funktion, dieselben Farben: Tuerkis fuer die Wolke, Dunkelgrau fuer das
Zeichen daneben. Die Kachel ist weiss, also gilt die HELLE Fassung.
Fassung 1.9.1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Gleiche Umstellung wie im Rechnungstool, gleiche gemeinsame Dateien
(gemeinsam.py, ordnerwahl.py, wasserzeichen.py, bauen.py).
%LOCALAPPDATA%/ravokk/
journal.sqlite3, berichte/, Nummernbuch, config.json <- Daten
Rechnungstool/ <- Programm
Steuerrechnungstool/ <- Programm
⚠ Hier gefunden und behoben: das Journal der INSTALLIERTEN Fassung lag im
Temp-Ordner. Der Merkzettel (ablage.py) zeigte auf
%TEMP%/abnahme_bst/Daten - haengengeblieben aus einem Abnahmelauf vom
03.09.2026. Windows raeumt den Temp-Ordner von selbst auf; das Journal
waere ohne Vorwarnung verschwunden. Ein Merkzettel, der dorthin zeigt,
wird jetzt verworfen statt befolgt.
Sein Echtbestand (238 Buchungen) lag davon unberuehrt in der Quelle und
ist gesichert.
Kein Ordner-Dialog mehr beim ersten Start - der gemeinsame Ordner steht
fest. Der Knopf hiess dort "Install-Ordner auswaehlen...", was schon immer
falsch war: es geht um das gemeinsame Nummernbuch, nicht um den
Installationsort.
Uninstaller raeumt jetzt auch die vom Updater geladenen Fassungen weg.
pruef_installation.py prueft beides zusammen: Programmordner leer, Daten
unangetastet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Gleiche Umstellung wie im Rechnungstool (gemeinsame wasserzeichen.py): das
Blaugruen wird Tuerkis (#06C6A4), die zweite Haelfte weiss im Dunkeln und
dunkelgrau im Hellen, unterschieden nach Saettigung.
"beim steuertool koennte es ein tick groesser sein" - 28 -> 34 Pixel, wie im
Rechnungstool. Die Stelle bleibt rechts in der Kopfleiste: links stehen die
Bedienelemente (Jahr, Einlesen, Bericht), ein Logo davor wuerde sie alle nach
rechts schieben.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Gleiche Aenderung wie im Rechnungstool, gleiche theme.py: theme.mittig()
setzt jeden Dialog mittig ueber sein Elternfenster, theme.auf_bildschirm()
begrenzt auf den gesamten Desktop ueber alle Monitore statt auf den
Hauptmonitor.
Sein Befund: "da gehen noch die popups auf dem video monitor auf". Ursache
war ein `max(0, x)`, das jede negative Koordinate auf null klemmte - bei ihm
steht der zweite Monitor links (x = -1920).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Seine Ansage: "teste links auf dem 1080p monitor nicht mehr auf dem main ...
weil da schau ich nun video" - und danach "das nun der richtige das fuer
beide".
Dieses Programm hatte ueberhaupt keine Sonderposition fuer den Testlauf:
seine Pruefstandsfenster gingen mitten auf den Hauptbildschirm auf, waehrend
jemand daran arbeitete. Jetzt auf dem zweiten Monitor und ohne Eintrag in der
Taskleiste, wie im Rechnungstool.
Der Platz kommt aus theme.pruefplatz() - dieselbe Datei in beiden Programmen.
Dazu im Installer: der Haken "Verknuepfung auf dem Desktop" ist vorgesetzt
statt abgewaehlt, und jede Verknuepfung traegt IconFilename ausdruecklich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Sein Befund
"und beim steuertool fehlt das theam in genze oder wird nicht durch die
automatik gesetzt"
"nur die einstellunden hilfe leiste die ist noch hell und der icon und
titel leiste auch"
Er hatte recht, und zwar wortwoertlich: dieses Programm lief im
Tk-Standard, mit dreimal fest eingetragenem foreground="black". Es gab hier
gar keine theme.py.
Gebaut
theme.py aus dem Rechnungstool uebernommen und dabei von config.py geloest
- eine Datei, die in BEIDEN Programmen liegt, darf nichts aus einem der
beiden importieren. Beim ersten Uebernehmen flog sie genau daran beim
Import auseinander.
Die Einstellungen liegen hier in der Journal-Tabelle, nicht in einer
config.json. _einstellungen() ist die Bruecke: etwas mit .get() und []=,
wie hinweis.py und theme.py es erwarten.
Menueleiste aus menueleiste.py statt tk.Menu - ein natives Menue laesst
sich unter Windows nicht einfaerben, das war der letzte helle Rest.
Treeview-Stil in theme.py ergaenzt (ttk zeichnet Listen nicht ueber den
Grundstil), Reiter schmaler, damit alle zwoelf Monatsnamen lesbar bleiben.
Die Summenleisten in gui_monat.py holen ihre Farben jetzt vom Fenster statt
sie fest zu tragen - sie waren ein weisser Block unten im dunklen Bild.
Logo und Fenstersymbol werden fuer die dunkle Darstellung aufgehellt.
⚠️ Altfehler behoben: die Meldung des Rechnungstools stand nie
pruef_wache lief mal gruen und mal rot - je nachdem, wann er hinsah. Das
war kein Wackler im Pruefstand, sondern sein Symptom: meldet das
Rechnungstool eine neue Rechnung, laeuft sofort das Einlesen an, und dessen
Ergebnis landete in derselben Zeile. Der Benutzer sah NIE, dass etwas
hereingekommen war. melde() kennt jetzt einen Vorrang in Sekunden; die
Meldung des Rechnungstools bekommt sechs. Dreimal hintereinander stabil
gruen.
Ein wackelnder Pruefstand ist keine Nebensache, die man wegdrueckt.
AUFGABE_STEUERSAETZE_DYNAMISCH.md
Seine naechste Ansage notiert: die festen Saetze sollen raus, dynamisch per
Tabelle wie im Rechnungstool. Mit dem, worauf dabei zu achten ist - ein
Satz gilt ab einem DATUM, und die Saetze bereits erfasster Buchungen
bleiben stehen (§ 147 AO).
Fassung 1.9.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Der Fehler
Das Release war angelegt, die EXE hing dran - und der Updater haette
trotzdem nie etwas gefunden. Der Anhang trug die Nummer im Namen, gesucht
wird aber "Steuerrechnungstool.exe" (version.EXE_NAME). Die Nummer kommt
erst beim Ablegen dazu.
Das Tueckische: nichts schlaegt fehl. Der Updater meldet freundlich
"Aktuell. Kein Update noetig." und startet die alte Fassung.
Zweiter Fund: die Pruefsummen standen nur im Release-TEXT. Der Updater
liest sie aus einer angehaengten Datei <exe>.sha256. Ohne die prueft er nur
die Groesse - und eine verfaelschte Datei hat genau die richtige Groesse.
bauen.py legt jetzt release/ an, pruef_release.py prueft gegen das echte
Repository nach. Beide Dateien sind in beiden Programmen gleich.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Logo
Das Programmlogo (Wolke mit Paragraphenzeichen) steht jetzt rechts in der
Kopfleiste - damit sich die beiden Werkzeuge auf einen Blick unterscheiden.
bauen.py
Der Weg von der Quelle zur Setup-Datei war eine Folge von Befehlen, die
jemand von Hand eintippen musste. Wer einen Schritt vergisst, liefert eine
Setup-Datei mit einer alten EXE aus - und sieht es ihr nicht an. Jetzt ist
es ein Befehl, die Nummer kommt aus version.py, und am Ende stehen die
SHA256-Summen fuer den Release-Text.
pruef_start_exe.py
Prueft, was kein anderer Pruefstand prueft: ob die GEBAUTE EXE ein
sichtbares Fenster zeigt. Alle uebrigen fahren das Programm aus der Quelle,
dort trat der Fehler nie auf.
pruef_einzelinstanz.py wieder gruen
Der Erprobungshinweis haette in jedem der drei Starts ein echtes Fenster
geoeffnet - in einem eigenen Prozess laesst sich kein Dialog abfangen, es
klickt niemand. Geprueft wird dort die SPERRE, nicht der Hinweis (der hat
einen eigenen Pruefstand). Die Kenntnisnahme wird deshalb vorher
eingetragen, und zwar mit genau dem Code, den auch der Klick auf "Ja"
ausfuehrt. Das trifft nur die Kopie im Temp-Ordner: im echten Journal
entsteht keine Zustimmung, die niemand gegeben hat.
Aufgeraeumt
Beherbergungssteuer.exe und die gleichnamige .spec sind raus - das Programm
heisst jetzt anders. Gebaute Dateien gehoeren ins Release, nicht ins Repo;
die .spec-Dateien dagegen schon.
Fassung 1.8.0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
NAME
Das Programm heisst jetzt Steuerrechnungstool - wie sein Repository
(https://git.pcore.de/TheMockTv/Steuerrechnungstool). Umgestellt: Fenstertitel,
Kopfzeile, "laeuft bereits"-Meldung, Startdatei, Spec-Datei (EXE-Name), Logzeile.
NICHT umbenannt, mit Absicht:
* "Beherbergungssteuer" als NAME DER STEUER - das ist ein Rechtsbegriff und
steht weiter so in Berichten, Anmeldung und Oberflaeche.
* LOCALAPPDATA\Beherbergungssteuer in ablage.py - dort liegt der Zeiger auf
den Datenordner. Wer den umbenennt, kappt bestehenden Installationen den
Weg zu ihren Daten.
* Der lokale Ordner C:\claude\beherbergungssteuer - steht in Pruefstaenden
und Spec-Dateien fest, eigener Schritt.
HINWEIS
hinweis.py aus dem Rechnungstool uebernommen (liegt in beiden Programmen
gleich). Der Hinweis kommt beim Start, Ablehnen beendet das Programm ohne
etwas zu vermerken, die Kenntnisnahme wird mit Benutzer, Zeit und Fassung in
der Einstellungstabelle des Journals gespeichert. Neu: Menue Hilfe -> Info mit
dem Text und der Signaturzeile.
PRUEFSTAENDE
Vier Prueflaeufe hatten gar keinen Dialogabfang - bisher fragte das Programm
beim Start nichts. Jetzt bleiben sie sonst vor einem echten Fenster stehen.
pruef_doppelte und pruef_storno_verrechnet haben einen bekommen, der bei
UNBEKANNTEN Fragen abbricht statt still "ja" zu sagen. pruef_storno_journal und
pruef_wache melden Hinweis und Freigabe ausdruecklich an. pruef_wache treibt
ausserdem die Ereignisschleife an (update), sonst kaeme after_idle nie dran.
pruef_wache: die Erwartung "im gemeinsamen Ordner liegt genau EINE Datei" ist
auf die richtige Menge gebracht - Nummernbuch UND Schluessel der Mini-API, der
seit dem 05.09.2026 dorthin gehoert. Alles darueber hinaus faellt weiter auf.
⚠️ pruef_wache bleibt ROT an einer Stelle, die NICHT von diesen Arbeiten kommt
(vor dem Umbau gemessen, war schon rot): die Statuszeile soll nach einem Push
"Rechnungstool meldet" zeigen, wird aber vom Ergebnis des Einlesens
ueberschrieben. Dokumentiert in AUFGABE_BEWEISKETTE_PRUEFBAR.md.
5 von 6 Pruefstaenden gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Die Rechnung des Rechnungstools ist seit dem 05.09.2026 EIN Blatt. Der
Kopfkommentar behauptete weiter, Seite 2 sei die 1:1-Kopie fuers Amt.
Die Leselogik war davon nie betroffen - sie liest ohnehin nur Seite 1.
ABGRENZUNG, DAMIT DAS NICHT VERWECHSELT WIRD
Der "Bericht fuers Amt" (Monats-/Jahresbericht als PDF) BLEIBT. Das ist die
Steueranmeldung nach der kommunalen Satzung: eine Summenmeldung ohne
Gastnamen, kein zweiter Beleg zu einem Umsatz. Ohne sie kann der Betreiber
seine Beherbergungssteuer nicht anmelden.
Herausgenommen wurde nur das, was rechtswidrig war: das zweite Rechnungsblatt
mit derselben Rechnungsnummer und einem anderen Gesamtbetrag (§ 14 Abs. 4
UStG, § 14c UStG, § 146 AO, § 379 Abs. 1 Nr. 1 AO, § 370 AO) - und das lag im
Rechnungstool, nicht hier.
Ansage des Auftragnehmers: was nach dem Gesetz richtig ist, bleibt; im
Rechnungserstellungstool musste es raus.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
Sein Einwand: "du musst die markieren als rechnung und storno oder
berichtigung, und das kannst einfach mit buchstaben machen: r fuer
rechnung, s fuer storno, b fuer berichtigung. am footer kannst eine
erklaerung fuer die buchstaben machen."
Er hat recht - ohne die Marke muss man aus der Begruendung raten, was fuer
ein Beleg die Zeile ueberhaupt ist. Mit dem Buchstaben liest sich die
Kette von selbst:
2026-900 R storniert mit 2026-901
2026-901 S neue Rechnung 2026-902
2026-902 B Neuausstellung
2026-911 S abgerechnet mit 2026-905 (Doppelungsfall)
Unter der Tabelle steht die Legende: "R = Rechnung, S = Stornorechnung,
B = berichtigte Rechnung (Neuausstellung nach einem Storno)". Bewusst
direkt unter die Tabelle und nicht in die Fusszeile - wer eine einzelne
Zeile prueft, hat sie dann vor Augen und muss nicht blaettern.
Dazu "neu abgerechnet mit" auf "abgerechnet mit" gekuerzt: mit dem S
davor ist das "neu" ueberfluessig, und die Zeile bricht nicht mehr um.
Spaltenbreiten neu verteilt (18/18/9/42/Rest/12/18/9/18 mm).
Erklaerungs-PDF um die Art-Spalte ergaenzt. Pruefkette gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
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
Auf seine Ansage: "erklaere dem auch das die rechnungs nummer nun fest
ist und nicht mehr aenderbar ist ausser mit dem storno butten".
Nachgesehen, was das Programm wirklich erzwingt, und genau das
aufgeschrieben - vier Sperren:
* eine vergebene Nummer wird nicht wiederverwendet (geprueft gegen die
PDFs im Ordner UND das gemeinsame Nummernbuch); die vorhandene
Rechnung wird nicht ueberschrieben, es wird die naechste freie
angeboten
* der Zaehler kann nicht zurueck, auch nicht ueber die Einstellungen
* beim Storno ist das Nummernfeld gesperrt, dort vergibt nur das
Programm
* keine Nummer auf Vorrat, wenn nichts folgt
Dazu der Hinweis, dass das Gesetz keine LUECKENLOSE Folge verlangt,
sondern eine EINMALIGE (§ 14 Abs. 4 Nr. 4 UStG) - vorwaerts darf es also
springen, zurueck nicht. Das ist genauer als "nicht mehr aenderbar" und
haelt einer Rueckfrage der Steuerberaterin stand.
Blatt hat jetzt vier Seiten; liegt auf dem Desktop und auf M:.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
Auf seine Bitte: ein Blatt, das erklaert, WAS an Rechnungsschreibung und
Steuerbuch geaendert wurde, WARUM, und auf welche Paragraphen es sich
stuetzt. Drei Seiten, im Briefkopf des Betriebs.
Inhalt: Ausgangslage (dieselbe Leistung mehrfach im Ordner, unvollstaendige
Empfaengerangaben), die zwei festen Wege (Berichtigung / Storno), die drei
Storno-Faelle A/B/C, Pflichtfelder, Umgang mit doppelten Nummern, wie ein
Storno in die Steueranmeldung eingeht - dazu eine Tabelle mit elf
Fundstellen (UStG, UStDV, AO, SaechsKAG, Beherbergungssteuersatzung
Markkleeberg) und was im Programm daraus folgt.
Am Ende die zwei Punkte, die noch offen sind: steuerbefreite
Uebernachtungen (§ 4 Abs. 1 Nr. 1 der Satzung - Kinder bis 18, im Katalog
gibt es eine eigene Position dafuer) und die Abrundung je Uebernachtung
(§ 3 Abs. 3). Beide wirken zugunsten der Stadt, sind aber ungebaut - das
gehoert offen aufs Blatt und nicht verschwiegen.
Als Skript und nicht von Hand geschrieben, weil der Text Paragraphen
nennt: aendert sich das Programm, aendert man den Text hier und erzeugt
das Blatt neu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
Sein Hinweis: "da ist noch so viel platz, die naechte und satz alleine
nehmen so viel raum ein auf dem blatt, da kannst locker zeile begruendung
oder so was setzen und da dann storno zu und die nummer vom storno".
Stimmt: die Zahlenspalten standen mit viel Luft nebeneinander, waehrend
die Begruendung klein gedruckt war. Neu verteilt (in mm):
Datum 19 | Rechnung 19 | Begruendung 44 | Name Rest | Naechte 12 |
Entgelt 19 | Satz 10 | Steuer 19
Damit passt "storniert mit 2026-901" in EINE Zeile, in normaler
Schriftgroesse statt 7,5 pt. Spaltenkopf heisst jetzt "Begruendung"
(sein Wort) und "Satz %" nur noch "Satz" - das Prozentzeichen steht
ohnehin nirgends im Wert.
Angesehen: Tabelle als Bild gerendert, alles einzeilig, auch mit langem
Namen. pruef_storno_verrechnet und pruef_berichtigung gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
Zwei Ansagen von ihm, beide am selben Blatt:
1. "weil die nummer hast nur auf der storno selber aber nicht am
stornierten nummer um die es geht" - die aufgehobene Rechnung stand
nur als "storniert" da. Jetzt steht dort "storniert mit 2026-901".
Damit ist das Paar in BEIDE Richtungen lesbar, und das zaehlt vor
allem dann, wenn der Storno in einem anderen Monat liegt und auf
diesem Blatt gar nicht auftaucht.
2. "mach eine neue spalte mit grund oder so was" - der Vermerk stand als
zweite Zeile unter der Rechnungsnummer. Jetzt ist es eine eigene
Spalte "Grund" zwischen Rechnung und Name, eine Zeile je Buchung.
Feste Breiten neu verteilt (20/20/34 mm + Rest fuer den Namen), damit
nichts umbricht.
Dafuer neu: modell.aufhebungen() gibt {id der Rechnung: Storno-Buchung}
statt nur der ids - die Anzeige will auch sagen, WOMIT storniert wurde,
nicht nur DASS. aufgehobene() bleibt als duenne Huelle darueber, damit
zeig_stornos und doppelte_nummern unveraendert weiterlaufen.
Fenster und Blatt zeigen wieder dieselben Worte.
pruef_storno_verrechnet prueft beide Richtungen mit, auch ueber die
Monatsgrenze ("storniert mit 2026-911" im August, der Storno selbst steht
im September). Angesehen: Tabelle als Bild gerendert, alles einzeilig,
auch mit langem Namen. doppelte und berichtigung gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
Sein Wort: "musst dann rein schreiben storniert oder so was dran setzen".
Im Bericht fuers Amt stand bisher nur die Rechnungsnummer. Bei einem
Storno sieht das Amt damit eine Stornonummer neben einer voellig anderen
Rechnungsnummer und im Folgemonat eine Minuszeile - ohne einen Hinweis,
was wozu gehoert. Im Fenster gibt es dafuer die Spalte "Art", auf dem
Blatt fehlte sie.
Jetzt steht unter der Nummer in kleiner grauer Schrift dasselbe Wort wie
im Fenster: "storniert", "Storno zu 2026-900", "Neuausstellung". Die
Zuordnung wird ueber ALLE uebergebenen Buchungen bestimmt (das ganze
Jahr), weil der Storno in einem anderen Monat liegen kann als seine
Rechnung - genau der Fall, um den es geht.
An den Summen aendert sich nichts: verrechnet bleibt verrechnet.
pruef_storno_verrechnet prueft die drei Beschriftungen jetzt mit.
Angesehen wurde es auch: Monatsbericht August und September als Bild
gerendert, Zeilen und Summen stimmen (August 9 Naechte/117,00,
September -4/-52,00).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
Heute Nacht war es andersherum gebaut (v1.6.3): Storno und aufgehobene
Rechnung zaehlten gar nicht mehr mit, die Berichtigung landete im Monat
der Rechnung. Sauber nach § 7 Abs. 5 der Satzung (angemeldet wird die im
Kalendermonat VEREINNAHMTE Steuer), aber nicht das, was er will.
Sein Wort:
"ich wuerde das wie beim alten lassen, nicht das er der Stadt zu
wenig gibt"
"ob er im Sep dann weniger gemacht hat ist doch egal, weil im August
hat er ja mehr - also gleicht es sich aus, es ist nur ein
Time-Problem. Aber um was es mir geht: die Steuern sind sauber."
Und er hat recht: der Unterschied ist NUR der Monat, nie das Jahr, und
die Richtung stimmt - zu viel zuerst ist beim Amt nie ein Problem, zu
wenig schon.
Also zurueckgebaut:
- modell.zaehlbar() ist wieder raus, summiere() summiert alle Zeilen mit
ihrem Vorzeichen. Die Begruendung samt Satzungs-Fundstelle steht im
Docstring, damit es niemand "repariert" - in EINEM Monat sieht eine
verrechnete Doppelung naemlich nach einem Fehler aus.
- Amtsbericht zeigt Rechnung und Storno wieder beide, jede in ihrem Monat
und mit ihrem Vorzeichen. Damit erklaert sich die Meldung von selbst.
- aufgehobene() bleibt, wird aber nur noch fuer die Spalte "Art" und fuer
die Dubletten-Meldung gebraucht, nicht mehr fuers Rechnen.
Nicht zurueckgebaut (das war eine eigene Ansage): Storno und aufgehobene
Rechnung werden NICHT mehr ausgegraut, sie stehen normal da und sind ueber
die Spalte "Art" gekennzeichnet.
pruef_storno_rechnet_nicht.py ist durch pruef_storno_verrechnet.py
ersetzt: derselbe Aufbau (Fake-Rechnungen in einer echten SQLite, auch
der Fall ueber die Monatsgrenze), aber es haelt jetzt das gewollte
Verhalten fest - August 9 Naechte/117,00, September -4/-52,00, Jahr
5/65,00. Restliche Kette (storno_journal, doppelte, berichtigung,
einzelinstanz, wache) gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
Reines Lesen - keine Buchung wird angelegt, geaendert oder geloescht und
der Rechnungsordner wird nicht gescannt. Damit kann man es ohne Sorge auf
das echte Journal loslassen.
Zeigt je Monat die alte Rechenweise (Rechnung + und Storno - heben sich
gegenseitig auf) gegen die jetzige (Storno und aufgehobene Rechnung
zaehlen gar nicht mit) und darunter jedes Storno-Paar einzeln, mit dem
Hinweis, wenn Rechnung und Storno in VERSCHIEDENEN Monaten liegen. Genau
dort unterscheiden sich die beiden Rechenweisen.
Anlass: die Frage "stimmen die 8.500 Euro jetzt" laesst sich nur an den
echten Daten beantworten, nicht durch Herleitung.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
Seine Ansage: "wenn es als storno getagt ist darf der rechner das nicht
mehr rechnen weil es minus ist, die rechnung gibt es nicht mehr" - und
"ausgrauen wuerde ich es nicht, ich wuerde es nur als storno taggen".
Bisher standen Rechnung (+) und Storno (-) beide in der Summe und hoben
sich gegenseitig auf. Naechte, Entgelt und Steuer kamen dabei zwar
richtig heraus, aber:
* die Zahl "Rechnungen" war je Stornofall um ZWEI zu hoch - im Fenster
wie im Amtsbericht, und
* lag der Storno in einem anderen MONAT als seine Rechnung, stand in
jedem der beiden Monate die Haelfte der Verrechnung allein da: der
August meldete eine Uebernachtung zu viel, der September eine zu wenig.
Erst im Jahr hob sich das wieder auf.
Neu ist modell.zaehlbar(): Storno und die von ihm aufgehobene Rechnung
zaehlen gar nicht mehr mit. summiere() geht durch diesen Filter, das Set
der aufgehobenen Rechnungen wird ueber das ganze JAHR bestimmt und an
Monatsleiste, Jahresleiste und Amtsbericht durchgereicht.
Der Amtsbericht zeigt die beiden Zeilen auch nicht mehr an - die
Rechnung gibt es nicht mehr, und Minuswerte auf dem Blatt fuers Amt
waeren ohne die Gegenzeile nicht erklaerbar.
Im Fenster bleibt alles sichtbar, nur nicht mehr grau: der Hinweis
steht in der Spalte "Art" (Storno zu .../storniert/Neuausstellung).
Pruefstand pruef_storno_rechnet_nicht.py (neu, 22 Pruefungen) legt die
Faelle als Fake-Rechnungen in einer echten SQLite an - auch den Fall
ueber die Monatsgrenze, den echte Daten nicht hergeben - und prueft
Rechenkern, Amtsbericht-PDF und das echte Fenster. Die uebrige
Pruefkette (storno_journal, doppelte, berichtigung, einzelinstanz,
wache) laeuft unveraendert gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
Sein Einwand: 'wenn man in der beherbergungstool ein datensatz loescht, bleibt
die in der sqlite - oder du patchst es raus, dass man das garnicht mehr loeschen
kann'.
Beides stimmt. Im gemeinsamen Nummernbuch BLEIBT die Nummer stehen, und das ist
richtig: vergeben ist vergeben, die Rechnung liegt beim Gast. Das Loeschen im
Journal gehoert dagegen weg - eine Zeile aus einer PDF kaeme beim naechsten
Einlesen ohnehin zurueck, eine Zeile aus dem Excel-Altbestand (quelle='xlsx')
gibt es dagegen nirgends sonst; die waere fuer immer weg, samt Uebernachtung im
Amtsbericht. § 146 Abs. 4 AO verbietet Aenderungen, bei denen der urspruengliche
Inhalt nicht mehr feststellbar ist.
Raus sind: Papierkorb-Knopf, Entf-Taste, Menuepunkt und die Haken-Spalte, die
nur dafuer da war. Damit ist das Monatsblatt reine Anzeige.
Der Weg, der bleibt: die PDF aus dem Rechnungsordner nehmen - dann raeumt der
Scan die Zeile von selbst weg, und nur dann, wenn das Laufwerk erreichbar ist
(ein abgezogenes NAS darf die Buchhaltung nicht leeren).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GYeAfLtccFrbU3MTj1MMTx
Das Rechnungstool schreibt jetzt unverbindliche Angebote (frueher Proforma).
Uebersprungen werden sie zuerst ueber die Kenndaten (art=angebot, die
ueberleben auch ein Umbenennen) und, falls die einmal fehlen, ueber Dateiname
und Unterordner ('Angebot_...' bzw. 'Angebote/') - sein Vorschlag: 'kann er ja
am dateinamen festmachen, steht ja dann rechnung oder angebot'. Eine echte
Rechnung wird davon nicht erfasst, das prueft pruef_angebot.py mit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GYeAfLtccFrbU3MTj1MMTx
Das Journal macht beim Start einen winzigen Server auf 127.0.0.1 auf und traegt
Port und PID in die gemeinsame SQLite ein (Tabelle "laeuft"). Das Rechnungstool
sieht daran, dass jemand zuhoert, und klopft nach jeder Rechnung an: "schau in
die sqlite". Dann wird sofort nachgelesen, statt bis zum naechsten Durchgang zu
warten. Faellt die API aus, findet die Wache die Meldung trotzdem - ein os.stat
auf die eine Datei, alle zwei Sekunden und sofort beim Zurueckklicken.
Die Proforma-Rechnung wird NICHT gebucht: keine_buchung() kennt jetzt
Berichtigung und Proforma. Der Scan fragt wieder keine_buchung() - seit dem
Berichtigungs-Umbau tat er das nicht mehr, und die Proforma waere als Buchung
im Journal gelandet (der Pruefstand hat es gefunden).
Pruefstand pruef_wache.py: 31 Pruefungen ueber BEIDE Programme - Anmeldung mit
PID, ping ("hallo, bin noch da"), genau eine Datei im gemeinsamen Ordner, Push
nach Rechnung und nach Storno, Einlesen samt Anzeige, Rueckfallebene ohne API,
tote PID wird weggeraeumt, kein Melden an ein geschlossenes Journal.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GYeAfLtccFrbU3MTj1MMTx
Stehen beide Programme offen und wird im Rechnungstool eine Rechnung
geschrieben, erscheint sie hier ohne Zutun. Das Journal traegt sich dafuer beim
Start mit seiner PID in der gemeinsamen SQLite ein (Tabelle "laeuft") und traegt
sich beim Schliessen wieder aus; das Rechnungstool sieht daran, dass jemand
zuhoert, und legt eine Zeile in die Tabelle "nachrichten".
Nachgesehen wird nur dort - erst ein os.stat auf die eine Datei, und nur wenn
sich etwas geruehrt hat, wird sie geoeffnet. Kein Absuchen des
Rechnungsordners, kein Server, kein Port. Beim Zurueckklicken ins Fenster wird
sofort nachgesehen statt zwei Sekunden zu warten.
Die Wache faengt jeden Fehler ab und stirbt nie - ein Netzlaufwerk, das kurz
weg ist, darf das Fenster nicht lahmlegen.
⚠ Ein Denkfehler daraus gleich behoben: der erste Blick nach dem Start merkt
sich den Stand AUCH dann, wenn es die Datei noch gar nicht gibt. Sonst galt die
erste Meldung danach als "schon gesehen" und wurde verschluckt.
Pruefstand pruef_wache.py (faehrt BEIDE Programme): 23 Pruefungen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GYeAfLtccFrbU3MTj1MMTx
Storno: das Journal zaehlte die Uebernachtungen der aufgehobenen Rechnung
weiter mit (4 - 0 + 3 = 7 statt 3 gemeldeter Naechte). Die Betraege kuerzten
sich, die Naechte nicht. Der Storno traegt jetzt die negative Zahl, und das
Journal kennt Art, Bezug und Datum des Belegs (vier neue Spalten, alte
Journale bauen sich beim Oeffnen um).
Berichtigung: das Blatt wurde nur uebersprungen. Der berichtigte NAME kommt
jetzt in der Buchung an - im Amtsbericht stand sonst weiter der falsche.
Angewandt wird erst am Ende des Scans, das Blatt kann vor seiner Rechnung im
Ordner liegen.
Doppelte Nummern: eine stornierte Rechnung ist keine offene mehr und faellt aus
der Meldung. Zugeordnet wird ueber Nummer + Datum + Empfaenger, nicht ueber die
Nummer allein - bei einer doppelt vergebenen Nummer waere die kein eindeutiger
Bezug, und genau den verlangt § 31 Abs. 5 UStDV. Die Texte nennen jetzt den
Weg: eine der beiden im Rechnungstool stornieren und mit freier Nummer neu
ausstellen (§ 14 Abs. 4 Nr. 4 UStG - jede Nummer nur einmal).
Neue Spalte "Art": Storno zu ..., storniert, Neuausstellung. Aufgehobene Zeilen
stehen grau - geloescht wird nichts.
Gemeinsames Nummernbuch (gemeinsam.py, ordnerwahl.py - in beiden Programmen
dieselbe Datei): eine SQLite in einem Ordner, den beide kennen. Das Journal
traegt seine Nummern ein, auch die aus der Excel-Mappe ohne PDF - genau die
kannte das Rechnungstool nicht und vergab sie ein zweites Mal. Beim ersten
Start wird nach dem Ordner gefragt (auswaehlen, OK, Sicherheitsfrage, bei Nein
zurueck ins Feld); wer ihn nicht hat, kommt mit "Spaeter einrichten" weiter.
Kein Doppelklick zum Bearbeiten mehr (gui_dialoge.py geloescht): wer hier Betrag
oder Nummer verstellt, meldet dem Amt etwas anderes, als auf dem Beleg steht.
Loeschen bleibt.
--test / CAMPINGHOF_TEST=1 unterdrueckt den Erststart-Dialog (Pruefstaende).
Pruefstaende: pruef_storno_journal.py (neu, ueber BEIDE Programme: Storno,
Berichtigung, doppelte Nummer aufloesen), pruef_doppelte, pruef_berichtigung,
pruef_einzelinstanz - alle gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GYeAfLtccFrbU3MTj1MMTx
Der Amtsbericht wird aus diesen Zeilen gebaut - es muss spaeter nachvollziehbar
sein, wann eine doppelt vergebene Nummer zuerst dastand. Eine Zeile je
Auffrischung, mit Jahr, Anzahl und den Nummern.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GYeAfLtccFrbU3MTj1MMTx
Doppelte Rechnungsnummern werden ANGEZEIGT statt still mitgeschleppt: rote
Zeile mit Warnzeichen, markierter Monatsreiter, rote Zeile unter der
Jahressumme und eine Liste aller Belege mit Dateinamen. Gerechnet wird ueber
das ganze Jahr - liegt die zweite Rechnung im naechsten Monat, sieht kein
Monat fuer sich eine Dublette, das Amt bekommt sie trotzdem doppelt. Die
Betraege bleiben in allen Summen und im Amtsbericht; gemeldet wird der Fund,
korrigiert wird nichts von allein.
Vorgeschichte: bis v1.2 war die Rechnungsnummer der Schluessel der Tabelle -
die zweite Rechnung ueberschrieb die erste still und fehlte im Amtsbericht.
v1.3 hat den Schluessel auf die PDF-Datei umgestellt, seitdem bleiben beide
Zeilen stehen. Erst jetzt sieht man den Fall auch.
Einzelinstanz aus dem Steuerrechner uebernommen (nur Mutex- und PID-Name
geaendert): zwei Fenster lesen denselben Rechnungsordner in dieselbe
journal.sqlite3 - was das eine loescht, steht im anderen noch da, und wer
dort "PDF fuers Amt" drueckt, meldet einen Stand, den es nicht mehr gibt.
Die Sperre greift vor ablage.daten_ordner() und nur beim echten Start.
"Neue Buchung" ist raus: jede Zeile gehoert zu einer Rechnung aus dem
Rechnungstool. Wer eine Buchung braucht, schreibt die Rechnung. Bestehende
Zeilen lassen sich weiter bearbeiten.
Pruefstaende: pruef_doppelte.py (27 Pruefungen am echten Fenster),
pruef_einzelinstanz.py (echte Prozesse). Beide gruen, dazu Abnahme mit den
Augen an Hauptfenster, Liste und Bearbeiten-Dialog.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GYeAfLtccFrbU3MTj1MMTx
Als EXE lagen Journal, Berichte und Log bisher direkt neben der EXE. Damit
laesst sich das Programm nicht in einen Ordner legen, in den Windows nicht
schreiben laesst - und beim Sichern uebersieht man leicht die Haelfte.
Jetzt: beim ersten Start ein Ordner "Daten" neben der EXE, alles darin. Geht
das nicht, weicht es nach LOCALAPPDATA aus. Was schon neben der EXE lag, zieht
mit um - sonst waere das Journal ploetzlich leer.
Ist der gemerkte Ordner nicht erreichbar (Stick ab, NAS aus), wird NICHTS
geaendert und der Merkzettel bleibt stehen: morgen steckt der Stick wieder
dran und alles ist da, wo es war.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
Das Rechnungstool schreibt seit heute auch Storno- und Berichtigungsblaetter in
denselben Ordner. Zwei Fehler, die daraus entstanden waeren - beide still:
1. Ein Berichtigungsblatt (§ 31 Abs. 5 UStDV) traegt die Nummer DER RECHNUNG,
die es berichtigt, und lauter Nullen. Unter dem alten Schluessel
(jahr, rechnungsnummer) hat es die echte Buchung ueberschrieben - im
Amtsbericht fehlte die Uebernachtung dann. Wird jetzt uebersprungen
(pdf_parser.keine_buchung), in beiden Scannern.
2. Der Schluessel ist jetzt die DATEI. Zwei Rechnungen mit derselben Nummer -
der Altbestand, bevor das Rechnungstool eine Sperre bekam - ueberschrieben
sich sonst gegenseitig. Bestehende Journale werden beim Oeffnen einmalig
umgebaut, in einer Transaktion, mit Rueckfall auf den alten Stand.
Buchungen von Hand (kein PDF-Pfad) bleiben davon unberuehrt.
Stornos zaehlen weiter mit - sie sind negativ und heben die Uebernachtung im
Bericht genau so auf, wie es sein soll.
pruef_berichtigung.py (neu): schreibt mit dem echten Renderer des
Rechnungstools eine Rechnung, ein Berichtigungsblatt dazu und zwei Rechnungen
mit derselben Nummer, liest sie ein und prueft das Ergebnis in der Tabelle.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
Der Briefkopf-Fuss (Bank, Steuernummer, Inhaber, Homepage, E-Mail, Telefon) wurde
oberhalb des unteren Seitenrands gezeichnet und lief damit in den Textbereich. Auf
vollen Seiten stand er quer ueber der letzten Tabellenzeile. Die Kontaktdaten waren
zudem Platzhalter (example.de).
Es bleibt die Seitenzahl, bewusst unterhalb von MARGIN_BOT.
Die Fusszeile druckte Bankname, IBAN, BIC und Steuernummer. In einer Meldung
ans Amt haben die nichts verloren - es zieht nichts ein und ueberweist nichts.
Es bleiben Inhaber (wer meldet) und die Kontaktdaten fuer Rueckfragen; leere
Felder werden uebersprungen. Auf der Rechnung bleibt alles unveraendert.
Der Parser nahm die erste Zeile unter "Rechnung an:" als Namen. Steht im
Rechnungstool eine Anrede, war das "Herr" statt "Mustermann".
- Neue Rechnungen: Kenndaten kommen aus den PDF-Metadaten (JSON), inkl.
getrenntem Nachnamen. Nichts wird mehr geraten.
- Alte Rechnungen ohne Metadaten: der Adressblock wird gesammelt, reine
Anrede-Zeilen (Herr/Frau/Familie/Firma) werden uebersprungen, fuehrende
Anreden abgeschnitten.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Die config.json des Rechnungstools wurde nur unter dem festen
Entwicklungspfad gesucht - als EXE auf einem anderen Rechner haette der
Bericht keinen Briefkopf bekommen. Jetzt: neben dem Programm, im
Nachbarordner, in Dokumente, und ueber "Daten -> Firmendaten waehlen".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ersetzt die Excel-Mappe des Campinghofs. Die Rechnungs-PDFs des
Rechnungstools sind die Quelle; SQLite ist nur Cache, Excel nur noch
Import des Altbestands. Bericht fuers Amt als PDF im Briefkopf der
Rechnungen (Firmendaten aus der config.json des Rechnungstools).
- pdf_parser: liest Datum, Nummer, Name, Naechte, Zwischensumme, Satz
- db: Journal + Scan mit Cache (Pfad/mtime/Groesse)
- xlsx_io: Import der alten Tabelle, vereinheitlicht Rechnungsnummern
- bericht_pdf: Monats- und Jahresbericht (reportlab)
- GUI: Monatsreiter, Suche, Anhaken + Papierkorb, Kennzahlen-Leiste
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>