Files
stiftung-management-system/app/templates/stiftung/destinataer_detail.html
SysAdmin Agent aed540fe4b
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy (push) Has been cancelled
Code Quality / quality (push) Has been cancelled
Add Vorlagen editor, upload portal, onboarding, and participant import command
- Dokument-Vorlagen-Editor: create/edit/reset document templates (admin)
- Upload-Portal: public portal for Nachweis uploads via token
- Onboarding: invite Destinatäre via email with multi-step wizard
- Bestätigungsschreiben: preview and send confirmation letters
- Email settings: SMTP configuration UI
- Management command: import_veranstaltung_teilnehmer for bulk participant import

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-21 09:25:18 +00:00

873 lines
59 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{% extends 'base.html' %}
{% load static %}
{% block title %}{{ destinataer.get_full_name }} - Destinataer{% endblock %}
{% block content %}
<div class="container-fluid px-4">
{# ── Profile Header ── #}
<div class="card shadow-sm mb-4 border-0" style="background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);">
<div class="card-body py-3">
<div class="row align-items-center">
<div class="col-auto">
<div class="rounded-circle bg-primary text-white d-flex align-items-center justify-content-center" style="width:56px;height:56px;font-size:1.4rem;">
{{ destinataer.vorname|first }}{{ destinataer.nachname|first }}
</div>
</div>
<div class="col">
<h4 class="mb-1">
{{ destinataer.get_full_name }}
{% if destinataer.aktiv %}
<span class="badge bg-success ms-2" style="font-size:.65rem;vertical-align:middle;">Aktiv</span>
{% else %}
<span class="badge bg-secondary ms-2" style="font-size:.65rem;vertical-align:middle;">Inaktiv</span>
{% endif %}
{% if destinataer.finanzielle_notlage %}
<span class="badge bg-danger ms-1" style="font-size:.65rem;vertical-align:middle;"><i class="fas fa-exclamation-triangle me-1"></i>Notlage</span>
{% endif %}
</h4>
<div class="text-muted small">
{% if destinataer.familienzweig %}<span class="me-3"><i class="fas fa-sitemap me-1"></i>{{ destinataer.get_familienzweig_display }}</span>{% endif %}
{% if destinataer.email %}<span class="me-3"><i class="fas fa-envelope me-1"></i><a href="mailto:{{ destinataer.email }}">{{ destinataer.email }}</a></span>{% endif %}
{% if destinataer.telefon %}<span class="me-3"><i class="fas fa-phone me-1"></i>{{ destinataer.telefon }}</span>{% endif %}
{% if destinataer.iban %}<span class="me-3"><i class="fas fa-university me-1"></i>{{ destinataer.iban }}</span>{% endif %}
</div>
</div>
<div class="col-auto">
{% if destinataer.vierteljaehrlicher_betrag %}
<div class="text-end">
<div class="text-muted small">Quartalsbetrag</div>
<div class="h5 text-success mb-0">&euro;{{ destinataer.vierteljaehrlicher_betrag|floatformat:2 }}</div>
</div>
{% endif %}
</div>
<div class="col-auto">
<div class="btn-group">
<button id="edit-btn" class="btn btn-outline-primary btn-sm" onclick="enableEditMode()">
<i class="fas fa-pen me-1"></i>Bearbeiten
</button>
<button id="save-btn" class="btn btn-success btn-sm" onclick="saveChanges()" style="display:none;">
<i class="fas fa-save me-1"></i>Speichern
</button>
<button id="cancel-btn" class="btn btn-outline-secondary btn-sm" onclick="cancelEdit()" style="display:none;">
<i class="fas fa-times"></i>
</button>
</div>
<a href="{% url 'stiftung:unterstuetzung_create' %}?destinataer={{ destinataer.pk }}" class="btn btn-success btn-sm ms-1">
<i class="fas fa-heart me-1"></i>Zahlung
</a>
<div class="btn-group ms-1">
<button class="btn btn-outline-secondary btn-sm dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-ellipsis-v"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="{% url 'stiftung:destinataer_export' pk=destinataer.pk %}"><i class="fas fa-download me-2"></i>Export</a></li>
<li><hr class="dropdown-divider"></li>
<li>
<a class="dropdown-item" href="{% url 'stiftung:bestaetigung_vorschau' pk=destinataer.pk %}" target="_blank">
<i class="fas fa-file-pdf me-2"></i>Bestätigung (Vorschau)
</a>
</li>
<li>
<form method="post" action="{% url 'stiftung:bestaetigung_versenden' pk=destinataer.pk %}" class="d-inline">
{% csrf_token %}
<button type="submit" class="dropdown-item" onclick="return confirm('Bestätigungsschreiben per E-Mail an {{ destinataer.email|default:'(keine E-Mail)'}} senden?')">
<i class="fas fa-envelope me-2"></i>Bestätigung versenden
</button>
</form>
</li>
<li><hr class="dropdown-divider"></li>
<li>
<form method="post" action="{% url 'stiftung:destinataer_toggle_archiv' pk=destinataer.pk %}" class="d-inline">
{% csrf_token %}
{% if destinataer.aktiv %}
<button type="submit" class="dropdown-item" onclick="return confirm('Destinataer archivieren?')">
<i class="fas fa-archive me-2"></i>Archivieren
</button>
{% else %}
<button type="submit" class="dropdown-item" onclick="return confirm('Destinataer reaktivieren?')">
<i class="fas fa-undo me-2"></i>Reaktivieren
</button>
{% endif %}
</form>
</li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="{% url 'stiftung:destinataer_delete' pk=destinataer.pk %}"><i class="fas fa-trash me-2"></i>Loeschen</a></li>
</ul>
</div>
<a href="{% url 'stiftung:destinataer_list' %}" class="btn btn-outline-secondary btn-sm ms-1" title="Zurueck">
<i class="fas fa-arrow-left"></i>
</a>
</div>
</div>
</div>
</div>
{# ── Tab Navigation ── #}
<ul class="nav nav-tabs mb-3" id="destTabs" role="tablist">
<li class="nav-item">
<button class="nav-link active" id="tab-stamm" data-bs-toggle="tab" data-bs-target="#pane-stamm" type="button">
<i class="fas fa-id-card me-1"></i>Stammdaten
</button>
</li>
<li class="nav-item">
<button class="nav-link" id="tab-nachweise" data-bs-toggle="tab" data-bs-target="#pane-nachweise" type="button">
<i class="fas fa-calendar-check me-1"></i>Nachweise
<span class="badge bg-primary ms-1">{{ quarterly_confirmations|length }}</span>
</button>
</li>
<li class="nav-item">
<button class="nav-link" id="tab-zahlungen" data-bs-toggle="tab" data-bs-target="#pane-zahlungen" type="button">
<i class="fas fa-money-bill-wave me-1"></i>Zahlungen
<span class="badge bg-success ms-1">{{ unterstuetzungen.count }}</span>
</button>
</li>
<li class="nav-item">
<button class="nav-link" id="tab-timeline" data-bs-toggle="tab" data-bs-target="#pane-timeline" type="button">
<i class="fas fa-stream me-1"></i>Timeline
</button>
</li>
<li class="nav-item">
<button class="nav-link" id="tab-dokumente" data-bs-toggle="tab" data-bs-target="#pane-dokumente" type="button">
<i class="fas fa-file-alt me-1"></i>Dokumente
<span class="badge bg-secondary ms-1">{{ verknuepfte_dokumente.count }}</span>
</button>
</li>
<li class="nav-item">
<button class="nav-link" id="tab-notizen" data-bs-toggle="tab" data-bs-target="#pane-notizen" type="button">
<i class="fas fa-sticky-note me-1"></i>Notizen
<span class="badge bg-secondary ms-1">{{ notizen_eintraege.count }}</span>
</button>
</li>
</ul>
{# ── Tab Content ── #}
<div class="tab-content" id="destTabContent">
{# ════════ TAB: Stammdaten ════════ #}
<div class="tab-pane fade show active" id="pane-stamm" role="tabpanel">
<form id="edit-form" method="post" action="{% url 'stiftung:destinataer_update' pk=destinataer.pk %}" style="display:contents;">
{% csrf_token %}
<div class="row g-3">
{# Left column Personal + Contact #}
<div class="col-lg-6">
<div class="card shadow-sm mb-3">
<div class="card-header py-2"><i class="fas fa-user me-2 text-primary"></i><strong>Persoenliche Daten</strong></div>
<div class="card-body py-2">
<table class="table table-sm table-borderless mb-0">
<tbody>
<tr>
<td class="text-muted" style="width:140px;">Vorname</td>
<td>
<span class="view-mode">{{ destinataer.vorname }}</span>
<input type="text" name="vorname" value="{{ destinataer.vorname }}" class="form-control form-control-sm edit-mode" style="display:none;" required>
</td>
</tr>
<tr>
<td class="text-muted">Nachname</td>
<td>
<span class="view-mode">{{ destinataer.nachname }}</span>
<input type="text" name="nachname" value="{{ destinataer.nachname }}" class="form-control form-control-sm edit-mode" style="display:none;" required>
</td>
</tr>
<tr>
<td class="text-muted">Geburtsdatum</td>
<td>
<span class="view-mode">{% if destinataer.geburtsdatum %}{{ destinataer.geburtsdatum|date:"d.m.Y" }}{% else %}<em class="text-muted">-</em>{% endif %}</span>
<input type="date" name="geburtsdatum" value="{% if destinataer.geburtsdatum %}{{ destinataer.geburtsdatum|date:'Y-m-d' }}{% endif %}" class="form-control form-control-sm edit-mode" style="display:none;">
</td>
</tr>
<tr>
<td class="text-muted">Familienzweig</td>
<td>
<span class="view-mode"><span class="badge bg-info">{{ destinataer.get_familienzweig_display|default:"-" }}</span></span>
<select name="familienzweig" class="form-select form-select-sm edit-mode" style="display:none;">
<option value="">---</option>
<option value="hauptzweig" {% if destinataer.familienzweig == 'hauptzweig' %}selected{% endif %}>Hauptzweig</option>
<option value="nebenzweig" {% if destinataer.familienzweig == 'nebenzweig' %}selected{% endif %}>Nebenzweig</option>
<option value="verwandt" {% if destinataer.familienzweig == 'verwandt' %}selected{% endif %}>Verwandt</option>
<option value="anderer" {% if destinataer.familienzweig == 'anderer' %}selected{% endif %}>Anderer</option>
</select>
</td>
</tr>
<tr>
<td class="text-muted">Berufsgruppe</td>
<td>
<span class="view-mode"><span class="badge bg-secondary">{{ destinataer.get_berufsgruppe_display|default:"-" }}</span></span>
<select name="berufsgruppe" class="form-select form-select-sm edit-mode" style="display:none;">
<option value="">---</option>
<option value="student" {% if destinataer.berufsgruppe == 'student' %}selected{% endif %}>Student/Studentin</option>
<option value="wissenschaftler" {% if destinataer.berufsgruppe == 'wissenschaftler' %}selected{% endif %}>Wissenschaftler/in</option>
<option value="kuenstler" {% if destinataer.berufsgruppe == 'künstler' %}selected{% endif %}>Kuenstler/in</option>
<option value="sozialarbeiter" {% if destinataer.berufsgruppe == 'sozialarbeiter' %}selected{% endif %}>Sozialarbeiter/in</option>
<option value="umweltschuetzer" {% if destinataer.berufsgruppe == 'umweltschützer' %}selected{% endif %}>Umweltschuetzer/in</option>
<option value="andere" {% if destinataer.berufsgruppe == 'andere' %}selected{% endif %}>Andere</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card shadow-sm mb-3">
<div class="card-header py-2"><i class="fas fa-address-book me-2 text-info"></i><strong>Kontakt & Adresse</strong></div>
<div class="card-body py-2">
<table class="table table-sm table-borderless mb-0">
<tbody>
<tr>
<td class="text-muted" style="width:140px;">E-Mail</td>
<td>
<span class="view-mode">{% if destinataer.email %}<a href="mailto:{{ destinataer.email }}">{{ destinataer.email }}</a>{% else %}<em class="text-muted">-</em>{% endif %}</span>
<input type="email" name="email" value="{{ destinataer.email|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;">
</td>
</tr>
<tr>
<td class="text-muted">Telefon</td>
<td>
<span class="view-mode">{{ destinataer.telefon|default:"<em class='text-muted'>-</em>" }}</span>
<input type="tel" name="telefon" value="{{ destinataer.telefon|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;">
</td>
</tr>
<tr>
<td class="text-muted">IBAN</td>
<td>
<span class="view-mode">{{ destinataer.iban|default:"<em class='text-muted'>-</em>" }}</span>
<input type="text" name="iban" value="{{ destinataer.iban|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;">
</td>
</tr>
<tr>
<td class="text-muted">Strasse</td>
<td>
<span class="view-mode">{{ destinataer.strasse|default:"<em class='text-muted'>-</em>" }}</span>
<input name="strasse" value="{{ destinataer.strasse|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;">
</td>
</tr>
<tr>
<td class="text-muted">PLZ / Ort</td>
<td>
<span class="view-mode">{% if destinataer.plz or destinataer.ort %}{{ destinataer.plz }} {{ destinataer.ort }}{% else %}<em class="text-muted">-</em>{% endif %}</span>
<div class="edit-mode" style="display:none;">
<div class="row g-2">
<div class="col-4"><input name="plz" value="{{ destinataer.plz|default:'' }}" class="form-control form-control-sm" placeholder="PLZ"></div>
<div class="col-8"><input name="ort" value="{{ destinataer.ort|default:'' }}" class="form-control form-control-sm" placeholder="Ort"></div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{# Right column Financial + Study #}
<div class="col-lg-6">
<div class="card shadow-sm mb-3">
<div class="card-header py-2"><i class="fas fa-euro-sign me-2 text-warning"></i><strong>Finanzen & Foerderung</strong></div>
<div class="card-body py-2">
<table class="table table-sm table-borderless mb-0">
<tbody>
<tr>
<td class="text-muted" style="width:180px;">Quartalsbetrag</td>
<td>
<span class="view-mode fw-bold text-success">{% if destinataer.vierteljaehrlicher_betrag %}&euro;{{ destinataer.vierteljaehrlicher_betrag|floatformat:2 }}{% else %}-{% endif %}</span>
<input type="number" name="vierteljaehrlicher_betrag" value="{{ destinataer.vierteljaehrlicher_betrag|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;" step="0.01">
</td>
</tr>
<tr>
<td class="text-muted">Monatliche Bezuege</td>
<td>
<span class="view-mode">{% if destinataer.monatliche_bezuege %}&euro;{{ destinataer.monatliche_bezuege|floatformat:2 }}{% else %}-{% endif %}</span>
<input type="number" name="monatliche_bezuege" value="{{ destinataer.monatliche_bezuege|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;" step="0.01">
</td>
</tr>
<tr>
<td class="text-muted">Jaehrliches Einkommen</td>
<td>
<span class="view-mode">{% if destinataer.jaehrliches_einkommen %}&euro;{{ destinataer.jaehrliches_einkommen|floatformat:2 }}{% else %}-{% endif %}</span>
<input type="number" name="jaehrliches_einkommen" value="{{ destinataer.jaehrliches_einkommen|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;" step="0.01">
</td>
</tr>
<tr>
<td class="text-muted">Vermoegen</td>
<td>
<span class="view-mode">{% if destinataer.vermoegen %}&euro;{{ destinataer.vermoegen|floatformat:2 }}{% else %}-{% endif %}</span>
<input type="number" name="vermoegen" value="{{ destinataer.vermoegen|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;" step="0.01">
</td>
</tr>
<tr>
<td class="text-muted">Haushaltsgroesse</td>
<td>
<span class="view-mode">{{ destinataer.haushaltsgroesse|default:"-" }}</span>
<input type="number" name="haushaltsgroesse" value="{{ destinataer.haushaltsgroesse }}" class="form-control form-control-sm edit-mode" style="display:none;" min="1">
</td>
</tr>
<tr>
<td class="text-muted">Standardkonto</td>
<td>
<span class="view-mode">{{ destinataer.standard_konto|default:"-" }}</span>
<select name="standard_konto" class="form-select form-select-sm edit-mode" style="display:none;">
<option value="">---</option>
{% for konto in stiftungskonten %}
<option value="{{ konto.pk }}" {% if destinataer.standard_konto_id == konto.pk %}selected{% endif %}>{{ konto.kontoname }}</option>
{% endfor %}
</select>
</td>
</tr>
<tr>
<td class="text-muted">Finanzielle Notlage</td>
<td>
<span class="view-mode">
{% if destinataer.finanzielle_notlage %}<span class="badge bg-danger">Ja</span>{% else %}<span class="badge bg-success">Nein</span>{% endif %}
</span>
<div class="edit-mode" style="display:none;">
<div class="form-check"><input type="checkbox" name="finanzielle_notlage" id="finanzielle_notlage" class="form-check-input" {% if destinataer.finanzielle_notlage %}checked{% endif %}><label class="form-check-label" for="finanzielle_notlage">Ja</label></div>
</div>
</td>
</tr>
<tr>
<td class="text-muted">Unterstuetzung bestaetigt</td>
<td>
<span class="view-mode">
{% if destinataer.unterstuetzung_bestaetigt %}<span class="badge bg-success">Ja</span>{% else %}<span class="badge bg-secondary">Nein</span>{% endif %}
</span>
<div class="edit-mode" style="display:none;">
<div class="form-check"><input type="checkbox" name="unterstuetzung_bestaetigt" id="unterstuetzung_bestaetigt" class="form-check-input" {% if destinataer.unterstuetzung_bestaetigt %}checked{% endif %}><label class="form-check-label" for="unterstuetzung_bestaetigt">Ja</label></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card shadow-sm mb-3">
<div class="card-header py-2"><i class="fas fa-graduation-cap me-2 text-secondary"></i><strong>Studium & Voraussetzungen</strong></div>
<div class="card-body py-2">
<table class="table table-sm table-borderless mb-0">
<tbody>
<tr>
<td class="text-muted" style="width:180px;">Abkoemmling gem. Satzung</td>
<td>
<span class="view-mode">{% if destinataer.ist_abkoemmling %}<span class="badge bg-success">Ja</span>{% else %}<span class="badge bg-secondary">Nein</span>{% endif %}</span>
<div class="edit-mode" style="display:none;">
<div class="form-check"><input type="checkbox" name="ist_abkoemmling" id="ist_abkoemmling" class="form-check-input" {% if destinataer.ist_abkoemmling %}checked{% endif %}><label class="form-check-label" for="ist_abkoemmling">Ja</label></div>
</div>
</td>
</tr>
<tr>
<td class="text-muted">Ausbildungsstand</td>
<td>
<span class="view-mode">{{ destinataer.ausbildungsstand|default:"-" }}</span>
<input name="ausbildungsstand" value="{{ destinataer.ausbildungsstand|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;">
</td>
</tr>
<tr>
<td class="text-muted">Institution</td>
<td>
<span class="view-mode">{{ destinataer.institution|default:"-" }}</span>
<input name="institution" value="{{ destinataer.institution|default:'' }}" class="form-control form-control-sm edit-mode" style="display:none;">
</td>
</tr>
<tr>
<td class="text-muted">Studiennachweis erf.</td>
<td>
<span class="view-mode">{% if destinataer.studiennachweis_erforderlich %}<span class="badge bg-info">Ja</span>{% else %}<span class="badge bg-secondary">Nein</span>{% endif %}</span>
<div class="edit-mode" style="display:none;">
<div class="form-check"><input type="checkbox" name="studiennachweis_erforderlich" id="studiennachweis_erforderlich" class="form-check-input" {% if destinataer.studiennachweis_erforderlich %}checked{% endif %}><label class="form-check-label" for="studiennachweis_erforderlich">Ja</label></div>
</div>
</td>
</tr>
<tr>
<td class="text-muted">Letzter Nachweis</td>
<td>
<span class="view-mode">{% if destinataer.letzter_studiennachweis %}{{ destinataer.letzter_studiennachweis|date:"d.m.Y" }}{% else %}-{% endif %}</span>
<input type="date" name="letzter_studiennachweis" value="{% if destinataer.letzter_studiennachweis %}{{ destinataer.letzter_studiennachweis|date:'Y-m-d' }}{% endif %}" class="form-control form-control-sm edit-mode" style="display:none;">
</td>
</tr>
</tbody>
</table>
</div>
</div>
{# Projektbeschreibung + Notizen #}
<div class="card shadow-sm mb-3">
<div class="card-header py-2"><i class="fas fa-sticky-note me-2 text-secondary"></i><strong>Beschreibung & Notizen</strong></div>
<div class="card-body py-2">
<div class="mb-2">
<small class="text-muted">Projektbeschreibung</small>
<div class="view-mode">{% if destinataer.projekt_beschreibung %}{{ destinataer.projekt_beschreibung|linebreaks }}{% else %}<em class="text-muted">-</em>{% endif %}</div>
<textarea name="projekt_beschreibung" class="form-control form-control-sm edit-mode" style="display:none;" rows="3">{{ destinataer.projekt_beschreibung|default:'' }}</textarea>
</div>
<div>
<small class="text-muted">Notizen</small>
<div class="view-mode">{% if destinataer.notizen %}{{ destinataer.notizen|linebreaks }}{% else %}<em class="text-muted">-</em>{% endif %}</div>
<textarea name="notizen" class="form-control form-control-sm edit-mode" style="display:none;" rows="3">{{ destinataer.notizen|default:'' }}</textarea>
</div>
</div>
</div>
{# Hidden fields for edit form #}
<div class="edit-mode" style="display:none;">
<div class="form-check mb-2"><input type="checkbox" name="aktiv" id="aktiv_edit" class="form-check-input" {% if destinataer.aktiv %}checked{% endif %}><label class="form-check-label" for="aktiv_edit">Aktiv</label></div>
</div>
</div>
</div>
</form>
</div>
{# ════════ TAB: Nachweise ════════ #}
<div class="tab-pane fade" id="pane-nachweise" role="tabpanel">
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<small class="text-muted">Studiennachweis: 15. Maerz / 15. September | Zahlung: vierteljaehrlich im Voraus</small>
</div>
<button type="button" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#addQuarterModal">
<i class="fas fa-plus me-1"></i>Quartal hinzufuegen
</button>
</div>
{% if quarterly_confirmations %}
<div class="table-responsive">
<table class="table table-hover table-sm align-middle">
<thead class="table-light">
<tr>
<th style="width:80px;">Zeitraum</th>
<th style="width:100px;">Status</th>
<th style="width:70px;">Fortschritt</th>
<th style="width:120px;">Fristen</th>
<th style="width:40px;text-align:center;" title="Studiennachweis"><i class="fas fa-graduation-cap"></i></th>
<th style="width:40px;text-align:center;" title="Einkommen"><i class="fas fa-euro-sign"></i></th>
<th style="width:40px;text-align:center;" title="Vermoegen"><i class="fas fa-piggy-bank"></i></th>
<th style="width:100px;">Aktionen</th>
</tr>
</thead>
<tbody>
{% for nachweis in quarterly_confirmations %}
<tr {% if nachweis.is_overdue %}class="table-warning"{% endif %}>
<td>
<strong>{{ nachweis.jahr }} Q{{ nachweis.quartal }}</strong>
{% if nachweis.is_overdue %}<br><small class="text-danger"><i class="fas fa-exclamation-triangle"></i></small>{% endif %}
</td>
<td>
{% if nachweis.status == 'offen' %}<span class="badge bg-secondary">Offen</span>
{% elif nachweis.status == 'teilweise' %}<span class="badge bg-warning">Teilweise</span>
{% elif nachweis.status == 'eingereicht' %}<span class="badge bg-info">Eingereicht</span>
{% elif nachweis.status == 'geprueft' %}<span class="badge bg-success">Freigegeben</span>
{% elif nachweis.status == 'auto_geprueft' %}<span class="badge bg-success"><i class="fas fa-magic"></i> Auto</span>
{% elif nachweis.status == 'nachbesserung' %}<span class="badge bg-warning">Nachbesserung</span>
{% elif nachweis.status == 'abgelehnt' %}<span class="badge bg-danger">Abgelehnt</span>
{% endif %}
</td>
<td>
{% with completion=nachweis.get_completion_percentage %}
<div class="progress" style="height:18px;" title="{{ completion }}%">
<div class="progress-bar {% if completion == 100 %}bg-success{% elif completion >= 70 %}bg-info{% elif completion >= 30 %}bg-warning{% else %}bg-danger{% endif %}"
style="width:{{ completion }}%" role="progressbar">{{ completion }}%</div>
</div>
{% endwith %}
</td>
<td>
<div class="small" style="line-height:1.4;">
{% if nachweis.studiennachweis_faelligkeitsdatum %}
<div class="mb-1"><i class="fas fa-graduation-cap text-primary"></i>
<span class="{% if nachweis.is_study_proof_overdue %}text-danger fw-bold{% endif %}">{{ nachweis.studiennachweis_faelligkeitsdatum|date:"d.m.Y" }}</span>
{% if nachweis.is_study_proof_overdue %}<i class="fas fa-exclamation-triangle text-danger"></i>{% endif %}
</div>
{% endif %}
{% if nachweis.zahlung_faelligkeitsdatum %}
<div><i class="fas fa-euro-sign text-success"></i>
<span class="{% if nachweis.is_payment_overdue %}text-danger fw-bold{% endif %}">{{ nachweis.zahlung_faelligkeitsdatum|date:"d.m.Y" }}</span>
{% if nachweis.is_payment_overdue %}<i class="fas fa-exclamation-triangle text-danger"></i>{% endif %}
</div>
{% endif %}
</div>
</td>
<td class="text-center">
{% if nachweis.studiennachweis_eingereicht %}
{% if nachweis.studiennachweis_datei %}<a href="{{ nachweis.studiennachweis_datei.url }}" target="_blank" class="text-success"><i class="fas fa-file-pdf"></i></a>
{% elif nachweis.studiennachweis_bemerkung %}<i class="fas fa-comment text-info"></i>
{% else %}<i class="fas fa-check text-success"></i>{% endif %}
{% else %}<i class="fas fa-times text-muted"></i>{% endif %}
</td>
<td class="text-center">
{% if nachweis.einkommenssituation_bestaetigt %}
{% if nachweis.einkommenssituation_datei %}<a href="{{ nachweis.einkommenssituation_datei.url }}" target="_blank" class="text-success"><i class="fas fa-file-pdf"></i></a>
{% elif nachweis.einkommenssituation_text %}<i class="fas fa-comment text-info" title="{{ nachweis.einkommenssituation_text|truncatechars:50 }}"></i>
{% else %}<i class="fas fa-check text-success"></i>{% endif %}
{% else %}<i class="fas fa-times text-muted"></i>{% endif %}
</td>
<td class="text-center">
{% if nachweis.vermogenssituation_bestaetigt %}
{% if nachweis.vermogenssituation_datei %}<a href="{{ nachweis.vermogenssituation_datei.url }}" target="_blank" class="text-success"><i class="fas fa-file-pdf"></i></a>
{% elif nachweis.vermogenssituation_text %}<i class="fas fa-comment text-info" title="{{ nachweis.vermogenssituation_text|truncatechars:50 }}"></i>
{% else %}<i class="fas fa-check text-success"></i>{% endif %}
{% else %}<i class="fas fa-times text-muted"></i>{% endif %}
</td>
<td>
<div class="btn-group btn-group-sm">
<a href="{% url 'stiftung:quarterly_confirmation_edit' nachweis.id %}" class="btn btn-outline-primary btn-sm" title="Bearbeiten"><i class="fas fa-edit"></i></a>
{% if nachweis.status == 'offen' or nachweis.status == 'teilweise' or nachweis.status == 'nachbesserung' %}
{% if destinataer.email %}
<form method="post" action="{% url 'stiftung:nachweis_aufforderung_senden' nachweis_pk=nachweis.id %}" style="display:inline;">
{% csrf_token %}
<button type="submit" class="btn btn-outline-info btn-sm" title="Upload-Aufforderung per E-Mail senden" onclick="return confirm('Upload-Link für {{ nachweis.jahr }} Q{{ nachweis.quartal }} an {{ destinataer.email }} senden?')"><i class="fas fa-paper-plane"></i></button>
</form>
{% endif %}
{% endif %}
{% if user.is_staff %}
{% if nachweis.status == 'eingereicht' %}
<button type="button" class="btn btn-outline-success btn-sm" onclick="approveQuarterly('{{ nachweis.id }}')" title="Freigeben"><i class="fas fa-check"></i></button>
{% elif nachweis.status == 'geprueft' %}
<button type="button" class="btn btn-outline-success btn-sm" onclick="approveQuarterly('{{ nachweis.id }}')" title="Erneut freigeben"><i class="fas fa-sync"></i></button>
<button type="button" class="btn btn-outline-warning btn-sm" onclick="resetQuarterly('{{ nachweis.id }}')" title="Zuruecksetzen"><i class="fas fa-undo"></i></button>
{% endif %}
{% endif %}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4 text-muted">
<i class="fas fa-calendar-check fa-2x mb-2"></i>
<p>Keine Nachweise vorhanden.</p>
</div>
{% endif %}
</div>
{# ════════ TAB: Zahlungen ════════ #}
<div class="tab-pane fade" id="pane-zahlungen" role="tabpanel">
<div class="d-flex justify-content-end mb-3">
<a href="{% url 'stiftung:unterstuetzung_create' %}?destinataer={{ destinataer.pk }}" class="btn btn-success btn-sm">
<i class="fas fa-plus me-1"></i>Neue Unterstuetzung
</a>
</div>
{% if unterstuetzungen %}
<div class="table-responsive">
<table class="table table-hover table-sm align-middle">
<thead class="table-light">
<tr>
<th>Faellig am</th>
<th>Betrag</th>
<th>Status</th>
<th>Beschreibung</th>
<th></th>
</tr>
</thead>
<tbody>
{% for u in unterstuetzungen %}
<tr>
<td>{{ u.faellig_am|date:"d.m.Y" }}</td>
<td class="text-success fw-bold">&euro;{{ u.betrag|floatformat:2 }}</td>
<td>
{% if u.status == 'ausgezahlt' %}<span class="badge bg-success">Ausgezahlt</span>
{% elif u.status == 'in_bearbeitung' %}<span class="badge bg-warning">In Bearbeitung</span>
{% elif u.status == 'geplant' %}<span class="badge bg-secondary">Geplant</span>
{% else %}<span class="badge bg-danger">{{ u.get_status_display }}</span>{% endif %}
</td>
<td>{{ u.beschreibung|truncatechars:50 }}</td>
<td><a href="{% url 'stiftung:unterstuetzung_detail' pk=u.pk %}" class="btn btn-sm btn-outline-primary"><i class="fas fa-eye"></i></a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4 text-muted">
<i class="fas fa-money-bill-wave fa-2x mb-2"></i>
<p>Keine Zahlungen vorhanden.</p>
</div>
{% endif %}
{% if foerderungen %}
<h6 class="mt-4 mb-2"><i class="fas fa-gift me-1"></i>Foerderungen ({{ foerderungen.count }})</h6>
<div class="table-responsive">
<table class="table table-hover table-sm align-middle">
<thead class="table-light">
<tr><th>Jahr</th><th>Betrag</th><th>Kategorie</th><th>Status</th><th>Nachweis</th><th></th></tr>
</thead>
<tbody>
{% for f in foerderungen %}
<tr>
<td>{{ f.jahr }}</td>
<td class="text-success fw-bold">&euro;{{ f.betrag|floatformat:2 }}</td>
<td>{{ f.get_kategorie_display }}</td>
<td>
{% if f.status == 'bewilligt' %}<span class="badge bg-success">Bewilligt</span>
{% elif f.status == 'abgelehnt' %}<span class="badge bg-danger">Abgelehnt</span>
{% elif f.status == 'in_bearbeitung' %}<span class="badge bg-warning">In Bearbeitung</span>
{% else %}<span class="badge bg-secondary">{{ f.get_status_display }}</span>{% endif %}
</td>
<td>{% if f.verwendungsnachweis %}<i class="fas fa-check text-success"></i>{% else %}<i class="fas fa-times text-muted"></i>{% endif %}</td>
<td><a href="{% url 'stiftung:foerderung_detail' pk=f.pk %}" class="btn btn-sm btn-outline-primary"><i class="fas fa-eye"></i></a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
{# ════════ TAB: Timeline ════════ #}
<div class="tab-pane fade" id="pane-timeline" role="tabpanel">
{% if timeline_events %}
<div class="timeline-list">
{% for event in timeline_events %}
<div class="d-flex align-items-start mb-3">
<div class="me-3 text-center" style="min-width:40px;">
<div class="rounded-circle bg-{{ event.farbe }} text-white d-inline-flex align-items-center justify-content-center" style="width:32px;height:32px;">
<i class="fas {{ event.icon }}" style="font-size:.75rem;"></i>
</div>
</div>
<div class="flex-grow-1 border-bottom pb-2">
<div class="d-flex justify-content-between">
<strong>{{ event.titel }}</strong>
<small class="text-muted">{{ event.datum|date:"d.m.Y" }}</small>
</div>
{% if event.beschreibung %}<div class="text-muted small">{{ event.beschreibung }}</div>{% endif %}
{% if event.status %}<span class="badge bg-{{ event.farbe }} mt-1" style="font-size:.7rem;">{{ event.status }}</span>{% endif %}
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="text-center py-4 text-muted">
<i class="fas fa-stream fa-2x mb-2"></i>
<p>Keine Ereignisse vorhanden.</p>
</div>
{% endif %}
</div>
{# ════════ TAB: Dokumente ════════ #}
<div class="tab-pane fade" id="pane-dokumente" role="tabpanel">
<div class="d-flex justify-content-end mb-3">
<a href="{% url 'stiftung:dms_upload' %}?destinataer={{ destinataer.pk }}" class="btn btn-success btn-sm">
<i class="fas fa-upload me-1"></i>Dokument hochladen
</a>
</div>
{% if verknuepfte_dokumente %}
<div class="table-responsive">
<table class="table table-hover table-sm align-middle">
<thead class="table-light">
<tr><th>Dokument</th><th>Kontext</th><th>Beschreibung</th><th></th></tr>
</thead>
<tbody>
{% for d in verknuepfte_dokumente %}
<tr>
<td>
<strong>{{ d.titel }}</strong>
{% if d.dateiname_original %}<br><small class="text-muted">{{ d.dateiname_original }} ({{ d.get_human_size }})</small>{% endif %}
</td>
<td><span class="badge bg-secondary">{{ d.get_kontext_display }}</span></td>
<td>{{ d.beschreibung|default:"-"|truncatewords:10 }}</td>
<td>
<div class="btn-group btn-group-sm">
<a href="{% url 'stiftung:dms_download' d.pk %}" class="btn btn-outline-primary" title="Herunterladen"><i class="fas fa-download"></i></a>
<a href="{% url 'stiftung:dms_edit' d.pk %}" class="btn btn-outline-warning" title="Bearbeiten"><i class="fas fa-edit"></i></a>
<a href="{% url 'stiftung:dms_delete' d.pk %}" class="btn btn-outline-danger" title="Loeschen"><i class="fas fa-trash"></i></a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="text-center py-4 text-muted">
<i class="fas fa-file-alt fa-2x mb-2"></i>
<p>Keine Dokumente vorhanden.</p>
</div>
{% endif %}
</div>
{# ════════ TAB: Notizen ════════ #}
<div class="tab-pane fade" id="pane-notizen" role="tabpanel">
<div class="d-flex justify-content-end mb-3">
<a class="btn btn-primary btn-sm" href="{% url 'stiftung:destinataer_notiz_create' pk=destinataer.pk %}">
<i class="fas fa-plus me-1"></i>Notiz hinzufuegen
</a>
</div>
{% if notizen_eintraege %}
<div class="list-group">
{% for n in notizen_eintraege %}
<div class="list-group-item py-2">
<div class="d-flex justify-content-between">
<div>
<strong>{{ n.erstellt_am|date:"d.m.Y H:i" }}</strong>
{% if n.erstellt_von %}<span class="text-muted">- {{ n.erstellt_von.username }}</span>{% endif %}
</div>
{% if n.datei %}<a href="{{ n.datei.url }}" target="_blank" class="btn btn-sm btn-outline-secondary"><i class="fas fa-paperclip"></i></a>{% endif %}
</div>
{% if n.titel %}<div class="mt-1"><em>{{ n.titel }}</em></div>{% endif %}
{% if n.text %}<div class="mt-1 small">{{ n.text|linebreaks }}</div>{% endif %}
</div>
{% endfor %}
</div>
{% else %}
<div class="text-center py-4 text-muted">
<i class="fas fa-sticky-note fa-2x mb-2"></i>
<p>Keine Notizen vorhanden.</p>
</div>
{% endif %}
</div>
</div>{# /tab-content #}
</div>
{# ── Add Quarter Modal ── #}
<div class="modal fade" id="addQuarterModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-plus me-2"></i>Neues Quartal</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="post" action="{% url 'stiftung:quarterly_confirmation_create' destinataer.pk %}" id="addQuarterForm">
{% csrf_token %}
<div class="modal-body">
<div class="row">
<div class="col-6">
<label class="form-label">Jahr</label>
<select class="form-select" name="jahr" required>
{% for year in available_years %}
<option value="{{ year }}" {% if year == current_year %}selected{% endif %}>{{ year }}</option>
{% endfor %}
</select>
</div>
<div class="col-6">
<label class="form-label">Quartal</label>
<select class="form-select" name="quartal" required>
<option value="1">Q1</option>
<option value="2">Q2</option>
<option value="3">Q3</option>
<option value="4">Q4</option>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Abbrechen</button>
<button type="submit" class="btn btn-primary btn-sm"><i class="fas fa-plus me-1"></i>Erstellen</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
{% block javascript %}
<style>
.edit-mode-active .view-mode { display: none !important; }
.edit-mode-active .edit-mode { display: block !important; }
.edit-notification { position: fixed; top: 20px; right: 20px; z-index: 1050; max-width: 300px; }
</style>
<script>
let originalFormData = {};
let isEditMode = false;
document.addEventListener('DOMContentLoaded', function() {
storeOriginalData();
// Restore active tab from URL hash
const hash = window.location.hash;
if (hash) {
const tab = document.querySelector(`[data-bs-target="${hash.replace('#','#pane-')}"]`);
if (tab) new bootstrap.Tab(tab).show();
}
// Save tab to URL hash
document.querySelectorAll('#destTabs button[data-bs-toggle="tab"]').forEach(btn => {
btn.addEventListener('shown.bs.tab', e => {
history.replaceState(null, null, '#' + e.target.dataset.bsTarget.replace('#pane-',''));
});
});
});
function storeOriginalData() {
const form = document.getElementById('edit-form');
if (!form) return;
const formData = new FormData(form);
originalFormData = {};
for (let [key, value] of formData.entries()) originalFormData[key] = value;
form.querySelectorAll('input[type="checkbox"]').forEach(cb => { originalFormData[cb.name] = cb.checked; });
}
function enableEditMode() {
isEditMode = true;
document.body.classList.add('edit-mode-active');
document.getElementById('edit-btn').style.display = 'none';
document.getElementById('save-btn').style.display = 'inline-block';
document.getElementById('cancel-btn').style.display = 'inline-block';
// Switch to Stammdaten tab
new bootstrap.Tab(document.getElementById('tab-stamm')).show();
showNotification('Bearbeitungsmodus aktiviert', 'info');
}
function cancelEdit() {
const form = document.getElementById('edit-form');
Object.keys(originalFormData).forEach(key => {
const el = form.querySelector(`[name="${key}"]`);
if (el) { el.type === 'checkbox' ? el.checked = originalFormData[key] : el.value = originalFormData[key] || ''; }
});
disableEditMode();
showNotification('Aenderungen verworfen', 'warning');
}
function disableEditMode() {
isEditMode = false;
document.body.classList.remove('edit-mode-active');
document.getElementById('edit-btn').style.display = 'inline-block';
document.getElementById('save-btn').style.display = 'none';
document.getElementById('cancel-btn').style.display = 'none';
}
function saveChanges() {
const form = document.getElementById('edit-form');
const formData = new FormData(form);
const saveBtn = document.getElementById('save-btn');
const orig = saveBtn.innerHTML;
saveBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>...';
saveBtn.disabled = true;
fetch(form.action, { method: 'POST', body: formData, headers: { 'X-Requested-With': 'XMLHttpRequest' } })
.then(r => r.json())
.then(data => {
if (data.success) { location.reload(); }
else { showNotification('Fehler: ' + (data.error || 'Unbekannt'), 'danger'); saveBtn.innerHTML = orig; saveBtn.disabled = false; }
})
.catch(() => { showNotification('Fehler beim Speichern', 'danger'); saveBtn.innerHTML = orig; saveBtn.disabled = false; });
}
function showNotification(msg, type) {
const existing = document.querySelector('.edit-notification');
if (existing) existing.remove();
const el = document.createElement('div');
el.className = `alert alert-${type} alert-dismissible fade show edit-notification`;
el.innerHTML = `${msg}<button type="button" class="btn-close" data-bs-dismiss="alert"></button>`;
document.body.appendChild(el);
setTimeout(() => { if (el.parentNode) el.remove(); }, 3000);
}
document.addEventListener('keydown', function(e) {
if (isEditMode) {
if (e.key === 'Escape') cancelEdit();
if (e.ctrlKey && e.key === 's') { e.preventDefault(); saveChanges(); }
}
});
function approveQuarterly(id) {
if (!confirm('Nachweis freigeben?')) return;
fetch(`/quarterly-confirmations/${id}/approve/`, { method: 'POST', headers: { 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value, 'Content-Type': 'application/json' } })
.then(r => { if (r.ok) location.reload(); else alert('Fehler'); }).catch(() => alert('Fehler'));
}
function resetQuarterly(id) {
if (!confirm('Nachweis zuruecksetzen?')) return;
fetch(`/quarterly-confirmations/${id}/reset/`, { method: 'POST', headers: { 'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value, 'Content-Type': 'application/json' } })
.then(r => { if (r.ok) location.reload(); else alert('Fehler'); }).catch(() => alert('Fehler'));
}
</script>
{% endblock %}