Fix quarterly payment schedule to correct advance payment dates
- 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
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
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")
|
||||
Reference in New Issue
Block a user