from django.core.management.base import BaseCommand from django.db import transaction from datetime import date from stiftung.models import DestinataerUnterstuetzung class Command(BaseCommand): help = 'Fix Q4 payment due dates from December 31 to December 15' def add_arguments(self, parser): parser.add_argument( '--dry-run', action='store_true', help='Show what would be updated without making changes', ) def handle(self, *args, **options): dry_run = options['dry_run'] if dry_run: self.stdout.write(self.style.WARNING('DRY RUN MODE - No changes will be made')) # Find all Q4/2025 payments with wrong due date (Dec 31 instead of Sep 15) wrong_payments = DestinataerUnterstuetzung.objects.filter( faellig_am='2025-12-31', beschreibung__icontains='Q4/2025' ) total_count = wrong_payments.count() self.stdout.write(f'Found {total_count} Q4/2025 payments with wrong due date (31.12 instead of 15.12)') if total_count == 0: self.stdout.write(self.style.SUCCESS('No payments need fixing!')) return updated_count = 0 correct_date = date(2025, 9, 15) # September 15, 2025 (advance payment for Q4) with transaction.atomic(): for payment in wrong_payments: old_date = payment.faellig_am if not dry_run: payment.faellig_am = correct_date payment.save(update_fields=['faellig_am']) updated_count += 1 # Show progress for every 5 updates or if verbose if updated_count % 5 == 0 or options['verbosity'] >= 2: self.stdout.write( f' {payment.destinataer.get_full_name()}: ' f'{old_date} → {correct_date} ({payment.betrag}€)' ) # Summary if dry_run: self.stdout.write( self.style.SUCCESS( f'DRY RUN: Would update {updated_count} payment due dates from 31.12.2025 to 15.09.2025' ) ) else: self.stdout.write( self.style.SUCCESS( f'Successfully updated {updated_count} payment due dates to September 15, 2025' ) ) # Also check for other quarters that might have wrong dates self.stdout.write('\nChecking other quarters for potential issues:') quarter_checks = { 'Q1/2025': ('2025-02-15', '2025-03-15'), 'Q2/2025': ('2025-05-15', '2025-06-15'), 'Q3/2025': ('2025-08-15', '2025-09-15'), } for quarter_desc, (old_expected, new_expected) in quarter_checks.items(): old_date_payments = DestinataerUnterstuetzung.objects.filter( faellig_am=old_expected, beschreibung__icontains=quarter_desc ).count() if old_date_payments > 0: self.stdout.write(f' ⚠️ {quarter_desc}: {old_date_payments} payments still use old date {old_expected}') self.stdout.write(f' Should be: {new_expected}') self.stdout.write('\nAdvance payment schedule (payments made in advance):') 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')