Amtsbericht: die Kette zeigt vorwaerts - Storno nennt die neue Rechnung

Sein Fund: "an der storno verweist du auf die alte rechnung, muss aber
lauten neu zu und neue rechnungs nummer. heisst kette ist so: rechnung
storniert weist auf die storno nummer, storno verweist auf neue rechnung.
wer soll denn sonst wissen wo er suchen muss."

Er hat recht: eine Zeile, die nur zurueckzeigt, laesst den Leser stehen.
Jetzt sagt jede Zeile, wo es WEITERGEHT:

  Rechnung   -> "storniert mit 2026-901"
  Storno     -> "neue Rechnung 2026-902"      (Fall A)
             -> "neu abgerechnet mit 2026-343" (Fall B, Doppelung)
             -> "Storno zu 2026-900"           (Fall C / alte Belege ohne Angabe)
  neue R.    -> "Neuausstellung"

Dafuer wandert die Folgenummer aus den PDF-Kenndaten bis ins Journal:
Buchung.folge_nummer + folge_art (neu | vorhanden | ""), gelesen aus
korrektur_nummer/ersatz_vorhanden/nur_storno, zwei neue DB-Spalten, alte
Journale bauen sich wie gehabt selbst um.

An seinen ECHTEN Belegen geprueft: Storno 2026-455 -> folge 2026-369
(vorhanden), 2026-456 -> 2026-343 (vorhanden). Die Angabe steht in den
Kenndaten schon drin, sie wurde bisher nur nicht gelesen.

Fenster und Blatt zeigen dieselben Worte. Erklaerungs-PDF um eine
Kettentabelle ergaenzt. Pruefkette gruen (storno_verrechnet inkl.
September-Blatt, doppelte_leistung, nur_storno).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
This commit is contained in:
TheMockTv 2026-09-04 02:19:49 +02:00
parent b4db3b3849
commit b2d933cb7c
7 changed files with 69 additions and 13 deletions

17
db.py
View file

@ -36,6 +36,8 @@ CREATE TABLE IF NOT EXISTS buchungen (
storno_zu TEXT NOT NULL DEFAULT '',
storno_datum TEXT NOT NULL DEFAULT '',
vorgang TEXT NOT NULL DEFAULT '',
folge_nummer TEXT NOT NULL DEFAULT '',
folge_art TEXT NOT NULL DEFAULT '',
pdf_pfad TEXT NOT NULL DEFAULT '',
pdf_mtime REAL NOT NULL DEFAULT 0,
pdf_groesse INTEGER NOT NULL DEFAULT 0
@ -127,7 +129,8 @@ class Journal:
"""
da = {z["name"] for z in self.con.execute("PRAGMA table_info('buchungen')")}
for name, vorgabe in (("art", "'rechnung'"), ("storno_zu", "''"),
("storno_datum", "''"), ("vorgang", "''")):
("storno_datum", "''"), ("vorgang", "''"),
("folge_nummer", "''"), ("folge_art", "''")):
if name not in da:
self.con.execute(
f"ALTER TABLE buchungen ADD COLUMN {name} TEXT NOT NULL DEFAULT {vorgabe}")
@ -180,6 +183,8 @@ class Journal:
storno_zu=(r["storno_zu"] if "storno_zu" in r.keys() else ""),
storno_datum=(r["storno_datum"] if "storno_datum" in r.keys() else ""),
vorgang=(r["vorgang"] if "vorgang" in r.keys() else ""),
folge_nummer=(r["folge_nummer"] if "folge_nummer" in r.keys() else ""),
folge_art=(r["folge_art"] if "folge_art" in r.keys() else ""),
)
def _pdf_bekannt(self, pfad: str) -> bool:
@ -204,8 +209,8 @@ class Journal:
"INSERT INTO buchungen "
" (jahr, rechnungsnummer, datum, nachname, naechte, gezahlt, satz, "
" quelle, pdf_pfad, pdf_mtime, pdf_groesse, art, storno_zu, "
" storno_datum, vorgang) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "
" storno_datum, vorgang, folge_nummer, folge_art) "
"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) "
"ON CONFLICT(pdf_pfad) WHERE pdf_pfad <> '' DO UPDATE SET "
" jahr=excluded.jahr, rechnungsnummer=excluded.rechnungsnummer, "
" datum=excluded.datum, nachname=excluded.nachname, naechte=excluded.naechte, "
@ -213,10 +218,12 @@ class Journal:
" pdf_pfad=excluded.pdf_pfad, pdf_mtime=excluded.pdf_mtime, "
" pdf_groesse=excluded.pdf_groesse, art=excluded.art, "
" storno_zu=excluded.storno_zu, storno_datum=excluded.storno_datum, "
" vorgang=excluded.vorgang",
" vorgang=excluded.vorgang, folge_nummer=excluded.folge_nummer, "
" folge_art=excluded.folge_art",
(b.jahr, b.rechnungsnummer, b.datum.isoformat(), b.nachname, int(b.naechte or 0),
float(b.gezahlt or 0), float(b.satz or 0), b.quelle, b.pdf_pfad, mtime, groesse,
b.art or "rechnung", b.storno_zu or "", b.storno_datum or "", b.vorgang or ""))
b.art or "rechnung", b.storno_zu or "", b.storno_datum or "", b.vorgang or "",
b.folge_nummer or "", b.folge_art or ""))
self.con.commit()
return cur.lastrowid