From ba66ce7bdc87b408c91360bc97872b099fb20746 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Thu, 1 Oct 2026 11:18:04 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20n.n.:=20Buchungsbericht=20=E2=80=93=20Bar?= =?UTF-8?q?geld-Abgleich,=20Gruppen-/Gesamtzeile,=20Filterbereich,=20Cockp?= =?UTF-8?q?it-Tooltip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5.5 --- Changes.md | 25 ++++++++++++++++++ docs/auswertungen.md | 2 +- docs/buchungen.md | 5 ++-- docs/cockpit.md | 5 +++- public/static/app.css | 29 ++++++++++++++++++++ src/Controllers/VerwaltungController.php | 9 +++++-- src/Models/Buchung.php | 10 +++---- src/Services/Auswertung.php | 22 ++++++++++++++-- src/Services/Cockpit.php | 32 +++++++++++++++++++++++ src/Views/auswertungen/bericht.php | 17 ++++++++++-- src/Views/auswertungen/teil-buchungen.php | 16 ++++++++---- src/Views/cockpit/index.php | 14 +++++++++- src/Views/verwaltung/bargeld_fehler.php | 17 ++++++++---- tests/14_AuswertungTest.php | 27 +++++++++++++++++++ tests/15_CockpitTest.php | 20 ++++++++++++++ 15 files changed, 224 insertions(+), 26 deletions(-) diff --git a/Changes.md b/Changes.md index b729359..a06147b 100644 --- a/Changes.md +++ b/Changes.md @@ -1,5 +1,30 @@ # Änderungen +## Buchungsbericht: Gruppen- und Gesamtzeile (01.10.2026) + +- Die Formatierung von Kategoriezeile und Gesamtzeile ist getauscht. Die Gesamtzeile zeigt nur noch „Gesamt“; die Anzahl der Buchungen steht im Tooltip („Anzahl n“). + +## Buchungsbericht: Bargeld-Tool-Abgleich (01.10.2026) + +- Ist ein Bargeld-Tool eingerichtet, zeigt der Buchungsbericht die Spalte „Bar“ (dasselbe Symbol wie im Kontoblatt) und bietet den Filter „Bargeld-Tool“: alle · gefunden · nicht gefunden · Abruf gescheitert · nicht abgeglichen. +- Der Filter wird mit dem Bericht gespeichert (`Auswertung::BARGELD_FILTER`) und wirkt nur im Buchungsbericht. +- Test: `14_AuswertungTest.php`. + +## Berichte: Filterbereich (01.10.2026) + +- Der Filterbereich erhält den hellblauen Bereichsrand samt Schatten. +- „Zeilen-Summe“ und „Spalten-Aufteilung“ stehen in der ersten Zeile hinter „Bericht anzeigen als“; das Suchfeld ist dafür breiter. + +## Cockpit: Tooltip der Kachel „Offene Vorgänge“ (01.10.2026) + +- Beim Überfahren der Überschrift nennt der Tooltip die Prüfungen, die gerade nichts melden und deshalb nicht in der Liste stehen (`Cockpit::VORGANGSPRUEFUNGEN`). +- Test: `15_CockpitTest.php`. + +## Cockpit: Offene Vorgänge für nicht gefundene Bargeld-Buchungen (01.10.2026) + +- Neuer offener Vorgang „im Bargeld-Tool nicht gefunden“ (Status `fehlt`) neben der fehlgeschlagenen Prüfung; die Liste unter `/verwaltung/bargeld/fehler?status=fehlt`. +- Test: `15_CockpitTest.php`. + ## Rahmen, Schatten und Tabs im Design (01.10.2026) - Tabellen (`table.liste`), Kacheln und breite Formulare (`.formular.breit`, u. a. Einstellungen) erhalten in beiden Themen einen 1px breiten hellblauen Rand (`--bereichsrand`) und einen leichten Schatten (`--bereichsschatten`) für mehr Kontrast zwischen den Bereichen. diff --git a/docs/auswertungen.md b/docs/auswertungen.md index 7c19121..823145f 100644 --- a/docs/auswertungen.md +++ b/docs/auswertungen.md @@ -48,7 +48,7 @@ Zwei Ausnahmen führen das Vorzeichen mit, weil sie keine Abschnitte haben: der | Typ | Zeilen | Spalten | |---|---|---| | **Summenbericht** | Zeilen-Summe, nach Einnahmen und Ausgaben getrennt | Zeitraum, je nach Spalten-Aufteilung | -| **Buchungsbericht** | Einzelbuchungen, gruppiert nach Zeilen-Summe | feste Buchungsspalten | +| **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 | diff --git a/docs/buchungen.md b/docs/buchungen.md index 0ce5484..ee91556 100644 --- a/docs/buchungen.md +++ b/docs/buchungen.md @@ -274,8 +274,9 @@ grauen Kreis. Buchungen mit dem Status `fehler` zählen im Cockpit als offener Vorgang „Bargeld-Tool-Prüfung fehlgeschlagen“ (siehe `docs/cockpit.md`) – ein Klick führt auf `/verwaltung/bargeld/fehler`, die kontoübergreifende Liste dieser Buchungen -(`Buchung::mitBargeldFehler()`). Der Status `fehlt` erscheint dort bewusst nicht: Er ist ein -Ergebnis, kein offenes Problem – eine erneute Zuordnung fragt einfach wieder ohne Erfolg. +(`Buchung::mitBargeldFehler()`). Buchungen mit dem Status `fehlt` zählen als eigener offener +Vorgang „im Bargeld-Tool nicht gefunden“ und führen auf dieselbe Seite mit `?status=fehlt` +(`Buchung::mitBargeldFehler('fehlt')`). **Ein Fehlschlag ist ein Ergebnis, kein Abbruch.** Weder ein abgeschaltetes Bargeld-Tool noch ein Netzfehler darf verhindern, dass die Kategorie gespeichert wird; der Abruf bricht diff --git a/docs/cockpit.md b/docs/cockpit.md index b781c03..a1b9d8b 100644 --- a/docs/cockpit.md +++ b/docs/cockpit.md @@ -172,7 +172,8 @@ zusammen und es entstünde keine Fläche – deshalb zwei Halbringe derselben Fa ## Offene Vorgänge -Was auf Bearbeitung wartet, mit Zahl und Weg dorthin: +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. @@ -182,6 +183,8 @@ Was auf Bearbeitung wartet, mit Zahl und Weg dorthin: 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. diff --git a/public/static/app.css b/public/static/app.css index e7332bf..70476e1 100644 --- a/public/static/app.css +++ b/public/static/app.css @@ -826,6 +826,28 @@ table.liste tr.gruppensumme td { background: color-mix(in srgb, var(--flaeche-gedaempft) 55%, var(--flaeche)); } +/* Buchungsbericht: Kategoriezeile fett wie sonst die Summe, Gesamtzeile gedämpft wie sonst der Kopf. */ +table.buchungsgruppen tr.gruppenzeile th { + background: color-mix(in srgb, var(--flaeche-gedaempft) 55%, var(--flaeche)); + font-size: inherit; + letter-spacing: normal; + text-transform: none; + font-weight: 600; + color: inherit; +} + +table.buchungsgruppen tr.gruppensumme td { + background: transparent; + border-top: 1px solid var(--rand); + font-size: .85rem; + letter-spacing: .03em; + text-transform: uppercase; + color: var(--text-gedaempft); + font-weight: 400; +} + +table.buchungsgruppen tr.gruppensumme td span { cursor: help; } + table.liste tfoot tr.summenzeile td { font-weight: 700; border-top: 2px solid var(--rand-kraeftig); @@ -1852,6 +1874,13 @@ body.schlicht { gap: .6rem; } +.berichtsfilter { + border: var(--bereichsrand); + box-shadow: var(--bereichsschatten); +} + +.berichtsfilter input[type="search"] { min-width: 24rem; } + .filterzeile { display: flex; flex-wrap: wrap; diff --git a/src/Controllers/VerwaltungController.php b/src/Controllers/VerwaltungController.php index ba71ee6..4955fec 100644 --- a/src/Controllers/VerwaltungController.php +++ b/src/Controllers/VerwaltungController.php @@ -286,9 +286,14 @@ class VerwaltungController extends BaseController { $this->verlangeAnmeldung(); + $fehlt = ($_GET['status'] ?? '') === 'fehlt'; + $this->render('verwaltung/bargeld_fehler.php', [ - 'titel' => 'Bargeld-Tool: fehlgeschlagene Prüfungen', - 'buchungen' => Buchung::mitBargeldFehler(), + 'titel' => $fehlt + ? 'Bargeld-Tool: nicht gefundene Buchungen' + : 'Bargeld-Tool: fehlgeschlagene Prüfungen', + 'fehlt' => $fehlt, + 'buchungen' => Buchung::mitBargeldFehler($fehlt ? 'fehlt' : 'fehler'), ]); } } diff --git a/src/Models/Buchung.php b/src/Models/Buchung.php index f3cba8e..a80d4e7 100644 --- a/src/Models/Buchung.php +++ b/src/Models/Buchung.php @@ -504,23 +504,23 @@ class Buchung /** * Alle Buchungen, an denen die Bargeld-Tool-Prüfung zuletzt einen Fehler - * festgestellt hat – kontoübergreifend, denn die Prüfung hängt an der + * ('fehler') oder keinen Treffer ('fehlt') ergeben hat – kontoübergreifend, denn die Prüfung hängt an der * Kategorie der Buchung, nicht an ihrem Konto. Der Status 'fehler' steht * für einen gescheiterten Abruf (siehe Services\BargeldAbgleich::FEHLER), - * nicht für eine im Bargeld-Tool fehlende Buchung. + * 'fehlt' für eine im Bargeld-Tool nicht gefundene Buchung. * * @return list> */ - public static function mitBargeldFehler(): array + public static function mitBargeldFehler(string $status = 'fehler'): array { return Database::fetchAll( 'SELECT b.id, b.datum, b.betrag, b.empfaenger, b.buchungstext, b.bargeld_hinweis, b.bargeld_geprueft_am, b.konto_id, k.name AS konto_name FROM buchungen b JOIN konten k ON k.id = b.konto_id - WHERE b.benutzer_id = ? AND b.bargeld_status = \'fehler\' + WHERE b.benutzer_id = ? AND b.bargeld_status = ? ORDER BY b.datum DESC, b.id DESC', - [Mandant::id()] + [Mandant::id(), $status === 'fehlt' ? 'fehlt' : 'fehler'] ); } diff --git a/src/Services/Auswertung.php b/src/Services/Auswertung.php index 646793e..3bc650f 100644 --- a/src/Services/Auswertung.php +++ b/src/Services/Auswertung.php @@ -53,6 +53,9 @@ class Auswertung 'budgetbericht' => 'Budgetbericht', ]; + /** Zulässige Werte des Bargeld-Filters; 'keiner' = nicht abgeglichen. */ + public const BARGELD_FILTER = ['gefunden', 'fehlt', 'fehler', 'keiner']; + /** Wonach die Zeilen zusammengefasst werden. */ public const ZEILENSUMMEN = [ 'kategorie' => 'Kategorie', @@ -114,6 +117,10 @@ class Auswertung 'kategorien' => self::ids($roh['kategorien'] ?? []), 'klassen' => self::ids($roh['klassen'] ?? []), 'suche' => mb_substr(trim((string)($roh['suche'] ?? '')), 0, 120), + // Nur der Buchungsbericht führt die Abgleichspalte und filtert danach. + 'bargeld' => $typ === 'buchungsbericht' && in_array($roh['bargeld'] ?? '', self::BARGELD_FILTER, true) + ? (string)$roh['bargeld'] + : '', ]; } @@ -654,6 +661,7 @@ class Auswertung return [ 'darstellung' => 'buchungen', + 'bargeld' => BargeldAbgleich::eingerichtet(), 'gruppen' => array_values($gruppen), 'summe' => round($summe, 2), 'anzahl' => $anzahl, @@ -825,6 +833,8 @@ class Auswertung 'gesplittet' => $zeile['split_id'] !== null, 'split_gesamt' => !empty($zeile['split_zusammengefasst']), 'betrag' => round((float)$zeile['betrag'], 2), + 'bargeld_status' => $zeile['bargeld_status'] ?? null, + 'bargeld_hinweis' => $zeile['bargeld_hinweis'] ?? null, ]; } @@ -1177,13 +1187,13 @@ class Auswertung $sql = 'SELECT * FROM ( SELECT b.id AS buchung_id, NULL AS split_id, b.datum, b.betrag, b.konto_id, b.kategorie_id, b.klasse_id, b.gegenkonto_id, b.empfaenger, - b.buchungstext AS text + b.buchungstext AS text, b.bargeld_status, b.bargeld_hinweis FROM buchungen b WHERE b.benutzer_id = ? AND b.gesplittet = 0 AND b.datum BETWEEN ? AND ? UNION ALL SELECT b.id AS buchung_id, s.id AS split_id, b.datum, s.betrag, b.konto_id, s.kategorie_id, s.klasse_id, s.gegenkonto_id, b.empfaenger, - s.notiz AS text + s.notiz AS text, b.bargeld_status, b.bargeld_hinweis FROM buchung_splits s JOIN buchungen b ON b.id = s.buchung_id WHERE b.benutzer_id = ? AND b.gesplittet = 1 AND b.datum BETWEEN ? AND ? @@ -1213,6 +1223,14 @@ class Auswertung $params = array_merge($params, $filter['klassen']); } + $bargeld = (string)($filter['bargeld'] ?? ''); + if ($bargeld === 'keiner') { + $wo[] = 'bargeld_status IS NULL'; + } elseif ($bargeld !== '') { + $wo[] = 'bargeld_status = ?'; + $params[] = $bargeld; + } + if (($filter['suche'] ?? '') !== '') { $wo[] = '(empfaenger LIKE ? OR text LIKE ?)'; $muster = '%' . $filter['suche'] . '%'; diff --git a/src/Services/Cockpit.php b/src/Services/Cockpit.php index 8af767e..7a7620c 100644 --- a/src/Services/Cockpit.php +++ b/src/Services/Cockpit.php @@ -49,6 +49,22 @@ class Cockpit ], ]; + /** + * Alle Prüfungen der Kachel „Offene Vorgänge“, in der Reihenfolge der Liste. + * Angezeigt wird nur, was etwas findet; der Tooltip der Überschrift nennt + * deshalb auch die, die gerade nichts melden. + */ + public const VORGANGSPRUEFUNGEN = [ + 'ohne_kategorie' => 'Buchungen ohne Kategorie', + 'nicht_abgeglichen' => 'Nicht abgeglichene Buchungen', + 'bankumsaetze' => 'Bankumsätze zum Abgleich', + 'bargeld_fehler' => 'Fehlgeschlagene Bargeld-Tool-Prüfungen', + 'bargeld_fehlt' => 'Im Bargeld-Tool nicht gefundene Buchungen', + 'termine' => 'Fällige regelmäßige Buchungen', + 'erinnerungen' => 'Fällige Erinnerungen', + 'monatsabschluss' => 'Offener Monatsabschluss', + ]; + /** * Die sichtbaren Kacheln in ihrer Reihenfolge. Ohne gespeicherte Auswahl * sind alle sichtbar – ein leeres Cockpit beim ersten Aufruf wäre nur @@ -288,6 +304,22 @@ class Cockpit ]; } + // Buchungen, die im Bargeld-Tool nicht gefunden wurden: der Abgleich + // lief, hat aber keinen Treffer ergeben. + $bargeldFehlt = (int)Database::fetchValue( + 'SELECT COUNT(*) FROM buchungen WHERE benutzer_id = ? AND bargeld_status = ?', + [$benutzer, BargeldAbgleich::FEHLT], + 0 + ); + if ($bargeldFehlt > 0) { + $vorgaenge[] = [ + 'schluessel' => 'bargeld_fehlt', + 'text' => 'im Bargeld-Tool nicht gefunden', + 'anzahl' => $bargeldFehlt, + 'pfad' => '/verwaltung/bargeld/fehler?status=fehlt', + ]; + } + // Fällige regelmäßige Buchungen – die automatischen zählen mit, denn // gebucht sind sie erst nach dem Fälligkeitslauf. $termine = Faelligkeitslauf::vorschau($heute); diff --git a/src/Views/auswertungen/bericht.php b/src/Views/auswertungen/bericht.php index d7d1a79..0a269d6 100644 --- a/src/Views/auswertungen/bericht.php +++ b/src/Views/auswertungen/bericht.php @@ -127,9 +127,7 @@ include __DIR__ . '/../layout/kopf.php'; - -
+
+
+ + + +