Fix semester system: 2x yearly docs, 4x yearly payments with Q4 on Sep 15

Document Submission (twice yearly):
- Q1 & Q2 documents: Due March 15 (Spring semester)
- Q3 & Q4 documents: Due September 15 (Fall semester)

Payment Schedule (quarterly):
- Q1 payments: Due March 15
- Q2 payments: Due June 15
- Q3 payments: Due September 15
- Q4 payments: Due September 15 (aligned with Fall semester docs)

This gives the desired Q4 payment due date of 15.09.2025 while maintaining
quarterly payment frequency and semester-based document submissions.
This commit is contained in:
2025-10-01 12:36:47 +02:00
parent 6aa218004c
commit 6adedc71c5
3 changed files with 22 additions and 26 deletions

View File

@@ -29,17 +29,17 @@ class Command(BaseCommand):
self.stdout.write(f'Checking quarterly payments for {year} using advance payment schedule...') self.stdout.write(f'Checking quarterly payments for {year} using advance payment schedule...')
# Define correct advance payment schedule # Define correct quarterly payment schedule
advance_schedule = { quarterly_schedule = {
f'Q1/{year}': date(year - 1, 12, 15), # Q1 paid in December of previous year f'Q1/{year}': date(year, 3, 15), # Q1 payment due March 15
f'Q2/{year}': date(year, 3, 15), # Q2 paid in March of same year f'Q2/{year}': date(year, 6, 15), # Q2 payment due June 15
f'Q3/{year}': date(year, 6, 15), # Q3 paid in June of same year f'Q3/{year}': date(year, 9, 15), # Q3 payment due September 15
f'Q4/{year}': date(year, 9, 15), # Q4 paid in September of same year f'Q4/{year}': date(year, 9, 15), # Q4 payment due September 15 (semester alignment)
} }
total_fixed = 0 total_fixed = 0
for quarter_desc, correct_date in advance_schedule.items(): for quarter_desc, correct_date in quarterly_schedule.items():
# Find payments for this quarter that have wrong dates # Find payments for this quarter that have wrong dates
wrong_payments = DestinataerUnterstuetzung.objects.filter( wrong_payments = DestinataerUnterstuetzung.objects.filter(
beschreibung__icontains=quarter_desc beschreibung__icontains=quarter_desc
@@ -81,9 +81,9 @@ class Command(BaseCommand):
self.style.SUCCESS(f'\n✅ Successfully fixed {total_fixed} payment due dates') self.style.SUCCESS(f'\n✅ Successfully fixed {total_fixed} payment due dates')
) )
# Show the advance payment schedule # Show the quarterly payment schedule
self.stdout.write(f'\nAdvance Payment Schedule for {year}:') self.stdout.write(f'\nQuarterly Payment Schedule for {year}:')
for quarter_desc, due_date in advance_schedule.items(): for quarter_desc, due_date in quarterly_schedule.items():
self.stdout.write(f' {quarter_desc}: Due {due_date.strftime("%B %d, %Y")}') self.stdout.write(f' {quarter_desc}: Due {due_date.strftime("%B %d, %Y")}')
# Check for other years that might need fixing # Check for other years that might need fixing
@@ -91,7 +91,7 @@ class Command(BaseCommand):
other_year_payments = DestinataerUnterstuetzung.objects.filter( other_year_payments = DestinataerUnterstuetzung.objects.filter(
beschreibung__regex=r'Q[1-4]/202[6-9]' beschreibung__regex=r'Q[1-4]/202[6-9]'
).exclude( ).exclude(
faellig_am__in=[date(2024, 12, 15), date(2026, 3, 15), date(2026, 6, 15), date(2026, 9, 15)] faellig_am__in=[date(2026, 3, 15), date(2026, 6, 15), date(2026, 9, 15), date(2026, 9, 15)]
).count() ).count()
if other_year_payments > 0: if other_year_payments > 0:

View File

@@ -2752,10 +2752,10 @@ class VierteljahresNachweis(models.Model):
if not self.faelligkeitsdatum: if not self.faelligkeitsdatum:
from datetime import date from datetime import date
quarter_deadlines = { quarter_deadlines = {
1: date(self.jahr, 3, 15), # Q1 deadline: March 15 (covers Q1+Q2 semester) 1: date(self.jahr, 3, 15), # Q1 deadline: March 15 (Spring semester)
2: date(self.jahr, 6, 15), # Q2 deadline: June 15 (auto-approved if Q1 complete) 2: date(self.jahr, 3, 15), # Q2 deadline: March 15 (Spring semester, same as Q1)
3: date(self.jahr, 9, 15), # Q3 deadline: September 15 (covers Q3+Q4 semester) 3: date(self.jahr, 9, 15), # Q3 deadline: September 15 (Fall semester)
4: date(self.jahr, 12, 15), # Q4 deadline: December 15 (auto-approved if Q3 complete) 4: date(self.jahr, 9, 15), # Q4 deadline: September 15 (Fall semester, same as Q3)
} }
self.faelligkeitsdatum = quarter_deadlines.get(self.quartal) self.faelligkeitsdatum = quarter_deadlines.get(self.quartal)

View File

@@ -7533,20 +7533,16 @@ def create_quarterly_support_payment(nachweis):
if not default_konto: if not default_konto:
return None return None
# Calculate payment due date (advance payment schedule) # Calculate payment due date (quarterly payments with Q4 aligned to semester)
# Payments are made in advance according to semester schedule: # Q1: March 15, Q2: June 15, Q3: September 15, Q4: September 15
# September 15: Payment for Q4 of current year
# December 15: Payment for Q1 of next year
# March 15: Payment for Q2 of current year
# June 15: Payment for Q3 of current year
if nachweis.quartal == 1: # Q1 payment due December 15 of previous year if nachweis.quartal == 1: # Q1 payment due March 15
payment_due_date = date(nachweis.jahr - 1, 12, 15)
elif nachweis.quartal == 2: # Q2 payment due March 15 of same year
payment_due_date = date(nachweis.jahr, 3, 15) payment_due_date = date(nachweis.jahr, 3, 15)
elif nachweis.quartal == 3: # Q3 payment due June 15 of same year elif nachweis.quartal == 2: # Q2 payment due June 15
payment_due_date = date(nachweis.jahr, 6, 15) payment_due_date = date(nachweis.jahr, 6, 15)
else: # Q4 payment due September 15 of same year elif nachweis.quartal == 3: # Q3 payment due September 15
payment_due_date = date(nachweis.jahr, 9, 15)
else: # Q4 payment due September 15 (same as Q3 for semester alignment)
payment_due_date = date(nachweis.jahr, 9, 15) payment_due_date = date(nachweis.jahr, 9, 15)
# Create the support payment # Create the support payment