Phase 2: Destinatär-Timeline, Nachweis-Board, Zahlungs-Pipeline & Pächter-Workflow

2a. Destinatär-Timeline (/destinataere/<pk>/timeline/)
    - Chronologische Ansicht aller Events (Zahlungen, Nachweise, E-Mails, Notizen)
    - Filter nach Typ via GET-Parameter

2b. Nachweis-Board (/nachweis-board/)
    - Quartals-Übersicht aller aktiver Destinatäre (Q1–Q4) in einer Tabellenansicht
    - Batch-Erinnerung: erzeugt Audit-Log-Einträge für säumige Destinatäre
    - Semester-Logik erhalten (15.03 / 15.09 Fristen)

2c. Zahlungs-Pipeline (/zahlungs-pipeline/)
    - 5-Stufen-Kanban: Offen → Nachweis eingereicht → Freigegeben → Überwiesen → Abgeschlossen
    - Vier-Augen-Prinzip: can_be_freigegeben() prüft anderen Nutzer als Ersteller
    - SEPA pain.001 XML-Export (/sepa-export/) für freigegebene Zahlungen
    - Neue Status-Werte: nachweis_eingereicht, freigegeben, abgeschlossen
    - Neue Felder: freigegeben_von, freigegeben_am, erstellt_von

2d. Pächter-Workflow (/paechter/workflow/)
    - Pipeline nach Restlaufzeit: abgelaufen / <6M / 6–24M / >24M / unbefristet
    - Ausstehende Jahresabrechnungen (Vorjahr ohne Abrechnung)
    - Pachtanpassungen fällig (Verträge > 5 Jahre laufend)
    - Top-Pächter nach Gesamtfläche

Sidebar-Navigation um Pipeline, Nachweis-Board und Pacht-Workflow erweitert.
Migration 0047 erzeugt und angewendet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
SysAdmin Agent
2026-03-11 10:40:43 +00:00
parent bf47ba11c9
commit ee2c827d85
11 changed files with 1327 additions and 3 deletions

View File

@@ -1551,3 +1551,114 @@ def verpachtung_delete(request, pk):
return render(request, 'stiftung/verpachtung_confirm_delete.html', context)
# ============================================================
# Phase 2d: Pächter-Workflow-Verbesserung
# ============================================================
@login_required
def paechter_workflow(request):
"""2d: Pipeline-Ansicht für Pächter Vertragsfristen, Pachtanpassungen, Abrechnungen."""
heute = date.today()
# Aktive Verpachtungen abrufen mit Restlaufzeit
aktive_verpachtungen = LandVerpachtung.objects.filter(
status="aktiv"
).select_related("land", "paechter").order_by("pachtende")
# Kategorisieren
abgelaufen = []
demnachst = [] # < 6 Monate
mittelfrisitig = [] # 624 Monate
langfristig = [] # > 24 Monate
kein_enddatum = []
for v in aktive_verpachtungen:
if not v.pachtende:
kein_enddatum.append(v)
continue
restlaufzeit = (v.pachtende - heute).days
if restlaufzeit < 0:
abgelaufen.append(v)
elif restlaufzeit <= 180:
demnachst.append(v)
elif restlaufzeit <= 730:
mittelfrisitig.append(v)
else:
langfristig.append(v)
# Ausstehende Jahresabrechnungen (letztes Jahr ohne Abrechnung)
letztes_jahr = heute.year - 1
laender_ohne_abrechnung = Land.objects.filter(
aktiv=True
).exclude(
landabrechnung__abrechnungsjahr=letztes_jahr
).order_by("lfd_nr")[:20]
# Pächter mit hoher Gesamtfläche (Top-Pächter)
top_paechter = Paechter.objects.annotate(
flaeche=Sum("landverpachtung__verpachtete_flaeche"),
anzahl_vertraege=Count("landverpachtung")
).filter(flaeche__gt=0).order_by("-flaeche")[:10]
# Anstehende Pachtanpassungen (> 5 Jahre laufend, keine Erhöhung dokumentiert)
fuenf_jahre_ago = date(heute.year - 5, heute.month, heute.day)
lang_laufend = LandVerpachtung.objects.filter(
status="aktiv",
pachtbeginn__lte=fuenf_jahre_ago,
).select_related("land", "paechter").order_by("pachtbeginn")[:20]
pipeline_stages = [
{
"key": "abgelaufen",
"label": "Abgelaufen / Handlungsbedarf",
"farbe": "danger",
"icon": "fa-exclamation-triangle",
"verpachtungen": abgelaufen,
"count": len(abgelaufen),
},
{
"key": "demnachst",
"label": "Bald fällig (< 6 Monate)",
"farbe": "warning",
"icon": "fa-clock",
"verpachtungen": demnachst,
"count": len(demnachst),
},
{
"key": "mittelfristig",
"label": "Mittelfristig (624 Monate)",
"farbe": "info",
"icon": "fa-calendar",
"verpachtungen": mittelfrisitig,
"count": len(mittelfrisitig),
},
{
"key": "langfristig",
"label": "Langfristig (> 24 Monate)",
"farbe": "success",
"icon": "fa-check",
"verpachtungen": langfristig,
"count": len(langfristig),
},
{
"key": "unbefristet",
"label": "Unbefristet / Kein Enddatum",
"farbe": "secondary",
"icon": "fa-infinity",
"verpachtungen": kein_enddatum,
"count": len(kein_enddatum),
},
]
context = {
"pipeline_stages": pipeline_stages,
"laender_ohne_abrechnung": laender_ohne_abrechnung,
"top_paechter": top_paechter,
"lang_laufend": lang_laufend,
"letztes_jahr": letztes_jahr,
"heute": heute,
}
return render(request, "stiftung/paechter_workflow.html", context)