diff --git a/finance/app/routers/gui.py b/finance/app/routers/gui.py index 992586f..5503fcb 100644 --- a/finance/app/routers/gui.py +++ b/finance/app/routers/gui.py @@ -392,7 +392,7 @@ def _parse_monat(value: str | None, today: date) -> date | None: if not value: return today.replace(day=1) m = re.fullmatch(r"(\d{4})-(\d{2})", value.strip()) - if not m or not 1 <= int(m.group(2)) <= 12: + if not m or not 1 <= int(m.group(2)) <= 12 or int(m.group(1)) < 1: return None return date(int(m.group(1)), int(m.group(2)), 1) @@ -429,7 +429,7 @@ def _aufteilung_context(session: Session, today: date, monat: str | None, ctx["monat_anzeige"] = month.strftime("%m.%Y") scenario = None if szenario: - valid_id = szenario.isdigit() and len(szenario) <= 9 # kein Integer-Überlauf in der DB + valid_id = re.fullmatch(r"[0-9]{1,9}", szenario) # ASCII, kein Integer-Überlauf scenario = session.get(Scenario, int(szenario)) if valid_id else None if scenario is None: ctx["error"] = "Unbekanntes Szenario – bitte neu wählen." diff --git a/finance/app/static/style.css b/finance/app/static/style.css index e56471f..8c06076 100644 --- a/finance/app/static/style.css +++ b/finance/app/static/style.css @@ -248,12 +248,13 @@ label:has(input:disabled), label:has(select:disabled) { .kennzahlen { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-bottom: 1rem; } .kennzahlen div { display: flex; flex-direction: column; } .kennzahlen strong { font-size: 1.25rem; } -.aufteilung-grid { - display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); - gap: 1.5rem; align-items: start; +.tabelle-scroll { overflow-x: auto; } +/* Torte: schmal untereinander, breit SVG neben Legende */ +.torte { margin: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; align-items: start; } +@media (min-width: 700px) { + .torte { grid-template-columns: 280px minmax(0, 1fr); } + .torte figcaption { grid-column: 1 / -1; } } -@media (max-width: 800px) { .aufteilung-grid { grid-template-columns: minmax(0, 1fr); } } -.torte { margin: 0; } .torte figcaption { font-weight: bold; margin-bottom: 0.5rem; } .torte-svg { width: 100%; max-width: 280px; display: block; margin: 0 auto; } .torte-svg .seg { stroke: #fff; stroke-width: 0.02; } diff --git a/finance/app/templates/aufteilung.html b/finance/app/templates/aufteilung.html index 222f52a..4ec874f 100644 --- a/finance/app/templates/aufteilung.html +++ b/finance/app/templates/aufteilung.html @@ -38,8 +38,7 @@ {% if s.deficit %}
Kosten übersteigen die Einkünfte um {{ (s.costs - s.income)|eur }} € — das Diagramm zeigt die Aufteilung der Gesamtkosten.
{% endif %} -
-
+
@@ -63,12 +62,11 @@
PostenKategorieArtMonatsbetrag% der Einkünfte
-

Gesamte Einkünfte: {{ s.income|eur }} €

-
+
+

Gesamte Einkünfte: {{ s.income|eur }} €

{% include "_aufteilung_torte.html" %}
-
{% endif %} {% endif %} diff --git a/finance/tests/test_aufteilung_gui.py b/finance/tests/test_aufteilung_gui.py index 3a69692..4092035 100644 --- a/finance/tests/test_aufteilung_gui.py +++ b/finance/tests/test_aufteilung_gui.py @@ -129,6 +129,8 @@ def test_ungueltiger_monat_und_unbekanntes_szenario(client): _login(client) for params, text in (({"monat": "2030-13"}, "Ungültiger Monat"), ({"monat": "abc"}, "Ungültiger Monat"), + ({"monat": "0000-01"}, "Ungültiger Monat"), + ({"monat": MONAT, "szenario": "²"}, "Unbekanntes Szenario"), ({"monat": MONAT, "szenario": "999"}, "Unbekanntes Szenario"), ({"monat": MONAT, "szenario": "x"}, "Unbekanntes Szenario"), ({"monat": MONAT, "szenario": "9" * 30}, "Unbekanntes Szenario")): @@ -148,3 +150,11 @@ def test_doppelzaehlungs_hinweis(client, db): db.commit() assert "⚠ Fixposten „Autorate“ zählt evtl. doppelt mit Kredit „Autokredit“" in _get(client, monat=MONAT).text assert "⚠" not in _get(client, monat=MONAT, gesendet="1", fixposten="1", einmal="1").text + + +def test_tabelle_scrollbar_torte_darunter(client, db): + _login(client) + _daten(db) + t = _get(client, monat=MONAT).text + assert re.search(r'
\s* t.index("")