feat: deutsche Betragsanzeige (eur-Filter) und deutsche GUI-Labels

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 11:23:26 +02:00
parent bd9df8ab8b
commit fe0e1b5e93
9 changed files with 138 additions and 35 deletions

View File

@@ -0,0 +1,43 @@
from decimal import Decimal
from app.formats import DE_LABELS, de_label, eur
def test_eur_basisformat():
assert eur(Decimal("2474.00")) == "2.474,00"
def test_eur_negativ_mit_mehreren_tausenderpunkten():
assert eur(Decimal("-1234567.5")) == "-1.234.567,50"
def test_eur_null_und_kleinbetraege():
assert eur(Decimal("0")) == "0,00"
assert eur(Decimal("-0.5")) == "-0,50"
assert eur(Decimal("999.99")) == "999,99"
def test_eur_rundung_half_up():
assert eur(Decimal("1.005")) == "1,01"
assert eur(Decimal("-1.005")) == "-1,01"
def test_eur_akzeptiert_strings_und_int():
# Templates reichen teils DB-Werte als str/int durch (z.B. Suggestions).
assert eur("1234.5") == "1.234,50"
assert eur(7) == "7,00"
def test_de_label_bekannte_und_unbekannte_werte():
assert de_label("monthly") == "monatlich"
assert de_label("quarterly") == "vierteljährlich"
assert de_label("yearly") == "jährlich"
assert de_label("annuity") == "Annuität"
assert de_label("bullet") == "endfällig"
assert de_label("percent") == "Prozent"
assert de_label("absolute") == "Absolut"
assert de_label("remove") == "Entfällt"
assert de_label("ende") == "Ende"
assert de_label("weirdvalue") == "weirdvalue"
assert set(DE_LABELS) == {"monthly", "quarterly", "yearly", "annuity",
"bullet", "percent", "absolute", "remove", "ende"}

View File

@@ -1,7 +1,8 @@
from datetime import date, timedelta
from decimal import Decimal
from app.models.tables import Account
from app.formats import eur
from app.models.tables import Account, RecurringItem
H = {"Authorization": "Bearer test-key"}
@@ -34,7 +35,7 @@ def test_index_shows_account_anchor(client, db):
r = client.get("/")
assert r.status_code == 200
assert "Anker: 321.00" in r.text
assert "Anker: 321,00" in r.text
assert "30.06.2026" in r.text
assert "kein Anker" in r.text
# Inline-Pflegeformular fuer den Anker muss je Konto vorhanden sein.
@@ -42,6 +43,29 @@ def test_index_shows_account_anchor(client, db):
assert 'name="anchor_balance"' in r.text
def test_gui_zeigt_deutsche_betragsformate(client, db):
client.post("/login", data={"username": "admin", "password": "geheim"})
acc = Account(bank="dkb", iban="DE-FMT-1", name="Formatkonto", type="giro")
db.add(acc)
db.flush()
acc.anchor_date = date(2026, 6, 30)
acc.anchor_balance = Decimal("12345.60")
db.commit()
r = client.get("/")
assert "12.345,60" in r.text
assert "12345.60" not in r.text
def test_planung_zeigt_deutsche_labels(client, db):
client.post("/login", data={"username": "admin", "password": "geheim"})
db.add(RecurringItem(name="Miete-Label-Test", amount=Decimal("-600.00"),
rhythm="monthly", due_day=1))
db.commit()
r = client.get("/planung")
assert "monatlich" in r.text
assert "-600,00" in r.text
def test_import_page_has_dropzone_and_list(client):
client.post("/login", data={"username": "admin", "password": "geheim"})
r = client.get("/import")
@@ -234,7 +258,7 @@ def test_salden_page_stichtag_and_month_overview(client, db):
expected_stichtag = Decimal("1000.00") + Decimal("111.11") + Decimal("22.22")
r = client.get(f"/salden?stichtag={stichtag.isoformat()}")
assert r.status_code == 200
assert f"{expected_stichtag:.2f}" in r.text
assert eur(expected_stichtag) in r.text
# Monatsuebersicht: genau 3 Monatszeilen (m2, m1, m0).
assert r.text.count('data-month="') == 3
@@ -245,7 +269,7 @@ def test_salden_page_stichtag_and_month_overview(client, db):
# m2), d.h. NACH Buchung 1 (in m2), aber VOR Buchung 2 (die faellt erst
# in m1 selbst und darf den Monatsanfang nicht verfaelschen).
expected_m1_start = Decimal("1000.00") + Decimal("111.11")
assert f"{expected_m1_start:.2f}" in r.text
assert eur(expected_m1_start) in r.text
def test_salden_stichtag_garbage_falls_back_to_today(client):