Files
2026-09-28 19:29:25 +02:00

141 lines
5.6 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}Buchungen – Finanzberatung{% endblock %}
{% block content %}
<h1>Buchungen</h1>
<form class="filter-form" method="get" action="/buchungen">
<label>Konto
<select name="account_id">
<option value="">alle</option>
{% for a in accounts %}
<option value="{{ a.id }}" {% if filters.account_id == a.id %}selected{% endif %}>{{ a.name }}</option>
{% endfor %}
</select>
</label>
<label>Von
<input type="date" name="date_from" value="{{ filters.date_from.isoformat() if filters.date_from else '' }}">
</label>
<label>Bis
<input type="date" name="date_to" value="{{ filters.date_to.isoformat() if filters.date_to else '' }}">
</label>
<label>Kategorie
<select name="category_id">
<option value="">alle</option>
{% for c in categories %}
<option value="{{ c.id }}" {% if filters.category_id == c.id %}selected{% endif %}>{{ c.name }}</option>
{% endfor %}
</select>
</label>
<label>Suche
<input type="text" name="q" value="{{ filters.q }}" placeholder="Verwendungszweck / Empfänger">
</label>
<label>Status
<select name="status">
{% for s in ("confirmed", "draft") %}
<option value="{{ s }}" {% if filters.status == s %}selected{% endif %}>{{ s }}</option>
{% endfor %}
</select>
</label>
<button type="submit">Filtern</button>
</form>
{% set filter_params = {
'account_id': filters.account_id,
'date_from': filters.date_from.isoformat() if filters.date_from else None,
'date_to': filters.date_to.isoformat() if filters.date_to else None,
'category_id': filters.category_id,
'q': filters.q,
'status': filters.status,
} %}
{% macro sort_th(key, label, params, cur_sort, cur_dir) -%}
{%- set active = cur_sort == key -%}
<th>{{ label }} <a class="sort-btn{{ ' active' if active else '' }}" aria-label="Nach {{ label }} sortieren"
href="/buchungen?{% for k, v in params.items() %}{% if v %}{{ k }}={{ v|urlencode }}&{% endif %}{% endfor %}sort={{ key }}&dir={{ 'desc' if active and cur_dir == 'asc' else 'asc' }}">{{ ('▲' if cur_dir == 'asc' else '▼') if active else '⇅' }}</a></th>
{%- endmacro %}
<table data-sort-mode="server">
<thead>
<tr>
{{ sort_th('datum', 'Datum', filter_params, sort, dir) }}{{ sort_th('konto', 'Konto', filter_params, sort, dir) }}
{{ sort_th('zweck', 'Verwendungszweck', filter_params, sort, dir) }}{{ sort_th('empfaenger', 'Empfänger/Zahler', filter_params, sort, dir) }}
{{ sort_th('betrag', 'Betrag (€)', filter_params, sort, dir) }}{{ sort_th('kategorie', 'Kategorie', filter_params, sort, dir) }}<th></th>
</tr>
</thead>
<tbody>
{% for tx in transactions %}
<tr>
<td>{{ tx.booking_date.strftime('%d.%m.%Y') }}</td>
<td class="account">{{ account_names.get(tx.account_id, tx.account_id) }}</td>
<td>{{ tx.purpose }}</td>
<td>{{ tx.counterparty }}</td>
<td class="amount {{ 'neg' if tx.amount < 0 else '' }}">{{ tx.amount|eur }}</td>
<td>
<select name="category_id" data-type="int" hx-ext="json-form"
hx-patch="/api/transactions/{{ tx.id }}" hx-trigger="change" hx-swap="none">
<option value="">–</option>
{% for c in categories %}
<option value="{{ c.id }}" {% if tx.category_id == c.id %}selected{% endif %}>{{ c.name }}</option>
{% endfor %}
</select>
</td>
<td>
<details>
<summary>Regel erzeugen</summary>
<form hx-ext="json-form" hx-post="/api/category-rules" hx-swap="none"
hx-on::after-request="if(event.detail.successful){this.closest('details').open=false}">
<input type="hidden" name="pattern" value="{{ tx.counterparty }}">
<label>Kategorie
<select name="category_id" data-type="int" required>
{% for c in categories %}
<option value="{{ c.id }}" {% if tx.category_id == c.id %}selected{% endif %}>{{ c.name }}</option>
{% endfor %}
</select>
</label>
<button type="submit">Regel speichern</button>
</form>
</details>
</td>
</tr>
{% else %}
<tr><td colspan="7">Keine Buchungen gefunden.</td></tr>
{% endfor %}
</tbody>
</table>
<p class="pager">
{% if page > 1 %}
<a href="/buchungen?{% for k, v in filter_params.items() %}{% if v %}{{ k }}={{ v|urlencode }}&{% endif %}{% endfor %}sort={{ sort }}&dir={{ dir }}&page={{ page - 1 }}">Zurück</a>
{% endif %}
Seite {{ page }} von {{ total_pages }}
{% if page < total_pages %}
<a href="/buchungen?{% for k, v in filter_params.items() %}{% if v %}{{ k }}={{ v|urlencode }}&{% endif %}{% endfor %}sort={{ sort }}&dir={{ dir }}&page={{ page + 1 }}">Weiter</a>
{% endif %}
</p>
<fieldset>
<legend>Buchung manuell erfassen</legend>
<form hx-ext="json-form" hx-post="/api/transactions" hx-swap="none"
hx-on::after-request="if(event.detail.successful){this.reset(); window.location.reload()}">
<label>Konto
<select name="account_id" data-type="int" required>
{% for a in accounts %}
<option value="{{ a.id }}">{{ a.name }}</option>
{% endfor %}
</select>
</label>
<label>Buchungsdatum
<input type="date" name="booking_date" required>
</label>
<label>Betrag
<input type="text" name="amount" placeholder="-12.50" required>
</label>
<label>Verwendungszweck
<input type="text" name="purpose">
</label>
<label>Empfänger/Zahler
<input type="text" name="counterparty">
</label>
<button type="submit">Buchung speichern</button>
</form>
</fieldset>
{% endblock %}