Storno wird wieder VERRECHNET statt weggelassen - seine Entscheidung
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
This commit is contained in:
parent
d9bff8f2ec
commit
13fe1d97f9
6 changed files with 102 additions and 128 deletions
BIN
Beherbergungssteuer.exe
Normal file
BIN
Beherbergungssteuer.exe
Normal file
Binary file not shown.
12
app.py
12
app.py
|
|
@ -52,7 +52,7 @@ import firma as firma_lib
|
|||
import bericht_pdf
|
||||
import ablage
|
||||
from modell import (MONATE, STANDARD_SATZ, summiere, eur, eur_kurz,
|
||||
aufgehobene, zaehlbar, doppelte_nummern)
|
||||
aufgehobene, doppelte_nummern)
|
||||
from gui_monat import MonatsTab, SummenLeiste, WARNUNG
|
||||
|
||||
# Als EXE liegt alles in einem eigenen Datenordner - siehe ablage.py.
|
||||
|
|
@ -261,10 +261,7 @@ class App(tk.Tk):
|
|||
else:
|
||||
self.jahr_titel.config(text=f"Jahr {jahr} – gesamt")
|
||||
|
||||
# Auch der Monats-Durchschnitt zaehlt nur, was zaehlt: ein Monat, in dem
|
||||
# nur ein Storno steht, ist kein Monat mit Umsatz.
|
||||
self.jahr_summe.setzen(summiere(sichtbar, self._aufgehoben),
|
||||
zaehlbar(sichtbar, self._aufgehoben))
|
||||
self.jahr_summe.setzen(summiere(sichtbar), sichtbar)
|
||||
self.jahr_wahl.config(values=self._jahre())
|
||||
self.ordner_anzeige.config(
|
||||
text=f"Rechnungen: {self.pdf_ordner}" if self.pdf_ordner
|
||||
|
|
@ -702,10 +699,7 @@ class App(tk.Tk):
|
|||
return
|
||||
if not pfad:
|
||||
return
|
||||
# Ueber das ganze Jahr bestimmen, was aufgehoben ist: der Storno kann in
|
||||
# einem anderen Monat stehen als die Rechnung, die er aufhebt.
|
||||
jahr_alle = self.journal.buchungen(jahr=jahr)
|
||||
s = summiere([b for b in jahr_alle if b.monat == monat], aufgehobene(jahr_alle))
|
||||
s = summiere(self.journal.buchungen(jahr=jahr, monat=monat))
|
||||
self.melde(f"Bericht geschrieben: {pfad}")
|
||||
if messagebox.askyesno(
|
||||
"Bericht fertig",
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ from reportlab.lib.styles import ParagraphStyle
|
|||
from reportlab.pdfbase.pdfmetrics import stringWidth
|
||||
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer
|
||||
|
||||
from modell import MONATE, summiere, zaehlbar, aufgehobene, eur, eur_kurz
|
||||
from modell import MONATE, summiere, eur, eur_kurz
|
||||
|
||||
log = logging.getLogger("bst.bericht")
|
||||
|
||||
|
|
@ -200,14 +200,12 @@ def _ort(firma):
|
|||
# ------------------------------------------------------------- Monat --------
|
||||
def render_monat(pfad, firma, jahr: int, monat: int, buchungen):
|
||||
st = _styles()
|
||||
# Was ein Storno aufgehoben hat, gehoert nicht in die Meldung ans Amt - die
|
||||
# Rechnung gibt es nicht mehr. Bestimmt wird das ueber ALLE uebergebenen
|
||||
# Buchungen (das ganze Jahr), weil der Storno in einem anderen Monat liegen
|
||||
# kann als seine Rechnung.
|
||||
weg = aufgehobene(buchungen)
|
||||
liste = sorted(zaehlbar([b for b in buchungen if b.jahr == jahr and b.monat == monat], weg),
|
||||
# Storno und aufgehobene Rechnung stehen BEIDE im Bericht, jede in ihrem
|
||||
# Monat und mit ihrem Vorzeichen - so ist die Meldung aus sich heraus
|
||||
# nachvollziehbar (Entscheidung des Auftraggebers, siehe modell.summiere).
|
||||
liste = sorted([b for b in buchungen if b.jahr == jahr and b.monat == monat],
|
||||
key=lambda b: (b.datum, b.rechnungsnummer))
|
||||
s = summiere(liste, weg)
|
||||
s = summiere(liste)
|
||||
saetze = {b.satz for b in liste}
|
||||
satz_text = f" ({eur_kurz(list(saetze)[0]).replace(',00','')} %)" if len(saetze) == 1 else ""
|
||||
|
||||
|
|
@ -271,9 +269,8 @@ def render_monat(pfad, firma, jahr: int, monat: int, buchungen):
|
|||
# -------------------------------------------------------------- Jahr --------
|
||||
def render_jahr(pfad, firma, jahr: int, buchungen):
|
||||
st = _styles()
|
||||
weg = aufgehobene(buchungen)
|
||||
liste = zaehlbar([b for b in buchungen if b.jahr == jahr], weg)
|
||||
gesamt = summiere(liste, weg)
|
||||
liste = [b for b in buchungen if b.jahr == jahr]
|
||||
gesamt = summiere(liste)
|
||||
|
||||
story = []
|
||||
_titel(story, st, firma, "Beherbergungssteuer – Jahresübersicht", f"Zeitraum: Jahr {jahr}")
|
||||
|
|
@ -281,7 +278,7 @@ def render_jahr(pfad, firma, jahr: int, buchungen):
|
|||
kopf = ["Monat", "Rechnungen", "Übernachtungen", "Entgelt", "Steuer"]
|
||||
daten = [[Paragraph(k, st["th_l"] if i == 0 else st["th"]) for i, k in enumerate(kopf)]]
|
||||
for m in range(1, 13):
|
||||
s = summiere([b for b in liste if b.monat == m], weg)
|
||||
s = summiere([b for b in liste if b.monat == m])
|
||||
daten.append([
|
||||
Paragraph(MONATE[m - 1], st["zelle"]),
|
||||
Paragraph(str(s.buchungen), st["zelle_c"]),
|
||||
|
|
|
|||
|
|
@ -170,6 +170,6 @@ class MonatsTab(ttk.Frame):
|
|||
QUELLE_TEXT.get(b.quelle, b.quelle),
|
||||
))
|
||||
|
||||
# Das Set der aufgehobenen Rechnungen kommt aus dem ganzen JAHR (app.py) -
|
||||
# Storno und Rechnung koennen in verschiedenen Monaten liegen.
|
||||
self.summen.setzen(summiere(self._buchungen, aufgehoben))
|
||||
# Verrechnet, nicht weggelassen: der Storno steht mit seinem Minus in
|
||||
# SEINEM Monat, die aufgehobene Rechnung mit ihrem Plus in ihrem.
|
||||
self.summen.setzen(summiere(self._buchungen))
|
||||
|
|
|
|||
60
modell.py
60
modell.py
|
|
@ -135,33 +135,6 @@ def doppelte_nummern(buchungen) -> dict:
|
|||
for nr, liste in sorted(nach_nummer.items()) if len(liste) > 1}
|
||||
|
||||
|
||||
def zaehlbar(buchungen, aufgehoben=None) -> list:
|
||||
"""Die Zeilen, die in einer Summe ueberhaupt stehen duerfen.
|
||||
|
||||
Ein Storno und die von ihm aufgehobene Rechnung zaehlen NICHT mit. Ansage
|
||||
des Auftraggebers (04.09.2026): *"wenn es als storno getagt ist darf der
|
||||
rechner das nicht mehr rechnen, weil es minus ist - die rechnung gibt es
|
||||
nicht mehr."*
|
||||
|
||||
Vorher standen beide Zeilen mit Plus- und Minusbetrag 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 - und
|
||||
lagen Rechnung und Storno in verschiedenen Monaten, stand in jedem Monat die
|
||||
Haelfte der Verrechnung alleine da.
|
||||
|
||||
⚠️ `aufgehoben` muss ueber ALLE Buchungen des Jahres bestimmt sein, nicht
|
||||
ueber den Monat: der Storno kann in einem anderen Monat liegen als seine
|
||||
Rechnung. Wer nur eine Monatsliste hat, holt sich das Set vorher mit
|
||||
`aufgehobene(alle_buchungen_des_jahres)` und reicht es durch.
|
||||
|
||||
Geloescht wird nichts - die Zeilen bleiben im Journal und im Fenster
|
||||
sichtbar, gekennzeichnet ueber die Spalte "Art".
|
||||
"""
|
||||
if aufgehoben is None:
|
||||
aufgehoben = aufgehobene(buchungen)
|
||||
return [b for b in buchungen if not b.storno_zu and b.id not in aufgehoben]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Summe:
|
||||
"""Aufsummierte Kennzahlen einer Menge von Buchungen (Monat oder Jahr)."""
|
||||
|
|
@ -172,11 +145,36 @@ class Summe:
|
|||
gesamt: float = field(default=0.0) # gezahlt + steuer (wie I2 in der Vorlage)
|
||||
|
||||
|
||||
def summiere(buchungen, aufgehoben=None) -> Summe:
|
||||
"""Kennzahlen einer Menge von Buchungen - ohne Storno und ohne aufgehobene
|
||||
Rechnung (siehe `zaehlbar`)."""
|
||||
def summiere(buchungen) -> Summe:
|
||||
"""Kennzahlen einer Menge von Buchungen - ALLE Zeilen, mit ihrem Vorzeichen.
|
||||
|
||||
⭐ Ein Storno wird VERRECHNET, nicht weggelassen: die aufgehobene Rechnung
|
||||
bleibt mit ihrem Plus im Monat der Rechnung stehen, der Storno steht mit
|
||||
seinem Minus im Monat des Storno-Belegs. Uebers Jahr hebt sich das auf.
|
||||
|
||||
Das ist eine Entscheidung des Auftraggebers vom 04.09.2026, nachdem beides
|
||||
durchgerechnet und die Satzung nachgelesen war (04.09. war es zwischenzeitlich
|
||||
andersherum gebaut). Sein Wort:
|
||||
|
||||
"ich wuerde das wie beim alten lassen, nicht das er der Stadt zu wenig
|
||||
gibt"
|
||||
|
||||
Der Unterschied zwischen beiden Wegen ist NUR der Monat, nie das Jahr:
|
||||
|
||||
verrechnet (so wie hier): August meldet die Doppelung mit,
|
||||
September zieht sie ab
|
||||
weggelassen (verworfen): August meldet sie gar nicht erst
|
||||
|
||||
⚠️ Streng nach § 7 Abs. 5 der Beherbergungssteuersatzung Markkleeberg wird
|
||||
die im Kalendermonat *vereinnahmte* Steuer angemeldet - fuer eine doppelt
|
||||
geschriebene, nie kassierte Rechnung waere das der Monat der Rechnung.
|
||||
Verrechnen meldet im ersten Monat also eher zu VIEL und im zweiten zu wenig.
|
||||
Genau in dieser Richtung ist es gewollt: zu viel zuerst ist beim Amt nie ein
|
||||
Problem, zu wenig schon. Wer das umbaut, aendert eine bewusste Entscheidung -
|
||||
bitte vorher fragen.
|
||||
"""
|
||||
s = Summe()
|
||||
for b in zaehlbar(buchungen, aufgehoben):
|
||||
for b in buchungen:
|
||||
s.buchungen += 1
|
||||
s.naechte += int(b.naechte or 0)
|
||||
s.gezahlt += float(b.gezahlt or 0)
|
||||
|
|
|
|||
|
|
@ -1,27 +1,25 @@
|
|||
"""Pruefstand: ein Storno wird NICHT mehr mitgerechnet.
|
||||
"""Pruefstand: ein Storno wird VERRECHNET, nicht weggelassen.
|
||||
|
||||
Ansage des Auftraggebers (04.09.2026):
|
||||
"wenn es als storno getagt ist darf der rechner das nicht mehr rechnen,
|
||||
weil es minus ist - die rechnung gibt es nicht mehr."
|
||||
Entscheidung des Auftraggebers vom 04.09.2026, nachdem beide Wege
|
||||
durchgerechnet und die Satzung nachgelesen waren:
|
||||
|
||||
Vorher hoben sich Rechnung (+) und Storno (-) in der Summe gegenseitig auf.
|
||||
Naechte und Steuer kamen dabei richtig heraus, aber:
|
||||
* die Zahl "Rechnungen" war je Stornofall um ZWEI zu hoch, und
|
||||
* lag der Storno in einem anderen MONAT als seine Rechnung, stand in jedem
|
||||
der beiden Monate die Haelfte der Verrechnung allein da (August meldete
|
||||
eine Uebernachtung zu viel, September eine zu wenig).
|
||||
"ich wuerde das wie beim alten lassen, nicht das er der Stadt zu wenig
|
||||
gibt, auch wenn er das so der Steuerberaterin gibt"
|
||||
|
||||
Der zweite Fall ist der, den echte Daten nicht hergeben, solange alles im
|
||||
selben Monat passiert - deshalb steht er hier.
|
||||
Heisst: die aufgehobene Rechnung bleibt mit ihrem PLUS im Monat der Rechnung
|
||||
stehen, der Storno steht mit seinem MINUS im Monat des Storno-Belegs. Uebers
|
||||
Jahr hebt sich das auf. Der andere Weg (beide Zeilen gar nicht zaehlen) war
|
||||
zwischenzeitlich gebaut und ist bewusst wieder raus - siehe modell.summiere.
|
||||
|
||||
Gerechnet wird auf einer ECHTEN SQLite (Ansage: "musst in der sqlite fake
|
||||
rechnungen anlegen"), nicht auf zusammengesteckten Objekten: nur so ist belegt,
|
||||
dass die Storno-Spalten (art, storno_zu, storno_datum) den Weg durch die
|
||||
Datenbank ueberstehen und dass die ids stimmen, an denen der Bezug haengt.
|
||||
Das echte Journal wird nicht angefasst - jeder Lauf legt eine eigene Datei
|
||||
in %TEMP% an.
|
||||
⚠️ Dieser Pruefstand haelt genau das fest, damit es niemand (auch ich nicht)
|
||||
"repariert": in einem Monat sieht eine verrechnete Doppelung nach einem Fehler
|
||||
aus. Sie ist keiner, sie ist gewollt.
|
||||
|
||||
Aufruf: python -u pruef_storno_rechnet_nicht.py
|
||||
Gerechnet wird auf einer ECHTEN SQLite ("musst in der sqlite fake rechnungen
|
||||
anlegen"), nicht auf zusammengesteckten Objekten. Das echte Journal wird nicht
|
||||
angefasst - jeder Lauf legt eine eigene Datei in %TEMP% an.
|
||||
|
||||
Aufruf: python -u pruef_storno_verrechnet.py
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
|
|
@ -92,7 +90,6 @@ fenster.jahr.set(JAHR)
|
|||
fenster.aktualisieren()
|
||||
fenster.update_idletasks()
|
||||
|
||||
# Ab hier wird NUR noch gelesen, was wirklich in der Datenbank steht.
|
||||
alle = fenster.journal.buchungen(jahr=JAHR)
|
||||
pruefe(len(alle) == 6, f"sechs Fake-Rechnungen stehen in der SQLite ({len(alle)})")
|
||||
stornos = [b for b in alle if b.storno_zu]
|
||||
|
|
@ -100,69 +97,60 @@ pruefe(len(stornos) == 2 and all(b.art == "storno" for b in stornos),
|
|||
"die Storno-Spalten haben den Weg durch die DB ueberstanden "
|
||||
f"({[(b.voll_nummer, b.art, b.storno_zu) for b in stornos]})")
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
print("--- Fall 1: Storno im selben Monat wie seine Rechnung ---")
|
||||
fall_a = [b for b in alle if b.nachname == "Muster"]
|
||||
s = summiere(fall_a)
|
||||
pruefe(s.naechte == 3, f"3 Uebernachtungen: 4 - 4 + 3 (ist {s.naechte})")
|
||||
pruefe(abs(s.gezahlt - 39.0) < 0.005, f"39,00 Euro: 52 - 52 + 39 (ist {s.gezahlt})")
|
||||
pruefe(abs(s.steuer - 1.95) < 0.005, f"1,95 Euro Steuer (ist {s.steuer})")
|
||||
pruefe(s.buchungen == 3,
|
||||
f"gezaehlt werden alle drei Belege - Rechnung, Storno, Neuausstellung "
|
||||
f"(ist {s.buchungen})")
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
print("--- Fall 2: Rechnung im August, Storno erst im September ---")
|
||||
aug = summiere([b for b in alle if b.monat == 8])
|
||||
sep = summiere([b for b in alle if b.monat == 9])
|
||||
pruefe(aug.naechte == 9 and abs(aug.gezahlt - 117.0) < 0.005,
|
||||
f"der August meldet die Doppelung MIT: 9 Naechte, 117,00 Euro "
|
||||
f"(ist {aug.naechte}, {aug.gezahlt})")
|
||||
pruefe(sep.naechte == -4 and abs(sep.gezahlt + 52.0) < 0.005,
|
||||
f"der September zieht sie ab: -4 Naechte, -52,00 Euro "
|
||||
f"(ist {sep.naechte}, {sep.gezahlt})")
|
||||
jahr = summiere(alle)
|
||||
pruefe(jahr.naechte == 5 and abs(jahr.gezahlt - 65.0) < 0.005,
|
||||
f"uebers JAHR hebt es sich auf: 5 Naechte, 65,00 Euro "
|
||||
f"(ist {jahr.naechte}, {jahr.gezahlt})")
|
||||
pruefe(abs(aug.steuer + sep.steuer - jahr.steuer) < 0.005,
|
||||
"und die Steuer der Monate ergibt die Steuer des Jahres")
|
||||
|
||||
# Die Zuordnung wird weiter gebraucht - fuer die Spalte "Art" und dafuer, dass
|
||||
# eine stornierte Rechnung nicht mehr als doppelte Nummer gemeldet wird.
|
||||
weg = aufgehobene(alle)
|
||||
pruefe({b.voll_nummer for b in alle if b.id in weg} == {"2026-900", "2026-910"},
|
||||
"aufgehoben sind genau die beiden stornierten Rechnungen "
|
||||
f"({sorted(b.voll_nummer for b in alle if b.id in weg)})")
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
print("--- Fall 1: Storno im selben Monat ---")
|
||||
fall_a = [b for b in alle if b.nachname == "Muster"]
|
||||
s = summiere(fall_a, weg)
|
||||
pruefe(s.buchungen == 1, f"gezaehlt wird EINE Rechnung, nicht drei (ist {s.buchungen})")
|
||||
pruefe(s.naechte == 3, f"3 Uebernachtungen (ist {s.naechte})")
|
||||
pruefe(abs(s.gezahlt - 39.0) < 0.005, f"39,00 Euro Entgelt (ist {s.gezahlt})")
|
||||
pruefe(abs(s.steuer - 1.95) < 0.005, f"1,95 Euro Steuer (ist {s.steuer})")
|
||||
pruefe(len(fall_a) == 3, "geloescht wird nichts - alle drei Zeilen bleiben in der DB")
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
print("--- Fall 2: Rechnung im August, Storno im September ---")
|
||||
aug = summiere([b for b in alle if b.monat == 8], weg)
|
||||
sep = summiere([b for b in alle if b.monat == 9], weg)
|
||||
pruefe(aug.buchungen == 2 and aug.naechte == 5,
|
||||
"August: 2 Rechnungen (Neuausstellung + Sauber), 5 Naechte "
|
||||
f"(ist {aug.buchungen}, {aug.naechte})")
|
||||
pruefe(sep.buchungen == 0 and sep.naechte == 0,
|
||||
"September meldet nichts - der Storno ist keine Buchung "
|
||||
f"(ist {sep.buchungen}, {sep.naechte})")
|
||||
pruefe(abs(aug.steuer - 3.25) < 0.005 and sep.steuer == 0,
|
||||
f"und die Steuer steht im richtigen Monat ({aug.steuer} / {sep.steuer})")
|
||||
|
||||
# Gegenprobe: ein Storno, der auf eine fremde Nummer zeigt, hebt nichts auf.
|
||||
fenster.journal.speichern(
|
||||
Buchung(date(JAHR, 9, 3), "912", JAHR, "Fremd", -3, -39.0, quelle="manuell",
|
||||
art="storno", storno_zu="2026-999", storno_datum="01.01.2026"))
|
||||
mit_fremd = fenster.journal.buchungen(jahr=JAHR)
|
||||
weg2 = aufgehobene(mit_fremd)
|
||||
pruefe({b.voll_nummer for b in mit_fremd if b.id in weg2} == {"2026-900", "2026-910"},
|
||||
"ein Storno hebt nur SEINE Rechnung auf, nicht irgendeine")
|
||||
pruefe(summiere([b for b in mit_fremd if b.monat == 9], weg2).buchungen == 0,
|
||||
"und ein Storno ins Leere zaehlt trotzdem nicht mit")
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
print("--- Fall 3: Amtsbericht aus der Datenbank ---")
|
||||
pfad = os.path.join(tmp, "August.pdf")
|
||||
bericht_pdf.render_monat(pfad, firma_lib.lade(), JAHR, 8, mit_fremd)
|
||||
bericht_pdf.render_monat(pfad, firma_lib.lade(), JAHR, 8, alle)
|
||||
text = (PdfReader(pfad).pages[0].extract_text() or "").replace("\n", " ")
|
||||
pruefe("2026-900" in text and "2026-901" in text,
|
||||
"Rechnung UND Storno stehen im Bericht - die Meldung erklaert sich selbst")
|
||||
pruefe("-52,00" in text, "der Storno steht mit seinem Minusbetrag drin")
|
||||
pruefe("117,00" in text, f"und die Monatssumme ist 117,00 Euro")
|
||||
|
||||
pruefe("2026-900" not in text, "die aufgehobene Rechnung steht nicht im Bericht")
|
||||
pruefe("2026-901" not in text, "der Storno steht nicht im Bericht")
|
||||
pruefe("2026-910" not in text, "auch die im September stornierte Rechnung nicht")
|
||||
pruefe("2026-902" in text and "2026-905" in text, "die gueltigen Rechnungen stehen drin")
|
||||
pruefe("-52" not in text, "und keine Minusbetraege mehr auf dem Blatt fuers Amt")
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# ---------------------------------------------------------------------------
|
||||
print("--- Fall 4: das echte Fenster ---")
|
||||
fenster.aktualisieren()
|
||||
fenster.update_idletasks()
|
||||
namen = [sp[0] for sp in SPALTEN]
|
||||
i_nr, i_art = namen.index("nummer"), namen.index("art")
|
||||
baum = fenster.monate[8].baum
|
||||
reihen = [(baum.item(i, "values")[i_nr], baum.item(i, "values")[i_art],
|
||||
tuple(baum.item(i, "tags"))) for i in baum.get_children()]
|
||||
|
||||
# 2026-900 (storniert), -901 (Storno), -902 (Neuausstellung), -905, -910 (storniert)
|
||||
pruefe(len(reihen) == 5, f"der August zeigt weiter ALLE fuenf Zeilen ({len(reihen)})")
|
||||
pruefe(len(reihen) == 5, f"der August zeigt alle fuenf Zeilen ({len(reihen)})")
|
||||
pruefe(not any("aufgehoben" in t for _nr, _a, t in reihen),
|
||||
f"keine Zeile ist ausgegraut ({sorted({t for _n, _a, t in reihen})})")
|
||||
arten = {nr: art for nr, art, _t in reihen}
|
||||
|
|
@ -174,12 +162,9 @@ pruefe(arten.get("2026-902") == "Neuausstellung",
|
|||
f"und die neue als Neuausstellung ({arten.get('2026-902')!r})")
|
||||
|
||||
leiste = fenster.monate[8].summen.werte
|
||||
pruefe(leiste["rechnungen"].cget("text") == "2",
|
||||
f"die Monatsleiste zeigt 2 Rechnungen ({leiste['rechnungen'].cget('text')})")
|
||||
pruefe(leiste["naechte"].cget("text") == "5",
|
||||
f"und 5 Uebernachtungen ({leiste['naechte'].cget('text')})")
|
||||
pruefe(fenster.jahr_summe.werte["rechnungen"].cget("text") == "2",
|
||||
f"die Jahresleiste ebenso ({fenster.jahr_summe.werte['rechnungen'].cget('text')})")
|
||||
pruefe(leiste["naechte"].cget("text") == "9",
|
||||
f"die Monatsleiste zeigt die verrechneten 9 Naechte "
|
||||
f"({leiste['naechte'].cget('text')})")
|
||||
|
||||
fenster.destroy()
|
||||
_wecker.cancel()
|
||||
Loading…
Add table
Add a link
Reference in a new issue