feat: Dashboard-Karte „Ausgaben-Anteile"
Zeigt für den laufenden Budget-Monat, wie sich die tatsächlichen Ausgaben prozentual auf die Kategorien verteilen – absteigend sortiert, mit Balken in der Kategoriefarbe, Prozentwert und Betrag. Anders als der Budget-Donut hängt sie nicht am geplanten Budget: Sie zeigt reine Ist-Ausgaben, auch wenn für den Monat nichts geplant wurde. Umschaltbar zwischen Kategorien (Standard) und Gruppen. Die Anteile rechnet die Oberfläche aus Betrag und Summe – gerundete Prozente vom Server addierten sich sonst nicht auf 100 %. Wird die Karte schmal, gibt zuerst der Betrag nach; ohne Kategorienamen sagt die Zeile nichts mehr aus. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -142,6 +142,39 @@ def budget_donut(
|
||||
"label": label, "group_by": "category" if by_category else "group"}
|
||||
|
||||
|
||||
@router.get("/expense-share")
|
||||
def expense_share(
|
||||
group_by: str = Query(default="category"),
|
||||
db: Session = Depends(get_db),
|
||||
user: User = Depends(get_current_user),
|
||||
) -> dict:
|
||||
"""Tatsächliche Ausgaben des laufenden Budget-Monats je Kategorie/Gruppe.
|
||||
|
||||
Anders als der Budget-Donut zeigt das rein die Ist-Ausgaben – unabhängig
|
||||
davon, ob für den Monat überhaupt geplant wurde. Die Anteile rechnet die
|
||||
Oberfläche aus `amount` und `total`, damit sich gerundete Prozente nicht zu
|
||||
99,9 % addieren."""
|
||||
base = base_currency(db, user)
|
||||
label = _label(db, user)
|
||||
start, end = budget.period_bounds(label, _start_day(db, user))
|
||||
actual = budget.actual_expense_by_category(db, user, start, end, base)
|
||||
by_category = group_by != "group"
|
||||
|
||||
rows = []
|
||||
for name, color, ids in _units(_expense_groups(db, user), by_category):
|
||||
val = sum(actual.get(i, 0) for i in ids)
|
||||
if val > 0:
|
||||
rows.append({"name": name, "color": color, "amount": val})
|
||||
rows.sort(key=lambda r: r["amount"], reverse=True)
|
||||
return {
|
||||
"rows": rows,
|
||||
"total": sum(r["amount"] for r in rows),
|
||||
"currency": base,
|
||||
"label": label,
|
||||
"group_by": "category" if by_category else "group",
|
||||
}
|
||||
|
||||
|
||||
@router.get("/budget-progress")
|
||||
def budget_progress(
|
||||
group_by: str = Query(default="group"),
|
||||
|
||||
Reference in New Issue
Block a user