Finanzmanager/docs/cockpit.md
fds2610-bot 275acd3285 Fix #134: Buchungen bewusst ohne Kategorie ermöglichen
Neuer Schalter „Bewusst ohne Kategorie“ in der Buchungsmaske für
Abschreibungen und rein rechnerische Solarerträge. Solche Buchungen
erscheinen nicht unter den offenen Vorgängen im Cockpit, nicht im
Prüflauf des Monatsabschlusses, setzen das Konto in der Kontenübersicht
nicht fett und werden von der Regelanwendung sowie dem automatischen
Zusammenführen zu Umbuchungen ausgelassen. Kommt eine Kategorie, ein
Gegenkonto oder eine Splitbuchung hinzu, entfällt die Markierung.

Migration 028_bewusst_ohne_kategorie.sql, Test 59 und E2E-Test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 16:22:22 +02:00

213 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Cockpit
Die Startseite. Jede Kachel beantwortet eine Frage auf einen Blick.
## Welche Kacheln erscheinen
Es gibt fünf: **Vermögensentwicklung**, **Einnahmen und Ausgaben**, **Meine Ausgaben**,
**Kontostände** und **Offene Vorgänge**. Welche davon gezeigt werden, steht im
Einstellungsdialog unter *Darstellung* – der Katalog dazu in `Cockpit::KACHELN`, die
Auswahl als kommagetrennte Liste unter `cockpit_kacheln`.
Vorgabe ist: alle. Eine abgewählte Kachel wird nicht nur ausgeblendet, sondern gar nicht
erst berechnet – `CockpitController::index()` holt die Daten je Kachel einzeln. Wer das
Cockpit entschlacken will, macht es damit auch schneller.
Die Reihenfolge im Raster ist die des Katalogs, nicht die der Ankreuzfelder: Ein Formular
liefert Ankreuzfelder in der Reihenfolge des HTML, und die wäre für den Nutzer keine
sinnvolle Sortierung.
## Vermögensentwicklung
Ein gestapeltes Balkendiagramm der **Kontostände zum Monatsende** über die letzten zwölf
Monate – ein Balken je Monat, ein Farbton je Konto.
### Woher die Zahlen kommen
Welche Konten zählen, entscheidet allein der Schalter „nur aktive“. Das Σ-Kennzeichen
(`in_summe`) spielt hier **keine** Rolle – anders als in der Kontenübersicht. Stillgelegte
Konten tragen es meist nicht; würde es mitfiltern, fiele beim Ausschalten des Schalters
genau das weg, was man sehen will. Die Summe der Kachel kann bei ausgeschaltetem Schalter
deshalb von der Summe der Kontenübersicht abweichen.
Der Stand eines Monats ist der Stand des Vormonats plus dessen Bewegungen:
* `Buchung::saldenJeKonto()` liefert den Stand am Tag vor dem Zeitraum – alles Ältere
steckt damit im ersten Balken.
* `Buchung::bewegungenJeKontoUndMonat()` liefert die Bewegungen innerhalb des Zeitraums,
nach Monat getrennt.
Zwei Abfragen statt zwölf Stichtagsabfragen. Beide Methoden zählen dieselben drei Quellen:
die Buchungen des Kontos, die Gegenseiten fremder Umbuchungen und die Gegenseiten aus
Splitzeilen. Eine Umbuchung verschiebt deshalb zwischen zwei Balkenstücken, ohne die Summe
zu ändern.
Konten, die zwölf Monate lang auf null standen, fallen weg; sie zeichnen ohnehin keinen
Balken.
### Der Schalter „nur aktive“
Oben rechts an der Kachel sitzt ein Ein/Aus-Schalter. Eingeschaltet – der Standard – zählen
nur Konten, die noch geführt werden. Ausgeschaltet kommen stillgelegte dazu: Sonst fehlte im
Rückblick Vermögen, das damals auf einem inzwischen aufgelösten Konto lag.
Der Zustand liegt unter `cockpit_vermoegen_nur_aktive` in den Einstellungen und gilt bis zur
nächsten Umschaltung – auch über das Abmelden hinaus. Im Einstellungsdialog erscheint er
nicht: Er gehört an die Kachel, nicht in einen Reiter.
Umgeschaltet wird über einen abschickenden Knopf, nicht über ein Ankreuzfeld. Ein
Ankreuzfeld könnte sein Formular nur mit einem Inline-Skript selbst abschicken, und die
Content-Security-Policy verbietet Inline-Skripte.
### Stapel und Farben
Positive Stände stapeln sich über der Nulllinie, negative darunter – ein überzogenes
Girokonto oder eine Kreditkarte zieht den Balken nach unten.
Die Palette in `app.css` hat zwölf Töne (`.serie-1` bis `.serie-12`). Gibt es mehr Konten,
behalten die größten ihre eigene Farbe und der Rest wird zu **Übrige Konten (n)**
zusammengefasst – zwei Konten in derselben Farbe wären in der Legende nicht auseinander zu
halten. Jede Serie setzt `--farbe`; davon leben der Balken (`fill`) und der Legendenpunkt
(`background`) gleichermaßen, und beide folgen dem hellen wie dem dunklen Thema.
### Ebenen: in „Übrige Konten“ hineinsehen
Der Legendeneintrag **Übrige Konten (n)** ist ein Link. Er führt auf `/?ebene=1`: Dort
stehen die nächstelf Konten einzeln, und was dann noch bleibt, sammelt sich erneut. So
geht es beliebig tief, bis der Rest in die Palette passt – dann entfällt das Sammelstück,
und das ist die letzte Ebene. `Vermoegensentwicklung::ebenen()` rechnet aus, wie viele es
sind; eine zu hohe Ebene fällt auf die letzte zurück, statt eine leere Kachel zu zeigen.
Zurück geht es über die Zeile unter der Legende: *eine Ebene zurück* und, ab der dritten,
*zu den größten Konten*.
Jedes Konto steht auf genau einer Ebene: Was oben schon eine eigene Farbe hatte, ist im
Sammelstück nicht mehr enthalten. Sonst wüchse der Rest mit jeder Ebene, statt zu
schrumpfen. Weil auf tieferen Ebenen die großen Konten fehlen, passt sich die Achse an –
die kleinen Konten werden dadurch überhaupt erst sichtbar. Die Ebene steht in der Adresse
und nicht in den Einstellungen: Beim nächsten Aufruf beginnt man wieder oben.
### SVG von Hand
Keine Diagrammbibliothek (siehe `PLAN.md`): `src/Views/cockpit/vermoegensdiagramm.php`
schreibt das SVG selbst. Farben stehen als Klasse am Element, nicht als `fill`-Attribut –
ein Attribut käme zwar an der Content-Security-Policy vorbei, könnte aber nicht auf die
Themenumschaltung reagieren. Ein `style`-Attribut verwürfe die CSP ohnehin.
Die Achse rundet über `Vermoegensentwicklung::skala()` auf Schritte von 1, 2, 2,5 oder 5
mal einer Zehnerpotenz und schließt die Null immer ein. Jedes Balkenstück trägt ein
`<title>` mit Konto, Monat und Betrag – das ist der Tooltip, ohne eine Zeile JavaScript.
Senkrecht rechnet die Zeichnung in Bildpunkten, waagerecht in Prozent: Die Balkenmitte von
Monat *i* liegt bei `(i + 0,5) / 12` der Fläche, der Balken selbst ist feste 16 Punkte breit
und wird per `transform` um seine halbe Breite nach links gerückt. In einer breiten Kachel
rücken die Balken damit **auseinander**, statt breiter zu werden.
Deshalb sind es zwei SVGs nebeneinander (`.diagrammflaeche`): links die Achsenbeschriftung
mit fester Breite, rechts die Zeichenfläche. In einem einzigen SVG ginge das nicht –
Prozentangaben rechnen immer auf die volle Breite, und ein Attribut kann davon keine feste
Achsenbreite abziehen. Ein `viewBox` verbietet sich aus demselben Grund: Es würde alles
gleichmäßig strecken, die Balken eingeschlossen.
Die Kachel ist eine gewöhnliche Kachel des Cockpit-Rasters, so breit wie ihre Nachbarn:
Ein Ausgriff über zwei Spalten machte sie zum Fremdkörper zwischen den anderen dreien.
Die Legende führt nur Farbe und Kontoname und steht darunter, in kleinerer Schrift und so
vielen Spalten, wie die Kachel hergibt (`auto-fill`). Die Beträge stehen am Balken im
Tooltip und in der Kachel *Kontostände*; in der Legende kosteten sie nur Breite.
Jeder Kontoname der Legende führt in das Kontoblatt des Kontos – dort stehen die
Buchungen, aus denen sich seine Stände zusammensetzen.
## Legenden führen zu den Buchungen
Jeder Legendeneintrag ist ein Link auf die Buchungen, aus denen sich sein Wert
zusammensetzt. Ziel ist der Drilldown der Auswertungen (`/auswertungen/buchungen`, siehe
`docs/auswertungen.md`), aufgerufen mit **demselben Filter, mit dem die Kachel rechnet** –
`Cockpit::buchungsadresse()` baut die Adresse. Die Liste siebt dieselben Bewegungen nach
wie die Kachel; ihre Summe trifft deshalb den Legendenwert (mit buchhalterischem
Vorzeichen, Ausgaben also mit Minus). Der Weg zurück führt ins Cockpit.
| Kachel | Legendeneintrag | Buchungsliste |
|---|---|---|
| Einnahmen und Ausgaben | Einnahmen / Ausgaben | alle Einnahmen bzw. Ausgaben der letzten zwölf Monate |
| Einnahmen und Ausgaben | Saldo | beides zusammen, ohne Umbuchungen |
| Meine Ausgaben | Kategorie | Ausgaben des laufenden Jahres in dieser obersten Kategorie samt Unterkategorien |
| Meine Ausgaben | Nicht kategorisiert | Ausgaben ohne Kategorie – unkategorisierte Gutschriften nicht |
| Meine Ausgaben | Übrige (n) | alle im Sammelsegment zusammengefassten Kategorien |
| Vermögensentwicklung | Konto | das Kontoblatt des Kontos |
## Einnahmen und Ausgaben
Balkenpaare über die letzten zwölf Monate: links die Einnahmen, rechts die Ausgaben,
darüber der Saldo als Linie mit einem Punkt je Monat.
Die Zahlen kommen **aus dem Summenbericht** (`Cockpit::monatsreihe()` ruft
`Auswertung::bericht()` mit Zeitraum *letzte zwölf Monate* und Spalten-Aufteilung *Monat*).
Damit zählt die Kachel dieselben Bewegungen wie der Bericht: Splitzeilen einzeln,
Umbuchungen gar nicht. Eine eigene Abfrage wäre schneller zu schreiben und liefe früher
oder später auseinander.
Ausgaben stehen wie im Bericht ohne Minuszeichen; der Saldo ist Einnahmen minus Ausgaben
und kann natürlich negativ sein. Der Knopf unter der Kachel öffnet denselben Ausschnitt
als Summenbericht.
## Meine Ausgaben
Ein Ring der Ausgaben des laufenden Jahres, aufgeteilt nach **oberster Kategorie**:
„300 - Wohnen“ statt Miete, Strom und Nebenkosten einzeln. Ein Ring mit hundert Segmenten
beantwortet keine Frage; wer es genauer braucht, klickt sich in den Summenbericht.
`Auswertung::verteilung()` rechnet das: Bewegungen des Zeitraums, Einnahmen oder Ausgaben,
je Bewegung die Wurzel ihrer Kategorie (über den Kategoriepfad, nicht über die
`eltern_id`-Kette), Beträge vorzeichenlos gedreht wie im Ausgabenabschnitt der Berichte.
Mehr als acht Segmente werden nicht gezeichnet – die kleinsten wandern in **Übrige (n)**.
Kategorien, die im Saldo negativ sind (mehr Erstattung als Ausgabe), bekommen kein Segment;
in der Gesamtsumme in der Mitte des Rings stecken sie weiter, sonst ergänzten sich die
Anteile nicht mehr zu hundert Prozent.
Gezeichnet wird als SVG-Pfad mit zwei Bögen je Segment (`ausgabendiagramm.php`). Sonderfall
ist die einzige Kategorie mit hundert Prozent: Anfangs- und Endpunkt des Bogens fielen
zusammen und es entstünde keine Fläche – deshalb zwei Halbringe derselben Farbe.
## Offene Vorgänge
Was auf Bearbeitung wartet, mit Zahl und Weg dorthin. Der Tooltip der Überschrift nennt die
Prüfungen, die gerade nichts melden und daher nicht in der Liste stehen:
* **ohne Kategorie** – Buchungen ohne Kategorie, die auch keine Umbuchung und nicht
gesplittet sind. Umbuchungen brauchen keine Kategorie und zählen deshalb nicht mit,
ebenso wenig Buchungen, die bewusst ohne Kategorie gebucht sind (siehe `docs/buchungen.md`).
* **nicht abgeglichen** – Buchungen aktiver Konten bis heute ohne Abgleich-Kennzeichen.
* **Bargeld-Tool-Prüfung fehlgeschlagen** – Buchungen mit `bargeld_status = 'fehler'`, also
einem gescheiterten Abruf beim Bargeld-Tool (siehe `docs/buchungen.md`), nicht zu
verwechseln mit „im Bargeld-Tool nicht gefunden“. Führt auf
`/verwaltung/bargeld/fehler`, die Liste dieser Buchungen kontoübergreifend
(`Buchung::mitBargeldFehler()`), denn die Prüfung hängt an der Kategorie, nicht am Konto.
* **Im Bargeld-Tool nicht gefunden** – Buchungen mit `bargeld_status = 'fehlt'`. Führt auf
`/verwaltung/bargeld/fehler?status=fehlt` (`Buchung::mitBargeldFehler('fehlt')`).
* **Monatsabschluss steht aus** – der Vorschlag aus `Monatsabschluss::naechsterOffener()`,
aber nur, wenn dieser Monat wirklich noch offen ist und Buchungen trägt.
Ist nichts offen, bleibt die Liste leer und die Kachel sagt es ausdrücklich. Ab Phase 5
kommen die noch nicht zugeordneten Bankumsätze hinzu, ab Phase 7 die fälligen
regelmäßigen Buchungen.
## Tests
* `tests/15_CockpitTest.php` – Kachelauswahl (Reihenfolge, Unbekanntes, leere Auswahl),
Monatsreihe mit Trennung von Einnahmen und Ausgaben, Umbuchungen bleiben draußen,
Verteilung auf die Wurzelkategorie, Kürzung auf die Segmentgrenze, offene Vorgänge
(auch fehlgeschlagene Bargeld-Tool-Prüfungen), Legendeneinträge führen zu
Buchungslisten, deren Summe den Legendenwert trifft
* `tests/34_BargeldAbgleichTest.php` – die Liste der fehlgeschlagenen Prüfungen
(`Buchung::mitBargeldFehler()`) und ihre Anzeige unter Verwaltung → Bargeld-Tool
* `tests/13_VermoegensentwicklungTest.php` – Zeitraum, Fortschreibung der Stände,
Umbuchungen, Σ-Kennzeichen, Schalter „nur aktive“, Zusammenfassen jenseits der Palette,
Ebenen (jedes Konto genau einmal, letzte Ebene ohne Sammelstück, zu tiefe Ebene fällt
zurück), Skala
* `tests/e2e/specs/smoke.spec.js` – die Kachel zeichnet zwölf Balken, keine Farbe der
Legende kommt doppelt vor, der Schalter behält seinen Zustand über den Neuaufruf, und
*Übrige Konten* führt eine Ebene tiefer und wieder zurück
* `tests/e2e/specs/module.spec.js` – Legendeneinträge der Kacheln *Einnahmen und Ausgaben*
und *Meine Ausgaben* öffnen die Buchungsliste und führen zurück ins Cockpit