upload
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Monatsreport {{ data.report.period.label }} - {{ data.customer.name }}</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary: {{ data.design.primary_color }};
|
||||
--accent: {{ data.design.accent_color }};
|
||||
--text: {{ data.design.text_color }};
|
||||
--muted: {{ data.design.muted_color }};
|
||||
--surface: {{ data.design.surface_color }};
|
||||
--line: #cfd6da;
|
||||
--positive: #236a4f;
|
||||
--negative: #9d3e3e;
|
||||
}
|
||||
@page { size: A4; margin: 15mm 16mm 19mm; }
|
||||
* { box-sizing: border-box; }
|
||||
html { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
||||
body { margin: 0; font-family: {{ data.design.font_family }}, Georgia, serif; color: var(--text); font-size: 9.5pt; line-height: 1.5; }
|
||||
h1, h2, h3, p { margin-top: 0; }
|
||||
h1 { font-size: 25pt; font-weight: 500; line-height: 1.12; margin-bottom: 2mm; }
|
||||
h2 { font-size: 15pt; font-weight: 600; color: var(--primary); margin-bottom: 3mm; }
|
||||
h3 { font-size: 10.5pt; margin-bottom: 1mm; }
|
||||
p { margin-bottom: 3mm; }
|
||||
.sans { font-family: Arial, sans-serif; }
|
||||
.header { border-top: 2.5mm solid var(--primary); padding-top: 7mm; margin-bottom: 8mm; display: grid; grid-template-columns: 1fr auto; gap: 8mm; }
|
||||
.brand { text-align: right; font-family: Arial, sans-serif; font-size: 8pt; color: var(--muted); }
|
||||
.brand strong { display: block; color: var(--primary); font-size: 10pt; margin-bottom: 1mm; }
|
||||
.period { font-family: Arial, sans-serif; text-transform: uppercase; letter-spacing: 1.4px; color: var(--accent); font-size: 8pt; font-weight: 700; }
|
||||
.meta { display: flex; gap: 6mm; color: var(--muted); font-family: Arial, sans-serif; font-size: 7.5pt; }
|
||||
.rule-heading { display: grid; grid-template-columns: auto 1fr; align-items: center; gap: 4mm; margin: 7mm 0 3mm; }
|
||||
.rule-heading h2 { margin: 0; white-space: nowrap; }
|
||||
.rule { height: .25mm; background: var(--line); }
|
||||
.summary { padding: 5mm 0 5mm 5mm; border-left: 1.2mm solid var(--accent); break-inside: avoid; }
|
||||
.summary h2 { color: var(--text); }
|
||||
.summary p { margin: 0; }
|
||||
.kpis { display: grid; grid-template-columns: repeat(4,1fr); border: .25mm solid var(--line); break-inside: avoid; }
|
||||
.kpi { padding: 4mm; border-right: .25mm solid var(--line); min-height: 28mm; }
|
||||
.kpi:last-child { border-right: 0; }
|
||||
.kpi-label { font-family: Arial, sans-serif; font-size: 7pt; text-transform: uppercase; letter-spacing: .8px; color: var(--muted); }
|
||||
.kpi-value { color: var(--primary); font-size: 15pt; font-weight: 600; margin: 2.5mm 0 1mm; white-space: nowrap; }
|
||||
.kpi-delta { font-family: Arial, sans-serif; font-size: 7pt; color: var(--muted); }
|
||||
.facts { display: grid; grid-template-columns: repeat(4,1fr); background: var(--surface); padding: 3mm 4mm; font-family: Arial, sans-serif; font-size: 7.5pt; }
|
||||
.facts strong { display: block; color: var(--primary); font-size: 9pt; margin-top: .5mm; }
|
||||
table { width: 100%; border-collapse: collapse; break-inside: avoid; font-family: Arial, sans-serif; font-size: 7.6pt; }
|
||||
th { text-align: left; color: var(--muted); font-size: 6.8pt; text-transform: uppercase; letter-spacing: .7px; padding: 2.5mm; border-bottom: .5mm solid var(--primary); }
|
||||
td { padding: 2.5mm; border-bottom: .25mm solid var(--line); }
|
||||
td.num, th.num { text-align: right; }
|
||||
.developments { columns: 2; column-gap: 6mm; }
|
||||
.development { break-inside: avoid; padding: 0 0 3mm 4mm; margin-bottom: 3mm; border-left: .8mm solid var(--line); }
|
||||
.development.positive { border-left-color: var(--positive); }
|
||||
.development.negative { border-left-color: var(--negative); }
|
||||
.development p { margin: 0; }
|
||||
.recommendation { break-inside: avoid; display: grid; grid-template-columns: 10mm 1fr; gap: 4mm; padding: 4mm 0; border-bottom: .25mm solid var(--line); }
|
||||
.recommendation:last-child { border-bottom: 0; }
|
||||
.number { width: 9mm; height: 9mm; border: .4mm solid var(--primary); color: var(--primary); display: flex; align-items: center; justify-content: center; align-self: start; border-radius: 50%; font-family: Arial, sans-serif; font-weight: 700; }
|
||||
.category { color: var(--accent); font-family: Arial, sans-serif; font-size: 7pt; text-transform: uppercase; letter-spacing: .8px; font-weight: 700; }
|
||||
.recommendation p { margin-bottom: 1.7mm; }
|
||||
.outlook { margin-top: 6mm; padding: 5mm; background: var(--surface); border-top: 1mm solid var(--primary); break-inside: avoid; }
|
||||
.outlook p { margin: 0; }
|
||||
.notes { font-family: Arial, sans-serif; font-size: 7pt; color: var(--muted); margin-top: 4mm; }
|
||||
.notes ul { margin: 1mm 0; padding-left: 4mm; }
|
||||
.legal { font-family: Arial, sans-serif; font-size: 6.6pt; color: var(--muted); margin-top: 4mm; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="header">
|
||||
<div>
|
||||
<div class="period">{{ data.report.period.label }}</div>
|
||||
<h1>Monatsreport</h1>
|
||||
<div class="meta"><span>{{ data.customer.property_name }}</span><span>{{ data.customer.location }}</span><span>{{ data.report.generated_at|date_de }}</span></div>
|
||||
</div>
|
||||
<div class="brand"><strong>{{ data.customer.name }}</strong>{{ data.customer.contact_line }}</div>
|
||||
</header>
|
||||
|
||||
<section class="summary">
|
||||
<div class="period">Kurzfazit</div>
|
||||
<h2>{{ data.content.summary.headline }}</h2>
|
||||
<p>{{ data.content.summary.text }}</p>
|
||||
</section>
|
||||
|
||||
<div class="rule-heading"><h2>Kennzahlen</h2><div class="rule"></div></div>
|
||||
<section class="kpis">
|
||||
<div class="kpi"><div class="kpi-label">Umsatz</div><div class="kpi-value">{{ data.metrics.revenue|currency_de(data.metrics.currency) }}</div><div class="kpi-delta">{{ data.metrics.comparison.revenue_delta_pct|delta_de(1, '%') }}</div></div>
|
||||
<div class="kpi"><div class="kpi-label">Auslastung</div><div class="kpi-value">{{ data.metrics.occupancy_rate|percent_de }}</div><div class="kpi-delta">{{ data.metrics.comparison.occupancy_delta_pp|delta_de(1, 'PP') }}</div></div>
|
||||
<div class="kpi"><div class="kpi-label">Ø Tagespreis</div><div class="kpi-value">{{ data.metrics.adr|currency_de(data.metrics.currency) }}</div><div class="kpi-delta">{{ data.metrics.comparison.adr_delta_pct|delta_de(1, '%') }}</div></div>
|
||||
<div class="kpi"><div class="kpi-label">Buchungen</div><div class="kpi-value">{{ data.metrics.bookings|number_de(0) }}</div><div class="kpi-delta">{{ data.metrics.comparison.bookings_delta|delta_de(0, '') }} Buchungen</div></div>
|
||||
</section>
|
||||
<section class="facts">
|
||||
<div>RevPAR<strong>{{ data.metrics.revpar|currency_de(data.metrics.currency) }}</strong></div>
|
||||
<div>Verkaufte Nächte<strong>{{ data.metrics.nights_sold|number_de(0) }}</strong></div>
|
||||
<div>Ø Aufenthalt<strong>{{ data.metrics.average_stay|number_de(1) }} Nächte</strong></div>
|
||||
<div>Stornoquote<strong>{{ data.metrics.cancellation_rate|percent_de }}</strong></div>
|
||||
</section>
|
||||
|
||||
<div class="rule-heading"><h2>Monatsverlauf</h2><div class="rule"></div></div>
|
||||
<table>
|
||||
<thead><tr><th>Monat</th><th class="num">Umsatz</th><th class="num">Auslastung</th><th class="num">Ø Tagespreis</th></tr></thead>
|
||||
<tbody>
|
||||
{% for item in data.trends %}<tr><td>{{ item.label }}</td><td class="num">{{ item.revenue|currency_de(data.metrics.currency) }}</td><td class="num">{{ item.occupancy_rate|percent_de }}</td><td class="num">{{ item.adr|currency_de(data.metrics.currency) }}</td></tr>{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="rule-heading"><h2>Wichtige Entwicklungen</h2><div class="rule"></div></div>
|
||||
<section class="developments">
|
||||
{% for item in data.content.developments %}<article class="development {{ item.impact }}"><h3>{{ item.title }}</h3><p>{{ item.text }}</p></article>{% endfor %}
|
||||
</section>
|
||||
|
||||
<div class="rule-heading"><h2>Empfehlungen</h2><div class="rule"></div></div>
|
||||
<section>
|
||||
{% for item in data.content.recommendations|sort(attribute='priority') %}
|
||||
<article class="recommendation">
|
||||
<div class="number">{{ item.priority }}</div>
|
||||
<div><div class="category">{{ item.category }}</div><h3>{{ item.title }}</h3><p><strong>Begründung:</strong> {{ item.reason }}</p><p><strong>Massnahme:</strong> {{ item.action }}</p><p><strong>Erwarteter Effekt:</strong> {{ item.expected_effect }}</p></div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</section>
|
||||
|
||||
<section class="outlook"><div class="period">Ausblick</div><h2>{{ data.content.outlook.headline }}</h2><p>{{ data.content.outlook.text }}</p></section>
|
||||
{% if data.content.data_quality_notes %}<section class="notes"><strong>Hinweise zur Datengrundlage</strong><ul>{% for note in data.content.data_quality_notes %}<li>{{ note }}</li>{% endfor %}</ul></section>{% endif %}
|
||||
<div class="legal">{{ data.legal_note }}</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user