- 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>
186 lines
11 KiB
HTML
186 lines
11 KiB
HTML
{% extends 'base.html' %}
|
||
{% load static help_tags %}
|
||
|
||
{% block title %}Nachweis-Board – 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-th text-primary me-2"></i>
|
||
Nachweis-Board {{ jahr_filter }}
|
||
</h1>
|
||
<div class="d-flex gap-2">
|
||
<form method="post" action="{% url 'stiftung:batch_nachweis_aufforderung_senden' %}">
|
||
{% csrf_token %}
|
||
<input type="hidden" name="jahr" value="{{ jahr_filter }}">
|
||
<button type="submit" class="btn btn-primary" onclick="return confirm('Nachweis-Aufforderungs-E-Mails für alle offenen Nachweise {{ jahr_filter }} versenden?')">
|
||
<i class="fas fa-paper-plane me-2"></i>Aufforderungen senden
|
||
</button>
|
||
</form>
|
||
{% if overdue_count > 0 %}
|
||
<form method="post" action="{% url 'stiftung:batch_erinnerung_senden' %}">
|
||
{% csrf_token %}
|
||
<input type="hidden" name="jahr" value="{{ jahr_filter }}">
|
||
<button type="submit" class="btn btn-danger" onclick="return confirm('{{ overdue_count }} säumige Destinatäre markieren?')">
|
||
<i class="fas fa-bell me-2"></i>{{ overdue_count }} Erinnerung(en)
|
||
</button>
|
||
</form>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Filter Bar -->
|
||
<div class="card shadow mb-4">
|
||
<div class="card-body py-2">
|
||
<form method="get" class="d-flex gap-3 flex-wrap align-items-center">
|
||
<div class="d-flex align-items-center gap-2">
|
||
<label class="text-muted small fw-bold mb-0">Jahr:</label>
|
||
<select name="jahr" class="form-select form-select-sm" style="width: auto;" onchange="this.form.submit()">
|
||
{% for j in verfuegbare_jahre %}
|
||
<option value="{{ j }}" {% if j == jahr_filter %}selected{% endif %}>{{ j }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<div class="d-flex align-items-center gap-2">
|
||
<label class="text-muted small fw-bold mb-0">Status:</label>
|
||
<select name="status" class="form-select form-select-sm" style="width: auto;" onchange="this.form.submit()">
|
||
<option value="">Alle</option>
|
||
{% for code, label in status_choices %}
|
||
<option value="{{ code }}" {% if code == status_filter %}selected{% endif %}>{{ label }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<span class="ms-auto text-muted small">{{ board|length }} Destinatäre</span>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Semester-Hinweis -->
|
||
<div class="alert alert-info py-2 mb-4 small">
|
||
<i class="fas fa-info-circle me-2"></i>
|
||
<strong>Semester-Logik:</strong>
|
||
Studiennachweis-Frist Q1/Q2 → 15. März · Q3/Q4 → 15. September.
|
||
Zahlungsfrist Q1 → 15. Dez (Vorjahr) · Q2 → 15. Mär · Q3 → 15. Jun · Q4 → 15. Sep.
|
||
</div>
|
||
|
||
<!-- Board Table -->
|
||
{% if board %}
|
||
<div class="card shadow">
|
||
<div class="card-body p-0">
|
||
<div class="table-responsive">
|
||
<table class="table table-hover table-sm mb-0">
|
||
<thead class="table-dark">
|
||
<tr>
|
||
<th style="min-width:180px">Destinatär</th>
|
||
<th class="text-center">Q1 (Jan–Mär)</th>
|
||
<th class="text-center">Q2 (Apr–Jun)</th>
|
||
<th class="text-center">Q3 (Jul–Sep)</th>
|
||
<th class="text-center">Q4 (Okt–Dez)</th>
|
||
<th class="text-center">Gesamt</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for row in board %}
|
||
<tr>
|
||
<td class="align-middle">
|
||
<a href="{% url 'stiftung:destinataer_detail' pk=row.destinataer.pk %}" class="text-decoration-none fw-semibold">
|
||
{{ row.destinataer.get_full_name }}
|
||
</a>
|
||
<div class="small text-muted">
|
||
<a href="{% url 'stiftung:destinataer_timeline' pk=row.destinataer.pk %}" class="text-muted">
|
||
<i class="fas fa-stream"></i> Timeline
|
||
</a>
|
||
</div>
|
||
</td>
|
||
{% for q in "1234" %}
|
||
{% with nachweis=row.quartale|get_item:q|default:None %}
|
||
<td class="text-center align-middle">
|
||
{% if nachweis %}
|
||
{% if nachweis.status == 'geprueft' or nachweis.status == 'auto_geprueft' %}
|
||
<span class="badge bg-success" title="{{ nachweis.get_status_display }}">
|
||
<i class="fas fa-check"></i>
|
||
</span>
|
||
{% elif nachweis.status == 'eingereicht' %}
|
||
<span class="badge bg-info" title="{{ nachweis.get_status_display }}">
|
||
<i class="fas fa-paper-plane"></i>
|
||
</span>
|
||
{% elif nachweis.status == 'teilweise' %}
|
||
<span class="badge bg-warning text-dark" title="{{ nachweis.get_status_display }}">
|
||
<i class="fas fa-circle-half-stroke"></i>
|
||
</span>
|
||
{% elif nachweis.status == 'nachbesserung' %}
|
||
<span class="badge bg-orange" title="{{ nachweis.get_status_display }}" style="background:#fd7e14">
|
||
<i class="fas fa-redo"></i>
|
||
</span>
|
||
{% elif nachweis.status == 'abgelehnt' %}
|
||
<span class="badge bg-danger" title="{{ nachweis.get_status_display }}">
|
||
<i class="fas fa-times"></i>
|
||
</span>
|
||
{% elif nachweis.is_overdue %}
|
||
<span class="badge bg-danger" title="Überfällig">
|
||
<i class="fas fa-exclamation-triangle"></i>
|
||
</span>
|
||
{% else %}
|
||
<span class="badge bg-secondary" title="{{ nachweis.get_status_display }}">
|
||
<i class="fas fa-clock"></i>
|
||
</span>
|
||
{% endif %}
|
||
<div class="small mt-1">
|
||
<a href="{% url 'stiftung:quarterly_confirmation_edit' pk=nachweis.pk %}" class="text-muted">
|
||
{{ nachweis.get_completion_percentage }}%
|
||
</a>
|
||
</div>
|
||
{% if nachweis.status == 'offen' or nachweis.status == 'teilweise' or nachweis.status == 'nachbesserung' %}{% if row.destinataer.email %}
|
||
<form method="post" action="{% url 'stiftung:nachweis_aufforderung_senden' nachweis_pk=nachweis.pk %}" class="mt-1">
|
||
{% csrf_token %}
|
||
<button type="submit" class="btn btn-outline-primary btn-xs" style="font-size:0.65rem;padding:1px 5px;" title="Upload-Link per E-Mail senden" onclick="return confirm('Upload-Aufforderung an {{ row.destinataer.email }} senden?')">
|
||
<i class="fas fa-paper-plane"></i>
|
||
</button>
|
||
</form>
|
||
{% endif %}{% endif %}
|
||
{% else %}
|
||
<span class="text-muted small">–</span>
|
||
{% endif %}
|
||
</td>
|
||
{% endwith %}
|
||
{% endfor %}
|
||
<td class="text-center align-middle">
|
||
{% with total=0 done=0 %}
|
||
{% for q, nachweis in row.quartale.items %}
|
||
{% if nachweis %}
|
||
{% if nachweis.status == 'geprueft' or nachweis.status == 'auto_geprueft' %}
|
||
<i class="fas fa-check-circle text-success"></i>
|
||
{% endif %}
|
||
{% endif %}
|
||
{% endfor %}
|
||
{% endwith %}
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Legend -->
|
||
<div class="mt-3 d-flex flex-wrap gap-3 small text-muted">
|
||
<span><span class="badge bg-success"><i class="fas fa-check"></i></span> Geprüft</span>
|
||
<span><span class="badge bg-info"><i class="fas fa-paper-plane"></i></span> Eingereicht</span>
|
||
<span><span class="badge bg-warning text-dark"><i class="fas fa-circle-half-stroke"></i></span> Teilweise</span>
|
||
<span><span class="badge bg-danger"><i class="fas fa-exclamation-triangle"></i></span> Überfällig</span>
|
||
<span><span class="badge bg-secondary"><i class="fas fa-clock"></i></span> Offen</span>
|
||
</div>
|
||
{% else %}
|
||
<div class="alert alert-info">
|
||
<i class="fas fa-info-circle me-2"></i>
|
||
Keine aktiven Destinatäre gefunden.
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|