feat: Email-Eingangsverarbeitung für Destinatäre implementieren
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

Neues System zur automatischen Verarbeitung eingehender E-Mails von
Destinatären. IMAP-Polling alle 15 Minuten via Celery Beat, automatische
Zuordnung zu Destinatären anhand der E-Mail-Adresse, Upload von Anhängen
zu Paperless-NGX.

Umfasst:
- DestinataerEmailEingang Model mit Status-Tracking
- Celery Task für IMAP-Polling und Paperless-Integration
- Web-UI (Liste + Detail) mit Such- und Filterfunktion
- Admin-Interface mit Bulk-Actions
- Agent-Dokumentation (SysAdmin, RentmeisterAI)
- Dev-Environment Modernisierung (docker compose v2)

Reviewed by: SysAdmin (STI-15), RentmeisterAI (STI-16)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Stiftung CEO Agent
2026-03-09 21:11:22 +00:00
parent 6c8ddbb4f0
commit 4b21f553c3
16 changed files with 1554 additions and 49 deletions

View File

@@ -0,0 +1,124 @@
import django.db.models.deletion
import uuid
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("stiftung", "0042_add_separate_deadlines"),
]
operations = [
migrations.CreateModel(
name="DestinataerEmailEingang",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"destinataer",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="email_eingaenge",
to="stiftung.destinataer",
verbose_name="Destinatär",
),
),
(
"absender_email",
models.EmailField(max_length=254, verbose_name="Absender-E-Mail"),
),
(
"absender_name",
models.CharField(
blank=True, max_length=255, verbose_name="Absender-Name"
),
),
(
"betreff",
models.CharField(
blank=True, max_length=500, verbose_name="Betreff"
),
),
(
"eingangsdatum",
models.DateTimeField(verbose_name="Eingangsdatum"),
),
(
"email_text",
models.TextField(blank=True, verbose_name="E-Mail-Text"),
),
(
"paperless_dokument_ids",
models.JSONField(
blank=True,
default=list,
help_text="Automatisch befüllte Liste der hochgeladenen Anhänge in Paperless-NGX",
verbose_name="Paperless Dokument-IDs (Anhänge)",
),
),
(
"status",
models.CharField(
choices=[
("neu", "Neu / Unbearbeitet"),
("zugewiesen", "Destinatär zugewiesen"),
("verarbeitet", "Verarbeitet"),
("unbekannt", "Unbekannter Absender"),
("fehler", "Fehler bei Verarbeitung"),
],
default="neu",
max_length=20,
verbose_name="Status",
),
),
(
"fehler_details",
models.TextField(
blank=True,
help_text="Technische Fehlermeldung bei Verarbeitungsfehlern",
verbose_name="Fehlerdetails",
),
),
(
"notizen",
models.TextField(
blank=True,
help_text="Manuelle Notizen der Verwaltung zur E-Mail",
verbose_name="Interne Notizen",
),
),
(
"quartalsnachweis",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="email_eingaenge",
to="stiftung.vierteljahresnachweis",
verbose_name="Quartalsnachweis (zugeordnet)",
),
),
(
"created_at",
models.DateTimeField(
auto_now_add=True, verbose_name="Erfasst am"
),
),
],
options={
"verbose_name": "E-Mail-Eingang (Destinatär)",
"verbose_name_plural": "E-Mail-Eingänge (Destinatäre)",
"ordering": ["-eingangsdatum"],
},
),
]