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>
78 lines
5.1 KiB
HTML
78 lines
5.1 KiB
HTML
{% extends "base.html" %}
|
|
{% block main_class %}grid-page{% endblock %}
|
|
{% block content %}
|
|
{% set unit_opts = rows|map(attribute='unit')|select|unique|sort %}
|
|
{% set nat_opts = rows|map(attribute='nationality')|select|unique|sort %}
|
|
<h1>{{ t('register_title') }}</h1>
|
|
<div class="toolbar">
|
|
<input class="search live-search" data-grid="reg" type="text" placeholder="{{ t('search_placeholder') }}">
|
|
<select class="live-filter" data-grid="reg" data-col="{{ t('col_unit') }}"><option value="">{{ t('filter_all', col=t('col_unit')) }}</option>
|
|
{% for u in unit_opts %}<option>{{ u }}</option>{% endfor %}</select>
|
|
<select class="live-filter" data-grid="reg" data-col="{{ t('col_departure') }}"><option value="">{{ t('filter_all', col=t('filter_stay')) }}</option>
|
|
<option value="__empty__">{{ t('filter_still_here') }}</option>
|
|
<option value="__filled__">{{ t('filter_departed') }}</option></select>
|
|
<select class="live-filter" data-grid="reg" data-col="{{ t('col_nationality') }}"><option value="">{{ t('filter_all', col=t('col_nationality')) }}</option>
|
|
{% for nat in nat_opts %}<option>{{ nat }}</option>{% endfor %}</select>
|
|
<span class="count"><span class="grid-count" data-grid="reg">{{ rows|length }}</span> {{ t('showing_count', count='')|trim }}</span>
|
|
<span class="spacer"></span>
|
|
<button class="btn secondary" type="button" onclick="invoiceFromSelection()">{{ t('btn_invoice_from_selection') }}</button>
|
|
<button class="btn secondary" type="button" onclick="gridPrint('reg')">{{ t('btn_print') }}</button>
|
|
<a class="btn" href="{{ url_for('stay_form') }}">+ {{ t('btn_add_stay') }}</a>
|
|
</div>
|
|
<p class="printinfo" data-grid="reg"></p>
|
|
|
|
<div class="tablewrap">
|
|
{# data-pin: checkbox, Einheit, G-Blatt, Name and Vorname stay on screen while scrolling #}
|
|
<table id="reg" class="grid" data-scroll="end" data-pin="1 2 3 4 5">
|
|
<thead><tr>
|
|
<th class="nosort selcol"></th><th>{{ t('col_unit') }}</th><th>{{ t('col_sheetno') }}</th>
|
|
<th>{{ t('col_lastname') }}</th><th>{{ t('col_firstname') }}</th><th>{{ t('col_birth') }}</th>
|
|
<th>{{ t('col_residence') }}</th><th>{{ t('col_room') }}</th>
|
|
<th>{{ t('col_arrival') }}</th><th>{{ t('col_departure') }}</th><th class="num">{{ t('col_days') }}</th>
|
|
<th>{{ t('col_tourism_liable') }}</th><th>{{ t('col_nationality') }}</th><th>{{ t('col_document') }}</th>
|
|
<th>{{ t('col_docnr') }}</th><th>{{ t('col_profession') }}</th><th>{{ t('col_address') }}</th>
|
|
<th>{{ t('col_postcode') }}</th><th>{{ t('col_city') }}</th><th>{{ t('col_country') }}</th>
|
|
<th>{{ t('col_phone') }}</th><th>{{ t('col_employer') }}</th><th>{{ t('col_employer_address') }}</th>
|
|
<th>{{ t('col_notes_long') }}</th>
|
|
<th class="nosort actions"></th>
|
|
</tr></thead>
|
|
<tbody>
|
|
{# rows ship inside an inert <template>: grids.js renders only the visible window (see freezeLayout) #}
|
|
<template>
|
|
{% for r in rows %}
|
|
<tr>
|
|
<td class="selcol"><input type="checkbox" class="rowsel" value="{{ r.stay_id }}"></td>
|
|
<td>{% if r.unit %}<span class="pill unit">{{ r.unit }}</span>{% endif %}</td>
|
|
<td>{{ r.sheet_number or '' }}</td><td>{{ r.last_name or '' }}</td><td>{{ r.first_name or '' }}</td>
|
|
<td>{{ r.birth_date|date }}</td>
|
|
<td>{{ 'HWS' if r.hauptwohnsitz == 1 else ('NWS' if r.hauptwohnsitz == 0 else '') }}</td>
|
|
<td>{{ r.room or '' }}</td>
|
|
{#- the weekday before the date; data-k = the ISO date, or the column would sort by "Mo/Di/Mi" -#}
|
|
<td{% if r.arrival %} data-k="{{ r.arrival|replace('-', '') }}"{% endif %}>{{ r.arrival|datewd }}</td><td{% if r.departure %} data-k="{{ r.departure|replace('-', '') }}"{% endif %}>{{ r.departure|datewd }}</td>
|
|
<td class="num">{{ r.days if r.days is not none else '' }}</td>
|
|
<td>{{ 'Ja' if r.tourism_liable == 1 else ('-' if r.tourism_liable == 0 else '') }}</td>
|
|
<td>{{ r.nationality or '' }}</td><td>{{ r.doc_type or '' }}</td>
|
|
<td>{{ r.doc_number or '' }}</td><td>{{ r.profession or '' }}</td><td>{{ r.home_street or '' }}</td>
|
|
<td>{{ r.home_postcode or '' }}</td><td>{{ r.home_city or '' }}</td><td>{{ r.home_country or '' }}</td>
|
|
<td>{{ r.phone or '' }}</td><td>{{ r.employer or '' }}</td>
|
|
<td>{{ r.employer_address or '' }}</td>
|
|
<td>{{ r.notes or '' }}</td>
|
|
<td class="actions"><a class="btn secondary small" href="{{ url_for('stay_form', stay_id=r.stay_id) }}">{{ t('btn_edit') }}</a></td>
|
|
</tr>
|
|
{% endfor %}
|
|
</template>
|
|
{% if not rows %}
|
|
<tr data-empty="1"><td class="empty" colspan="25">{{ t('no_results') }}</td></tr>
|
|
{% endif %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<script>
|
|
function invoiceFromSelection() {
|
|
var ids = window.gridChecked('reg'); // from the grid model — most rows are not in the DOM
|
|
if (!ids.length) { alert('Bitte zuerst Zeilen auswählen.'); return; }
|
|
window.location = '{{ url_for("invoice_new") }}?stays=' + ids.join(',');
|
|
}
|
|
</script>
|
|
{% endblock %}
|