Format code with Black and isort for CI/CD compliance
- Apply Black formatting to all Python files in core and stiftung modules - Fix import statement ordering with isort - Ensure all code meets automated quality standards - Resolve CI/CD pipeline formatting failures - Maintain consistent code style across the entire codebase
This commit is contained in:
@@ -3,60 +3,64 @@ Management command to generate due recurring support payments.
|
||||
This command should be run daily via cron or similar scheduling system.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
|
||||
from stiftung.models import UnterstuetzungWiederkehrend
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Generate due recurring support payments'
|
||||
|
||||
help = "Generate due recurring support payments"
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument(
|
||||
'--dry-run',
|
||||
action='store_true',
|
||||
help='Show what would be generated without actually creating payments',
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Show what would be generated without actually creating payments",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--days-ahead',
|
||||
"--days-ahead",
|
||||
type=int,
|
||||
default=0,
|
||||
help='Generate payments that are due within this many days (default: 0 = only today)',
|
||||
help="Generate payments that are due within this many days (default: 0 = only today)",
|
||||
)
|
||||
|
||||
|
||||
def handle(self, *args, **options):
|
||||
dry_run = options['dry_run']
|
||||
days_ahead = options['days_ahead']
|
||||
|
||||
dry_run = options["dry_run"]
|
||||
days_ahead = options["days_ahead"]
|
||||
|
||||
heute = timezone.now().date()
|
||||
cutoff_date = heute + timedelta(days=days_ahead)
|
||||
|
||||
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f'Checking for recurring payments due up to {cutoff_date.strftime("%d.%m.%Y")}...'
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if dry_run:
|
||||
self.stdout.write(self.style.WARNING('DRY RUN MODE - No payments will be created'))
|
||||
|
||||
self.stdout.write(
|
||||
self.style.WARNING("DRY RUN MODE - No payments will be created")
|
||||
)
|
||||
|
||||
# Get all active recurring payment templates that are due
|
||||
templates = UnterstuetzungWiederkehrend.objects.filter(
|
||||
aktiv=True,
|
||||
naechste_generierung__lte=cutoff_date
|
||||
).select_related('destinataer', 'konto')
|
||||
|
||||
aktiv=True, naechste_generierung__lte=cutoff_date
|
||||
).select_related("destinataer", "konto")
|
||||
|
||||
generated_count = 0
|
||||
error_count = 0
|
||||
|
||||
|
||||
for template in templates:
|
||||
try:
|
||||
if dry_run:
|
||||
self.stdout.write(
|
||||
f'Would generate: {template.destinataer.get_full_name()} - '
|
||||
f"Would generate: {template.destinataer.get_full_name()} - "
|
||||
f'€{template.betrag} due {template.naechste_generierung.strftime("%d.%m.%Y")}'
|
||||
)
|
||||
generated_count += 1
|
||||
@@ -66,68 +70,67 @@ class Command(BaseCommand):
|
||||
if neue_zahlung:
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f'Generated: {neue_zahlung.destinataer.get_full_name()} - '
|
||||
f"Generated: {neue_zahlung.destinataer.get_full_name()} - "
|
||||
f'€{neue_zahlung.betrag} due {neue_zahlung.faellig_am.strftime("%d.%m.%Y")}'
|
||||
)
|
||||
)
|
||||
generated_count += 1
|
||||
logger.info(f'Generated recurring payment: {neue_zahlung.pk}')
|
||||
logger.info(f"Generated recurring payment: {neue_zahlung.pk}")
|
||||
else:
|
||||
self.stdout.write(
|
||||
self.style.WARNING(
|
||||
f'No payment generated for {template.destinataer.get_full_name()} '
|
||||
f'(may have reached end date or not yet due)'
|
||||
f"No payment generated for {template.destinataer.get_full_name()} "
|
||||
f"(may have reached end date or not yet due)"
|
||||
)
|
||||
)
|
||||
except Exception as e:
|
||||
error_count += 1
|
||||
self.stdout.write(
|
||||
self.style.ERROR(
|
||||
f'Error generating payment for {template.destinataer.get_full_name()}: {str(e)}'
|
||||
f"Error generating payment for {template.destinataer.get_full_name()}: {str(e)}"
|
||||
)
|
||||
)
|
||||
logger.error(f'Error generating recurring payment for template {template.pk}: {str(e)}')
|
||||
|
||||
logger.error(
|
||||
f"Error generating recurring payment for template {template.pk}: {str(e)}"
|
||||
)
|
||||
|
||||
# Summary
|
||||
self.stdout.write('\n' + '='*50)
|
||||
self.stdout.write("\n" + "=" * 50)
|
||||
if dry_run:
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f'DRY RUN COMPLETE: {generated_count} payments would be generated'
|
||||
f"DRY RUN COMPLETE: {generated_count} payments would be generated"
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.stdout.write(
|
||||
self.style.SUCCESS(
|
||||
f'GENERATION COMPLETE: {generated_count} payments generated'
|
||||
f"GENERATION COMPLETE: {generated_count} payments generated"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if error_count > 0:
|
||||
self.stdout.write(
|
||||
self.style.ERROR(f'{error_count} errors encountered')
|
||||
)
|
||||
|
||||
self.stdout.write(self.style.ERROR(f"{error_count} errors encountered"))
|
||||
|
||||
# Also check for overdue payments and report them
|
||||
from stiftung.models import DestinataerUnterstuetzung
|
||||
|
||||
|
||||
overdue_payments = DestinataerUnterstuetzung.objects.filter(
|
||||
faellig_am__lt=heute,
|
||||
status__in=['geplant', 'faellig']
|
||||
).select_related('destinataer')
|
||||
|
||||
faellig_am__lt=heute, status__in=["geplant", "faellig"]
|
||||
).select_related("destinataer")
|
||||
|
||||
if overdue_payments.exists():
|
||||
self.stdout.write('\n' + '='*50)
|
||||
self.stdout.write("\n" + "=" * 50)
|
||||
self.stdout.write(
|
||||
self.style.WARNING(
|
||||
f'WARNING: {overdue_payments.count()} overdue payments found:'
|
||||
f"WARNING: {overdue_payments.count()} overdue payments found:"
|
||||
)
|
||||
)
|
||||
for payment in overdue_payments[:10]: # Limit to first 10
|
||||
days_overdue = (heute - payment.faellig_am).days
|
||||
self.stdout.write(
|
||||
f' - {payment.destinataer.get_full_name()}: €{payment.betrag} '
|
||||
f'({days_overdue} days overdue)'
|
||||
f" - {payment.destinataer.get_full_name()}: €{payment.betrag} "
|
||||
f"({days_overdue} days overdue)"
|
||||
)
|
||||
if overdue_payments.count() > 10:
|
||||
self.stdout.write(f' ... and {overdue_payments.count() - 10} more')
|
||||
self.stdout.write(f" ... and {overdue_payments.count() - 10} more")
|
||||
|
||||
Reference in New Issue
Block a user