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>
152 lines
7.0 KiB
HTML
152 lines
7.0 KiB
HTML
{% extends 'base.html' %}
|
||
{% load static %}
|
||
|
||
{% block title %}Timeline – {{ destinataer.get_full_name }} – Stiftungsverwaltung{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="row">
|
||
<div class="col-12">
|
||
<!-- Header -->
|
||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||
<h1 class="h3">
|
||
<i class="fas fa-stream text-primary me-2"></i>
|
||
Timeline: {{ destinataer.get_full_name }}
|
||
</h1>
|
||
<div>
|
||
<a href="{% url 'stiftung:destinataer_detail' pk=destinataer.pk %}" class="btn btn-outline-secondary">
|
||
<i class="fas fa-arrow-left me-2"></i>Zum Destinatär
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Filter Bar -->
|
||
<div class="card shadow mb-4">
|
||
<div class="card-body py-2">
|
||
<div class="d-flex gap-2 flex-wrap align-items-center">
|
||
<span class="text-muted small fw-bold me-2">Filter:</span>
|
||
<a href="?typ=" class="btn btn-sm {% if not typ_filter %}btn-primary{% else %}btn-outline-primary{% endif %}">
|
||
<i class="fas fa-list me-1"></i>Alle
|
||
</a>
|
||
<a href="?typ=zahlung" class="btn btn-sm {% if typ_filter == 'zahlung' %}btn-success{% else %}btn-outline-success{% endif %}">
|
||
<i class="fas fa-money-bill-wave me-1"></i>Zahlungen
|
||
</a>
|
||
<a href="?typ=nachweis" class="btn btn-sm {% if typ_filter == 'nachweis' %}btn-warning{% else %}btn-outline-warning{% endif %}">
|
||
<i class="fas fa-file-alt me-1"></i>Nachweise
|
||
</a>
|
||
<a href="?typ=email" class="btn btn-sm {% if typ_filter == 'email' %}btn-info{% else %}btn-outline-info{% endif %}">
|
||
<i class="fas fa-envelope me-1"></i>E-Mails
|
||
</a>
|
||
<a href="?typ=notiz" class="btn btn-sm {% if typ_filter == 'notiz' %}btn-secondary{% else %}btn-outline-secondary{% endif %}">
|
||
<i class="fas fa-sticky-note me-1"></i>Notizen
|
||
</a>
|
||
<span class="ms-auto text-muted small">{{ events|length }} Einträge</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Timeline -->
|
||
{% if events %}
|
||
<div class="timeline-wrapper">
|
||
{% for event in events %}
|
||
<div class="timeline-item mb-3">
|
||
<div class="card shadow-sm border-start border-4 border-{{ event.farbe }}">
|
||
<div class="card-body py-2 px-3">
|
||
<div class="d-flex align-items-start gap-3">
|
||
<!-- Icon -->
|
||
<div class="timeline-icon text-{{ event.farbe }} pt-1">
|
||
<i class="fas {{ event.icon }} fa-lg"></i>
|
||
</div>
|
||
<!-- Content -->
|
||
<div class="flex-grow-1">
|
||
<div class="d-flex justify-content-between align-items-start">
|
||
<div>
|
||
<span class="fw-semibold">{{ event.titel }}</span>
|
||
{% if event.beschreibung %}
|
||
<span class="text-muted ms-2 small">{{ event.beschreibung }}</span>
|
||
{% endif %}
|
||
</div>
|
||
<div class="text-end ms-3 text-nowrap">
|
||
<div class="small text-muted">{{ event.datum|date:"d.m.Y" }}</div>
|
||
{% if event.status %}
|
||
<span class="badge bg-{{ event.farbe }} text-white small">{{ event.status }}</span>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Extra info per type -->
|
||
{% if event.typ == 'zahlung' %}
|
||
<div class="small mt-1">
|
||
{% with u=event.objekt %}
|
||
Konto: {{ u.konto.kontoname }}
|
||
{% if u.empfaenger_iban %} · IBAN: {{ u.empfaenger_iban|slice:":4" }}…{% endif %}
|
||
{% if u.ausgezahlt_von %} · Ausgezahlt von: {{ u.ausgezahlt_von.get_full_name|default:u.ausgezahlt_von.username }}{% endif %}
|
||
{% if u.freigegeben_von %} · Freigegeben: {{ u.freigegeben_von.get_full_name|default:u.freigegeben_von.username }} ({{ u.freigegeben_am|date:"d.m.Y" }}){% endif %}
|
||
{% endwith %}
|
||
</div>
|
||
{% elif event.typ == 'nachweis' %}
|
||
<div class="small mt-1">
|
||
{% with n=event.objekt %}
|
||
Fortschritt: {{ n.get_completion_percentage }}%
|
||
{% if n.geprueft_von %} · Geprüft von: {{ n.geprueft_von.get_full_name|default:n.geprueft_von.username }}{% endif %}
|
||
{% endwith %}
|
||
</div>
|
||
{% elif event.typ == 'email' %}
|
||
<div class="small mt-1">
|
||
{% with e=event.objekt %}
|
||
Von: {{ e.absender_name|default:e.absender_email }}
|
||
{% if e.quartalsnachweis %} · Zugeordnet: Q{{ e.quartalsnachweis.quartal }}/{{ e.quartalsnachweis.jahr }}{% endif %}
|
||
{% endwith %}
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
{% else %}
|
||
<div class="alert alert-info">
|
||
<i class="fas fa-info-circle me-2"></i>
|
||
Keine Timeline-Einträge vorhanden{% if typ_filter %} für den gewählten Filter{% endif %}.
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<style>
|
||
.timeline-wrapper {
|
||
position: relative;
|
||
}
|
||
.timeline-wrapper::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 20px;
|
||
top: 0;
|
||
bottom: 0;
|
||
width: 2px;
|
||
background: #dee2e6;
|
||
z-index: 0;
|
||
}
|
||
.timeline-item {
|
||
position: relative;
|
||
padding-left: 48px;
|
||
}
|
||
.timeline-icon {
|
||
position: absolute;
|
||
left: -28px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
width: 32px;
|
||
height: 32px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: white;
|
||
border-radius: 50%;
|
||
border: 2px solid #dee2e6;
|
||
z-index: 1;
|
||
}
|
||
</style>
|
||
{% endblock %}
|