Implement modular report system with 6 report types and composer UI
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy (push) Has been cancelled
Code Quality / quality (push) Has been cancelled

Refactors the Berichte section from a single hardcoded Jahresbericht into
a modular report-building system. Jahresbericht now uses PDFGenerator for
corporate identity (logo, colors, headers/footers, cover page). 8 reusable
section templates can be freely combined. 6 predefined report templates
(Jahres-, Destinatär-, Grundstücks-, Finanz-, Förder-, Pachtbericht) with
HTML preview and PDF export. New Bericht-Baukasten UI lets users compose
custom reports from individual sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
SysAdmin Agent
2026-03-14 20:55:31 +00:00
parent 042114b1e7
commit faeb7c1073
15 changed files with 1081 additions and 439 deletions

View File

@@ -13,8 +13,52 @@
</div>
</div>
<!-- Berichtsvorlagen -->
<div class="row mb-4">
<div class="col-12">
<div class="card shadow">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-file-alt me-2"></i>Berichtsvorlagen
</h6>
</div>
<div class="card-body">
<div class="row g-4">
{% for key, vorlage in bericht_vorlagen.items %}
<div class="col-md-4 col-lg-2">
<div class="card border-0 shadow-sm h-100">
<div class="card-body text-center p-3">
<i class="fas {{ vorlage.icon }} fa-2x text-primary mb-2"></i>
<h6 class="card-title mb-1">{{ vorlage.label }}</h6>
<p class="card-text text-muted small mb-2">{{ vorlage.beschreibung }}</p>
<div class="d-flex gap-1 justify-content-center flex-wrap">
<div class="input-group input-group-sm" style="max-width: 200px;">
<select class="form-select form-select-sm vorlage-jahr" data-vorlage="{{ key }}">
<option value="">Jahr...</option>
{% for year in jahre %}
<option value="{{ year }}">{{ year }}</option>
{% endfor %}
</select>
<button class="btn btn-sm btn-outline-primary vorlage-html-btn" data-vorlage="{{ key }}" title="HTML anzeigen">
<i class="fas fa-eye"></i>
</button>
<button class="btn btn-sm btn-outline-success vorlage-pdf-btn" data-vorlage="{{ key }}" title="PDF herunterladen">
<i class="fas fa-file-pdf"></i>
</button>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Jahresberichte -->
<!-- Jahresberichte (Schnellzugriff) -->
<div class="col-lg-6 mb-4">
<div class="card shadow h-100">
<div class="card-header py-3">
@@ -23,11 +67,10 @@
</h6>
</div>
<div class="card-body">
<p class="text-muted mb-4">
Generieren Sie detaillierte Jahresberichte mit allen wichtigen Informationen zu Destinatären,
Förderungen und Ländereien.
<p class="text-muted mb-3">
Generieren Sie detaillierte Jahresberichte mit allen wichtigen Informationen.
</p>
<form method="get" action="{% url 'stiftung:jahresbericht_generate_redirect' %}">
<div class="row g-3">
<div class="col-md-6">
@@ -46,18 +89,17 @@
</div>
</div>
</form>
<div class="mt-4">
<h6 class="text-primary">Verfügbare Berichte:</h6>
<div class="list-group list-group-flush">
<div class="mt-3">
<div class="list-group list-group-flush" style="max-height: 250px; overflow-y: auto;">
{% for year in jahre %}
<div class="list-group-item d-flex justify-content-between align-items-center">
<div class="list-group-item d-flex justify-content-between align-items-center py-2">
<span>Jahresbericht {{ year }}</span>
<div class="btn-group" role="group">
<a href="{% url 'stiftung:jahresbericht_generate' year %}" class="btn btn-sm btn-outline-primary">
<i class="fas fa-eye me-1"></i>Anzeigen
<div class="btn-group btn-group-sm" role="group">
<a href="{% url 'stiftung:jahresbericht_generate' year %}" class="btn btn-outline-primary">
<i class="fas fa-eye me-1"></i>HTML
</a>
<a href="{% url 'stiftung:jahresbericht_pdf' year %}" class="btn btn-sm btn-outline-success">
<a href="{% url 'stiftung:jahresbericht_pdf' year %}" class="btn btn-outline-success">
<i class="fas fa-download me-1"></i>PDF
</a>
</div>
@@ -69,9 +111,70 @@
</div>
</div>
<!-- Statistik-Übersicht -->
<!-- Bericht-Baukasten -->
<div class="col-lg-6 mb-4">
<div class="card shadow h-100">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-puzzle-piece me-2"></i>Bericht zusammenstellen
</h6>
</div>
<div class="card-body">
<p class="text-muted mb-3">
Stellen Sie einen individuellen Bericht aus einzelnen Sektionen zusammen.
</p>
<form method="post" action="{% url 'stiftung:bericht_zusammenstellen' %}">
{% csrf_token %}
<div class="mb-3">
<label class="form-label fw-bold">Sektionen auswählen:</label>
{% for key, sektion in bericht_sektionen.items %}
<div class="form-check">
<input class="form-check-input" type="checkbox" name="sektionen" value="{{ key }}" id="sek_{{ key }}">
<label class="form-check-label" for="sek_{{ key }}">
<i class="fas {{ sektion.icon }} me-1 text-muted"></i>{{ sektion.label }}
</label>
</div>
{% endfor %}
</div>
<div class="row g-2 mb-3">
<div class="col-md-6">
<label for="composer_jahr" class="form-label">Jahr (optional)</label>
<select name="jahr" id="composer_jahr" class="form-select form-select-sm">
<option value="">Kein Jahr</option>
{% for year in jahre %}
<option value="{{ year }}">{{ year }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-6">
<label class="form-label">&nbsp;</label>
<div class="form-check mt-1">
<input class="form-check-input" type="checkbox" name="show_cover" id="show_cover" checked>
<label class="form-check-label" for="show_cover">Deckblatt anzeigen</label>
</div>
</div>
</div>
<div class="d-flex gap-2">
<button type="submit" name="format" value="html" class="btn btn-primary flex-fill">
<i class="fas fa-eye me-1"></i>HTML Vorschau
</button>
<button type="submit" name="format" value="pdf" class="btn btn-success flex-fill">
<i class="fas fa-file-pdf me-1"></i>PDF Export
</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Statistik-Übersicht -->
<div class="row">
<div class="col-12">
<div class="card shadow">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-chart-pie me-2"></i>Statistik-Übersicht
@@ -79,116 +182,39 @@
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<div class="col-md-3">
<div class="card bg-primary text-white">
<div class="card-body text-center">
<div class="card-body text-center py-3">
<i class="fas fa-users fa-2x mb-2"></i>
<h5 class="card-title">Destinatäre</h5>
<h3 class="card-text">{{ total_destinataere|default:"0" }}</h3>
<h6 class="card-title mb-0">Destinatäre</h6>
<h3 class="card-text mb-0">{{ total_destinataere|default:"0" }}</h3>
</div>
</div>
</div>
<div class="col-md-6">
<div class="col-md-3">
<div class="card bg-success text-white">
<div class="card-body text-center">
<div class="card-body text-center py-3">
<i class="fas fa-gift fa-2x mb-2"></i>
<h5 class="card-title">Förderungen</h5>
<h3 class="card-text">{{ total_foerderungen|default:"0" }}</h3>
<h6 class="card-title mb-0">Förderungen</h6>
<h3 class="card-text mb-0">{{ total_foerderungen|default:"0" }}</h3>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card bg-secondary text-white">
<div class="card-body text-center">
<i class="fas fa-user-friends fa-2x mb-2"></i>
<h5 class="card-title">Destinatäre</h5>
<h3 class="card-text">{{ total_destinataere|default:"0" }}</h3>
</div>
</div>
</div>
<div class="col-md-6">
<div class="col-md-3">
<div class="card bg-info text-white">
<div class="card-body text-center">
<div class="card-body text-center py-3">
<i class="fas fa-map fa-2x mb-2"></i>
<h5 class="card-title">Ländereien</h5>
<h3 class="card-text">{{ total_laendereien|default:"0" }}</h3>
<h6 class="card-title mb-0">Ländereien</h6>
<h3 class="card-text mb-0">{{ total_laendereien|default:"0" }}</h3>
</div>
</div>
</div>
<div class="col-md-6">
<div class="col-md-3">
<div class="card bg-warning text-white">
<div class="card-body text-center">
<div class="card-body text-center py-3">
<i class="fas fa-handshake fa-2x mb-2"></i>
<h5 class="card-title">Verpachtungen</h5>
<h3 class="card-text">{{ total_verpachtungen|default:"0" }}</h3>
</div>
</div>
</div>
</div>
<div class="mt-4">
<h6 class="text-primary">Schnellzugriff:</h6>
<div class="d-grid gap-2">
<a href="{% url 'stiftung:destinataer_list' %}" class="btn btn-outline-primary">
<i class="fas fa-users me-2"></i>Alle Destinatäre anzeigen
</a>
<a href="{% url 'stiftung:foerderung_list' %}" class="btn btn-outline-success">
<i class="fas fa-gift me-2"></i>Alle Förderungen anzeigen
</a>
<a href="{% url 'stiftung:land_list' %}" class="btn btn-outline-info">
<i class="fas fa-map me-2"></i>Alle Ländereien anzeigen
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Zusätzliche Berichte -->
<div class="row">
<div class="col-12">
<div class="card shadow">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">
<i class="fas fa-cogs me-2"></i>Weitere Berichtstypen
</h6>
</div>
<div class="card-body">
<div class="row g-4">
<div class="col-md-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-body text-center">
<i class="fas fa-euro-sign fa-3x text-success mb-3"></i>
<h5 class="card-title">Finanzberichte</h5>
<p class="card-text">Detaillierte Auswertungen zu Förderungen und Ausgaben.</p>
<button class="btn btn-outline-success" disabled>
<i class="fas fa-clock me-2"></i>In Entwicklung
</button>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-body text-center">
<i class="fas fa-chart-line fa-3x text-info mb-3"></i>
<h5 class="card-title">Trendanalysen</h5>
<p class="card-text">Langzeitentwicklungen und Prognosen für die Zukunft.</p>
<button class="btn btn-outline-info" disabled>
<i class="fas fa-clock me-2"></i>In Entwicklung
</button>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card border-0 shadow-sm h-100">
<div class="card-body text-center">
<i class="fas fa-file-export fa-3x text-warning mb-3"></i>
<h5 class="card-title">Export-Funktionen</h5>
<p class="card-text">Datenexport in verschiedene Formate (Excel, CSV, PDF).</p>
<button class="btn btn-outline-warning" disabled>
<i class="fas fa-clock me-2"></i>In Entwicklung
</button>
<h6 class="card-title mb-0">Verpachtungen</h6>
<h3 class="card-text mb-0">{{ total_verpachtungen|default:"0" }}</h3>
</div>
</div>
</div>
@@ -198,4 +224,30 @@
</div>
</div>
{% endblock %}
{% endblock %}
{% block extra_js %}
<script>
// Berichtsvorlagen Schnellzugriff
document.querySelectorAll('.vorlage-html-btn, .vorlage-pdf-btn').forEach(btn => {
btn.addEventListener('click', function() {
const vorlage = this.dataset.vorlage;
const select = document.querySelector(`.vorlage-jahr[data-vorlage="${vorlage}"]`);
const jahr = select ? select.value : '';
const format = this.classList.contains('vorlage-pdf-btn') ? 'pdf' : 'html';
if (!jahr) {
alert('Bitte wählen Sie ein Jahr aus.');
return;
}
const url = `{% url 'stiftung:bericht_list' %}${vorlage}/?jahr=${jahr}&format=${format}`;
if (format === 'pdf') {
window.location.href = url;
} else {
window.open(url, '_blank');
}
});
});
</script>
{% endblock %}

View File

@@ -4,109 +4,62 @@
<meta charset="utf-8">
<title>Stiftung Jahresbericht {{ jahr }}</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
color: #333;
font-size: 14px;
}
.header {
text-align: center;
border-bottom: 3px solid #2c3e50;
padding-bottom: 20px;
margin-bottom: 30px;
}
.header h1 { color: #2c3e50; margin: 0; font-size: 2.2em; }
.header .subtitle { color: #7f8c8d; font-size: 1.1em; margin-top: 8px; }
.section { margin-bottom: 30px; page-break-inside: avoid; }
.section h2 {
color: #1a4a2e;
border-bottom: 2px solid #2c7a4b;
padding-bottom: 8px;
margin-bottom: 16px;
font-size: 1.2em;
}
.section h3 { color: #34495e; font-size: 1em; margin-top: 16px; margin-bottom: 8px; }
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
gap: 16px;
margin-bottom: 20px;
}
.stat-card {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 8px;
padding: 16px;
{{ css_content }}
/* Cover page styles */
.cover-page {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 85vh;
text-align: center;
}
.stat-card .value { font-size: 1.6em; font-weight: bold; color: #1a4a2e; }
.stat-card .label { color: #7f8c8d; margin-top: 4px; font-size: 0.85em; }
.cover-logo-img { max-height: 100px; max-width: 250px; margin-bottom: 30px; }
.cover-title h1 {
font-size: 24pt;
color: {{ corporate_settings.primary_color|default:"#2c3e50" }};
margin: 0 0 10px 0;
border-bottom: none;
}
.cover-title h2 {
font-size: 18pt;
color: {{ corporate_settings.secondary_color|default:"#3498db" }};
margin: 0 0 5px 0;
}
.cover-subtitle { font-size: 12pt; color: #666; }
.cover-meta { margin-top: 40px; font-size: 11pt; color: #555; }
.cover-meta p { margin: 5px 0; }
.cover-footer { margin-top: 60px; font-size: 9pt; color: #999; }
.cover-footer p { margin: 3px 0; }
.cover-confidential {
margin-top: 15px !important;
font-weight: bold;
color: {{ corporate_settings.primary_color|default:"#2c3e50" }} !important;
font-size: 10pt;
}
/* Bilanz cards */
.bilanz-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
margin-bottom: 20px;
}
.bilanz-card {
border-radius: 8px;
padding: 16px;
text-align: center;
}
.bilanz-card { border-radius: 8px; padding: 16px; text-align: center; }
.bilanz-card.einnahmen { background: #d4edda; border: 1px solid #c3e6cb; }
.bilanz-card.ausgaben { background: #f8d7da; border: 1px solid #f5c6cb; }
.bilanz-card.netto-positiv { background: #d1ecf1; border: 1px solid #bee5eb; }
.bilanz-card.netto-negativ { background: #fff3cd; border: 1px solid #ffeeba; }
.bilanz-card .value { font-size: 1.5em; font-weight: bold; }
.bilanz-card .label { font-size: 0.85em; margin-top: 4px; color: #555; }
table {
border-collapse: collapse;
width: 100%;
margin-bottom: 16px;
font-size: 0.9em;
}
th, td { border: 1px solid #dee2e6; padding: 8px 10px; text-align: left; }
th { background-color: #f0f7f4; font-weight: 600; color: #1a4a2e; }
tr:nth-child(even) { background-color: #f8f9fa; }
.amount { text-align: right; font-family: 'Courier New', monospace; }
.status-badge {
padding: 3px 7px;
border-radius: 4px;
font-size: 0.8em;
font-weight: 500;
}
.status-beantragt { background-color: #fff3cd; color: #856404; }
.status-genehmigt { background-color: #d1ecf1; color: #0c5460; }
.status-ausgezahlt, .status-abgeschlossen { background-color: #d4edda; color: #155724; }
.status-abgelehnt, .status-storniert { background-color: #f8d7da; color: #721c24; }
/* Status badges extra */
.status-aktiv { background-color: #d4edda; color: #155724; }
.status-beendet { background-color: #e2e3e5; color: #383d41; }
.status-gekuendigt { background-color: #f8d7da; color: #721c24; }
.status-geplant, .status-faellig { background-color: #e2e3e5; color: #383d41; }
.footer {
margin-top: 40px;
padding-top: 16px;
border-top: 1px solid #dee2e6;
text-align: center;
color: #7f8c8d;
font-size: 0.85em;
}
.status-abgeschlossen { background-color: #d4edda; color: #155724; }
@media print {
body { margin: 0; padding: 10px; }
.section { page-break-inside: avoid; }
.no-print { display: none; }
}
.print-btn {
display: inline-block;
padding: 8px 20px;
background: #1a4a2e;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 0.9em;
text-decoration: none;
margin-right: 8px;
}
</style>
</head>
<body>
@@ -114,253 +67,52 @@
<div class="no-print" style="margin-bottom: 20px; display: flex; align-items: center; gap: 12px;">
<a href="{% url 'stiftung:bericht_list' %}" style="color: #1a4a2e;">&#8592; Berichte</a>
<span style="color: #dee2e6;">|</span>
<a href="{% url 'stiftung:jahresbericht_pdf' jahr=jahr %}" class="print-btn">
<a href="{% url 'stiftung:jahresbericht_pdf' jahr=jahr %}" style="display: inline-block; padding: 8px 20px; background: #1a4a2e; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.9em; text-decoration: none; margin-right: 8px;">
PDF herunterladen
</a>
<button onclick="window.print()" class="print-btn" style="background: #34495e;">
<button onclick="window.print()" style="display: inline-block; padding: 8px 20px; background: #34495e; color: white; border: none; border-radius: 6px; cursor: pointer; font-size: 0.9em;">
Drucken
</button>
</div>
{% if show_cover %}
{% include "berichte/cover_page.html" %}
{% endif %}
<!-- Kopfzeile -->
<div class="header">
<h1>Jahresbericht {{ jahr }}</h1>
<div class="subtitle">van Hees-Theyssen-Vogel'sche Familienstiftung</div>
<div class="subtitle">Erstellt am {% now "d.m.Y" %}</div>
</div>
<!-- 1. Gesamtübersicht / Bilanz -->
<div class="section">
<h2>1. Jahresbilanz {{ jahr }}</h2>
<div class="bilanz-grid">
<div class="bilanz-card einnahmen">
<div class="value">&#8364;{{ total_einnahmen|floatformat:2 }}</div>
<div class="label">Einnahmen (Pacht)</div>
<div class="header-content">
<div class="header-left">
{% if logo_base64 %}
<img src="{{ logo_base64 }}" alt="Logo" class="logo">
{% endif %}
<p class="stiftung-name">{{ corporate_settings.stiftung_name }}</p>
<p class="document-title">Jahresbericht {{ jahr }}</p>
</div>
<div class="bilanz-card ausgaben">
<div class="value">&#8364;{{ total_ausgaben|floatformat:2 }}</div>
<div class="label">Ausgaben gesamt</div>
</div>
<div class="bilanz-card {% if netto >= 0 %}netto-positiv{% else %}netto-negativ{% endif %}">
<div class="value">{% if netto >= 0 %}+{% endif %}&#8364;{{ netto|floatformat:2 }}</div>
<div class="label">Nettosaldo</div>
<div class="header-right">
<div class="contact-info">
{% if corporate_settings.address_line1 %}<p>{{ corporate_settings.address_line1 }}</p>{% endif %}
{% if corporate_settings.address_line2 %}<p>{{ corporate_settings.address_line2 }}</p>{% endif %}
{% if corporate_settings.phone %}<p>{{ corporate_settings.phone }}</p>{% endif %}
{% if corporate_settings.email %}<p>{{ corporate_settings.email }}</p>{% endif %}
</div>
</div>
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="value">&#8364;{{ total_ausgaben_foerderung|floatformat:2 }}</div>
<div class="label">Förderausgaben</div>
</div>
<div class="stat-card">
<div class="value">&#8364;{{ total_verwaltungskosten|floatformat:2 }}</div>
<div class="label">Verwaltungskosten</div>
</div>
<div class="stat-card">
<div class="value">&#8364;{{ pacht_vereinnahmt|floatformat:2 }}</div>
<div class="label">Pacht vereinnahmt</div>
</div>
<div class="stat-card">
<div class="value">&#8364;{{ grundsteuer_gesamt|floatformat:2 }}</div>
<div class="label">Grundsteuer</div>
</div>
<div class="header-info">
Erstellt am {% now "d.m.Y" %} &middot; Berichtszeitraum: {{ jahr }}
</div>
</div>
<!-- 2. Unterstützungen (Zahlungs-Pipeline) -->
{% if unterstuetzungen %}
<div class="section">
<h2>2. Unterstützungszahlungen {{ jahr }}</h2>
<p style="color: #666; margin-bottom: 12px;">
{{ unterstuetzungen.count }} Unterstützung(en) geplant/ausgezahlt &middot;
{{ unterstuetzungen_ausgezahlt.count }} überwiesen (&#8364;{{ total_unterstuetzungen|floatformat:2 }})
</p>
<table>
<thead>
<tr>
<th>Destinatär</th>
<th>Betrag</th>
<th>Fällig am</th>
<th>Status</th>
<th>Verwendungszweck</th>
</tr>
</thead>
<tbody>
{% for u in unterstuetzungen %}
<tr>
<td>{{ u.destinataer.get_full_name }}</td>
<td class="amount">&#8364;{{ u.betrag|floatformat:2 }}</td>
<td>{{ u.faellig_am|date:"d.m.Y" }}</td>
<td>
<span class="status-badge status-{{ u.status }}">{{ u.get_status_display }}</span>
</td>
<td>{{ u.beschreibung|default:"-" }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr style="font-weight: bold; background: #f0f7f4;">
<td>Summe ausgezahlt</td>
<td class="amount">&#8364;{{ total_unterstuetzungen|floatformat:2 }}</td>
<td colspan="3"></td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
<!-- 3. Förderungen (legacy Foerderung-Modell) -->
{% if foerderungen %}
<div class="section">
<h2>3. Förderungen {{ jahr }}</h2>
<table>
<thead>
<tr>
<th>Begünstigter</th>
<th>Kategorie</th>
<th>Betrag</th>
<th>Status</th>
<th>Antragsdatum</th>
</tr>
</thead>
<tbody>
{% for f in foerderungen %}
<tr>
<td>
{% if f.destinataer %}{{ f.destinataer.get_full_name }}
{% elif f.person %}{{ f.person.get_full_name }}
{% else %}{% endif %}
</td>
<td>{{ f.get_kategorie_display }}</td>
<td class="amount">&#8364;{{ f.betrag|floatformat:2 }}</td>
<td>
<span class="status-badge status-{{ f.status }}">{{ f.get_status_display }}</span>
</td>
<td>{{ f.antragsdatum|date:"d.m.Y" }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr style="font-weight: bold; background: #f0f7f4;">
<td colspan="2">Summe</td>
<td class="amount">&#8364;{{ total_foerderungen_legacy|floatformat:2 }}</td>
<td colspan="2"></td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
<!-- 4. Grundstücksverwaltung -->
<div class="section">
<h2>4. Grundstücksverwaltung</h2>
{% if verpachtungen %}
<h3>Aktive Verpachtungen</h3>
<table>
<thead>
<tr>
<th>Länderei</th>
<th>Pächter</th>
<th>Verpachtete Fläche</th>
<th>Jahrespachtzins</th>
<th>Pachtende</th>
</tr>
</thead>
<tbody>
{% for v in verpachtungen %}
<tr>
<td>{{ v.land }}</td>
<td>{{ v.paechter.get_full_name }}</td>
<td class="amount">{{ v.verpachtete_flaeche|floatformat:0 }} qm</td>
<td class="amount">&#8364;{{ v.pachtzins_pauschal|floatformat:2 }}</td>
<td>{% if v.pachtende %}{{ v.pachtende|date:"d.m.Y" }}{% else %}unbefristet{% endif %}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr style="font-weight: bold; background: #f0f7f4;">
<td colspan="3">Gesamtpachtzins (kalkuliert)</td>
<td class="amount">&#8364;{{ total_pachtzins|floatformat:2 }}</td>
<td></td>
</tr>
</tfoot>
</table>
{% endif %}
{% if landabrechnungen %}
<h3>Landabrechnungen {{ jahr }}</h3>
<table>
<thead>
<tr>
<th>Länderei</th>
<th>Pacht vereinnahmt</th>
<th>Umlagen</th>
<th>Grundsteuer</th>
<th>Sonstige Einnahmen</th>
</tr>
</thead>
<tbody>
{% for a in landabrechnungen %}
<tr>
<td>{{ a.land }}</td>
<td class="amount">&#8364;{{ a.pacht_vereinnahmt|floatformat:2 }}</td>
<td class="amount">&#8364;{{ a.umlagen_vereinnahmt|floatformat:2 }}</td>
<td class="amount">&#8364;{{ a.grundsteuer_betrag|floatformat:2 }}</td>
<td class="amount">&#8364;{{ a.sonstige_einnahmen|floatformat:2 }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr style="font-weight: bold; background: #f0f7f4;">
<td>Summe</td>
<td class="amount">&#8364;{{ pacht_vereinnahmt|floatformat:2 }}</td>
<td></td>
<td class="amount">&#8364;{{ grundsteuer_gesamt|floatformat:2 }}</td>
<td></td>
</tr>
</tfoot>
</table>
{% endif %}
{% if not verpachtungen and not landabrechnungen %}
<p style="color: #999;">Keine Verpachtungs- oder Abrechnungsdaten für {{ jahr }} vorhanden.</p>
{% endif %}
</div>
<!-- 5. Verwaltungskosten -->
{% if verwaltungskosten_nach_kategorie %}
<div class="section">
<h2>5. Verwaltungskosten {{ jahr }}</h2>
<table>
<thead>
<tr>
<th>Kategorie</th>
<th>Anzahl</th>
<th>Betrag</th>
</tr>
</thead>
<tbody>
{% for k in verwaltungskosten_nach_kategorie %}
<tr>
<td>{{ k.kategorie|capfirst }}</td>
<td>{{ k.anzahl }}</td>
<td class="amount">&#8364;{{ k.summe|floatformat:2 }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr style="font-weight: bold; background: #f0f7f4;">
<td colspan="2">Gesamt</td>
<td class="amount">&#8364;{{ total_verwaltungskosten|floatformat:2 }}</td>
</tr>
</tfoot>
</table>
</div>
{% endif %}
<!-- Modulare Sektionen -->
{% include "berichte/sektionen/bilanz.html" %}
{% include "berichte/sektionen/unterstuetzungen.html" %}
{% include "berichte/sektionen/foerderungen.html" %}
{% include "berichte/sektionen/grundstuecke.html" %}
{% include "berichte/sektionen/verwaltungskosten.html" %}
<div class="footer">
<p>Jahresbericht {{ jahr }} &mdash; automatisch generiert von der Stiftungsverwaltung</p>
<p>van Hees-Theyssen-Vogel'sche Familienstiftung &middot; Vertraulich</p>
<p>{{ corporate_settings.stiftung_name }} &middot; {{ corporate_settings.footer_text }}</p>
</div>
</body>
</html>