Amtsbericht: Spalte "Art" mit R/S/B und Legende unter der Tabelle
Sein Einwand: "du musst die markieren als rechnung und storno oder berichtigung, und das kannst einfach mit buchstaben machen: r fuer rechnung, s fuer storno, b fuer berichtigung. am footer kannst eine erklaerung fuer die buchstaben machen." Er hat recht - ohne die Marke muss man aus der Begruendung raten, was fuer ein Beleg die Zeile ueberhaupt ist. Mit dem Buchstaben liest sich die Kette von selbst: 2026-900 R storniert mit 2026-901 2026-901 S neue Rechnung 2026-902 2026-902 B Neuausstellung 2026-911 S abgerechnet mit 2026-905 (Doppelungsfall) Unter der Tabelle steht die Legende: "R = Rechnung, S = Stornorechnung, B = berichtigte Rechnung (Neuausstellung nach einem Storno)". Bewusst direkt unter die Tabelle und nicht in die Fusszeile - wer eine einzelne Zeile prueft, hat sie dann vor Augen und muss nicht blaettern. Dazu "neu abgerechnet mit" auf "abgerechnet mit" gekuerzt: mit dem S davor ist das "neu" ueberfluessig, und die Zeile bricht nicht mehr um. Spaltenbreiten neu verteilt (18/18/9/42/Rest/12/18/9/18 mm). Erklaerungs-PDF um die Art-Spalte ergaenzt. Pruefkette gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017bEsoFUk16DfnNA7MjY36H
This commit is contained in:
parent
b2d933cb7c
commit
379afbd9c1
5 changed files with 50 additions and 15 deletions
Binary file not shown.
|
|
@ -198,6 +198,23 @@ def _ort(firma):
|
|||
|
||||
|
||||
# ------------------------------------------------------------- Monat --------
|
||||
def _art_kuerzel(b) -> str:
|
||||
"""Ein Buchstabe je Beleg - seine Ansage vom 04.09.2026: *"du musst die
|
||||
markieren als rechnung und storno oder berichtigung, und das kannst einfach
|
||||
mit buchstaben machen"*. Ohne die Marke muss man aus der Begruendung raten,
|
||||
was fuer ein Beleg die Zeile ueberhaupt ist.
|
||||
|
||||
R = Rechnung
|
||||
S = Stornorechnung
|
||||
B = berichtigte Rechnung (die Neuausstellung nach einem Storno)
|
||||
"""
|
||||
if b.storno_zu or b.art == "storno":
|
||||
return "S"
|
||||
if b.art == "korrektur":
|
||||
return "B"
|
||||
return "R"
|
||||
|
||||
|
||||
def _art_text(b, weg) -> str:
|
||||
"""Was in der Rechnungsspalte unter der Nummer steht.
|
||||
|
||||
|
|
@ -211,7 +228,7 @@ def _art_text(b, weg) -> str:
|
|||
# Ein Storno, der nur zurueckzeigt, laesst den Leser stehen ("wer soll
|
||||
# denn sonst wissen, wo er suchen muss" - 04.09.2026).
|
||||
if b.folge_nummer and b.folge_art == "vorhanden":
|
||||
return f"neu abgerechnet mit {b.folge_nummer}"
|
||||
return f"abgerechnet mit {b.folge_nummer}"
|
||||
if b.folge_nummer:
|
||||
return f"neue Rechnung {b.folge_nummer}"
|
||||
if b.folge_art == "" and b.art == "storno" and not b.folge_nummer:
|
||||
|
|
@ -250,13 +267,15 @@ def render_monat(pfad, firma, jahr: int, monat: int, buchungen):
|
|||
|
||||
# Eigene Spalte "Grund" statt einer zweiten Zeile unter der Nummer - seine
|
||||
# Ansage vom 04.09.2026: "mach eine neue spalte mit grund oder so was".
|
||||
kopf = ["Datum", "Rechnung", "Begründung", "Name", "Nächte", "Entgelt", "Satz", "Steuer"]
|
||||
stile = ["th", "th", "th_l", "th_l", "th", "th", "th", "th"]
|
||||
kopf = ["Datum", "Rechnung", "Art", "Begründung", "Name",
|
||||
"Nächte", "Entgelt", "Satz", "Steuer"]
|
||||
stile = ["th", "th", "th", "th_l", "th_l", "th", "th", "th", "th"]
|
||||
daten = [[Paragraph(k, st[s_]) for k, s_ in zip(kopf, stile)]]
|
||||
for b in liste:
|
||||
daten.append([
|
||||
Paragraph(b.datum.strftime("%d.%m.%Y"), st["zelle_c"]),
|
||||
Paragraph(b.voll_nummer, st["zelle_c"]),
|
||||
Paragraph(f'<b>{_art_kuerzel(b)}</b>', st["zelle_c"]),
|
||||
Paragraph(_art_text(b, weg), st["zelle"]),
|
||||
Paragraph(b.nachname, st["zelle"]),
|
||||
Paragraph(str(b.naechte), st["zelle_c"]),
|
||||
|
|
@ -267,7 +286,7 @@ def render_monat(pfad, firma, jahr: int, monat: int, buchungen):
|
|||
if len(daten) == 1:
|
||||
daten.append([Paragraph("", st["zelle_c"]),
|
||||
Paragraph("<i>(keine Buchungen in diesem Monat)</i>", st["zelle"]),
|
||||
"", "", "", "", "", ""])
|
||||
"", "", "", "", "", "", ""])
|
||||
|
||||
# Namensspalte nur so breit wie der breiteste Name (Rest der Tabelle ist fest)
|
||||
breiteste = max([stringWidth(b.nachname, "Helvetica", 8.5) for b in liste]
|
||||
|
|
@ -278,11 +297,11 @@ def render_monat(pfad, firma, jahr: int, monat: int, buchungen):
|
|||
# raum ein, da kannst locker zeile begruendung setzen"*. Also enger gestellt
|
||||
# und der Begruendung so viel gegeben, dass "storniert mit 2026-901" in EINE
|
||||
# Zeile passt - in normaler Schriftgroesse, nicht kleingedruckt.
|
||||
name_w = min(max(breiteste + 6 * mm, 22 * mm), CONTENT_W - 142 * mm)
|
||||
name_w = min(max(breiteste + 6 * mm, 22 * mm), CONTENT_W - 144 * mm)
|
||||
|
||||
tabelle = Table(daten, repeatRows=1, hAlign="LEFT",
|
||||
colWidths=[19 * mm, 19 * mm, 44 * mm, name_w,
|
||||
12 * mm, 19 * mm, 10 * mm, 19 * mm])
|
||||
colWidths=[18 * mm, 18 * mm, 9 * mm, 42 * mm, name_w,
|
||||
12 * mm, 18 * mm, 9 * mm, 18 * mm])
|
||||
tabelle.setStyle(TableStyle([
|
||||
("BACKGROUND", (0, 0), (-1, 0), GREY_BG),
|
||||
("LINEBELOW", (0, 0), (-1, 0), 0.8, ACCENT),
|
||||
|
|
@ -294,6 +313,14 @@ def render_monat(pfad, firma, jahr: int, monat: int, buchungen):
|
|||
("RIGHTPADDING", (0, 0), (-1, -1), 3),
|
||||
]))
|
||||
story.append(tabelle)
|
||||
# Legende zu den Buchstaben - direkt unter der Tabelle, damit sie beim Lesen
|
||||
# da ist und nicht auf der naechsten Seite. Wer nur eine Zeile prueft, muss
|
||||
# nicht raten, was fuer ein Beleg sie ist.
|
||||
story.append(Spacer(1, 1.5 * mm))
|
||||
story.append(Paragraph(
|
||||
"<b>Art:</b> R = Rechnung · S = Stornorechnung · B = berichtigte Rechnung "
|
||||
"(Neuausstellung nach einem Storno). Die Spalte Begründung nennt den Beleg, "
|
||||
"bei dem es weitergeht.", st["klein"]))
|
||||
|
||||
_summenblock(story, st, s, satz_text)
|
||||
story.append(Spacer(1, 3 * mm))
|
||||
|
|
|
|||
|
|
@ -207,16 +207,20 @@ def bauen(pfad, cfg):
|
|||
"<b>Begründung</b>, und zwar als <b>Kette, die vorwärts zeigt</b> – jede Zeile sagt, wo es "
|
||||
"weitergeht:")
|
||||
s.append(tabelle([
|
||||
["Zeile im Bericht", "Begründung", "Bedeutung"],
|
||||
["die aufgehobene Rechnung", "storniert mit 2026-901",
|
||||
["Art", "Zeile im Bericht", "Begründung", "Bedeutung"],
|
||||
["<b>R</b>", "die aufgehobene Rechnung", "storniert mit 2026-901",
|
||||
"hier steht, welcher Beleg sie aufhebt"],
|
||||
["die Stornorechnung", "neue Rechnung 2026-902",
|
||||
["<b>S</b>", "die Stornorechnung", "neue Rechnung 2026-902",
|
||||
"hier steht, unter welcher Nummer die Leistung jetzt abgerechnet ist"],
|
||||
["die Stornorechnung im Doppelungsfall", "neu abgerechnet mit 2026-343",
|
||||
["<b>S</b>", "Stornorechnung im Doppelungsfall", "abgerechnet mit 2026-343",
|
||||
"die Leistung war bereits abgerechnet – das ist die Rechnung, die bleibt"],
|
||||
["die neue Rechnung", "Neuausstellung",
|
||||
["<b>B</b>", "die berichtigte Rechnung", "Neuausstellung",
|
||||
"sie ersetzt die aufgehobene"],
|
||||
], st, [45 * mm, 47 * mm, CONTENT_W - 92 * mm]))
|
||||
], st, [9 * mm, 40 * mm, 40 * mm, CONTENT_W - 89 * mm]))
|
||||
s.append(Spacer(1, 1 * mm))
|
||||
P("Die Spalte <b>Art</b> markiert jeden Beleg mit einem Buchstaben – <b>R</b> Rechnung, "
|
||||
"<b>S</b> Stornorechnung, <b>B</b> berichtigte Rechnung. Die Erklärung dazu steht auf jedem "
|
||||
"Blatt unter der Tabelle.", "klein")
|
||||
s.append(Spacer(1, 2 * mm))
|
||||
P("So findet man von jedem Beleg aus den nächsten, auch wenn Rechnung und Storno in "
|
||||
"verschiedenen Monaten liegen und gar nicht auf demselben Blatt stehen.")
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ class MonatsTab(ttk.Frame):
|
|||
if b.storno_zu:
|
||||
# Kette vorwaerts: Rechnung -> Storno -> die Rechnung, die gilt.
|
||||
if b.folge_nummer and b.folge_art == "vorhanden":
|
||||
art_text = f"neu abgerechnet mit {b.folge_nummer}"
|
||||
art_text = f"abgerechnet mit {b.folge_nummer}"
|
||||
elif b.folge_nummer:
|
||||
art_text = f"neue Rechnung {b.folge_nummer}"
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -157,9 +157,13 @@ pruefe("neue Rechnung 2026-902" in text,
|
|||
pfad_sep = os.path.join(tmp, "September.pdf")
|
||||
bericht_pdf.render_monat(pfad_sep, firma_lib.lade(), JAHR, 9, alle)
|
||||
text_sep = " ".join((PdfReader(pfad_sep).pages[0].extract_text() or "").split())
|
||||
pruefe("neu abgerechnet mit 2026-905" in text_sep,
|
||||
pruefe("abgerechnet mit 2026-905" in text_sep,
|
||||
"und beim Doppelungsfall zeigt er auf die Rechnung, die bleibt")
|
||||
pruefe("-52,00" in text_sep, "der September traegt weiter seinen Minusbetrag")
|
||||
# Die Buchstaben-Marke: ohne sie muss man aus der Begruendung raten, was fuer ein
|
||||
# Beleg die Zeile ist ("du musst die markieren als rechnung und storno").
|
||||
pruefe("R = Rechnung" in text and "S = Stornorechnung" in text,
|
||||
"unter der Tabelle steht die Erklaerung der Buchstaben")
|
||||
pruefe("Neuausstellung" in text, "die neue Rechnung ist als Neuausstellung beschriftet")
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue