From 69128196ef45d1e6194a12f868f9cb2c2b7ae544 Mon Sep 17 00:00:00 2001
From: Stiftung Development
Date: Fri, 19 Sep 2025 23:52:26 +0200
Subject: [PATCH] Enhance Destinataer functionality: inline editing and
improved list view
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add inline edit mode to destinataer detail view with AJAX save/cancel
- Fix form validation by aligning select choices with model definitions
- Update Destinataer model to make familienzweig and berufsgruppe optional
- Fix StiftungsKonto integration in forms and views
- Redesign destinataer list view with new column layout:
* Vorname, Nachname, E-Mail, Vierteljährlicher Betrag
* Letzter Studiennachweis, Unterstützung bestätigt, Aktionen
- Improve form styling and user experience
- Add proper field validation and error handling
- Enhance UI with better badges, icons, and formatting
---
app/stiftung/forms.py | 22 +++++++-
...alter_destinataer_berufsgruppe_and_more.py | 23 ++++++++
app/stiftung/models.py | 5 +-
app/stiftung/views.py | 6 ++-
.../stiftung/destinataer_detail.html | 24 ++++++---
app/templates/stiftung/destinataer_list.html | 54 +++++++++----------
6 files changed, 91 insertions(+), 43 deletions(-)
create mode 100644 app/stiftung/migrations/0029_alter_destinataer_berufsgruppe_and_more.py
diff --git a/app/stiftung/forms.py b/app/stiftung/forms.py
index 9bede74..7e0cc19 100644
--- a/app/stiftung/forms.py
+++ b/app/stiftung/forms.py
@@ -369,14 +369,13 @@ class DestinataerForm(forms.ModelForm):
"haushaltsgroesse": forms.NumberInput(
attrs={"class": "form-control", "min": 1}
),
- # renamed in UI: use vierteljaehrlicher_betrag field
"vermoegen": forms.NumberInput(
attrs={"class": "form-control", "step": "0.01"}
),
"unterstuetzung_bestaetigt": forms.CheckboxInput(
attrs={"class": "form-check-input"}
),
- "standard_konto": forms.Select(attrs={"class": "form-select"}),
+ "standard_konto": forms.Select(attrs={"class": "form-select"}, choices=[(None, "---")] + [(c.pk, str(c)) for c in getattr(Destinataer, 'konten_queryset', lambda: [])()]),
"vierteljaehrlicher_betrag": forms.NumberInput(
attrs={"class": "form-control", "step": "0.01"}
),
@@ -386,8 +385,27 @@ class DestinataerForm(forms.ModelForm):
"letzter_studiennachweis": forms.DateInput(
attrs={"class": "form-control", "type": "date"}
),
+ "familienzweig": forms.Select(attrs={"class": "form-select"}),
+ "berufsgruppe": forms.Select(attrs={"class": "form-select"}),
}
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ for field_name, field in self.fields.items():
+ if field_name not in ["vorname", "nachname"]:
+ field.required = False
+ # Set choices for familienzweig and berufsgruppe to match model
+ self.fields["familienzweig"].choices = [("", "Bitte wählen...")] + list(Destinataer.FAMILIENZWIG_CHOICES)
+ self.fields["berufsgruppe"].choices = [("", "Bitte wählen...")] + list(Destinataer.BERUFSGRUPPE_CHOICES)
+ # Set choices for standard_konto to allow blank
+ self.fields["standard_konto"].empty_label = "---"
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ for field_name, field in self.fields.items():
+ if field_name not in ["vorname", "nachname"]:
+ field.required = False
+
class LandForm(forms.ModelForm):
"""Form für das Erstellen und Bearbeiten von Ländern"""
diff --git a/app/stiftung/migrations/0029_alter_destinataer_berufsgruppe_and_more.py b/app/stiftung/migrations/0029_alter_destinataer_berufsgruppe_and_more.py
new file mode 100644
index 0000000..5630b1c
--- /dev/null
+++ b/app/stiftung/migrations/0029_alter_destinataer_berufsgruppe_and_more.py
@@ -0,0 +1,23 @@
+# Generated by Django 5.0.6 on 2025-09-19 21:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('stiftung', '0028_alter_helpbox_page_key'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='destinataer',
+ name='berufsgruppe',
+ field=models.CharField(blank=True, choices=[('student', 'Student/Studentin'), ('wissenschaftler', 'Wissenschaftler/in'), ('künstler', 'Künstler/in'), ('sozialarbeiter', 'Sozialarbeiter/in'), ('umweltschützer', 'Umweltschützer/in'), ('andere', 'Andere')], max_length=20, null=True, verbose_name='Berufsgruppe'),
+ ),
+ migrations.AlterField(
+ model_name='destinataer',
+ name='familienzweig',
+ field=models.CharField(blank=True, choices=[('hauptzweig', 'Hauptzweig'), ('nebenzweig', 'Nebenzweig'), ('verwandt', 'Verwandt'), ('anderer', 'Anderer')], max_length=100, null=True),
+ ),
+ ]
diff --git a/app/stiftung/models.py b/app/stiftung/models.py
index 6e4e42e..1c6433b 100644
--- a/app/stiftung/models.py
+++ b/app/stiftung/models.py
@@ -199,7 +199,7 @@ class Destinataer(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
familienzweig = models.CharField(
- max_length=100, choices=FAMILIENZWIG_CHOICES, default="hauptzweig"
+ max_length=100, choices=FAMILIENZWIG_CHOICES, blank=True, null=True
)
vorname = models.CharField(max_length=100, verbose_name="Vorname")
nachname = models.CharField(max_length=100, verbose_name="Nachname")
@@ -221,7 +221,8 @@ class Destinataer(models.Model):
berufsgruppe = models.CharField(
max_length=20,
choices=BERUFSGRUPPE_CHOICES,
- default="andere",
+ blank=True,
+ null=True,
verbose_name="Berufsgruppe",
)
ausbildungsstand = models.CharField(
diff --git a/app/stiftung/views.py b/app/stiftung/views.py
index 0658362..0936959 100644
--- a/app/stiftung/views.py
+++ b/app/stiftung/views.py
@@ -24,7 +24,7 @@ from rest_framework.response import Response
from .models import (AppConfiguration, CSVImport, Destinataer,
DestinataerUnterstuetzung, DokumentLink, Foerderung, Land,
LandAbrechnung, LandVerpachtung, Paechter, Person,
- UnterstuetzungWiederkehrend)
+ StiftungsKonto, UnterstuetzungWiederkehrend)
def get_pdf_generator():
@@ -1167,12 +1167,16 @@ def destinataer_detail(request, pk):
destinataer=destinataer
).order_by("-erstellt_am")
+ # Alle verfügbaren StiftungsKonten für das Select-Feld laden
+ stiftungskonten = StiftungsKonto.objects.all().order_by("kontoname")
+
context = {
"destinataer": destinataer,
"verknuepfte_dokumente": verknuepfte_dokumente,
"foerderungen": foerderungen,
"unterstuetzungen": unterstuetzungen,
"notizen_eintraege": notizen_eintraege,
+ "stiftungskonten": stiftungskonten,
}
return render(request, "stiftung/destinataer_detail.html", context)
diff --git a/app/templates/stiftung/destinataer_detail.html b/app/templates/stiftung/destinataer_detail.html
index fe462bc..7afe50f 100644
--- a/app/templates/stiftung/destinataer_detail.html
+++ b/app/templates/stiftung/destinataer_detail.html
@@ -87,9 +87,10 @@
@@ -120,10 +121,12 @@
@@ -369,7 +372,12 @@
Nicht angegeben
{% endif %}
-
+
diff --git a/app/templates/stiftung/destinataer_list.html b/app/templates/stiftung/destinataer_list.html
index ffad155..d496094 100644
--- a/app/templates/stiftung/destinataer_list.html
+++ b/app/templates/stiftung/destinataer_list.html
@@ -88,25 +88,22 @@
|
- Name
+ Vorname
|
- Familienzweig
- |
-
- Berufsgruppe
- |
-
- Institution
+ Nachname
|
E-Mail
|
- Förderungen
+ Vierteljährlicher Betrag
|
- Status
+ Letzter Studiennachweis
+ |
+
+ Unterstützung bestätigt
|
Aktionen |
@@ -115,24 +112,14 @@
{% for destinataer in page_obj %}
|
- {{ destinataer.nachname }}, {{ destinataer.vorname }}
+ {{ destinataer.vorname|default:"-" }}
+ |
+
+ {{ destinataer.nachname }}
{% if destinataer.geburtsdatum %}
{{ destinataer.geburtsdatum|date:"d.m.Y" }}
{% endif %}
|
-
- {{ destinataer.get_familienzweig_display }}
- |
-
- {{ destinataer.get_berufsgruppe_display }}
- |
-
- {% if destinataer.institution %}
- {{ destinataer.institution }}
- {% else %}
- -
- {% endif %}
- |
{% if destinataer.email %}
{{ destinataer.email }}
@@ -141,17 +128,24 @@
{% endif %}
|
- {% if destinataer.total_foerderungen %}
- €{{ destinataer.total_foerderungen|floatformat:2 }}
+ {% if destinataer.vierteljaehrlicher_betrag %}
+ €{{ destinataer.vierteljaehrlicher_betrag|floatformat:2 }}
{% else %}
- €0.00
+ -
{% endif %}
|
- {% if destinataer.aktiv %}
- Aktiv
+ {% if destinataer.letzter_studiennachweis %}
+ {{ destinataer.letzter_studiennachweis|date:"d.m.Y" }}
{% else %}
- Inaktiv
+ -
+ {% endif %}
+ |
+
+ {% if destinataer.unterstuetzung_bestaetigt %}
+ Bestätigt
+ {% else %}
+ Ausstehend
{% endif %}
|
|