Implement modular report system with 6 report types and composer UI
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:
@@ -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"> </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 %}
|
||||
|
||||
Reference in New Issue
Block a user