feat: Szenarien-Seite mit zwei Formularen, Zeitraum-Spalte und wiederkehrenden Szenario-Zahlungen (A14-T4)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,8 +4,9 @@ from decimal import Decimal
|
||||
|
||||
from app.config import get_settings
|
||||
from app.formats import eur
|
||||
from app.models.tables import (Account, Loan, PlannedItem, RecurringItem,
|
||||
Scenario, ScenarioModifier, ScenarioPlannedItem)
|
||||
from app.models.tables import (Account, Category, Loan, PlannedItem, RecurringItem,
|
||||
Scenario, ScenarioModifier, ScenarioPlannedItem,
|
||||
ScenarioRecurringItem)
|
||||
|
||||
H = {"Authorization": "Bearer test-key"}
|
||||
|
||||
@@ -432,7 +433,7 @@ def test_szenario_eintraege_tabelle(client, db):
|
||||
# Anlege-Formular: Eintragsart inkl. Einmalzahlung + Endpunkt-Wechsel-Attribute
|
||||
assert 'value="einmal"' in r
|
||||
assert f'data-planned-url="/api/scenarios/{sc.id}/planned"' in r
|
||||
assert "onEntryArtChange" in r and "onModKindChange" not in r
|
||||
assert "FBSzenario.aenderungArt" in r and "onEntryArtChange" not in r
|
||||
|
||||
|
||||
def test_szenarien_seite_und_nav(client, db):
|
||||
@@ -459,7 +460,7 @@ def test_neuer_eintrag_formular_struktur(client, db):
|
||||
db.add(Scenario(name="UX-Test", description=""))
|
||||
db.commit()
|
||||
r = client.get("/szenarien").text
|
||||
assert 'class="entry-form"' in r
|
||||
assert 'class="entry-form aenderung-form"' in r and 'class="entry-form zahlung-form"' in r
|
||||
assert 'class="entry-art"' in r # Eintragsart-Zeile
|
||||
assert 'class="value-label"' in r # dynamisches Wert-Label
|
||||
assert 'Für diese Eintragsart nicht relevant' in r # Tooltip an Umschaltfeldern
|
||||
@@ -650,6 +651,57 @@ def test_statische_dateien_mit_versionskennung(client):
|
||||
assert re.search(r'/static/[^"?]+"', login) is None
|
||||
client.post("/login", data={"username": "admin", "password": "geheim"})
|
||||
html = client.get("/").text
|
||||
for datei in ("style.css", "htmx.min.js", "sort.js", "doppelzaehlung.js"):
|
||||
for datei in ("style.css", "htmx.min.js", "sort.js", "doppelzaehlung.js", "szenarien.js"):
|
||||
assert f'/static/{datei}?v={v}"' in html
|
||||
assert re.search(r'/static/[^"?]+"', html) is None
|
||||
|
||||
|
||||
def test_szenario_zwei_formulare(client, db):
|
||||
client.post("/login", data={"username": "admin", "password": "geheim"})
|
||||
sc = Scenario(name="Formulare-A14", description="")
|
||||
db.add(sc)
|
||||
db.commit()
|
||||
r = client.get("/szenarien").text
|
||||
assert "Neue Änderung an Bestehendem" in r and "Neue Zahlung nur in diesem Szenario" in r
|
||||
assert 'class="entry-form aenderung-form"' in r and 'class="entry-form zahlung-form"' in r
|
||||
assert f'hx-post="/api/scenarios/{sc.id}/modifiers"' in r
|
||||
assert f'data-planned-url="/api/scenarios/{sc.id}/planned"' in r
|
||||
assert f'data-recurring-url="/api/scenarios/{sc.id}/recurring"' in r
|
||||
assert 'value="set">Neuer Betrag<' in r and 'value="absolute">Kürzung (€)<' in r
|
||||
for feld in ('name="start_date"', 'name="end_date"', 'name="rhythm"',
|
||||
'name="due_day"', 'name="category_id"', 'name="due"'):
|
||||
assert feld in r, feld
|
||||
assert 'class="zahlung-art"' in r and '<option value="">(keine)</option>' in r
|
||||
assert 'class="bis-label"' in r
|
||||
|
||||
|
||||
def test_szenario_eintraege_zeitraum_und_wiederkehrend(client, db):
|
||||
client.post("/login", data={"username": "admin", "password": "geheim"})
|
||||
cat = Category(name="Kat-Anzeige")
|
||||
sc = Scenario(name="Anzeige-A14", description="")
|
||||
db.add_all([cat, sc])
|
||||
db.flush()
|
||||
db.add_all([
|
||||
ScenarioModifier(scenario_id=sc.id, target_type="recurring", target_id=1,
|
||||
kind="percent", value=Decimal("50"), start_date=date(2026, 10, 16)),
|
||||
ScenarioModifier(scenario_id=sc.id, target_type="recurring", target_id=1,
|
||||
kind="set", value=Decimal("-80.00"),
|
||||
start_date=date(2026, 11, 1), end_date=date(2027, 3, 31)),
|
||||
ScenarioModifier(scenario_id=sc.id, target_type="category", target_id=cat.id,
|
||||
kind="remove", value=Decimal("0"), end_date=date(2027, 6, 30)),
|
||||
ScenarioRecurringItem(scenario_id=sc.id, name="Zahlung-W", amount=Decimal("-137.50"),
|
||||
rhythm="monthly", due_day=14, start_date=date(2026, 10, 16),
|
||||
category_id=cat.id),
|
||||
ScenarioPlannedItem(scenario_id=sc.id, name="Zahlung-E", amount=Decimal("-5.00"),
|
||||
due=date(2026, 12, 1), category_id=cat.id),
|
||||
])
|
||||
db.commit()
|
||||
r = client.get("/szenarien").text
|
||||
assert "<th>Zeitraum</th>" in r
|
||||
assert "ab 16.10.2026" in r and "01.11.2026 – 31.03.2027" in r and "bis 30.06.2027" in r
|
||||
assert ">Neuer Betrag<" in r and "-80,00" in r
|
||||
assert "Zahlung-W" in r and "Wiederkehrend (monatlich, am 14.)" in r and "-137,50" in r
|
||||
assert f'hx-patch="/api/scenarios/{sc.id}/recurring/' in r
|
||||
assert f'hx-delete="/api/scenarios/{sc.id}/recurring/' in r
|
||||
assert "Kat-Anzeige" in r and "Zahlung-E" in r
|
||||
assert 'id="sri-row-' in r and 'id="sri-edit-' in r
|
||||
|
||||
Reference in New Issue
Block a user