Vermietungs-Tool

A local web app for a small room-rental business in Austria: guest register,
room ledger, occupancy plan, invoices, the monthly tourist-tax report and the
quarterly VAT list. Application code only; it ships no data.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
BlackMarkandClaude Opus 5.5 committed 2026-11-02 16:52:27 +01:00
commit 45424e6fd6
47 files changed
+6701

No files matched your search

+89
View File
@@ -0,0 +1,89 @@
{% extends "base.html" %}
{% block content %}
{# Landscape when printed — the wide detail table reads better that way. As THIS document's default
page, not a named page: with mixed page sizes a printer may still print a later unit's part portrait.
This way there is only one size. #}
<style>@media print { @page { size: A4 landscape; margin: 10mm; } }</style>
<h1>{{ t('tvb_title') }} – {{ r.month_name }}</h1>
<p class="lead noprint">{{ t('tvb_intro') }}</p>
<form method="get" style="margin:10px 0 18px" class="noprint">
<label style="font-weight:600; margin-right:8px">{{ t('tvb_month') }}</label>
<input type="month" name="month" value="{{ month_value }}" onchange="this.form.submit()">
<button type="button" class="btn" style="margin-left:14px" onclick="window.print()">{{ t('btn_print') }}</button>
</form>
{% for u in r.units %}
<section class="tvb-unit" style="margin:0 0 34px">
<h2 style="margin:18px 0 4px">{{ u.name }}
<small style="font-weight:400; color:#6b756e">— {{ t('tvb_number') }} {{ u.tvb_number or '?' }}</small></h2>
{% if u.warnings %}
<div class="flash" style="margin:8px 0">
<b>{{ t('tvb_warnings') }}:</b>
{% for w in u.warnings %}<div>{{ w }}</div>{% endfor %}
</div>
{% endif %}
{% if not u.rows %}
<p>{{ t('tvb_empty') }}</p>
{% else %}
<h3 style="margin:12px 0 6px">{{ t('tvb_detail') }}</h3>
<div class="tablewrap" style="max-height:420px">
<table>
<thead><tr>
<th>{{ t('col_room') }}</th><th>{{ t('col_name') }}</th><th>{{ t('tvb_col_land') }}</th>
<th>{{ t('col_sheetno') }}</th><th class="num">{{ t('tvb_col_gb_new') }}</th>
<th>{{ t('tvb_col_stay') }}</th><th class="num">{{ t('tvb_col_nights_month') }}</th>
<th></th><th>{{ t('tvb_col_note') }}</th>
</tr></thead>
<tbody>
{% for row in u.rows %}
<tr>
<td>{{ row.room or '' }}</td><td>{{ row.name }}</td><td>{{ row.land }}</td>
<td>{{ row.sheet or '' }}</td><td class="num">{{ row.person }}</td>
<td>{{ row.arrival|date }}–{{ row.departure|date }}{% if row.total_nights %} ({{ row.total_nights }}){% endif %}</td>
<td class="num">{{ row.nights }}</td>
<td><span class="pill {{ 'paid' if row.exempt else 'open' }}">
{{ t('tvb_status_frei') if row.exempt else t('tvb_status_pflichtig') }}</span></td>
<td class="note"><div>{{ row.note or '' }}</div></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{# heading and tables stay on ONE sheet: otherwise "Für Feratel" can slide alone to the bottom of a
page and the figures onto the next #}
<div class="tvb-feratel">
<h3 style="margin:16px 0 6px">{{ t('tvb_feratel') }}</h3>
<div class="tvb-summary" style="display:flex; gap:26px; flex-wrap:wrap; align-items:flex-start">
{% for part, label in (('pflichtig', t('tvb_pflichtig')), ('frei', t('tvb_frei'))) %}
<div class="tablewrap" style="flex:0 1 340px">
<table>
<thead><tr><th>{{ label }}</th><th class="num">{{ t('tvb_col_pn') }}</th></tr></thead>
<tbody>
{% for v in u[part] %}
<tr><td>{{ v.land }}</td><td class="num">{{ v.persons }}/{{ v.nights }}</td></tr>
{% endfor %}
<tr style="font-weight:700; border-top:2px solid #9a9a9a">
<td>{{ t('sum_label') }}</td>
<td class="num">{{ u[part + '_sum'].persons }}/{{ u[part + '_sum'].nights }}</td></tr>
</tbody>
</table>
</div>
{% endfor %}
</div>
<p style="margin:10px 0 0">
<b>{{ t('tvb_total') }}:</b>
{{ t('tvb_pflichtig') }} {{ u.pflichtig_sum.persons }}/{{ u.pflichtig_sum.nights }} ·
{{ t('tvb_frei') }} {{ u.frei_sum.persons }}/{{ u.frei_sum.nights }}
&nbsp;·&nbsp; <b>{{ t('tvb_betrag') }}:</b> {{ u.betrag|euro }}
({{ u.pflichtig_sum.nights }} × {{ r.rate|euro }})
&nbsp;·&nbsp; {{ t('tvb_new_sheets') }}: <b>{{ u.new_sheets }}</b>
</p>
</div>
{% endif %}
</section>
{% endfor %}
{% endblock %}