Statt einer Zustandsmaschine ("offener Storno" ueber den Neustart retten) traegt
das Storno jetzt einfach beide Nummern:
Storno zu Rechnung: 2026-002
Neue Rechnung: 2026-004
und im Text "2026-002 -> 2026-003 -> 2026-004". Damit ist die Kette aus dem
Beleg allein lesbar. Wird das Programm zwischendurch geschlossen, sagt der
Storno, unter welcher Nummer die berichtigte Rechnung gehoert; der Dialog
nennt sie ebenfalls, statt nur "bereits storniert" zu melden.
naechste_freie_nummer_nach() bestimmt die Folgenummer, damit sie nicht von der
Reihenfolge abhaengt, in der der Zaehler mitzieht.
Ausserdem: die Pruefstaende raeumen ihren Wegwerf-Ordner wieder weg, wenn sie
gruen sind. Ein Testlauf hatte 398 Ordner im Temp-Verzeichnis hinterlassen.
Bei Fehlern bleibt der Ordner stehen, damit man hineinsehen kann.
Weitere Funde des Code-Agenten behoben:
- "Kopie von Rechnung_...pdf" und klein geschriebene Dateinamen zaehlen jetzt
bei der Nummernvergabe mit (vorher galt die Nummer als frei).
- Strg+P feuerte auch aus einem offenen Dialog heraus (bind_all -> bind).
167 Pruefungen gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
97 lines
3.1 KiB
Python
97 lines
3.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""Pruefstand: geht jeder Dialog ueberhaupt auf?
|
|
|
|
Klingt banal, ist es nicht: beim Aufteilen von app.py in Module sind zwei
|
|
Dialoge stumm kaputtgegangen (fehlende Importe), und kein anderer Pruefstand
|
|
hat es gemerkt, weil keiner sie oeffnet. Dieser hier oeffnet ALLE.
|
|
|
|
Geprueft wird ausserdem, dass jeder Dialog auch wieder zugeht - ein modales
|
|
Fenster, das haengenbleibt, sperrt das Programm.
|
|
"""
|
|
import json
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
import tkinter as tk
|
|
|
|
QUELLE = r"C:\claude\rechnungstool"
|
|
sys.path.insert(0, QUELLE)
|
|
|
|
tmp = tempfile.mkdtemp(prefix="dialog_pruef_")
|
|
ordner = os.path.join(tmp, "rechnungen")
|
|
os.makedirs(ordner)
|
|
|
|
import config # noqa: E402
|
|
shutil.copy(os.path.join(QUELLE, "config.json"), os.path.join(tmp, "config.json"))
|
|
config.CONFIG_PATH = os.path.join(tmp, "config.json")
|
|
roh = json.load(open(config.CONFIG_PATH, encoding="utf-8"))
|
|
roh["output_dir"] = ordner
|
|
json.dump(roh, open(config.CONFIG_PATH, "w", encoding="utf-8"), ensure_ascii=False)
|
|
|
|
import app as A # noqa: E402
|
|
from tkinter import messagebox # noqa: E402
|
|
|
|
messagebox.showinfo = lambda *a, **k: None
|
|
messagebox.showwarning = lambda *a, **k: None
|
|
messagebox.showerror = lambda *a, **k: None
|
|
messagebox.askyesno = lambda *a, **k: False
|
|
|
|
fehler = 0
|
|
f = A.RechnungsApp()
|
|
f.update()
|
|
|
|
# Damit "Storno"/"Berichtigen" nicht an "nichts zu korrigieren" scheitern:
|
|
# eine echte Rechnung in den Wegwerf-Ordner legen.
|
|
f.k_vorname.set("Anna")
|
|
f.k_name.set("Beispiel")
|
|
f.k_strasse.set("Musterweg 1")
|
|
f.k_plzort.set("12345 Musterstadt")
|
|
f.anzahl_vars[sorted(f.anzahl_vars)[0]].set("2")
|
|
f.update()
|
|
f.pdf_erstellen()
|
|
|
|
DIALOGE = ["dlg_steuern", "dlg_katalog", "dlg_firma", "dlg_nummer",
|
|
"dlg_storno", "dlg_berichtigen"]
|
|
|
|
for name in DIALOGE:
|
|
offen_vorher = [w for w in f.winfo_children() if isinstance(w, tk.Toplevel)]
|
|
try:
|
|
getattr(f, name)()
|
|
f.update()
|
|
except Exception as e: # noqa: BLE001 - genau das wollen wir sehen
|
|
print(f"ABSTURZ | {name}: {type(e).__name__}: {e}")
|
|
fehler += 1
|
|
continue
|
|
neu = [w for w in f.winfo_children()
|
|
if isinstance(w, tk.Toplevel) and w not in offen_vorher]
|
|
if not neu:
|
|
print(f"FEHLER | {name}: kein Fenster aufgegangen")
|
|
fehler += 1
|
|
continue
|
|
titel = neu[-1].title()
|
|
for w in neu:
|
|
w.grab_release()
|
|
w.destroy()
|
|
f.update()
|
|
print(f" OK | {name} -> „{titel}“")
|
|
|
|
# Der Speicherort-Dialog oeffnet einen Systemdialog - nur die Vorstufe pruefen
|
|
try:
|
|
f._frage_speicherort_falls_noetig()
|
|
f.update()
|
|
print(" OK | _frage_speicherort_falls_noetig")
|
|
except Exception as e: # noqa: BLE001
|
|
print(f"ABSTURZ | _frage_speicherort_falls_noetig: {type(e).__name__}: {e}")
|
|
fehler += 1
|
|
|
|
f.destroy()
|
|
|
|
# Wegwerf-Ordner nur bei Fehlern behalten - sonst laeuft das Temp-Verzeichnis
|
|
# voll. Ein Pruefstand, der 400 Ordner hinterlaesst, ist selbst ein Problem.
|
|
if not fehler: # fehler ist hier ein Zaehler
|
|
import shutil as _sh
|
|
_sh.rmtree(tmp, ignore_errors=True)
|
|
print("---")
|
|
print("alles gruen" if not fehler else f"{fehler} Fehler")
|
|
sys.exit(1 if fehler else 0)
|