BREAKING CHANGE: Payment due dates now follow advance payment schedule: - Q1 payments: Due December 15 of previous year - Q2 payments: Due March 15 of same year - Q3 payments: Due June 15 of same year - Q4 payments: Due September 15 of same year Changes: - Updated create_quarterly_support_payment() to use advance schedule - Enhanced diagnostic commands to check advance payment dates - Added fix_advance_payment_dates command for comprehensive fixes - Updated fix_q4_payment_dates to correct Q4 from 31.12 to 15.09 This aligns with semester-based document submissions while maintaining the advance payment system where payments are made before each quarter.
117 lines
5.5 KiB
Python
117 lines
5.5 KiB
Python
from django.core.management.base import BaseCommand
|
|
from django.db import connection
|
|
from stiftung.models import VierteljahresNachweis, DestinataerUnterstuetzung
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = 'Diagnose deadline and payment due date issues on production'
|
|
|
|
def handle(self, *args, **options):
|
|
self.stdout.write(self.style.SUCCESS('=== PRODUCTION DEADLINE DIAGNOSTIC ==='))
|
|
|
|
# Check if migrations have been applied
|
|
with connection.cursor() as cursor:
|
|
cursor.execute(
|
|
"SELECT name FROM django_migrations WHERE app = 'stiftung' AND name LIKE '%deadline%' ORDER BY id"
|
|
)
|
|
migration_results = cursor.fetchall()
|
|
|
|
self.stdout.write('\n1. Migration Status:')
|
|
if migration_results:
|
|
for migration in migration_results:
|
|
self.stdout.write(f' ✓ {migration[0]}')
|
|
else:
|
|
self.stdout.write(' ❌ No deadline-related migrations found!')
|
|
|
|
# Check quarterly confirmation deadlines
|
|
self.stdout.write('\n2. Quarterly Confirmation Deadlines (2025):')
|
|
quarterly_records = VierteljahresNachweis.objects.filter(jahr=2025).order_by('quartal', 'destinataer__nachname')
|
|
|
|
deadline_summary = {}
|
|
for record in quarterly_records[:20]: # Limit to first 20 for readability
|
|
quarter = record.quartal
|
|
if quarter not in deadline_summary:
|
|
deadline_summary[quarter] = []
|
|
deadline_summary[quarter].append(str(record.faelligkeitsdatum))
|
|
|
|
for quarter in sorted(deadline_summary.keys()):
|
|
unique_dates = list(set(deadline_summary[quarter]))
|
|
expected_dates = {
|
|
1: '2025-03-15',
|
|
2: '2025-06-15',
|
|
3: '2025-09-15',
|
|
4: '2025-12-15'
|
|
}
|
|
expected = expected_dates[quarter]
|
|
status = '✓' if len(unique_dates) == 1 and unique_dates[0] == expected else '❌'
|
|
self.stdout.write(f' Q{quarter}: {status} Found: {unique_dates}, Expected: {expected}')
|
|
|
|
# Check payment due dates
|
|
self.stdout.write('\n3. Payment Due Dates (Recent):')
|
|
recent_payments = DestinataerUnterstuetzung.objects.filter(
|
|
beschreibung__icontains='Q4/2025'
|
|
).order_by('-faellig_am')[:5]
|
|
|
|
if recent_payments:
|
|
for payment in recent_payments:
|
|
self.stdout.write(f' {payment.destinataer.get_full_name()}: {payment.faellig_am} - {payment.beschreibung}')
|
|
else:
|
|
self.stdout.write(' No Q4/2025 payments found')
|
|
|
|
# Check all 2025 payments pattern
|
|
self.stdout.write('\n4. All 2025 Payment Due Date Pattern:')
|
|
all_2025_payments = DestinataerUnterstuetzung.objects.filter(
|
|
faellig_am__year=2025,
|
|
beschreibung__icontains='/'
|
|
).values_list('faellig_am', 'beschreibung').order_by('faellig_am')
|
|
|
|
payment_patterns = {}
|
|
for payment_date, desc in all_2025_payments:
|
|
if 'Q' in desc and '2025' in desc:
|
|
quarter_info = desc.split('/')[-1] if '/' in desc else desc
|
|
if quarter_info not in payment_patterns:
|
|
payment_patterns[quarter_info] = []
|
|
payment_patterns[quarter_info].append(str(payment_date))
|
|
|
|
for quarter_desc in sorted(payment_patterns.keys()):
|
|
unique_dates = list(set(payment_patterns[quarter_desc]))
|
|
self.stdout.write(f' {quarter_desc}: {unique_dates[:3]}{"..." if len(unique_dates) > 3 else ""}')
|
|
|
|
# Provide recommendations
|
|
self.stdout.write('\n5. Recommendations:')
|
|
|
|
# Check if deadline migration worked
|
|
q4_deadlines = VierteljahresNachweis.objects.filter(jahr=2025, quartal=4).values_list('faelligkeitsdatum', flat=True)
|
|
unique_q4_deadlines = list(set(q4_deadlines))
|
|
|
|
if len(unique_q4_deadlines) == 1 and str(unique_q4_deadlines[0]) == '2025-12-15':
|
|
self.stdout.write(' ✓ Quarterly confirmation deadlines are correct')
|
|
else:
|
|
self.stdout.write(' ❌ Run: python manage.py update_semester_deadlines')
|
|
|
|
# Check if payments need updating (advance payment schedule)
|
|
wrong_q4_payments = DestinataerUnterstuetzung.objects.filter(
|
|
faellig_am='2025-12-31',
|
|
beschreibung__icontains='Q4/2025'
|
|
).count()
|
|
|
|
# Also check for other quarters with wrong advance payment dates
|
|
wrong_q1_payments = DestinataerUnterstuetzung.objects.filter(
|
|
faellig_am='2025-03-31',
|
|
beschreibung__icontains='Q1/2025'
|
|
).count()
|
|
|
|
if wrong_q4_payments > 0:
|
|
self.stdout.write(f' ❌ {wrong_q4_payments} Q4 payments have wrong due date (31.12 instead of 15.09)')
|
|
self.stdout.write(' Run: python manage.py fix_q4_payment_dates')
|
|
elif wrong_q1_payments > 0:
|
|
self.stdout.write(f' ❌ {wrong_q1_payments} Q1 payments have wrong due date (advance payment schedule)')
|
|
else:
|
|
self.stdout.write(' ✓ Payment due dates appear correct')
|
|
|
|
# Show the advance payment schedule
|
|
self.stdout.write('\nAdvance Payment Schedule:')
|
|
self.stdout.write(' Q1 payments: Due December 15 of previous year')
|
|
self.stdout.write(' Q2 payments: Due March 15 of same year')
|
|
self.stdout.write(' Q3 payments: Due June 15 of same year')
|
|
self.stdout.write(' Q4 payments: Due September 15 of same year') |