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>
254 lines
12 KiB
HTML
254 lines
12 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Berichte - Stiftungsverwaltung{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<h1 class="h3 mb-4">
|
|
<i class="fas fa-chart-bar text-primary me-2"></i>Berichte & Auswertungen
|
|
</h1>
|
|
</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 (Schnellzugriff) -->
|
|
<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-calendar-alt me-2"></i>Jahresberichte
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<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">
|
|
<label for="jahr" class="form-label">Jahr auswählen</label>
|
|
<select name="jahr" id="jahr" class="form-select" required>
|
|
<option value="">Jahr wählen...</option>
|
|
{% for year in jahre %}
|
|
<option value="{{ year }}">{{ year }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="col-md-6 d-flex align-items-end">
|
|
<button type="submit" class="btn btn-primary w-100">
|
|
<i class="fas fa-file-alt me-2"></i>Bericht generieren
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<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 py-2">
|
|
<span>Jahresbericht {{ year }}</span>
|
|
<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-outline-success">
|
|
<i class="fas fa-download me-1"></i>PDF
|
|
</a>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 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
|
|
</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row g-3">
|
|
<div class="col-md-3">
|
|
<div class="card bg-primary text-white">
|
|
<div class="card-body text-center py-3">
|
|
<i class="fas fa-users fa-2x mb-2"></i>
|
|
<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-3">
|
|
<div class="card bg-success text-white">
|
|
<div class="card-body text-center py-3">
|
|
<i class="fas fa-gift fa-2x mb-2"></i>
|
|
<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-3">
|
|
<div class="card bg-info text-white">
|
|
<div class="card-body text-center py-3">
|
|
<i class="fas fa-map fa-2x mb-2"></i>
|
|
<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-3">
|
|
<div class="card bg-warning text-white">
|
|
<div class="card-body text-center py-3">
|
|
<i class="fas fa-handshake fa-2x mb-2"></i>
|
|
<h6 class="card-title mb-0">Verpachtungen</h6>
|
|
<h3 class="card-text mb-0">{{ total_verpachtungen|default:"0" }}</h3>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% 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 %}
|