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>
62 lines
4.2 KiB
Python
62 lines
4.2 KiB
Python
# Generated by Django 5.0.6 on 2026-03-10 21:47
|
|
|
|
import django.db.models.deletion
|
|
import uuid
|
|
from django.db import migrations, models
|
|
|
|
|
|
class Migration(migrations.Migration):
|
|
|
|
dependencies = [
|
|
('stiftung', '0043_destinataer_email_eingang'),
|
|
]
|
|
|
|
operations = [
|
|
migrations.CreateModel(
|
|
name='Veranstaltung',
|
|
fields=[
|
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
|
('titel', models.CharField(max_length=200, verbose_name='Titel')),
|
|
('datum', models.DateField(verbose_name='Datum')),
|
|
('uhrzeit', models.TimeField(blank=True, null=True, verbose_name='Uhrzeit')),
|
|
('ort', models.CharField(max_length=200, verbose_name='Ort / Gasthaus')),
|
|
('adresse', models.TextField(blank=True, verbose_name='Adresse Gasthaus')),
|
|
('beschreibung', models.TextField(blank=True, verbose_name='Beschreibung / Zweck')),
|
|
('status', models.CharField(choices=[('geplant', 'Geplant'), ('einladungen_versendet', 'Einladungen versendet'), ('abgeschlossen', 'Abgeschlossen'), ('abgesagt', 'Abgesagt')], default='geplant', max_length=30, verbose_name='Status')),
|
|
('budget_pro_person', models.DecimalField(blank=True, decimal_places=2, help_text='Geschätztes Budget je Teilnehmer in €', max_digits=8, null=True, verbose_name='Budget pro Person (€)')),
|
|
('briefvorlage', models.TextField(blank=True, help_text='HTML/Text-Template für Serienbrief. Platzhalter: {{ anrede }}, {{ vorname }}, {{ nachname }}, {{ strasse }}, {{ plz }}, {{ ort }}, {{ datum }}, {{ uhrzeit }}, {{ veranstaltungsort }}, {{ gasthaus_adresse }}', verbose_name='Briefvorlage')),
|
|
('erstellt_am', models.DateTimeField(auto_now_add=True)),
|
|
('aktualisiert_am', models.DateTimeField(auto_now=True)),
|
|
],
|
|
options={
|
|
'verbose_name': 'Veranstaltung',
|
|
'verbose_name_plural': 'Veranstaltungen',
|
|
'ordering': ['-datum'],
|
|
},
|
|
),
|
|
migrations.CreateModel(
|
|
name='Veranstaltungsteilnehmer',
|
|
fields=[
|
|
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
|
('anrede', models.CharField(blank=True, choices=[('Herr', 'Herr'), ('Frau', 'Frau'), ('', 'Keine Anrede')], max_length=10, verbose_name='Anrede')),
|
|
('vorname', models.CharField(max_length=100, verbose_name='Vorname')),
|
|
('nachname', models.CharField(max_length=100, verbose_name='Nachname')),
|
|
('strasse', models.CharField(blank=True, max_length=200, verbose_name='Straße')),
|
|
('plz', models.CharField(blank=True, max_length=10, verbose_name='PLZ')),
|
|
('ort', models.CharField(blank=True, max_length=100, verbose_name='Ort')),
|
|
('email', models.EmailField(blank=True, help_text='Optional, für späteren E-Mail-Versand', max_length=254, verbose_name='E-Mail')),
|
|
('rsvp_status', models.CharField(choices=[('eingeladen', 'Eingeladen'), ('zugesagt', 'Zugesagt'), ('abgesagt', 'Abgesagt'), ('keine_rueckmeldung', 'Keine Rückmeldung')], default='eingeladen', max_length=20, verbose_name='RSVP-Status')),
|
|
('bemerkungen', models.TextField(blank=True, verbose_name='Bemerkungen')),
|
|
('erstellt_am', models.DateTimeField(auto_now_add=True)),
|
|
('destinataer', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='stiftung.destinataer', verbose_name='Destinatär (optional)')),
|
|
('paechter', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='stiftung.paechter', verbose_name='Pächter (optional)')),
|
|
('veranstaltung', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teilnehmer', to='stiftung.veranstaltung', verbose_name='Veranstaltung')),
|
|
],
|
|
options={
|
|
'verbose_name': 'Veranstaltungsteilnehmer',
|
|
'verbose_name_plural': 'Veranstaltungsteilnehmer',
|
|
'ordering': ['nachname', 'vorname'],
|
|
},
|
|
),
|
|
]
|