Im Journal wird nichts mehr von Hand geloescht

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
This commit is contained in:
TheMockTv 2026-09-03 22:43:23 +02:00
parent c230a27cff
commit 0218abaebe
3 changed files with 25 additions and 114 deletions

78
app.py
View file

@ -102,7 +102,6 @@ class App(tk.Tk):
self.bind("<F5>", lambda _e: self.einlesen())
self.bind("<Control-f>", lambda _e: self.suchfeld.focus_set())
self.bind("<Delete>", lambda _e: self.buchung_loeschen())
self.protocol("WM_DELETE_WINDOW", self._beenden)
self.aktualisieren()
@ -137,7 +136,6 @@ class App(tk.Tk):
daten.add_command(label="Rechnungen einlesen (F5)", command=self.einlesen)
daten.add_command(label="Alle Rechnungen neu einlesen", command=lambda: self.einlesen(voll=True))
daten.add_separator()
daten.add_command(label="Markierte Buchung löschen (Entf)", command=self.buchung_loeschen)
daten.add_separator()
daten.add_command(label="Steuersatz ändern…", command=self.satz_aendern)
daten.add_command(label="Firmendaten des Rechnungstools wählen…",
@ -160,9 +158,11 @@ class App(tk.Tk):
ttk.Button(leiste, text="Rechnungen einlesen", command=self.einlesen).pack(side="left")
ttk.Button(leiste, text="PDF fürs Amt", command=self.bericht_monat).pack(side="left", padx=(6, 0))
self.papierkorb = ttk.Button(leiste, text="🗑 Löschen", state="disabled",
command=self.angehakte_loeschen)
self.papierkorb.pack(side="left", padx=(6, 0))
# Kein Papierkorb mehr: im Journal wird nichts von Hand geloescht. Eine
# Zeile aus einer PDF kaeme beim naechsten Einlesen ohnehin zurueck, eine
# Zeile aus dem Excel-Altbestand waere fuer immer weg - samt Uebernachtung
# im Amtsbericht (§ 146 Abs. 4 AO). Soll eine Buchung raus, wandert die PDF
# aus dem Rechnungsordner; den Rest macht der Scan von selbst.
ttk.Label(leiste, text="Suche:").pack(side="left", padx=(20, 4))
self.suchfeld = ttk.Entry(leiste, textvariable=self.suche, width=22)
@ -175,7 +175,7 @@ class App(tk.Tk):
self.blaetter.pack(fill="both", expand=True, padx=10, pady=(0, 6))
self.monate = {}
for m in range(1, 13):
tab = MonatsTab(self.blaetter, m, bei_haken=self.papierkorb_auffrischen)
tab = MonatsTab(self.blaetter, m)
self.blaetter.add(tab, text=MONATE[m - 1])
self.monate[m] = tab
self.blaetter.select(min(date.today().month, 12) - 1)
@ -262,7 +262,6 @@ class App(tk.Tk):
self.jahr_summe.setzen(summiere(sichtbar), sichtbar)
self.jahr_wahl.config(values=self._jahre())
self.papierkorb_auffrischen()
self.ordner_anzeige.config(
text=f"Rechnungen: {self.pdf_ordner}" if self.pdf_ordner
else "kein Rechnungs-Ordner gewählt (Datei → Rechnungs-Ordner wählen…)")
@ -588,71 +587,6 @@ class App(tk.Tk):
"Nicht eingelesen",
f"{len(fehler)} Datei(en) sind keine lesbare Rechnung:\n\n{namen}",
parent=self)
# Im Journal wird NICHTS von Hand geaendert - weder angelegt noch bearbeitet.
# Jede Zeile gehoert zu einer Rechnung aus dem Rechnungstool; wer hier Betrag
# oder Nummer verstellt, meldet dem Amt etwas anderes, als auf dem Beleg
# steht, und beim naechsten Einlesen kaeme die Aenderung ohnehin zurueck.
# Stimmt eine Rechnung nicht, wird sie im Rechnungstool storniert oder
# berichtigt. Loeschen bleibt moeglich (Entf / Papierkorb) - es entfernt nur
# die Zeile aus dem Zwischenspeicher, die PDF bleibt liegen.
def _markierte(self):
return self.monate[self._monat].markierte()
def buchung_loeschen(self):
b = self._markierte()
if not b:
return
if not messagebox.askyesno(
"Buchung löschen",
f"Rechnung {b.voll_nummer} ({b.nachname}) aus dem Journal löschen?\n\n"
"Die PDF-Datei bleibt erhalten – beim nächsten Einlesen "
"taucht die Buchung wieder auf.", parent=self):
return
self.journal.loeschen(b.id)
self.aktualisieren()
self.melde(f"Buchung {b.voll_nummer} gelöscht")
# ---- Anhaken + Papierkorb ----------------------------------------------
def _angehakte(self):
"""Alle angehakten Buchungen – über alle Monate hinweg."""
return [b for m in range(1, 13) for b in self.monate[m].angehakte()]
def papierkorb_auffrischen(self):
anzahl = len(self._angehakte())
self.papierkorb.config(
text=f"🗑 Löschen ({anzahl})" if anzahl else "🗑 Löschen",
state="normal" if anzahl else "disabled")
def angehakte_loeschen(self):
angehakt = self._angehakte()
if not angehakt:
return
aus_pdf = [b for b in angehakt if b.quelle == "pdf"]
namen = "\n".join(f"• {b.datum.strftime('%d.%m.%Y')} {b.voll_nummer} "
f"{b.nachname or 'ohne Namen'}" for b in angehakt[:15])
if len(angehakt) > 15:
namen += f"\n… und {len(angehakt) - 15} weitere"
hinweis = ""
if aus_pdf:
hinweis = (f"\n\n{len(aus_pdf)} davon stammen aus einer Rechnungs-PDF – die Dateien "
"bleiben liegen und tauchen beim nächsten Einlesen wieder auf.")
if not messagebox.askyesno(
"Angehakte Buchungen löschen",
f"{len(angehakt)} Buchung(en) aus dem Journal löschen?\n\n{namen}{hinweis}",
parent=self):
return
for b in angehakt:
self.journal.loeschen(b.id)
for m in range(1, 13):
self.monate[m].haken_loesen()
self.aktualisieren()
self.papierkorb_auffrischen()
self.melde(f"{len(angehakt)} Buchung(en) gelöscht")
def satz_aendern(self):
fenster = tk.Toplevel(self)
fenster.title("Steuersatz")