feat: Ringdiagramm faerbt Legende und Mitte nach Budget

Eingefaerbt war bisher nur die Listen-Darstellung der Ausgaben-Anteile. In der
Kreis-Darstellung blieben die Betraege der Legende grau, und die Summe in der
Mitte sagte gar nichts ueber den Stand.

Jetzt tragen beide die Aussage: gruen im geplanten Rahmen, rot darueber. Faehrt
man ein Segment an, zeigt die Mitte dessen Betrag – dann gilt dort das Budget
dieser Kategorie, sonst das des Ganzen.

Fuer die Mitte liefert der Server jetzt auch das Geplante ueber ALLE
Ausgaben-Einheiten, nicht nur ueber die mit Ausgaben: Der Monatsplan umfasst
auch, wofuer noch nichts ausgegeben wurde.

Ohne Plan bleibt alles, wie es war. Der Donut faerbt nur, wenn ein Segment die
Angabe mitbringt – die Budget-Karte, die dieselbe Komponente benutzt, bleibt
also unberuehrt.

Der Test hat dabei gleich einen Fehler gefunden: ``_units`` ist ein Generator,
und ich lief zweimal darueber – beim zweiten Mal war er leer und das Geplante
immer 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Guido
2026-08-30 14:13:49 +02:00
co-authored by Claude Opus 5
parent 4d3b9a8207
commit 63056ae76a
5 changed files with 51 additions and 7 deletions
+12 -2
View File
@@ -164,8 +164,11 @@ def expense_share(
planned = budget.effective_planned(db, user, label)
by_category = group_by != "group"
# Als Liste: ``_units`` ist ein Generator, und er wird hier zweimal
# gebraucht – beim zweiten Mal waere er leer und das Geplante 0.
einheiten = list(_units(_expense_groups(db, user), by_category))
rows = []
for name, color, ids in _units(_expense_groups(db, user), by_category):
for name, color, ids in einheiten:
val = sum(actual.get(i, 0) for i in ids)
if val > 0:
geplant = sum(planned.get(i, 0) for i in ids)
@@ -173,9 +176,16 @@ def expense_share(
"planned": geplant,
"over": geplant > 0 and val > geplant})
rows.sort(key=lambda r: r["amount"], reverse=True)
# Das Geplante ueber ALLE Ausgaben-Einheiten, nicht nur die mit Ausgaben:
# Der Monatsplan umfasst auch, wofuer noch nichts ausgegeben wurde.
gesamt = sum(r["amount"] for r in rows)
gesamt_geplant = sum(planned.get(i, 0) for _, _, ids in einheiten for i in ids)
return {
"rows": rows,
"total": sum(r["amount"] for r in rows),
"total": gesamt,
"total_planned": gesamt_geplant,
"total_over": gesamt_geplant > 0 and gesamt > gesamt_geplant,
"currency": base,
"label": label,
"group_by": "category" if by_category else "group",