diff --git a/zeig_stornos.py b/zeig_stornos.py new file mode 100644 index 0000000..b2eaf58 --- /dev/null +++ b/zeig_stornos.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +"""Zeigt, was die Stornos in einem Journal bewirken. NUR LESEN. + + python zeig_stornos.py [Pfad zur journal.sqlite3] + +Ohne Pfad nimmt es den Datenordner, den sich das Programm gemerkt hat. + +Es wird ausschliesslich gelesen - keine Buchung angelegt, geaendert oder +geloescht, kein Scan des Rechnungsordners. Man kann es also bedenkenlos auf +das echte Journal loslassen. + +Ausgegeben wird je Monat: + ALT = wie frueher gerechnet wurde (Rechnung + und Storno - stehen beide + in der Summe und heben sich gegenseitig auf) + JETZT = Storno und die von ihm aufgehobene Rechnung zaehlen gar nicht mit + (Berichtigung im Monat der Rechnung) + +Der Unterschied wird nur dort sichtbar, wo Rechnung und Storno in +VERSCHIEDENEN Monaten liegen - genau der Fall, um den es geht. +""" +import os +import sys + +HIER = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, HIER) + +from modell import MONATE, aufgehobene, eur, summiere # noqa: E402 + + +def journal_pfad(argv): + if len(argv) > 1: + return argv[1] + merker = os.path.join(os.environ.get("LOCALAPPDATA", ""), + "Beherbergungssteuer", "datenordner.txt") + if os.path.exists(merker): + ordner = open(merker, encoding="utf-8").read().strip() + if ordner: + return os.path.join(ordner, "journal.sqlite3") + return os.path.join(HIER, "journal.sqlite3") + + +def main(): + pfad = journal_pfad(sys.argv) + if not os.path.exists(pfad): + print(f"Kein Journal unter {pfad}") + print("Pfad angeben: python zeig_stornos.py <...\\journal.sqlite3>") + return 2 + print(f"Journal: {pfad} (wird nur gelesen)\n") + + from db import Journal + j = Journal(pfad) + try: + for jahr in sorted(j.jahre() or []): + alle = j.buchungen(jahr=jahr) + weg = aufgehobene(alle) + stornos = [b for b in alle if b.storno_zu] + print(f"=== {jahr} === {len(alle)} Buchungen, " + f"{len(stornos)} Storno-Beleg(e), " + f"{len(weg)} aufgehobene Rechnung(en)") + + print(f"{'Monat':12s} {'ALT (verrechnet)':>18s} {'JETZT':>14s} " + f"{'Unterschied':>14s} Naechte alt/jetzt") + for m in range(1, 13): + des_monats = [b for b in alle if b.monat == m] + if not des_monats: + continue + alt_g = round(sum(float(b.gezahlt or 0) for b in des_monats), 2) + alt_n = sum(int(b.naechte or 0) for b in des_monats) + s = summiere(des_monats, weg) + marke = " <<<" if abs(alt_g - s.gezahlt) > 0.004 else "" + print(f"{MONATE[m-1]:12s} {eur(alt_g):>18s} {eur(s.gezahlt):>14s} " + f"{eur(s.gezahlt - alt_g):>14s} {alt_n}/{s.naechte}{marke}") + + jahr_alt = round(sum(float(b.gezahlt or 0) for b in alle), 2) + jahr_neu = summiere(alle, weg) + print(f"{'JAHR':12s} {eur(jahr_alt):>18s} {eur(jahr_neu.gezahlt):>14s} " + f"{eur(jahr_neu.gezahlt - jahr_alt):>14s} " + f"{sum(int(b.naechte or 0) for b in alle)}/{jahr_neu.naechte}") + + if not stornos: + print("\n(keine Stornos in diesem Jahr)\n") + continue + + print("\nDie Storno-Paare im Einzelnen:") + for s_ in sorted(stornos, key=lambda b: (b.datum, b.rechnungsnummer)): + ziel = [b for b in alle if b.id in weg and b.voll_nummer == s_.storno_zu] + z = ziel[0] if ziel else None + print(f" Storno {s_.voll_nummer} vom {s_.datum:%d.%m.%Y} " + f"({MONATE[s_.monat-1]}) {eur(s_.gezahlt)}, {s_.naechte} Naechte") + if z: + gleich = "gleicher Monat" if z.monat == s_.monat else \ + f"ANDERER Monat: Rechnung in {MONATE[z.monat-1]}" + print(f" hebt auf: {z.voll_nummer} vom {z.datum:%d.%m.%Y}, " + f"{z.nachname}, {eur(z.gezahlt)}, {z.naechte} Naechte [{gleich}]") + else: + print(f" ACHTUNG: zu {s_.storno_zu} liegt KEINE Rechnung im Journal - " + f"der Storno zieht also einfach ab, ohne dass etwas aufgehoben wird") + print() + finally: + j.schliessen() + return 0 + + +if __name__ == "__main__": + sys.exit(main())