Commit graph

9 commits

Author SHA1 Message Date
TheMockTv
2277a12e0f Zwei getrennte Knoepfe und app.py in Module aufgeteilt
Knoepfe: "Storno" und "Berichtigen" setzen den Weg schon beim Oeffnen fest,
das Popup fragt dann nur noch die Nummer. Vorher entschied ein zweiter Knopf
im Popup - der ist raus.

app.py war 1802 Zeilen, jetzt 672. Neu daneben:
  helfer.py        Zahlen, Datum, Namen, Pruefungen        (87)
  bestand.py       was im Rechnungsordner liegt, nur lesen (171)
  storno.py        den spiegelbildlichen Storno rechnen     (57)
  einzelinstanz.py nur ein Fenster zulassen                 (90)
  theme.py         Farben nach Windows hell/dunkel         (120)
  korrektur.py     Storno- und Berichtigungsweg            (306)
  einstellungen.py die Dialoge aus dem Menue               (358)

Die Oberflaeche bleibt eine Klasse - die Teile sind Mixins, damit kein
einziger self-Zugriff umgeschrieben werden musste. Kein Modul importiert
app.py zurueck, keine ungenutzten Importe mehr. Die Pruefstaende holen die
Funktionen jetzt aus dem Modul, dem sie gehoeren.

pruef_storno.py 100 gruen, pruef_nummern.py 7 gruen, Fenster nach der
Aufteilung gestartet und angesehen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
2026-09-02 19:41:00 +02:00
TheMockTv
d3962ec8d1 Berichtigen: zweiter Knopf im Storno-Popup, alles haengt an einem Flag
Fuer Rechnungen, bei denen nur die Kundenangaben falsch sind - falsche
Betraege bleiben der Storno-Weg.

- Kein eigener Dialog: das Storno-Popup hat jetzt zwei Knoepfe. "Nur
  berichtigen" laedt die Rechnung ins Formular, sperrt die Nummer und setzt
  ein Flag; "PDF erstellen" schreibt daraus das berichtigte Blatt.
- Die Rechnung behaelt Nummer, Datum und Betraege; dazu kommt "Berichtigt am".
  Der Zaehler bleibt stehen - das Blatt verbraucht keine Nummer.
- Ueberschrift "Berichtigte Rechnung", darunter die vollstaendige Rechnung,
  darunter der Bezug nach § 31 Abs. 5 UStDV und der Satz, dass es KEINE
  zusaetzliche Leistung und keine zweite Rechnung ist. Ohne den kann ein
  zweites Blatt mit ausgewiesener USt die Steuer nach § 14c UStG ein zweites
  Mal ausloesen.
- Kenndaten des Blattes tragen Nullen und "art": "berichtigung". Damit zaehlt
  ein Programm, das die Art nicht kennt, 0,00 € statt den Umsatz doppelt; der
  Steuerrechner ueberspringt es ganz (einnahmen.py).
- Dateiname "Berichtigte Rechnung_JJJJ-MM-TT_<Nummer>.pdf".

pruef_storno.py: 100 Pruefungen gruen, darunter der ganze Berichtigungsweg
inklusive Text auf dem Blatt und Gegenprobe mit dem Steuerrechner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
2026-09-02 19:32:24 +02:00
TheMockTv
abb462725f Altrechnungen: Namen aufteilen und Anschrift aus dem Rechnungstext holen
Die bisherigen Rechnungen tragen den ganzen Namen in der Vornamen-Zeile und
oft gar keine Anschrift. Beim Stornieren stand dann nur "Andres Schaefer" da
und niemand wusste, wer der Gast ist.

- name_aufteilen(): am Leerzeichen trennen, das letzte Wort ist der Nachname.
- adresse_aus_pdf(): der Adressblock steht im Fliesstext zwischen
  "Rechnung an:" und der Rechnungsnummer. Anrede wird an der Auswahlliste
  erkannt, PLZ/Ort an der 4- bis 5-stelligen Zahl am Zeilenanfang, die Zeile
  davor ist die Strasse - aber nur, wenn sie nicht die Namenszeile ist.
- kundendaten_ermitteln(): Kenndaten zuerst, Text als Rueckfall; benutzt vom
  Storno (der geht an denselben Empfaenger) und vom Formular.
- Der Hinweis nach dem Storno sagt jetzt, was aus dem Text gelesen wurde und
  was in der alten Rechnung schlicht nicht drinsteht.

Es wird nichts erfunden: fehlt die Anschrift in der alten PDF, bleiben die
Felder leer und die Pflichtpruefung greift.

pruef_storno.py: 80 Pruefungen gruen, darunter eine echte Altrechnung im
Muster "alles in der Vornamen-Zeile" - mit und ohne Anschrift.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
2026-09-02 19:20:05 +02:00
TheMockTv
0095305176 Kundenfelder: nicht nur "irgendwas", sondern brauchbar geprueft
Leerzeichen allein waren schon vorher raus, aber "x" oder "123" als Nachname
und "12345" ohne Ort gingen durch.

- Felder werden vor der Pruefung gesaeubert (Rand- und Mehrfachleerzeichen),
  damit geprueft wird, was nachher gedruckt wird.
- Vorname, Nachname/Firma, Strasse brauchen mindestens zwei Buchstaben.
- PLZ/Ort braucht mindestens vier Ziffern UND zwei Buchstaben - damit gehen
  auch 4-stellige Postleitzahlen (AT, NL) durch, aber nicht PLZ ohne Ort.
- Fehlende Hausnummer wird nur nachgefragt, nicht gesperrt: Postfach- und
  Feldweg-Anschriften gibt es wirklich, eine falsche Sperre waere schlimmer.

pruef_storno.py: 67 Pruefungen gruen, darunter Auslandsanschriften und kurze
Namen, die durchgehen MUESSEN.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
2026-09-02 19:14:40 +02:00
TheMockTv
d2fee38bfd Storno: Nummer eintippen statt Auswahlliste, Anrede als Liste, Pflichtfelder
- Storno-Dialog: die alte Nummer wird eingetippt, das Programm sucht sie im
  Ordner und zeigt sofort Datum, Name und den Betrag des Stornos. Kurze
  Schreibweise (2026-3) findet 2026-003.
- Zwei Funde beim Pruefen: Storno-PDFs heissen "Storno_..." und fielen sowohl
  aus der Ordnerliste als auch aus der Nummernpruefung heraus. Dadurch galt
  eine schon stornierte Rechnung als stornierbar und eine vom Storno belegte
  Nummer als frei - die haette ein zweites Mal vergeben werden koennen.
- Anrede ist eine Auswahlliste (tippbar fuer Sonderfaelle).
- Vorname, Nachname, Strasse und PLZ/Ort sind Pflicht; ohne sie wird keine
  PDF geschrieben (§ 14 Abs. 4 Nr. 1 UStG). Die alte "trotzdem erstellen?"-
  Frage ist raus.

Prueflauf: pruef_storno.py 46 Pruefungen gruen, pruef_nummern.py 7 gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
2026-09-02 19:11:37 +02:00
TheMockTv
790ac4c0f6 Storno statt Ueberschreiben: Rechnungskette 005 -> Storno -> Korrektur
Eine ausgestellte Rechnung darf nicht geaendert und nicht geloescht werden
(§ 146 Abs. 4 AO), und jede Nummer gibt es nur einmal (§ 14 Abs. 4 Nr. 4
UStG). Korrigiert wird deshalb ueber ein eigenes Dokument mit neuer Nummer,
das sich auf die alte bezieht (§ 31 Abs. 5 UStDV).

- Knopf "Rechnung stornieren": alte Nummer waehlen, Programm liest deren PDF
  und schreibt eine Stornorechnung mit eigener neuer Nummer, Betraege
  negativ, mit Bezug auf Nummer und Datum der alten Rechnung.
- Danach steht das Formular auf der naechsten Nummer, gefuellt aus der alten
  Rechnung; die Nummer ist gesperrt. "PDF erstellen" fragt noch einmal nach
  und legt bei Nein das Storno-PDF wieder weg - dann bleibt allein das
  Original stehen.
- Die alte Rechnung wird nie angefasst.
- Metadaten v3: art / storno_zu / ersetzt / storno_nummer, dazu Anschrift und
  Positionen, damit eine Rechnung wieder ins Formular geladen werden kann.
  Alle Felder aus v1/v2 bleiben unveraendert - daran haengt das Steuerjournal.
- Zaehler laeuft nur noch vorwaerts; eine vergebene Nummer wird nicht mehr
  ueberschrieben, sondern die naechste freie angeboten.
- Combobox im Storno-Dialog blieb leer: die StringVar hing nur an einer
  lokalen Variable und wurde weggeraeumt. Jetzt ohne textvariable.

Prueflauf (pruef_storno.py, 36 Pruefungen gruen): echte PDFs in einem
Wegwerf-Ordner, danach liest der Steuerrechner den Ordner - 001 + Storno +
Korrektur ergeben genau die berichtigte Rechnung, kein Beleg unsicher.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
2026-09-02 19:06:45 +02:00
TheMockTv
1564d769c9 Nur eine Instanz: zweiter Start holt das offene Fenster nach vorn
Zwei offene Fenster lesen beim Start denselben Zaehler aus der config und
schlagen darum dieselbe Rechnungsnummer vor - die Nummer wurde doppelt
vergeben.

- Windows-Mutex sperrt eine zweite Instanz ab.
- Die laufende Instanz legt ihre PID neben der config.json ab; die zweite
  sucht darueber das Fenster (nicht ueber den Titel - der haengt am
  Firmennamen aus der config) und holt es nach vorn.
- Popup nur noch als Rueckfall, wenn kein Fenster gefunden wird.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
2026-09-02 18:28:58 +02:00
TheMockTv
0c83f9d821 Vor- und Nachname getrennt + Kenndaten in die PDF-Metadaten
Bisher gab es nur ein Feld "Name / Firma". Stand in der Anrede etwas,
war die Anrede die erste Zeile des Adressblocks - das Steuerjournal hat
sie als Namen gelesen.

- Kundenblock hat jetzt "Vorname (optional)" und "Nachname / Firma".
  Auf der Rechnung stehen beide wie gewohnt in einer Zeile.
- Die Kenndaten der Rechnung (Nummer, Datum, Nachname, Naechte,
  Zwischensumme, Steuersatz und -betrag) stehen zusaetzlich als JSON in
  den PDF-Metadaten. Das Steuerjournal liest sie von dort und muss
  nichts mehr aus dem Fliesstext raten. Der Ausdruck aendert sich nicht.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 19:45:53 +02:00
TheMockTv
dc170a9d9c Rechnungstool Campinghof - Rechnungen als PDF statt Excel-Vorlage
Desktop-Programm (Python/Tkinter): Kundendaten + Leistungen eingeben,
druckfertige PDF-Rechnung im Briefkopf des Betriebs. Optionale
Beherbergungssteuer wird eigen ausgewiesen und bekommt ein zweites
Blatt fuers Amt.

Firmendaten, Preise und Steuersaetze stehen in der config.json neben
dem Programm (nicht im Repo) und werden im Menue "Einstellungen"
gepflegt. Im Code stehen nur Platzhalter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 19:18:38 +02:00