Files
stiftung-management-system/app/templates/stiftung/veranstaltung/detail.html
SysAdmin Agent 28621d2774
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
feat: Veranstaltungsmodul + Serienbrief mit editierbaren Feldern (STI-35, STI-39)
Implementierung des Veranstaltungsmoduls inkl. Serienbrief-PDF-Generator
mit dynamischen, editierbaren Feldern für Betreff und Unterschriften.

### Veranstaltungsmodul (STI-35)
- Neues Veranstaltungs-Modell: Titel, Datum, Uhrzeit, Ort, Gasthaus-Adresse,
  Briefvorlage, Gästeliste (VerstaltungsGast mit freien/Destinatär-Feldern)
- Views: Veranstaltungsliste, -detail, Serienbrief-PDF-Generator
- Templates: list.html, detail.html, serienbrief_pdf.html (A4, einseitig)
- API: Serializer + Endpunkte für Veranstaltungen
- Admin: Inline-Bearbeitung der Gästeliste
- Migration: 0044_veranstaltungsmodul

### Serienbrief editierbare Felder + PDF-Fix (STI-39)
- Neue Felder an Veranstaltung: betreff, unterschrift_1_name/titel,
  unterschrift_2_name/titel (mit Defaults: Katrin Kleinpaß / Jan Remmer Siebels)
- PDF-CSS: Margins, Font-Sizes und Line-Heights reduziert für einseitigen Druck
- Migration: 0045_add_serienbrief_editable_fields

### Infrastruktur
- scripts/init-paperless-db.sh: Erstellt separate Paperless-DB beim DB-Init
- compose.yml: init-paperless-db.sh eingebunden, PAPERLESS_DBNAME-Fix
- .gitignore: .claude/ ausgeschlossen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 22:36:58 +00:00

200 lines
9.6 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" %}
{% block title %}{{ veranstaltung.titel }} Stiftungsverwaltung{% endblock %}
{% block content %}
<div class="container-fluid py-4">
<!-- Header -->
<div class="d-flex justify-content-between align-items-start mb-4">
<div>
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'stiftung:veranstaltung_list' %}">Veranstaltungen</a></li>
<li class="breadcrumb-item active">{{ veranstaltung.titel }}</li>
</ol>
</nav>
<h1 class="h3 mb-1">{{ veranstaltung.titel }}</h1>
<p class="text-muted mb-0">
{{ veranstaltung.datum|date:"l, d. F Y" }}{% if veranstaltung.uhrzeit %}, {{ veranstaltung.uhrzeit|time:"H:i" }} Uhr{% endif %}
&nbsp;·&nbsp; {{ veranstaltung.ort }}
</p>
</div>
<div class="d-flex gap-2">
<a href="{% url 'admin:stiftung_veranstaltung_change' veranstaltung.pk %}" class="btn btn-outline-secondary">
<i class="fas fa-edit me-1"></i>Bearbeiten
</a>
<a href="{% url 'stiftung:veranstaltung_serienbrief_pdf' veranstaltung.pk %}" class="btn btn-success">
<i class="fas fa-file-pdf me-1"></i>Serienbrief-PDF
</a>
</div>
</div>
<div class="row g-4">
<!-- Veranstaltungsdetails -->
<div class="col-lg-4">
<div class="card shadow-sm h-100">
<div class="card-header bg-dark text-white">
<i class="fas fa-info-circle me-2"></i>Details
</div>
<div class="card-body">
<dl class="row mb-0">
<dt class="col-sm-5">Status</dt>
<dd class="col-sm-7">
{% if veranstaltung.status == "geplant" %}
<span class="badge bg-secondary">Geplant</span>
{% elif veranstaltung.status == "einladungen_versendet" %}
<span class="badge bg-primary">Einladungen versendet</span>
{% elif veranstaltung.status == "abgeschlossen" %}
<span class="badge bg-success">Abgeschlossen</span>
{% elif veranstaltung.status == "abgesagt" %}
<span class="badge bg-danger">Abgesagt</span>
{% endif %}
</dd>
<dt class="col-sm-5">Gasthaus</dt>
<dd class="col-sm-7">{{ veranstaltung.ort }}</dd>
{% if veranstaltung.adresse %}
<dt class="col-sm-5">Adresse</dt>
<dd class="col-sm-7">{{ veranstaltung.adresse }}</dd>
{% endif %}
{% if veranstaltung.budget_pro_person %}
<dt class="col-sm-5">Budget/Person</dt>
<dd class="col-sm-7">{{ veranstaltung.budget_pro_person }} €</dd>
{% endif %}
{% if veranstaltung.beschreibung %}
<dt class="col-sm-5">Beschreibung</dt>
<dd class="col-sm-7">{{ veranstaltung.beschreibung }}</dd>
{% endif %}
</dl>
</div>
</div>
</div>
<!-- RSVP-Statistik -->
<div class="col-lg-4">
<div class="card shadow-sm h-100">
<div class="card-header bg-dark text-white">
<i class="fas fa-chart-pie me-2"></i>RSVP-Übersicht
</div>
<div class="card-body">
<div class="row text-center g-3">
<div class="col-6">
<div class="border rounded p-3">
<div class="fs-2 fw-bold text-primary">{{ teilnehmer.count }}</div>
<div class="small text-muted">Eingeladen gesamt</div>
</div>
</div>
<div class="col-6">
<div class="border rounded p-3">
<div class="fs-2 fw-bold text-success">{{ zugesagte.count }}</div>
<div class="small text-muted">Zugesagt</div>
</div>
</div>
<div class="col-6">
<div class="border rounded p-3">
<div class="fs-2 fw-bold text-danger">{{ abgesagte.count }}</div>
<div class="small text-muted">Abgesagt</div>
</div>
</div>
<div class="col-6">
<div class="border rounded p-3">
<div class="fs-2 fw-bold text-warning">{{ keine_rueckmeldung.count }}</div>
<div class="small text-muted">Keine Rückmeldung</div>
</div>
</div>
{% if eingeladen.count %}
<div class="col-12">
<div class="border rounded p-3">
<div class="fs-2 fw-bold text-secondary">{{ eingeladen.count }}</div>
<div class="small text-muted">Nur eingeladen (noch kein RSVP)</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Schnellaktionen -->
<div class="col-lg-4">
<div class="card shadow-sm h-100">
<div class="card-header bg-dark text-white">
<i class="fas fa-tools me-2"></i>Aktionen
</div>
<div class="card-body d-flex flex-column gap-2">
<a href="{% url 'stiftung:veranstaltung_serienbrief_pdf' veranstaltung.pk %}"
class="btn btn-success w-100">
<i class="fas fa-file-pdf me-2"></i>Serienbrief-PDF (alle Teilnehmer)
</a>
<a href="{% url 'admin:stiftung_veranstaltungsteilnehmer_add' %}?veranstaltung={{ veranstaltung.pk }}"
class="btn btn-outline-primary w-100">
<i class="fas fa-user-plus me-2"></i>Teilnehmer hinzufügen
</a>
<a href="{% url 'admin:stiftung_veranstaltung_change' veranstaltung.pk %}"
class="btn btn-outline-secondary w-100">
<i class="fas fa-edit me-2"></i>Veranstaltung bearbeiten
</a>
</div>
</div>
</div>
</div>
<!-- Teilnehmerliste -->
<div class="card shadow-sm mt-4">
<div class="card-header bg-dark text-white d-flex justify-content-between align-items-center">
<span><i class="fas fa-users me-2"></i>Teilnehmerliste ({{ teilnehmer.count }})</span>
</div>
<div class="card-body p-0">
{% if teilnehmer %}
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th>Name</th>
<th>Adresse</th>
<th>E-Mail</th>
<th>RSVP</th>
<th>Bemerkungen</th>
</tr>
</thead>
<tbody>
{% for t in teilnehmer %}
<tr>
<td>
{{ t.anrede }} {{ t.vorname }} {{ t.nachname }}
</td>
<td>
{% if t.strasse %}{{ t.strasse }},{% endif %}
{% if t.plz %}{{ t.plz }}{% endif %}
{% if t.ort %}{{ t.ort }}{% endif %}
</td>
<td>{% if t.email %}<a href="mailto:{{ t.email }}">{{ t.email }}</a>{% else %}{% endif %}</td>
<td>
{% if t.rsvp_status == "eingeladen" %}
<span class="badge bg-secondary">Eingeladen</span>
{% elif t.rsvp_status == "zugesagt" %}
<span class="badge bg-success">Zugesagt</span>
{% elif t.rsvp_status == "abgesagt" %}
<span class="badge bg-danger">Abgesagt</span>
{% elif t.rsvp_status == "keine_rueckmeldung" %}
<span class="badge bg-warning text-dark">Keine Rückmeldung</span>
{% endif %}
</td>
<td>{{ t.bemerkungen|default:"" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="p-4 text-center text-muted">
<i class="fas fa-users fa-2x mb-2"></i>
<p>Noch keine Teilnehmer eingetragen.</p>
<a href="{% url 'admin:stiftung_veranstaltungsteilnehmer_add' %}?veranstaltung={{ veranstaltung.pk }}"
class="btn btn-primary">
<i class="fas fa-user-plus me-1"></i>Ersten Teilnehmer hinzufügen
</a>
</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}