v4.1.0: DMS email documents, category-specific Nachweis linking, version system
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

- Save cover email body as DMS document with new 'email' context type
- Show email body separately from attachments in email detail view
- Add per-category DMS document assignment in quarterly confirmation
  (Studiennachweis, Einkommenssituation, Vermögenssituation)
- Add VERSION file and context processor for automatic version display
- Add MCP server, agent system, import/export, and new migrations
- Update compose files and production environment template

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
SysAdmin Agent
2026-03-15 18:48:52 +00:00
parent faeb7c1073
commit e0b377014c
49 changed files with 5913 additions and 55 deletions

View File

@@ -1299,16 +1299,53 @@ def quarterly_confirmation_create(request, destinataer_id):
@login_required
def quarterly_confirmation_edit(request, pk):
"""Standalone edit view for quarterly confirmation"""
from stiftung.models import DokumentDatei
nachweis = get_object_or_404(VierteljahresNachweis, pk=pk)
if request.method == "POST":
# DMS-Dokument entfernen (Verknuepfung loesen)
entferne_dok_id = request.POST.get("entferne_dms_dokument")
if entferne_dok_id:
nachweis.nachweis_dokumente.remove(entferne_dok_id)
messages.success(request, "DMS-Dokument-Verknuepfung entfernt.")
return redirect("stiftung:quarterly_confirmation_edit", pk=pk)
form = VierteljahresNachweisForm(request.POST, request.FILES, instance=nachweis)
if form.is_valid():
quarterly_proof = form.save(commit=False)
# Kategorie-spezifische DMS-Dokumente zuweisen
for field_name, dms_field in [
("studiennachweis_dms_id", "studiennachweis_dms_dokument"),
("einkommenssituation_dms_id", "einkommenssituation_dms_dokument"),
("vermogenssituation_dms_id", "vermogenssituation_dms_dokument"),
]:
dms_id = request.POST.get(field_name)
if dms_id:
try:
dok = DokumentDatei.objects.get(pk=dms_id)
setattr(quarterly_proof, dms_field, dok)
except DokumentDatei.DoesNotExist:
pass
elif dms_id == "":
# Leere Auswahl = Verknuepfung entfernen
setattr(quarterly_proof, dms_field, None)
# Generisches DMS-Dokument hinzufuegen (Abwaertskompatibilitaet)
dms_dok_id = request.POST.get("dms_dokument_hinzufuegen")
if dms_dok_id:
try:
dok = DokumentDatei.objects.get(pk=dms_dok_id)
# Save first so M2M can be set
quarterly_proof.save()
quarterly_proof.nachweis_dokumente.add(dok)
except DokumentDatei.DoesNotExist:
pass
# Calculate current status before saving
old_status = nachweis.status
# Auto-update status based on completion
if quarterly_proof.is_complete():
if quarterly_proof.status in ['offen', 'teilweise']:
@@ -1317,15 +1354,15 @@ def quarterly_confirmation_edit(request, pk):
else:
# If not complete, set to teilweise if some fields are filled
has_partial_data = (
quarterly_proof.einkommenssituation_bestaetigt or
quarterly_proof.einkommenssituation_bestaetigt or
quarterly_proof.vermogenssituation_bestaetigt or
quarterly_proof.studiennachweis_eingereicht
)
if has_partial_data and quarterly_proof.status == 'offen':
quarterly_proof.status = 'teilweise'
quarterly_proof.save()
# Try to create automatic support payment if complete
if quarterly_proof.is_complete() and quarterly_proof.status == 'eingereicht':
support_payment = create_quarterly_support_payment(quarterly_proof)
@@ -1343,17 +1380,17 @@ def quarterly_confirmation_edit(request, pk):
reasons.append("keine IBAN hinterlegt")
if not quarterly_proof.destinataer.standard_konto and not StiftungsKonto.objects.exists():
reasons.append("kein Auszahlungskonto verfügbar")
if reasons:
messages.warning(
request,
f"Automatische Unterstützung konnte nicht erstellt werden: {', '.join(reasons)}"
)
# Debug message to see what happened
status_changed = old_status != quarterly_proof.status
status_msg = f" (Status: {old_status}{quarterly_proof.status})" if status_changed else f" (Status: {quarterly_proof.status})"
messages.success(
request,
f"Vierteljahresnachweis für {nachweis.destinataer.get_full_name()} "
@@ -1367,12 +1404,27 @@ def quarterly_confirmation_edit(request, pk):
messages.error(request, f"Fehler in {field}: {error}")
else:
form = VierteljahresNachweisForm(instance=nachweis)
# Alle DMS-Dokumente des Destinataers (fuer Kategorie-Auswahl in den Sektionen)
alle_dms_dokumente = (
DokumentDatei.objects.filter(destinataer=nachweis.destinataer)
.exclude(kontext="email")
.order_by("kontext", "titel")
)
# Generisch verknuepfte Dokumente (M2M) und noch nicht verknuepfte (fuer Bottom-Sektion)
verknuepfte_nachweis_dokumente = nachweis.nachweis_dokumente.all().order_by("kontext", "titel")
verknuepfte_ids = set(verknuepfte_nachweis_dokumente.values_list("pk", flat=True))
verfuegbare_dms_dokumente = alle_dms_dokumente.exclude(pk__in=verknuepfte_ids)
context = {
'form': form,
'nachweis': nachweis,
'destinataer': nachweis.destinataer,
'title': f'Vierteljahresnachweis bearbeiten - {nachweis.destinataer.get_full_name()} {nachweis.jahr} Q{nachweis.quartal}',
'alle_dms_dokumente': alle_dms_dokumente,
'verknuepfte_nachweis_dokumente': verknuepfte_nachweis_dokumente,
'verfuegbare_dms_dokumente': verfuegbare_dms_dokumente,
}
return render(request, 'stiftung/quarterly_confirmation_edit.html', context)