feat: Vorschlaege mit Rhythmus, Start und Hinweis
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,15 +88,19 @@
|
||||
{% if suggestions %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>Name</th><th>Betrag</th><th>Rhythmus</th><th>Fälligkeitstag</th><th></th></tr>
|
||||
<tr><th>Name</th><th>Betrag</th><th>Rhythmus</th><th>Fälligkeitstag</th><th>Start</th><th></th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for s in suggestions %}
|
||||
<tr>
|
||||
<td>{{ s.name }}</td>
|
||||
<td class="{{ 'neg' if s.amount < 0 else '' }}">{{ s.amount|eur }} €</td>
|
||||
<td class="{{ 'neg' if s.amount < 0 else '' }}">
|
||||
{{ s.amount|eur }} €
|
||||
{% if s.hinweis %}<span class="muted">{{ s.hinweis }}</span>{% endif %}
|
||||
</td>
|
||||
<td>{{ s.rhythm|de_label }}</td>
|
||||
<td>{{ s.due_day }}</td>
|
||||
<td>{{ s.start_date.strftime('%d.%m.%Y') if s.start_date else '–' }}</td>
|
||||
<td>
|
||||
<form class="inline-form" hx-ext="json-form" hx-post="/api/recurring" hx-swap="none"
|
||||
hx-on::after-request="if(event.detail.successful){window.location.reload()}">
|
||||
@@ -105,6 +109,7 @@
|
||||
<input type="hidden" name="rhythm" value="{{ s.rhythm }}">
|
||||
<input type="hidden" name="due_day" data-type="int" value="{{ s.due_day }}">
|
||||
<input type="hidden" name="category_id" data-type="int" value="{{ s.category_id if s.category_id is not none else '' }}">
|
||||
<input type="hidden" name="start_date" value="{{ s.start_date.isoformat() if s.start_date else '' }}">
|
||||
<button type="submit">Vorschlag übernehmen</button>
|
||||
</form>
|
||||
</td>
|
||||
@@ -113,8 +118,9 @@
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="muted">Keine Vorschläge — erkannt werden Serien aus mindestens 3 Monaten gleichartiger Buchungen.</p>
|
||||
<p class="muted">Keine Vorschläge.</p>
|
||||
{% endif %}
|
||||
<p class="muted">Erkannt werden monatliche, vierteljährliche und jährliche Serien; Betrag = jeweils letzte Buchung.</p>
|
||||
</fieldset>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -246,6 +246,33 @@ def test_planning_page_shows_empty_suggestions_hint(client):
|
||||
assert r.status_code == 200
|
||||
assert "Vorschläge aus Buchungen" in r.text
|
||||
assert "Keine Vorschläge" in r.text
|
||||
assert ("Erkannt werden monatliche, vierteljährliche und jährliche "
|
||||
"Serien; Betrag = jeweils letzte Buchung.") in r.text
|
||||
|
||||
|
||||
def test_vorschlaege_zeigen_rhythmus_und_start(client, db):
|
||||
# Synthetische vierteljaehrliche Serie relativ zu date.today(), da die
|
||||
# Route suggest_recurring() ohne today-Injektion aufruft (echter
|
||||
# Aktiv-Check gegen date.today()). Schrittweite ~91 Tage rueckwaerts,
|
||||
# letzte Buchung 30 Tage vor heute (innerhalb des Aktiv-Fensters).
|
||||
from app.models.tables import Transaction
|
||||
|
||||
client.post("/login", data={"username": "admin", "password": "geheim"})
|
||||
acc = Account(bank="dkb", iban="DE-SUG-1", name="S", type="giro")
|
||||
db.add(acc)
|
||||
db.flush()
|
||||
today = date.today()
|
||||
booking_dates = [today - timedelta(days=d) for d in (303, 212, 121, 30)]
|
||||
for d in booking_dates:
|
||||
db.add(Transaction(account_id=acc.id, booking_date=d, amount=Decimal("-55.08"),
|
||||
purpose="p", counterparty="Rundfunk Synth", status="confirmed",
|
||||
dedup_hash=f"sug-{d.isoformat()}"))
|
||||
db.commit()
|
||||
r = client.get("/planung").text
|
||||
letzte_buchung = booking_dates[-1]
|
||||
assert "vierteljährlich" in r
|
||||
assert letzte_buchung.strftime("%d.%m.%Y") in r
|
||||
assert 'name="start_date"' in r
|
||||
|
||||
|
||||
def test_salden_page_stichtag_and_month_overview(client, db):
|
||||
|
||||
Reference in New Issue
Block a user