Finanzmanager/docs/auswertungen.md
fds2610-bot ba66ce7bdc Fix n.n.: Buchungsbericht – Bargeld-Abgleich, Gruppen-/Gesamtzeile, Filterbereich, Cockpit-Tooltip
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 11:18:04 +02:00

10 KiB
Raw Blame History

Auswertungen

Der Bereich Auswertungen baut die Berichte des FinanzManagers nach: fünf Berichtstypen, eine Filterleiste, gespeicherte Berichte in Gruppen, Drilldown in die Buchungen und CSV-Export.

Ein Bericht wird nie gerechnet gespeichert, sondern immer nur seine Frage. Die Zahlen entstehen bei jedem Aufruf neu aus den Buchungen. Ein Bericht mit der Zeitraumvorgabe „Letzter Monat“ zeigt im August den Juli und nicht für immer den Monat seiner Entstehung.

Was gezählt wird

Grundlage sind die Bewegungen: nicht gesplittete Buchungen mit ihrem Betrag, gesplittete über ihre Splitzeilen. Sonst zählte eine Splitbuchung doppelt oder gar nicht.

Umbuchungen bleiben außen vor. Sie verschieben Vermögen zwischen eigenen Konten und sind weder Einnahme noch Ausgabe – dieselbe Regel wie im Budgetplaner. Allein der Buchungsbericht kann sie über den Schalter Umbuchungen mitzählen mitführen; dann weicht seine Summe naturgemäß vom Summenbericht ab.

Nicht kategorisierte Buchungen verschwinden nicht. Sie stehen als eigene Zeile Nicht kategorisiert am Ende ihres Abschnitts. Geld, das keiner Kategorie zugeordnet ist, fiele sonst lautlos aus der Summe.

Ob eine Bewegung zu den Einnahmen oder den Ausgaben zählt, entscheidet die Art ihrer Kategorie, nicht das Vorzeichen: Eine Erstattung ist eine negative Ausgabe und gehört unter die Ausgaben. Nur wo keine Kategorie steht, bleibt das Vorzeichen als einziger Anhaltspunkt.

Aggregiert wird in PHP, nicht in SQL. Die Datenbank liefert die Bewegungen des Zeitraums, das Einsortieren in Zeilen und Spalten passiert in Auswertung. Bei Zehntausenden Buchungen ist das Millisekundensache, und Baumsummen über Kategorien, Vorzeichenregeln und Spaltenraster wären in SQL erheblich schwerer nachzulesen.

Vorzeichen

Intern gilt durchgehend die Buchhaltung: Ausgaben negativ. In der Anzeige dreht der Ausgabenabschnitt sein Vorzeichen – dort steht 636,39 statt −636,39, wie im FinanzManager; die Überschrift sagt ja bereits, worum es geht. Die Schlusszeile Gesamt Einnahmen − Ausgaben rechnet wieder mit den echten Werten.

Zwei Ausnahmen führen das Vorzeichen mit, weil sie keine Abschnitte haben: der Buchungsbericht (eine Buchungsliste, kein Summenbericht) und der Budgetbericht (Vorzeichen wie im Budgetplaner). Der Drilldown zeigt ebenfalls die echten Vorzeichen.

Die fünf Berichtstypen

Typ Zeilen Spalten
Summenbericht Zeilen-Summe, nach Einnahmen und Ausgaben getrennt Zeitraum, je nach Spalten-Aufteilung
Buchungsbericht Einzelbuchungen, gruppiert nach Zeilen-Summe; bei eingerichtetem Bargeld-Tool mit Spalte „Bar“ und Filter „Bargeld-Tool“ feste Buchungsspalten
Vergleichsbericht wie Summenbericht Zeitraum, Vorjahreszeitraum, Differenz, Veränderung
Kontostandsbericht Konten Salden zu den Enden der Spaltenzeiträume
Budgetbericht Kategoriebaum Budget, Ist, Saldo

Summenbericht

Bei der Zeilen-Summe Kategorie entsteht der eingerückte Baum: Jede Kategorie zeigt ihre eigenen Werte, Kategorien mit Nachfahren bekommen dahinter eine Zeile Gesamt <Name> mit der Summe des Astes. Eine Elternkategorie ohne eigene Buchungen steht deshalb als bloße Kopfzeile da – genau wie im Original.

Der Schalter mit Einrückung schaltet auf eine flache Liste mit vollem Kategoriepfad um. Dort zählt jede Kategorie nur sich selbst, und es gibt keine Astsummen; sonst stünde eine Summe wie ein gleichrangiger Posten neben ihren eigenen Bestandteilen.

Bei Klasse, Konto und Empfänger ist die Liste flach und alphabetisch. Die Aufteilung in Einnahmen und Ausgaben bleibt: Eine Klasse mit beidem erscheint in beiden Abschnitten.

Vergleichsbericht

Verglichen wird gegen denselben Zeitraum ein Jahr früher. Die Spalten-Aufteilung spielt hier keine Rolle – die Spalten gibt der Vergleich vor.

Ohne Vorjahreswert bleibt die Prozentspalte leer: „unendlich viel mehr“ ist keine Aussage, die in eine Spalte gehört. Ein Monatsende bleibt beim Rückrechnen ein Monatsende, damit der 28.02. nicht auf einen 29.02. trifft und der Vergleichszeitraum einen Tag zu lang wird.

Kontostandsbericht

Anders als die übrigen Berichte zählt hier nicht die Bewegung im Zeitraum, sondern der Stand: alle Buchungen bis zum Stichtag, auch die vor dem Berichtszeitraum, und die Gegenseiten von Umbuchungen. Konten, die im ganzen Zeitraum auf null standen, fallen weg – dieselbe Regel wie in der Cockpit-Kachel. Die Summe zählt alle gezeigten Konten, unabhängig vom Σ-Kennzeichen der Kontenübersicht.

Die Null wird hier ausgeschrieben: Ein Konto, das auf null steht, ist eine Aussage.

Budgetbericht

Gerechnet wird über die vollen Monate, die der Zeitraum berührt. Ein Budget ist ein Monatswert, und ein halber Monat hat kein halbes Budget; anders wären Budget und Ist nicht vergleichbar und die Saldospalte bedeutungslos. Der Berichtskopf nennt deshalb den Monatsbereich.

Geht der Zeitraum über den Jahreswechsel, gilt je Jahr dessen eigenes aktives Budget (Budget::aktivesFuerJahr()). Vorzeichen und Saldo folgen dem Budgetplaner: Ausgaben negativ, Saldo ist ist − budget, positiv heißt besser als geplant. Übergeordnete Kategorien zeigen die Summe ihres Astes.

Filterleiste

Feld Wirkung
Zeitraum Vorgabe oder Benutzerdefiniert; von/bis sind immer gefüllt und zeigen, was die Vorgabe gerade bedeutet
Bericht anzeigen als wechselt den Berichtstyp, ohne den übrigen Filter zu verlieren
Zeilen-Summe Kategorie, Klasse, Konto oder Empfänger
Spalten-Aufteilung Keine, Monat, Quartal, Jahr
mit Einrückung Kategoriebaum oder flache Liste mit Pfad
Suche Empfänger oder Buchungstext
Einschränken Konten, Kategorien, Klassen (Mehrfachauswahl)

Eine gewählte Kategorie schließt ihre Unterkategorien ein – wer „400 - Leben“ filtert, meint den ganzen Ast. Nichts ausgewählt heißt alles.

Zwei Berichte bestimmen ihre Zeilen selbst und sperren das Feld: der Kontostandsbericht führt immer Konten, der Budgetbericht immer Kategorien. Zwei bestimmen ihre Spalten selbst: Vergleichs- und Budgetbericht.

Die Filterleiste sendet per GET. Jeder Zwischenstand ist damit eine Adresse, die man sich merken, weitergeben und mit Speichern unter festhalten kann.

Gespeicherte Berichte und Gruppen

Ein gespeicherter Bericht ist Name, Typ und Filter – mehr nicht. Der Filter liegt als JSON in einer Spalte und wird beim Lesen immer durch Auswertung::normalisiere() geschickt: Was dort nicht vorgesehen ist, fällt weg. Ein alter Bericht kann nach einer Programmänderung höchstens eine Einstellung verlieren, aber nichts Unerwartetes in die Abfrage tragen.

Speichern unter legt unter neuem Namen an und kann die Berichtsgruppe gleich mit anlegen – wer sie erst anderswo erzeugen müsste, verlöre den eingestellten Filter. Speichern überschreibt den geöffneten Bericht.

Berichtsgruppen sind die Kacheln der Übersicht, wie „Bankgeschäfte“ oder „Steuern“ im Original. Wird eine Gruppe gelöscht, bleiben ihre Berichte erhalten und rücken unter Nicht gruppiert: Ein Bericht ist Arbeit, eine Gruppe nicht.

Leere Gruppen bleiben in der Übersicht stehen. Sie sind angelegt worden, um befüllt zu werden, und ohne Kachel gäbe es keinen Ort, an den ein Bericht könnte.

Drilldown

Jeder Zeilenname und jede Zahl im Summen-, Vergleichs- und Budgetbericht ist ein Link auf die Buchungen dahinter. Eine Zahl schränkt zusätzlich auf ihre Spalte ein.

Gefiltert wird nicht, indem die Zeile in einen neuen Filter übersetzt wird, sondern indem dieselben Bewegungen nachgesiebt werden, aus denen die Zelle entstanden ist. Nur so trifft der Drilldown auch das, was ein Filter gar nicht ausdrücken könnte: die Zeile Nicht kategorisiert etwa, oder eine Astsumme über mehrere Unterkategorien.

Die Legenden der Cockpit-Kacheln nutzen denselben Weg (/auswertungen/buchungen) mit drei Zusätzen: art=einnahme|ausgabe siebt zusätzlich nach Einnahme oder Ausgabe (entschieden wie im Bericht über die Art der Kategorie, ohne Kategorie über das Vorzeichen), eine leere zeile nimmt alle Bewegungen, und zeile=kategorie:12,15,0 fasst mehrere Kategorien zusammen (die 0 steht für Nicht kategorisiert). herkunft=cockpit lenkt den Weg zurück ins Cockpit statt in einen Bericht.

CSV-Export

Dieselben Zeilen, dieselben Zahlen, dieselben Vorzeichen wie am Bildschirm – wer den Export mit der Anzeige vergleicht, soll nicht rechnen müssen.

Deutsches Tabellenkalkulations-CSV: Semikolon als Trenner, Komma als Dezimalzeichen, kein Tausenderpunkt (der machte aus der Zahl einen Text), CRLF als Zeilenende und ein vorangestelltes BOM – sonst zeigen Excel und LibreOffice beim Doppelklick „Übrige“ statt „Übrige“. Die Einrückung des Kategoriebaums steht als führende Leerzeichen im Namensfeld, sonst wäre die Hierarchie verloren.

PDF gibt es bewusst nicht (siehe PLAN.md); Papier läuft über die Druckfunktion des Browsers.

Dateien

Datei Inhalt
src/Services/Auswertung.php die Rechenmaschine: Bewegungen, die fünf Berichtstypen, Drilldown
src/Services/Zeitraum.php Zeitraumvorgaben und Spaltenraster, reine Kalenderrechnung ohne Datenbank
src/Services/BerichtExport.php CSV
src/Models/Bericht.php gespeicherte Berichte, Filter-JSON
src/Models/Berichtsgruppe.php Gruppen
src/Controllers/AuswertungenController.php Übersicht, Berichtsansicht, Drilldown, Export
src/Views/auswertungen/ Übersicht, Filterleiste, ein Teiltemplate je Darstellung
migrations/005_berichte.sql berichte, berichtsgruppen

Tests

  • tests/14_AuswertungTest.php – Zeitraumvorgaben und Spaltenraster, Filterprüfung, alle fünf Berichtstypen, Astsummen, Splitbuchungen, Ausschluss der Umbuchungen, unkategorisierte Buchungen, Einschränkungen, Drilldown, CSV, gespeicherte Berichte
  • tests/e2e/specs/auswertungen.spec.js – Übersicht und Standardvorlagen, die fünf Tabellen, Spalten-Aufteilung, Drilldown und zurück, Speichern/Wiederfinden/Löschen, CSV-Download