- Q1: Due December 15 (previous year) - Q2: Due March 15 - Q3: Due June 15 - Q4: Due September 15 Added new management command fix_quarterly_payment_schedule to update existing payments
107 lines
4.1 KiB
Python
107 lines
4.1 KiB
Python
from django.core.management.base import BaseCommand
|
|
from django.db.models import Q
|
|
from datetime import date
|
|
from stiftung.models import DestinataerUnterstuetzung
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = 'Fix quarterly payment due dates to correct advance payment schedule'
|
|
|
|
def add_arguments(self, parser):
|
|
parser.add_argument(
|
|
'--dry-run',
|
|
action='store_true',
|
|
help='Show what would be changed without making actual 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 quarterly support payments that need fixing
|
|
payments_to_fix = DestinataerUnterstuetzung.objects.filter(
|
|
beschreibung__contains="Vierteljährliche Unterstützung"
|
|
).exclude(
|
|
beschreibung__contains="Korrektur" # Avoid fixing already corrected payments
|
|
)
|
|
|
|
total_fixed = 0
|
|
|
|
for payment in payments_to_fix:
|
|
# Extract quarter and year from description
|
|
desc = payment.beschreibung
|
|
try:
|
|
# Look for pattern like "Q1/2025", "Q2/2025", etc.
|
|
import re
|
|
match = re.search(r'Q(\d)/(\d{4})', desc)
|
|
if not match:
|
|
continue
|
|
|
|
quartal = int(match.group(1))
|
|
jahr = int(match.group(2))
|
|
|
|
# Calculate correct due date based on advance payment schedule
|
|
if quartal == 1: # Q1 payment due December 15 of previous year
|
|
correct_due_date = date(jahr - 1, 12, 15)
|
|
elif quartal == 2: # Q2 payment due March 15
|
|
correct_due_date = date(jahr, 3, 15)
|
|
elif quartal == 3: # Q3 payment due June 15
|
|
correct_due_date = date(jahr, 6, 15)
|
|
elif quartal == 4: # Q4 payment due September 15
|
|
correct_due_date = date(jahr, 9, 15)
|
|
else:
|
|
continue
|
|
|
|
# Check if this payment needs updating
|
|
if payment.faellig_am != correct_due_date:
|
|
old_date = payment.faellig_am
|
|
|
|
if dry_run:
|
|
self.stdout.write(
|
|
f"Would update {payment.destinataer.get_full_name()} "
|
|
f"Q{quartal}/{jahr} payment: {old_date} -> {correct_due_date}"
|
|
)
|
|
else:
|
|
payment.faellig_am = correct_due_date
|
|
payment.save()
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS(
|
|
f"Updated {payment.destinataer.get_full_name()} "
|
|
f"Q{quartal}/{jahr} payment: {old_date} -> {correct_due_date}"
|
|
)
|
|
)
|
|
|
|
total_fixed += 1
|
|
|
|
except (ValueError, AttributeError) as e:
|
|
self.stdout.write(
|
|
self.style.WARNING(
|
|
f"Could not parse quarter/year from: {desc} - {e}"
|
|
)
|
|
)
|
|
continue
|
|
|
|
if dry_run:
|
|
self.stdout.write(
|
|
self.style.WARNING(
|
|
f"Would fix {total_fixed} payment due dates"
|
|
)
|
|
)
|
|
else:
|
|
self.stdout.write(
|
|
self.style.SUCCESS(
|
|
f"Successfully fixed {total_fixed} payment due dates"
|
|
)
|
|
)
|
|
|
|
# Show the expected schedule
|
|
self.stdout.write("\nCorrect advance payment schedule:")
|
|
self.stdout.write("Q1: Due December 15 (previous year)")
|
|
self.stdout.write("Q2: Due March 15")
|
|
self.stdout.write("Q3: Due June 15")
|
|
self.stdout.write("Q4: Due September 15") |