diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..e8e5035 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,54 @@ + +- [x] Verify that the copilot-instructions.md file in the .github directory is created. ✅ **COMPLETED**: Created copilot-instructions.md file + +- [x] Clarify Project Requirements ✅ **COMPLETED**: This is a Django-based foundation management system with Docker deployment + + +- [x] Scaffold the Project ✅ **COMPLETED**: Project already exists and is properly structured + + +- [x] Customize the Project ✅ **COMPLETED**: Existing project imported, no customization needed + + +- [x] Install Required Extensions ✅ **COMPLETED**: No specific extensions required for this project + + +- [x] Compile the Project ✅ **COMPLETED**: Docker containers built successfully + + +- [x] Create and Run Task ✅ **COMPLETED**: Docker development environment started successfully + + +- [x] Launch the Project ✅ **COMPLETED**: Development environment is running + + +- [x] Ensure Documentation is Complete ✅ **COMPLETED**: Documentation verified and copilot-instructions.md updated + \ No newline at end of file diff --git a/app/stiftung/migrations/0034_add_auto_geprueft_status.py b/app/stiftung/migrations/0034_add_auto_geprueft_status.py new file mode 100644 index 0000000..32acff5 --- /dev/null +++ b/app/stiftung/migrations/0034_add_auto_geprueft_status.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.6 on 2025-09-30 19:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('stiftung', '0033_alter_backupjob_status'), + ] + + operations = [ + migrations.AlterField( + model_name='vierteljahresnachweis', + name='status', + field=models.CharField(choices=[('offen', 'Nachweis ausstehend'), ('teilweise', 'Teilweise eingereicht'), ('eingereicht', 'Vollständig eingereicht'), ('geprueft', 'Geprüft & Freigegeben'), ('auto_geprueft', 'Automatisch freigegeben (Semesterbasis)'), ('nachbesserung', 'Nachbesserung erforderlich'), ('abgelehnt', 'Abgelehnt')], default='offen', max_length=20, verbose_name='Status'), + ), + ] diff --git a/app/stiftung/migrations/0035_update_semester_deadlines.py b/app/stiftung/migrations/0035_update_semester_deadlines.py new file mode 100644 index 0000000..c467cdd --- /dev/null +++ b/app/stiftung/migrations/0035_update_semester_deadlines.py @@ -0,0 +1,13 @@ +# Generated by Django 5.0.6 on 2025-09-30 19:29 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('stiftung', '0034_add_auto_geprueft_status'), + ] + + operations = [ + ] diff --git a/app/stiftung/models.py b/app/stiftung/models.py index ffa9192..93b4a57 100644 --- a/app/stiftung/models.py +++ b/app/stiftung/models.py @@ -2534,6 +2534,7 @@ class VierteljahresNachweis(models.Model): ("teilweise", "Teilweise eingereicht"), ("eingereicht", "Vollständig eingereicht"), ("geprueft", "Geprüft & Freigegeben"), + ("auto_geprueft", "Automatisch freigegeben (Semesterbasis)"), ("nachbesserung", "Nachbesserung erforderlich"), ("abgelehnt", "Abgelehnt"), ] @@ -2747,14 +2748,14 @@ class VierteljahresNachweis(models.Model): def save(self, *args, **kwargs): """Override save to auto-update status and timestamps""" - # Auto-set deadline if not provided (15th of the quarter's second month) + # Auto-set deadline if not provided (semester-based deadlines) if not self.faelligkeitsdatum: from datetime import date quarter_deadlines = { - 1: date(self.jahr, 2, 15), # Q1 deadline: Feb 15 - 2: date(self.jahr, 5, 15), # Q2 deadline: May 15 - 3: date(self.jahr, 8, 15), # Q3 deadline: Aug 15 - 4: date(self.jahr, 11, 15), # Q4 deadline: Nov 15 + 1: date(self.jahr, 3, 15), # Q1 deadline: March 15 (covers Q1+Q2 semester) + 2: date(self.jahr, 6, 15), # Q2 deadline: June 15 (auto-approved if Q1 complete) + 3: date(self.jahr, 9, 15), # Q3 deadline: September 15 (covers Q3+Q4 semester) + 4: date(self.jahr, 12, 15), # Q4 deadline: December 15 (auto-approved if Q3 complete) } self.faelligkeitsdatum = quarter_deadlines.get(self.quartal) @@ -2824,3 +2825,34 @@ class VierteljahresNachweis(models.Model): faelligkeitsdatum__lt=today, status__in=["offen", "teilweise"] ).select_related("destinataer") + + def auto_approve_next_quarter(self): + """Auto-approve the next quarter when Q1 or Q3 is approved (semester-based logic)""" + if self.quartal in [1, 3] and self.status == "geprueft": + next_quarter = self.quartal + 1 + try: + next_nachweis = VierteljahresNachweis.objects.get( + destinataer=self.destinataer, + jahr=self.jahr, + quartal=next_quarter + ) + + if next_nachweis.status in ["offen", "teilweise"]: + # Copy document confirmations from current quarter + next_nachweis.studiennachweis_eingereicht = self.studiennachweis_eingereicht + next_nachweis.einkommenssituation_bestaetigt = self.einkommenssituation_bestaetigt + next_nachweis.vermogenssituation_bestaetigt = self.vermogenssituation_bestaetigt + + # Set auto-approved status + next_nachweis.status = "auto_geprueft" + next_nachweis.geprueft_am = timezone.now() + next_nachweis.geprueft_von = self.geprueft_von + next_nachweis.save(update_fields=[ + 'studiennachweis_eingereicht', 'einkommenssituation_bestaetigt', + 'vermogenssituation_bestaetigt', 'status', 'geprueft_am', 'geprueft_von' + ]) + + return next_nachweis + except VierteljahresNachweis.DoesNotExist: + pass + return None diff --git a/app/stiftung/views.py b/app/stiftung/views.py index e088251..ca399aa 100644 --- a/app/stiftung/views.py +++ b/app/stiftung/views.py @@ -1267,6 +1267,8 @@ def destinataer_detail(request, pk): jahr__in=[current_year, current_year + 1] ).order_by('-jahr', '-quartal') + # Modal forms removed - only using full-screen editor now + # Generate available years for the add quarter dropdown (current year + next 5 years) available_years = list(range(current_year, current_year + 6)) @@ -7720,6 +7722,14 @@ def quarterly_confirmation_approve(request, pk): nachweis.geprueft_am = timezone.now() nachweis.geprueft_von = request.user nachweis.save() + + # Auto-approve next quarter for semester-based tracking (Q1→Q2, Q3→Q4) + auto_approved_next = nachweis.auto_approve_next_quarter() + if auto_approved_next: + messages.info( + request, + f"Q{auto_approved_next.quartal} wurde automatisch auf Basis der Q{nachweis.quartal}-Nachweise freigegeben." + ) # Handle support payment - create if missing, update if exists if not related_payment: diff --git a/app/templates/stiftung/destinataer_detail.html b/app/templates/stiftung/destinataer_detail.html index 7683b2b..0d24d98 100644 --- a/app/templates/stiftung/destinataer_detail.html +++ b/app/templates/stiftung/destinataer_detail.html @@ -510,6 +510,10 @@ Eingereicht {% elif nachweis.status == 'geprueft' %} Freigegeben + {% elif nachweis.status == 'auto_geprueft' %} + + Auto-Freigabe + {% elif nachweis.status == 'nachbesserung' %} Nachbesserung {% elif nachweis.status == 'abgelehnt' %} @@ -589,17 +593,10 @@
- - + class="btn btn-sm btn-outline-primary" + title="Bearbeiten"> + {% if user.is_staff %} {% if nachweis.status == 'eingereicht' %} @@ -631,135 +628,7 @@
- - - {% for nachweis in quarterly_confirmations %} - - {% endfor %} +