diff --git a/app/stiftung/urls.py b/app/stiftung/urls.py index 1017844..6bddf21 100644 --- a/app/stiftung/urls.py +++ b/app/stiftung/urls.py @@ -158,6 +158,16 @@ urlpatterns = [ views.jahresbericht_pdf, name="jahresbericht_pdf", ), + path( + "berichte/zusammenstellen/", + views.bericht_zusammenstellen, + name="bericht_zusammenstellen", + ), + path( + "berichte//", + views.bericht_vorlage, + name="bericht_vorlage", + ), # Geschäftsführung URLs path("geschaeftsfuehrung/", views.geschaeftsfuehrung, name="geschaeftsfuehrung"), path("geschaeftsfuehrung/konten/", views.konto_list, name="konto_list"), diff --git a/app/stiftung/views/__init__.py b/app/stiftung/views/__init__.py index 60c3935..7a40182 100644 --- a/app/stiftung/views/__init__.py +++ b/app/stiftung/views/__init__.py @@ -29,6 +29,10 @@ from .finanzen import ( # noqa: F401 jahresbericht_generate, jahresbericht_generate_redirect, jahresbericht_pdf, + bericht_zusammenstellen, + bericht_vorlage, + BERICHT_SEKTIONEN, + BERICHT_VORLAGEN, geschaeftsfuehrung, konto_list, verwaltungskosten_list, diff --git a/app/stiftung/views/finanzen.py b/app/stiftung/views/finanzen.py index 0bd88d1..6aa5c4e 100644 --- a/app/stiftung/views/finanzen.py +++ b/app/stiftung/views/finanzen.py @@ -59,7 +59,7 @@ from stiftung.forms import ( @login_required def bericht_list(request): - """List available reports""" + """List available reports with modular report builder""" # Get available years from data jahre = sorted( set( @@ -69,7 +69,7 @@ def bericht_list(request): reverse=True, ) - # Statistics for overview tiles (removed legacy Person and Verpachtung) + # Statistics for overview tiles total_destinataere = Destinataer.objects.count() total_laendereien = Land.objects.count() total_verpachtungen = LandVerpachtung.objects.count() @@ -82,10 +82,25 @@ def bericht_list(request): "total_laendereien": total_laendereien, "total_verpachtungen": total_verpachtungen, "total_foerderungen": total_foerderungen, + "bericht_vorlagen": BERICHT_VORLAGEN, + "bericht_sektionen": BERICHT_SEKTIONEN, } return render(request, "stiftung/bericht_list.html", context) +def _get_corporate_context(): + """Holt Corporate-Identity-Einstellungen und CSS für Berichte.""" + from stiftung.utils.pdf_generator import pdf_generator + corporate_settings = pdf_generator.get_corporate_settings() + logo_base64 = pdf_generator.get_logo_base64(corporate_settings.get("logo_path", "")) + css_content = pdf_generator.get_base_css(corporate_settings) + return { + "corporate_settings": corporate_settings, + "logo_base64": logo_base64, + "css_content": css_content, + } + + def _jahresbericht_context(jahr): """Phase 4: Aggregiert alle Daten für den Jahresbericht.""" from stiftung.models import ( @@ -138,7 +153,7 @@ def _jahresbericht_context(jahr): total_ausgaben = total_ausgaben_foerderung + total_verwaltungskosten netto = total_einnahmen - total_ausgaben - return { + context = { "jahr": jahr, "title": f"Jahresbericht {jahr}", "foerderungen": foerderungen, @@ -157,9 +172,14 @@ def _jahresbericht_context(jahr): "total_einnahmen": total_einnahmen, "total_ausgaben": total_ausgaben, "netto": netto, - # Rückwärtskompatibilität "total_foerderungen": total_ausgaben_foerderung, + "show_cover": True, + "bericht_titel": f"Jahresbericht {jahr}", + "bericht_untertitel": "Gesamtübersicht des Geschäftsjahres", + "berichtszeitraum": str(jahr), } + context.update(_get_corporate_context()) + return context @login_required @@ -181,24 +201,276 @@ def jahresbericht_generate_redirect(request): @login_required def jahresbericht_pdf(request, jahr): - """Phase 4: PDF-Export des Jahresberichts.""" - from django.http import HttpResponse + """Phase 4: PDF-Export des Jahresberichts via PDFGenerator.""" from django.template.loader import render_to_string - from weasyprint import HTML + from stiftung.utils.pdf_generator import pdf_generator context = _jahresbericht_context(jahr) - - # Render HTML html_string = render_to_string("stiftung/jahresbericht.html", context) + return pdf_generator.generate_pdf_response( + html_string, f"jahresbericht_{jahr}.pdf", context.get("css_content") + ) - # Generate PDF - pdf = HTML(string=html_string).write_pdf() - # Create response - response = HttpResponse(pdf, content_type="application/pdf") - response["Content-Disposition"] = f'attachment; filename="jahresbericht_{jahr}.pdf"' +# ============================================================================= +# MODULARE BERICHTE – Berichts-Baukasten +# ============================================================================= - return response +# Verfügbare Sektionen mit Metadaten +BERICHT_SEKTIONEN = { + "bilanz": {"label": "Jahresbilanz", "icon": "fa-balance-scale", "needs_jahr": True}, + "unterstuetzungen": {"label": "Unterstützungszahlungen", "icon": "fa-hand-holding-heart", "needs_jahr": True}, + "foerderungen": {"label": "Förderungen", "icon": "fa-gift", "needs_jahr": True}, + "grundstuecke": {"label": "Grundstücksverwaltung", "icon": "fa-map", "needs_jahr": True}, + "verwaltungskosten": {"label": "Verwaltungskosten", "icon": "fa-file-invoice-dollar", "needs_jahr": True}, + "destinataere_uebersicht": {"label": "Destinatär-Übersicht", "icon": "fa-users", "needs_jahr": False}, + "konten_uebersicht": {"label": "Kontenübersicht", "icon": "fa-university", "needs_jahr": False}, + "verpachtungen": {"label": "Pachtbericht", "icon": "fa-handshake", "needs_jahr": False}, +} + +# Vordefinierte Berichtstypen +BERICHT_VORLAGEN = { + "jahresbericht": { + "label": "Jahresbericht", + "beschreibung": "Vollständige Übersicht eines Geschäftsjahres", + "sektionen": ["bilanz", "unterstuetzungen", "foerderungen", "grundstuecke", "verwaltungskosten"], + "needs_jahr": True, + "icon": "fa-calendar-alt", + }, + "destinataerbericht": { + "label": "Destinatärbericht", + "beschreibung": "Übersicht aller Destinatäre mit Förderstatus", + "sektionen": ["destinataere_uebersicht", "unterstuetzungen", "foerderungen"], + "needs_jahr": True, + "icon": "fa-users", + }, + "grundstuecksbericht": { + "label": "Grundstücksbericht", + "beschreibung": "Liegenschaftsübersicht mit Pachtverträgen", + "sektionen": ["grundstuecke", "verpachtungen"], + "needs_jahr": True, + "icon": "fa-map", + }, + "finanzbericht": { + "label": "Finanzbericht", + "beschreibung": "Einnahmen/Ausgaben und Kontenübersicht", + "sektionen": ["bilanz", "konten_uebersicht", "verwaltungskosten"], + "needs_jahr": True, + "icon": "fa-euro-sign", + }, + "foerderbericht": { + "label": "Förderbericht", + "beschreibung": "Detailansicht aller Förderungen", + "sektionen": ["foerderungen", "unterstuetzungen"], + "needs_jahr": True, + "icon": "fa-gift", + }, + "pachtbericht": { + "label": "Pachtbericht", + "beschreibung": "Pachtzinseinnahmen und Vertragsübersicht", + "sektionen": ["verpachtungen", "grundstuecke"], + "needs_jahr": True, + "icon": "fa-handshake", + }, +} + + +def _build_section_context(sektionen, jahr=None): + """Baut den Context für die gewählten Sektionen zusammen.""" + from stiftung.models import ( + DestinataerUnterstuetzung, LandAbrechnung, Verwaltungskosten, + ) + context = {} + + if jahr: + context["jahr"] = jahr + + needs_jahresbericht = any(s in sektionen for s in [ + "bilanz", "unterstuetzungen", "foerderungen", "grundstuecke", "verwaltungskosten" + ]) + if needs_jahresbericht and jahr: + jb = _jahresbericht_context(jahr) + context.update(jb) + + if "destinataere_uebersicht" in sektionen: + from django.db.models import Count, Sum as DSum + qs = Destinataer.objects.all() + context["destinataere_aktiv"] = qs.filter(aktiv=True).count() + context["destinataere_gesamt"] = qs.count() + + # Annotate with support stats + if jahr: + dest_qs = qs.annotate( + unterstuetzung_count=Count( + "unterstuetzungen", + filter=Q(unterstuetzungen__faellig_am__year=jahr), + ), + unterstuetzung_summe=Coalesce( + DSum( + "unterstuetzungen__betrag", + filter=Q( + unterstuetzungen__faellig_am__year=jahr, + unterstuetzungen__status__in=["ausgezahlt", "abgeschlossen"], + ), + ), + Decimal("0"), + ), + ) + else: + dest_qs = qs.annotate( + unterstuetzung_count=Count("unterstuetzungen"), + unterstuetzung_summe=Coalesce( + DSum( + "unterstuetzungen__betrag", + filter=Q(unterstuetzungen__status__in=["ausgezahlt", "abgeschlossen"]), + ), + Decimal("0"), + ), + ) + context["destinataere_liste"] = dest_qs.order_by("nachname", "vorname") + context["destinataere_total_unterstuetzung"] = ( + dest_qs.aggregate(total=DSum("unterstuetzung_summe"))["total"] or 0 + ) + + if "konten_uebersicht" in sektionen: + konten = StiftungsKonto.objects.filter(aktiv=True).order_by("bank_name", "kontoname") + context["konten_liste"] = konten + context["konten_anzahl"] = konten.count() + context["konten_gesamtsaldo"] = konten.aggregate(total=Sum("saldo"))["total"] or 0 + + if "verpachtungen" in sektionen: + from datetime import timedelta + heute = date.today() + in_12_monaten = heute + timedelta(days=365) + + aktive = LandVerpachtung.objects.filter( + status="aktiv" + ).select_related("land", "paechter") + + auslaufend = aktive.filter( + pachtende__isnull=False, + pachtende__lte=in_12_monaten, + pachtende__gte=heute, + ).order_by("pachtende") + + total_flaeche = aktive.aggregate(total=Sum("verpachtete_flaeche"))["total"] or 0 + total_pz = aktive.aggregate(total=Sum("pachtzins_pauschal"))["total"] or 0 + + context["pacht_statistik"] = { + "aktive_vertraege": aktive.count(), + "total_pachtzins": total_pz, + "total_flaeche": total_flaeche, + "auslaufend_12m": auslaufend.count(), + } + context["pacht_auslaufend"] = auslaufend + # Also provide full list if not already from jahresbericht + if "verpachtungen" not in context or not context.get("verpachtungen"): + if jahr: + context["verpachtungen"] = LandVerpachtung.objects.filter( + pachtbeginn__year__lte=jahr + ).filter( + Q(pachtende__isnull=True) | Q(pachtende__year__gte=jahr) + ).select_related("land", "paechter") + else: + context["verpachtungen"] = aktive + + return context + + +@login_required +def bericht_zusammenstellen(request): + """Modularer Bericht: Sektionen auswählen und zusammenstellen.""" + if request.method == "POST": + sektionen = request.POST.getlist("sektionen") + jahr_str = request.POST.get("jahr", "") + show_cover = request.POST.get("show_cover") == "on" + output_format = request.POST.get("format", "html") + vorlage = request.POST.get("vorlage", "") + + # Vorlage anwenden falls gewählt + if vorlage and vorlage in BERICHT_VORLAGEN and not sektionen: + sektionen = BERICHT_VORLAGEN[vorlage]["sektionen"] + + if not sektionen: + messages.error(request, "Bitte wählen Sie mindestens eine Sektion aus.") + return redirect("stiftung:bericht_list") + + jahr = int(jahr_str) if jahr_str and jahr_str.isdigit() else None + + # Build context + context = _build_section_context(sektionen, jahr) + context["sektionen"] = sektionen + context["show_cover"] = show_cover + + # Set titles + if vorlage and vorlage in BERICHT_VORLAGEN: + titel = BERICHT_VORLAGEN[vorlage]["label"] + else: + titel = "Bericht" + if jahr: + context["bericht_titel"] = f"{titel} {jahr}" + context["berichtszeitraum"] = str(jahr) + else: + context["bericht_titel"] = titel + context["berichtszeitraum"] = "Aktuell" + + context["bericht_untertitel"] = BERICHT_VORLAGEN.get(vorlage, {}).get("beschreibung", "") + + # Add corporate context if not already present + if "corporate_settings" not in context: + context.update(_get_corporate_context()) + + if output_format == "pdf": + from django.template.loader import render_to_string + from stiftung.utils.pdf_generator import pdf_generator + html_string = render_to_string("berichte/bericht_modular.html", context) + filename = f"bericht_{vorlage or 'custom'}_{jahr or 'aktuell'}.pdf" + return pdf_generator.generate_pdf_response( + html_string, filename, context.get("css_content") + ) + else: + return render(request, "berichte/bericht_modular.html", context) + + # GET: Redirect to bericht_list + return redirect("stiftung:bericht_list") + + +@login_required +def bericht_vorlage(request, vorlage_key): + """Schnellzugriff: Vordefinierte Berichtsvorlage generieren.""" + if vorlage_key not in BERICHT_VORLAGEN: + messages.error(request, f"Unbekannter Berichtstyp: {vorlage_key}") + return redirect("stiftung:bericht_list") + + vorlage = BERICHT_VORLAGEN[vorlage_key] + jahr_str = request.GET.get("jahr", "") + jahr = int(jahr_str) if jahr_str and jahr_str.isdigit() else None + output_format = request.GET.get("format", "html") + + if vorlage["needs_jahr"] and not jahr: + messages.error(request, "Bitte wählen Sie ein Jahr für diesen Bericht.") + return redirect("stiftung:bericht_list") + + context = _build_section_context(vorlage["sektionen"], jahr) + context["sektionen"] = vorlage["sektionen"] + context["show_cover"] = True + context["bericht_titel"] = f"{vorlage['label']}" + (f" {jahr}" if jahr else "") + context["bericht_untertitel"] = vorlage["beschreibung"] + context["berichtszeitraum"] = str(jahr) if jahr else "Aktuell" + + if "corporate_settings" not in context: + context.update(_get_corporate_context()) + + if output_format == "pdf": + from django.template.loader import render_to_string + from stiftung.utils.pdf_generator import pdf_generator + html_string = render_to_string("berichte/bericht_modular.html", context) + filename = f"{vorlage_key}_{jahr or 'aktuell'}.pdf" + return pdf_generator.generate_pdf_response( + html_string, filename, context.get("css_content") + ) + else: + return render(request, "berichte/bericht_modular.html", context) # API Views for AJAX diff --git a/app/templates/berichte/bericht_modular.html b/app/templates/berichte/bericht_modular.html new file mode 100644 index 0000000..e2cbd30 --- /dev/null +++ b/app/templates/berichte/bericht_modular.html @@ -0,0 +1,109 @@ + + + + + {{ bericht_titel }} – {{ corporate_settings.stiftung_name }} + + + + {% if show_cover %} + {% include "berichte/cover_page.html" %} + {% endif %} + + +
+
+
+ {% if logo_base64 %} + + {% endif %} +

{{ corporate_settings.stiftung_name }}

+

{{ bericht_titel }}

+
+
+
+ {% if corporate_settings.address_line1 %}

{{ corporate_settings.address_line1 }}

{% endif %} + {% if corporate_settings.address_line2 %}

{{ corporate_settings.address_line2 }}

{% endif %} + {% if corporate_settings.phone %}

{{ corporate_settings.phone }}

{% endif %} + {% if corporate_settings.email %}

{{ corporate_settings.email }}

{% endif %} +
+
+
+
+ Erstellt am {% now "d.m.Y" %}{% if berichtszeitraum %} · Zeitraum: {{ berichtszeitraum }}{% endif %} +
+
+ + + {% for sektion in sektionen %} + {% if sektion == "bilanz" %}{% include "berichte/sektionen/bilanz.html" %} + {% elif sektion == "unterstuetzungen" %}{% include "berichte/sektionen/unterstuetzungen.html" %} + {% elif sektion == "foerderungen" %}{% include "berichte/sektionen/foerderungen.html" %} + {% elif sektion == "grundstuecke" %}{% include "berichte/sektionen/grundstuecke.html" %} + {% elif sektion == "verwaltungskosten" %}{% include "berichte/sektionen/verwaltungskosten.html" %} + {% elif sektion == "destinataere_uebersicht" %}{% include "berichte/sektionen/destinataere_uebersicht.html" %} + {% elif sektion == "konten_uebersicht" %}{% include "berichte/sektionen/konten_uebersicht.html" %} + {% elif sektion == "verpachtungen" %}{% include "berichte/sektionen/verpachtungen.html" %} + {% endif %} + {% endfor %} + + + + diff --git a/app/templates/berichte/cover_page.html b/app/templates/berichte/cover_page.html new file mode 100644 index 0000000..cb34985 --- /dev/null +++ b/app/templates/berichte/cover_page.html @@ -0,0 +1,39 @@ + +
+ +
+

{{ corporate_settings.stiftung_name }}

+

{{ bericht_titel }}

+ {% if bericht_untertitel %} +

{{ bericht_untertitel }}

+ {% endif %} +
+
+

Berichtszeitraum: {{ berichtszeitraum }}

+

Erstellt am: {% now "d.m.Y" %}

+ {% if cover_freitext %} +

{{ cover_freitext }}

+ {% endif %} +
+ +
+
diff --git a/app/templates/berichte/sektionen/bilanz.html b/app/templates/berichte/sektionen/bilanz.html new file mode 100644 index 0000000..71bdebb --- /dev/null +++ b/app/templates/berichte/sektionen/bilanz.html @@ -0,0 +1,36 @@ + +
+

Jahresbilanz {{ jahr }}

+
+
+
€{{ total_einnahmen|floatformat:2 }}
+
Einnahmen (Pacht)
+
+
+
€{{ total_ausgaben|floatformat:2 }}
+
Ausgaben gesamt
+
+
+
{% if netto >= 0 %}+{% endif %}€{{ netto|floatformat:2 }}
+
Nettosaldo
+
+
+
+
+
€{{ total_ausgaben_foerderung|floatformat:2 }}
+
Förderausgaben
+
+
+
€{{ total_verwaltungskosten|floatformat:2 }}
+
Verwaltungskosten
+
+
+
€{{ pacht_vereinnahmt|floatformat:2 }}
+
Pacht vereinnahmt
+
+
+
€{{ grundsteuer_gesamt|floatformat:2 }}
+
Grundsteuer
+
+
+
diff --git a/app/templates/berichte/sektionen/destinataere_uebersicht.html b/app/templates/berichte/sektionen/destinataere_uebersicht.html new file mode 100644 index 0000000..6224008 --- /dev/null +++ b/app/templates/berichte/sektionen/destinataere_uebersicht.html @@ -0,0 +1,46 @@ + +
+

Destinatär-Übersicht{% if jahr %} {{ jahr }}{% endif %}

+ +
+
+
{{ destinataere_aktiv }}
+
Aktive Destinatäre
+
+
+
{{ destinataere_gesamt }}
+
Gesamt
+
+
+
€{{ destinataere_total_unterstuetzung|floatformat:2 }}
+
Gesamte Unterstützungen
+
+
+ + {% if destinataere_liste %} + + + + + + + + + + + + + {% for d in destinataere_liste %} + + + + + + + + + {% endfor %} + +
NameOrtBerufsgruppeAktivUnterstützungenBetrag gesamt
{{ d.get_full_name }}{{ d.ort|default:"-" }}{{ d.get_berufsgruppe_display|default:"-" }}{% if d.aktiv %}Ja{% else %}Nein{% endif %}{{ d.unterstuetzung_count }}€{{ d.unterstuetzung_summe|floatformat:2 }}
+ {% endif %} +
diff --git a/app/templates/berichte/sektionen/foerderungen.html b/app/templates/berichte/sektionen/foerderungen.html new file mode 100644 index 0000000..b5ec634 --- /dev/null +++ b/app/templates/berichte/sektionen/foerderungen.html @@ -0,0 +1,41 @@ + +{% if foerderungen %} +
+

Förderungen {{ jahr }}

+ + + + + + + + + + + + {% for f in foerderungen %} + + + + + + + + {% endfor %} + + + + + + + + +
BegünstigterKategorieBetragStatusAntragsdatum
+ {% if f.destinataer %}{{ f.destinataer.get_full_name }} + {% elif f.person %}{{ f.person.get_full_name }} + {% else %}–{% endif %} + {{ f.get_kategorie_display }}€{{ f.betrag|floatformat:2 }} + {{ f.get_status_display }} + {{ f.antragsdatum|date:"d.m.Y" }}
Summe€{{ total_foerderungen_legacy|floatformat:2 }}
+
+{% endif %} diff --git a/app/templates/berichte/sektionen/grundstuecke.html b/app/templates/berichte/sektionen/grundstuecke.html new file mode 100644 index 0000000..71e9581 --- /dev/null +++ b/app/templates/berichte/sektionen/grundstuecke.html @@ -0,0 +1,76 @@ + +
+

Grundstücksverwaltung

+ + {% if verpachtungen %} +

Aktive Verpachtungen

+ + + + + + + + + + + + {% for v in verpachtungen %} + + + + + + + + {% endfor %} + + + + + + + + +
LändereiPächterVerpachtete FlächeJahrespachtzinsPachtende
{{ v.land }}{{ v.paechter.get_full_name }}{{ v.verpachtete_flaeche|floatformat:0 }} qm€{{ v.pachtzins_pauschal|floatformat:2 }}{% if v.pachtende %}{{ v.pachtende|date:"d.m.Y" }}{% else %}unbefristet{% endif %}
Gesamtpachtzins (kalkuliert)€{{ total_pachtzins|floatformat:2 }}
+ {% endif %} + + {% if landabrechnungen %} +

Landabrechnungen {{ jahr }}

+ + + + + + + + + + + + {% for a in landabrechnungen %} + + + + + + + + {% endfor %} + + + + + + + + + + +
LändereiPacht vereinnahmtUmlagenGrundsteuerSonstige Einnahmen
{{ a.land }}€{{ a.pacht_vereinnahmt|floatformat:2 }}€{{ a.umlagen_vereinnahmt|floatformat:2 }}€{{ a.grundsteuer_betrag|floatformat:2 }}€{{ a.sonstige_einnahmen|floatformat:2 }}
Summe€{{ pacht_vereinnahmt|floatformat:2 }}€{{ grundsteuer_gesamt|floatformat:2 }}
+ {% endif %} + + {% if not verpachtungen and not landabrechnungen %} +

Keine Verpachtungs- oder Abrechnungsdaten für {{ jahr }} vorhanden.

+ {% endif %} +
diff --git a/app/templates/berichte/sektionen/konten_uebersicht.html b/app/templates/berichte/sektionen/konten_uebersicht.html new file mode 100644 index 0000000..a64fadc --- /dev/null +++ b/app/templates/berichte/sektionen/konten_uebersicht.html @@ -0,0 +1,46 @@ + +
+

Kontenübersicht

+ +
+
+
{{ konten_anzahl }}
+
Aktive Konten
+
+
+
€{{ konten_gesamtsaldo|floatformat:2 }}
+
Gesamtsaldo
+
+
+ + {% if konten_liste %} + + + + + + + + + + + + {% for k in konten_liste %} + + + + + + + + {% endfor %} + + + + + + + +
KontonameBankKontotypIBANSaldo
{{ k.kontoname }}{{ k.bank_name }}{{ k.get_konto_typ_display }}{{ k.iban|default:"-" }}€{{ k.saldo|floatformat:2 }}
Gesamtsaldo€{{ konten_gesamtsaldo|floatformat:2 }}
+ {% endif %} +
diff --git a/app/templates/berichte/sektionen/unterstuetzungen.html b/app/templates/berichte/sektionen/unterstuetzungen.html new file mode 100644 index 0000000..09d4faf --- /dev/null +++ b/app/templates/berichte/sektionen/unterstuetzungen.html @@ -0,0 +1,41 @@ + +{% if unterstuetzungen %} +
+

Unterstützungszahlungen {{ jahr }}

+

+ {{ unterstuetzungen.count }} Unterstützung(en) geplant/ausgezahlt · + {{ unterstuetzungen_ausgezahlt.count }} überwiesen (€{{ total_unterstuetzungen|floatformat:2 }}) +

+ + + + + + + + + + + + {% for u in unterstuetzungen %} + + + + + + + + {% endfor %} + + + + + + + + +
DestinatärBetragFällig amStatusVerwendungszweck
{{ u.destinataer.get_full_name }}€{{ u.betrag|floatformat:2 }}{{ u.faellig_am|date:"d.m.Y" }} + {{ u.get_status_display }} + {{ u.beschreibung|default:"-" }}
Summe ausgezahlt€{{ total_unterstuetzungen|floatformat:2 }}
+
+{% endif %} diff --git a/app/templates/berichte/sektionen/verpachtungen.html b/app/templates/berichte/sektionen/verpachtungen.html new file mode 100644 index 0000000..6ee6477 --- /dev/null +++ b/app/templates/berichte/sektionen/verpachtungen.html @@ -0,0 +1,88 @@ + +
+

Pachtbericht{% if jahr %} {{ jahr }}{% endif %}

+ + {% if pacht_statistik %} +
+
+
{{ pacht_statistik.aktive_vertraege }}
+
Aktive Pachtverträge
+
+
+
€{{ pacht_statistik.total_pachtzins|floatformat:2 }}
+
Gesamtpachtzins p.a.
+
+
+
{{ pacht_statistik.total_flaeche|floatformat:0 }} qm
+
Verpachtete Fläche
+
+
+
{{ pacht_statistik.auslaufend_12m }}
+
Laufen in 12 Mon. aus
+
+
+ {% endif %} + + {% if pacht_auslaufend %} +

Auslaufende Verträge (nächste 12 Monate)

+ + + + + + + + + + + {% for v in pacht_auslaufend %} + + + + + + + {% endfor %} + +
LändereiPächterPachtendePachtzins
{{ v.land }}{{ v.paechter.get_full_name }}{{ v.pachtende|date:"d.m.Y" }}€{{ v.pachtzins_pauschal|floatformat:2 }}
+ {% endif %} + + {% if verpachtungen %} +

Alle Verpachtungen

+ + + + + + + + + + + + + + {% for v in verpachtungen %} + + + + + + + + + + {% endfor %} + + + + + + + + +
LändereiPächterFlächePachtzinsBeginnEndeStatus
{{ v.land }}{{ v.paechter.get_full_name }}{{ v.verpachtete_flaeche|floatformat:0 }} qm€{{ v.pachtzins_pauschal|floatformat:2 }}{{ v.pachtbeginn|date:"d.m.Y" }}{% if v.pachtende %}{{ v.pachtende|date:"d.m.Y" }}{% else %}unbefristet{% endif %} + {{ v.get_status_display }} +
Gesamtpachtzins€{{ total_pachtzins|floatformat:2 }}
+ {% endif %} +
diff --git a/app/templates/berichte/sektionen/verwaltungskosten.html b/app/templates/berichte/sektionen/verwaltungskosten.html new file mode 100644 index 0000000..4b2f04a --- /dev/null +++ b/app/templates/berichte/sektionen/verwaltungskosten.html @@ -0,0 +1,30 @@ + +{% if verwaltungskosten_nach_kategorie %} +
+

Verwaltungskosten {{ jahr }}

+ + + + + + + + + + {% for k in verwaltungskosten_nach_kategorie %} + + + + + + {% endfor %} + + + + + + + +
KategorieAnzahlBetrag
{{ k.kategorie|capfirst }}{{ k.anzahl }}€{{ k.summe|floatformat:2 }}
Gesamt€{{ total_verwaltungskosten|floatformat:2 }}
+
+{% endif %} diff --git a/app/templates/stiftung/bericht_list.html b/app/templates/stiftung/bericht_list.html index 955e20f..683ec7c 100644 --- a/app/templates/stiftung/bericht_list.html +++ b/app/templates/stiftung/bericht_list.html @@ -13,8 +13,52 @@ + +
+
+
+
+
+ Berichtsvorlagen +
+
+
+
+ {% for key, vorlage in bericht_vorlagen.items %} +
+
+
+ +
{{ vorlage.label }}
+

{{ vorlage.beschreibung }}

+
+
+ + + +
+
+
+
+
+ {% endfor %} +
+
+
+
+
+
- +
@@ -23,11 +67,10 @@
-

- Generieren Sie detaillierte Jahresberichte mit allen wichtigen Informationen zu Destinatären, - Förderungen und Ländereien. +

+ Generieren Sie detaillierte Jahresberichte mit allen wichtigen Informationen.

- +
@@ -46,18 +89,17 @@
- -
-
Verfügbare Berichte:
-
+ +
+
{% for year in jahre %} -
+
Jahresbericht {{ year }} -
- +
+
+
+ Bericht zusammenstellen +
+
+
+

+ Stellen Sie einen individuellen Bericht aus einzelnen Sektionen zusammen. +

+
+ {% csrf_token %} + +
+ + {% for key, sektion in bericht_sektionen.items %} +
+ + +
+ {% endfor %} +
+ +
+
+ + +
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+
+
+
+ + +
+
+
Statistik-Übersicht @@ -79,116 +182,39 @@
-
+
-
+
-
Destinatäre
-

{{ total_destinataere|default:"0" }}

+
Destinatäre
+

{{ total_destinataere|default:"0" }}

-
+
-
+
-
Förderungen
-

{{ total_foerderungen|default:"0" }}

+
Förderungen
+

{{ total_foerderungen|default:"0" }}

-
-
-
- -
Destinatäre
-

{{ total_destinataere|default:"0" }}

-
-
-
-
+
-
+
-
Ländereien
-

{{ total_laendereien|default:"0" }}

+
Ländereien
+

{{ total_laendereien|default:"0" }}

-
+
-
+
-
Verpachtungen
-

{{ total_verpachtungen|default:"0" }}

-
-
-
-
- - -
-
-
-
- - -
-
-
-
-
- Weitere Berichtstypen -
-
-
-
-
-
-
- -
Finanzberichte
-

Detaillierte Auswertungen zu Förderungen und Ausgaben.

- -
-
-
-
-
-
- -
Trendanalysen
-

Langzeitentwicklungen und Prognosen für die Zukunft.

- -
-
-
-
-
-
- -
Export-Funktionen
-

Datenexport in verschiedene Formate (Excel, CSV, PDF).

- +
Verpachtungen
+

{{ total_verpachtungen|default:"0" }}

@@ -198,4 +224,30 @@
-{% endblock %} +{% endblock %} + +{% block extra_js %} + +{% endblock %} diff --git a/app/templates/stiftung/jahresbericht.html b/app/templates/stiftung/jahresbericht.html index 54450bf..e76891a 100644 --- a/app/templates/stiftung/jahresbericht.html +++ b/app/templates/stiftung/jahresbericht.html @@ -4,109 +4,62 @@ Stiftung – Jahresbericht {{ jahr }} @@ -114,253 +67,52 @@ + {% if show_cover %} + {% include "berichte/cover_page.html" %} + {% endif %} +
-

Jahresbericht {{ jahr }}

-
van Hees-Theyssen-Vogel'sche Familienstiftung
-
Erstellt am {% now "d.m.Y" %}
-
- - -
-

1. Jahresbilanz {{ jahr }}

-
-
-
€{{ total_einnahmen|floatformat:2 }}
-
Einnahmen (Pacht)
+
+
+ {% if logo_base64 %} + + {% endif %} +

{{ corporate_settings.stiftung_name }}

+

Jahresbericht {{ jahr }}

-
-
€{{ total_ausgaben|floatformat:2 }}
-
Ausgaben gesamt
-
-
-
{% if netto >= 0 %}+{% endif %}€{{ netto|floatformat:2 }}
-
Nettosaldo
+
+
+ {% if corporate_settings.address_line1 %}

{{ corporate_settings.address_line1 }}

{% endif %} + {% if corporate_settings.address_line2 %}

{{ corporate_settings.address_line2 }}

{% endif %} + {% if corporate_settings.phone %}

{{ corporate_settings.phone }}

{% endif %} + {% if corporate_settings.email %}

{{ corporate_settings.email }}

{% endif %} +
-
-
-
€{{ total_ausgaben_foerderung|floatformat:2 }}
-
Förderausgaben
-
-
-
€{{ total_verwaltungskosten|floatformat:2 }}
-
Verwaltungskosten
-
-
-
€{{ pacht_vereinnahmt|floatformat:2 }}
-
Pacht vereinnahmt
-
-
-
€{{ grundsteuer_gesamt|floatformat:2 }}
-
Grundsteuer
-
+
+ Erstellt am {% now "d.m.Y" %} · Berichtszeitraum: {{ jahr }}
- - {% if unterstuetzungen %} -
-

2. Unterstützungszahlungen {{ jahr }}

-

- {{ unterstuetzungen.count }} Unterstützung(en) geplant/ausgezahlt · - {{ unterstuetzungen_ausgezahlt.count }} überwiesen (€{{ total_unterstuetzungen|floatformat:2 }}) -

- - - - - - - - - - - - {% for u in unterstuetzungen %} - - - - - - - - {% endfor %} - - - - - - - - -
DestinatärBetragFällig amStatusVerwendungszweck
{{ u.destinataer.get_full_name }}€{{ u.betrag|floatformat:2 }}{{ u.faellig_am|date:"d.m.Y" }} - {{ u.get_status_display }} - {{ u.beschreibung|default:"-" }}
Summe ausgezahlt€{{ total_unterstuetzungen|floatformat:2 }}
-
- {% endif %} - - - {% if foerderungen %} -
-

3. Förderungen {{ jahr }}

- - - - - - - - - - - - {% for f in foerderungen %} - - - - - - - - {% endfor %} - - - - - - - - -
BegünstigterKategorieBetragStatusAntragsdatum
- {% if f.destinataer %}{{ f.destinataer.get_full_name }} - {% elif f.person %}{{ f.person.get_full_name }} - {% else %}–{% endif %} - {{ f.get_kategorie_display }}€{{ f.betrag|floatformat:2 }} - {{ f.get_status_display }} - {{ f.antragsdatum|date:"d.m.Y" }}
Summe€{{ total_foerderungen_legacy|floatformat:2 }}
-
- {% endif %} - - -
-

4. Grundstücksverwaltung

- - {% if verpachtungen %} -

Aktive Verpachtungen

- - - - - - - - - - - - {% for v in verpachtungen %} - - - - - - - - {% endfor %} - - - - - - - - -
LändereiPächterVerpachtete FlächeJahrespachtzinsPachtende
{{ v.land }}{{ v.paechter.get_full_name }}{{ v.verpachtete_flaeche|floatformat:0 }} qm€{{ v.pachtzins_pauschal|floatformat:2 }}{% if v.pachtende %}{{ v.pachtende|date:"d.m.Y" }}{% else %}unbefristet{% endif %}
Gesamtpachtzins (kalkuliert)€{{ total_pachtzins|floatformat:2 }}
- {% endif %} - - {% if landabrechnungen %} -

Landabrechnungen {{ jahr }}

- - - - - - - - - - - - {% for a in landabrechnungen %} - - - - - - - - {% endfor %} - - - - - - - - - - -
LändereiPacht vereinnahmtUmlagenGrundsteuerSonstige Einnahmen
{{ a.land }}€{{ a.pacht_vereinnahmt|floatformat:2 }}€{{ a.umlagen_vereinnahmt|floatformat:2 }}€{{ a.grundsteuer_betrag|floatformat:2 }}€{{ a.sonstige_einnahmen|floatformat:2 }}
Summe€{{ pacht_vereinnahmt|floatformat:2 }}€{{ grundsteuer_gesamt|floatformat:2 }}
- {% endif %} - - {% if not verpachtungen and not landabrechnungen %} -

Keine Verpachtungs- oder Abrechnungsdaten für {{ jahr }} vorhanden.

- {% endif %} -
- - - {% if verwaltungskosten_nach_kategorie %} -
-

5. Verwaltungskosten {{ jahr }}

- - - - - - - - - - {% for k in verwaltungskosten_nach_kategorie %} - - - - - - {% endfor %} - - - - - - - -
KategorieAnzahlBetrag
{{ k.kategorie|capfirst }}{{ k.anzahl }}€{{ k.summe|floatformat:2 }}
Gesamt€{{ total_verwaltungskosten|floatformat:2 }}
-
- {% endif %} + + {% 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" %}