Der Buchungsbericht zeigt vor der Spalte „Bar“ des Bargeld-Tools die Spalte „✓“ (abgeglichen) und lässt sich nach abgeglichenen bzw. nicht abgeglichenen Buchungen filtern. „Buchungen nicht abgeglichen“ unter den offenen Vorgängen im Cockpit öffnet jetzt diesen Bericht mit dem Filter „nicht abgeglichen“ statt der Kontenübersicht. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
11 KiB
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; Spalte „✓“ (abgeglichen) mit Filter „Abgeglichen“ (#137); 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.
Im Buchungsbericht stehen unter den Kategorien zusätzlich die aktiven Umbuchungskonten,
je Kontengruppe (#124). Ihr Wert konto:7 landet im Filter als gegenkonten; eine
Bewegung passt, wenn sie zu einer gewählten Kategorie oder einem gewählten
Umbuchungskonto gehört. Ein gewähltes Umbuchungskonto bringt seine Umbuchungen auch ohne
„Umbuchungen mitzählen“ mit – sonst bliebe die Auswahl leer. Die übrigen Berichte zählen
Umbuchungen nicht und bieten die Konten deshalb nicht an.
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 Berichtetests/e2e/specs/auswertungen.spec.js– Übersicht und Standardvorlagen, die fünf Tabellen, Spalten-Aufteilung, Drilldown und zurück, Speichern/Wiederfinden/Löschen, CSV-Download