feat: deutsche Betragsanzeige (eur-Filter) und deutsche GUI-Labels
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
<td>{{ tx.booking_date.strftime('%d.%m.%Y') }}</td>
|
||||
<td>{{ tx.purpose }}</td>
|
||||
<td>{{ tx.counterparty }}</td>
|
||||
<td class="{{ 'neg' if tx.amount < 0 else '' }}">{{ '%.2f'|format(tx.amount) }} €</td>
|
||||
<td class="{{ 'neg' if tx.amount < 0 else '' }}">{{ tx.amount|eur }} €</td>
|
||||
<td>{% if tx.is_duplicate %}<span class="badge badge-warning">Duplikat</span>{% endif %}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
@@ -25,7 +25,7 @@
|
||||
{% else %}
|
||||
<span class="badge badge-error">Saldo-Differenz – bitte prüfen</span>
|
||||
{% endif %}
|
||||
· Eröffnungssaldo: {{ '%.2f'|format(statement.opening_balance) if statement.opening_balance is not none else '–' }} €
|
||||
· Endsaldo: {{ '%.2f'|format(statement.closing_balance) if statement.closing_balance is not none else '–' }} €
|
||||
· Eröffnungssaldo: {{ statement.opening_balance|eur if statement.opening_balance is not none else '–' }} €
|
||||
· Endsaldo: {{ statement.closing_balance|eur if statement.closing_balance is not none else '–' }} €
|
||||
· Duplikate: {{ duplicates }}
|
||||
</p>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{% endif %}
|
||||
|
||||
<div class="total-balance {{ 'neg' if total < 0 else '' }}">
|
||||
Gesamtsaldo: {{ '%.2f'|format(total) }} €
|
||||
Gesamtsaldo: {{ total|eur }} €
|
||||
</div>
|
||||
|
||||
<table>
|
||||
@@ -26,10 +26,10 @@
|
||||
<tr>
|
||||
<td class="account">{{ account.name }}</td>
|
||||
<td>{{ account.bank }}</td>
|
||||
<td class="{{ 'neg' if balance < 0 else '' }}">{{ '%.2f'|format(balance) }} €</td>
|
||||
<td class="{{ 'neg' if balance < 0 else '' }}">{{ balance|eur }} €</td>
|
||||
<td>
|
||||
{% if account.anchor_date is not none and account.anchor_balance is not none %}
|
||||
Anker: {{ '%.2f'|format(account.anchor_balance) }} € am {{ account.anchor_date.strftime('%d.%m.%Y') }}
|
||||
Anker: {{ account.anchor_balance|eur }} € am {{ account.anchor_date.strftime('%d.%m.%Y') }}
|
||||
{% else %}
|
||||
kein Anker
|
||||
{% endif %}
|
||||
@@ -47,7 +47,7 @@
|
||||
<input type="date" name="anchor_date"
|
||||
value="{{ account.anchor_date.isoformat() if account.anchor_date is not none else '' }}" required>
|
||||
<input type="text" name="anchor_balance" placeholder="500.00"
|
||||
value="{{ account.anchor_balance if account.anchor_balance is not none else '' }}" required>
|
||||
value="{{ account.anchor_balance|eur if account.anchor_balance is not none else '' }}" required>
|
||||
<button type="submit">Anker setzen</button>
|
||||
</form>
|
||||
</td>
|
||||
@@ -68,7 +68,7 @@
|
||||
<tr>
|
||||
<td>{{ item.date.strftime('%d.%m.%Y') }}</td>
|
||||
<td>{{ item.name }}</td>
|
||||
<td class="{{ 'neg' if item.amount < 0 else '' }}">{{ '%.2f'|format(item.amount) }} €</td>
|
||||
<td class="{{ 'neg' if item.amount < 0 else '' }}">{{ item.amount|eur }} €</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="3">Keine anstehenden Posten.</td></tr>
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
{% for r in recurring %}
|
||||
<tr>
|
||||
<td>{{ r.name }}</td>
|
||||
<td class="{{ 'neg' if r.amount < 0 else '' }}">{{ '%.2f'|format(r.amount) }} €</td>
|
||||
<td>{{ r.rhythm }}</td>
|
||||
<td class="{{ 'neg' if r.amount < 0 else '' }}">{{ r.amount|eur }} €</td>
|
||||
<td>{{ r.rhythm|de_label }}</td>
|
||||
<td>{{ r.due_day }}</td>
|
||||
<td>{{ category_names.get(r.category_id, '–') }}</td>
|
||||
<td>
|
||||
@@ -39,7 +39,7 @@
|
||||
<label>Betrag <input type="text" name="amount" placeholder="-49.99" required></label>
|
||||
<label>Rhythmus
|
||||
<select name="rhythm" data-type="str">
|
||||
{% for rh in rhythms %}<option value="{{ rh }}">{{ rh }}</option>{% endfor %}
|
||||
{% for rh in rhythms %}<option value="{{ rh }}">{{ rh|de_label }}</option>{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
<label>Fälligkeitstag <input type="number" name="due_day" data-type="int" min="1" max="31" required></label>
|
||||
@@ -64,8 +64,8 @@
|
||||
{% for s in suggestions %}
|
||||
<tr>
|
||||
<td>{{ s.name }}</td>
|
||||
<td class="{{ 'neg' if s.amount < 0 else '' }}">{{ '%.2f'|format(s.amount) }} €</td>
|
||||
<td>{{ s.rhythm }}</td>
|
||||
<td class="{{ 'neg' if s.amount < 0 else '' }}">{{ s.amount|eur }} €</td>
|
||||
<td>{{ s.rhythm|de_label }}</td>
|
||||
<td>{{ s.due_day }}</td>
|
||||
<td>
|
||||
<form class="inline-form" hx-ext="json-form" hx-post="/api/recurring" hx-swap="none"
|
||||
@@ -98,7 +98,7 @@
|
||||
{% for p in planned %}
|
||||
<tr>
|
||||
<td>{{ p.name }}</td>
|
||||
<td class="{{ 'neg' if p.amount < 0 else '' }}">{{ '%.2f'|format(p.amount) }} €</td>
|
||||
<td class="{{ 'neg' if p.amount < 0 else '' }}">{{ p.amount|eur }} €</td>
|
||||
<td>{{ p.due.strftime('%d.%m.%Y') }}</td>
|
||||
<td>{{ category_names.get(p.category_id, '–') }}</td>
|
||||
<td>
|
||||
@@ -143,11 +143,11 @@
|
||||
{% for l in loans %}
|
||||
<tr>
|
||||
<td>{{ l.name }}</td>
|
||||
<td>{{ '%.2f'|format(l.principal) }} €</td>
|
||||
<td>{{ '%.2f'|format(l.annual_rate_pct) }} %</td>
|
||||
<td>{{ l.principal|eur }} €</td>
|
||||
<td>{{ l.annual_rate_pct|eur }} %</td>
|
||||
<td>{{ l.term_months }} Monate</td>
|
||||
<td>{{ l.payout_date.strftime('%d.%m.%Y') }}</td>
|
||||
<td>{{ l.repayment_type }}</td>
|
||||
<td>{{ l.repayment_type|de_label }}</td>
|
||||
<td>
|
||||
<form class="inline-form" hx-delete="/api/loans/{{ l.id }}" hx-swap="none"
|
||||
hx-confirm="„{{ l.name }}“ wirklich löschen?"
|
||||
@@ -181,7 +181,7 @@
|
||||
<label>Auszahlungsdatum <input type="date" name="payout_date" required></label>
|
||||
<label>Tilgungsart
|
||||
<select name="repayment_type" data-type="str">
|
||||
{% for rt in repayment_types %}<option value="{{ rt }}">{{ rt }}</option>{% endfor %}
|
||||
{% for rt in repayment_types %}<option value="{{ rt }}">{{ rt|de_label }}</option>{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
<button type="submit">Anlegen</button>
|
||||
@@ -227,8 +227,8 @@
|
||||
{% if m.target_type == "category" %}Kategorie: {{ category_names.get(m.target_id, m.target_id) }}
|
||||
{% else %}Posten: {{ recurring_names.get(m.target_id, m.target_id) }}{% endif %}
|
||||
</td>
|
||||
<td>{{ m.kind }}</td>
|
||||
<td>{{ '%.2f'|format(m.value) }}</td>
|
||||
<td>{{ m.kind|de_label }}</td>
|
||||
<td>{{ m.value|eur }}</td>
|
||||
<td>
|
||||
<form class="inline-form" hx-delete="/api/scenarios/{{ sc.id }}/modifiers/{{ m.id }}" hx-swap="none"
|
||||
hx-on::after-request="if(event.detail.successful){window.location.reload()}">
|
||||
@@ -266,7 +266,7 @@
|
||||
</span>
|
||||
<label>Art
|
||||
<select name="kind" data-type="str">
|
||||
{% for k in modifier_kinds %}<option value="{{ k }}">{{ k }}</option>{% endfor %}
|
||||
{% for k in modifier_kinds %}<option value="{{ k }}">{{ k|de_label }}</option>{% endfor %}
|
||||
</select>
|
||||
</label>
|
||||
<label>Wert <input type="text" name="value" value="0"></label>
|
||||
@@ -281,7 +281,7 @@
|
||||
|
||||
{% if row.result %}
|
||||
<p>
|
||||
Tiefpunkt: {{ '%.2f'|format(row.result.low_point_balance) }} € am {{ row.result.low_point_date.strftime('%d.%m.%Y') }}<br>
|
||||
Tiefpunkt: {{ row.result.low_point_balance|eur }} € am {{ row.result.low_point_date.strftime('%d.%m.%Y') }}<br>
|
||||
{% if row.result.below_zero_date %}Unterschreitet 0 € ab {{ row.result.below_zero_date.strftime('%d.%m.%Y') }}<br>{% endif %}
|
||||
{% if row.result.below_threshold_date %}Unterschreitet Warnschwelle ab {{ row.result.below_threshold_date.strftime('%d.%m.%Y') }}<br>{% endif %}
|
||||
Kurven in <a href="http://{{ request.url.hostname or '127.0.0.1' }}:8097" target="_blank" rel="noopener">Grafana</a> ansehen.
|
||||
@@ -343,6 +343,9 @@
|
||||
var parts = iso.split('-');
|
||||
return parts[2] + '.' + parts[1] + '.' + parts[0];
|
||||
}
|
||||
function fmtEur(n) {
|
||||
return Number(n).toLocaleString('de-DE', {minimumFractionDigits: 2, maximumFractionDigits: 2});
|
||||
}
|
||||
function loadLoanSchedule(loanId) {
|
||||
if (loadedSchedules[loanId]) return;
|
||||
loadedSchedules[loanId] = true;
|
||||
@@ -353,10 +356,10 @@
|
||||
+ '<th>Tilgung</th><th>Restschuld</th></tr></thead><tbody>';
|
||||
rows.forEach(function (r) {
|
||||
html += '<tr><td>' + formatIsoDate(r.due) + '</td>'
|
||||
+ '<td>' + Number(r.payment).toFixed(2) + ' €</td>'
|
||||
+ '<td>' + Number(r.interest).toFixed(2) + ' €</td>'
|
||||
+ '<td>' + Number(r.principal).toFixed(2) + ' €</td>'
|
||||
+ '<td>' + Number(r.remaining).toFixed(2) + ' €</td></tr>';
|
||||
+ '<td>' + fmtEur(r.payment) + ' €</td>'
|
||||
+ '<td>' + fmtEur(r.interest) + ' €</td>'
|
||||
+ '<td>' + fmtEur(r.principal) + ' €</td>'
|
||||
+ '<td>' + fmtEur(r.remaining) + ' €</td></tr>';
|
||||
});
|
||||
html += '</tbody></table>';
|
||||
document.getElementById('schedule-' + loanId).innerHTML = html;
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
{% for account, balance in balances %}
|
||||
<tr>
|
||||
<td class="account">{{ account.name }}</td>
|
||||
<td class="amount {{ 'neg' if balance < 0 else '' }}">{{ '%.2f'|format(balance) }} €</td>
|
||||
<td class="amount {{ 'neg' if balance < 0 else '' }}">{{ balance|eur }} €</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="2">Keine Konten angelegt.</td></tr>
|
||||
{% endfor %}
|
||||
<tr class="total-row">
|
||||
<td><strong>Gesamt</strong></td>
|
||||
<td class="amount {{ 'neg' if total < 0 else '' }}"><strong>{{ '%.2f'|format(total) }} €</strong></td>
|
||||
<td class="amount {{ 'neg' if total < 0 else '' }}"><strong>{{ total|eur }} €</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -48,9 +48,9 @@
|
||||
<tr data-month="{{ row['month'].isoformat() }}">
|
||||
<td>{{ row['month'].strftime('%m.%Y') }}</td>
|
||||
{% for account, value in row['values'] %}
|
||||
<td class="amount {{ 'neg' if value < 0 else '' }}">{{ '%.2f'|format(value) }} €</td>
|
||||
<td class="amount {{ 'neg' if value < 0 else '' }}">{{ value|eur }} €</td>
|
||||
{% endfor %}
|
||||
<td class="amount {{ 'neg' if row['total'] < 0 else '' }}">{{ '%.2f'|format(row['total']) }} €</td>
|
||||
<td class="amount {{ 'neg' if row['total'] < 0 else '' }}">{{ row['total']|eur }} €</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="{{ accounts|length + 2 }}">Keine bestätigten Buchungen vorhanden.</td></tr>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<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 '' }}">{{ '%.2f'|format(tx.amount) }}</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">
|
||||
|
||||
Reference in New Issue
Block a user