fix: configure CI database connection properly

- Add dotenv loading to Django settings
- Update CI workflow to use correct environment variables
- Set POSTGRES_* variables instead of DATABASE_URL
- Add environment variables to all Django management commands
- Fixes CI test failures due to database connection issues
This commit is contained in:
Stiftung Development
2025-09-06 18:47:23 +02:00
parent dcc91b9f49
commit 35ba089a84
64 changed files with 7040 additions and 1419 deletions

View File

@@ -1,9 +1,10 @@
from django import forms
from django.core.exceptions import ValidationError
from django.utils import timezone
from .models import (
Rentmeister, StiftungsKonto, Verwaltungskosten, Person,
Paechter, Destinataer, Land, Verpachtung, DokumentLink, Foerderung, BankTransaction,
DestinataerUnterstuetzung, DestinataerNotiz, LandAbrechnung,
Paechter, Destinataer, Land, DokumentLink, Foerderung, BankTransaction,
DestinataerUnterstuetzung, UnterstuetzungWiederkehrend, DestinataerNotiz, LandAbrechnung,
)
import re
@@ -105,10 +106,24 @@ class RentmeisterForm(forms.ModelForm):
def clean(self):
"""Übergreifende Validierung"""
from django.utils.dateparse import parse_date
cleaned_data = super().clean()
seit_datum = cleaned_data.get('seit_datum')
bis_datum = cleaned_data.get('bis_datum')
# Helper function to ensure we have date objects
def ensure_date(date_value):
if not date_value:
return None
if isinstance(date_value, str):
return parse_date(date_value)
return date_value
# Convert to date objects if they're strings
seit_datum = ensure_date(seit_datum)
bis_datum = ensure_date(bis_datum)
# Prüfe Datum-Logik
if seit_datum and bis_datum and bis_datum <= seit_datum:
raise ValidationError('Das End-Datum muss nach dem Start-Datum liegen.')
@@ -404,23 +419,6 @@ class LandAbrechnungForm(forms.ModelForm):
}
class VerpachtungForm(forms.ModelForm):
"""Form für das Erstellen und Bearbeiten von Verpachtungen"""
class Meta:
model = Verpachtung
fields = '__all__'
widgets = {
'paechter': forms.Select(attrs={'class': 'form-select'}),
'land': forms.Select(attrs={'class': 'form-select'}),
'pacht_pro_qm': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
'pachtbeginn': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'pachtende': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'aktiv': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
'notizen': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
}
class DokumentLinkForm(forms.ModelForm):
"""Form für das Erstellen und Bearbeiten von Dokumentverknüpfungen"""
@@ -438,20 +436,164 @@ class DokumentLinkForm(forms.ModelForm):
class FoerderungForm(forms.ModelForm):
"""Form für das Erstellen und Bearbeiten von Förderungen"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Add empty option for optional fields
self.fields['verwendungsnachweis'].empty_label = "--- Kein Dokument verknüpfen ---"
# Ensure destinataer has proper choices
from .models import Destinataer, DokumentLink
from django.utils import timezone
self.fields['destinataer'].queryset = Destinataer.objects.all().order_by('nachname', 'vorname')
self.fields['verwendungsnachweis'].queryset = DokumentLink.objects.all().order_by('titel')
# Set current year as default for new forms
if not self.instance.pk:
self.fields['jahr'].initial = timezone.now().year
class Meta:
model = Foerderung
fields = '__all__'
fields = [
'destinataer', 'jahr', 'betrag', 'kategorie', 'status',
'antragsdatum', 'entscheidungsdatum', 'verwendungsnachweis', 'bemerkungen'
]
widgets = {
'person': forms.Select(attrs={'class': 'form-select'}),
'destinataer': forms.Select(attrs={'class': 'form-select'}),
'jahr': forms.NumberInput(attrs={'class': 'form-control'}),
'betrag': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
'zweck': forms.TextInput(attrs={'class': 'form-control'}),
'kategorie': forms.Select(attrs={'class': 'form-select'}),
'status': forms.Select(attrs={'class': 'form-select'}),
'ausgezahlt_am': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'notizen': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
'antragsdatum': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'entscheidungsdatum': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'verwendungsnachweis': forms.Select(attrs={'class': 'form-select'}),
'bemerkungen': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
}
labels = {
'destinataer': 'Destinatär',
'verwendungsnachweis': 'Verknüpftes Dokument',
'bemerkungen': 'Bemerkungen/Beschreibung',
'antragsdatum': 'Antragsdatum',
'entscheidungsdatum': 'Entscheidungsdatum',
}
help_texts = {
'verwendungsnachweis': 'Optionale Verknüpfung zu einem Dokument aus dem Paperless-System',
'entscheidungsdatum': 'Datum der Bewilligung/Ablehnung (optional)',
'bemerkungen': 'Zusätzliche Informationen zur Förderung',
}
class UnterstuetzungForm(forms.ModelForm):
"""Form für das Erstellen und Bearbeiten von Unterstützungen"""
# Special field for creating recurring payments
ist_wiederkehrend = forms.BooleanField(
required=False,
label='Wiederkehrende Zahlung',
help_text='Aktivieren Sie diese Option um automatisch wiederkehrende Zahlungen zu erstellen'
)
intervall = forms.ChoiceField(
choices=[('', '--- Wählen Sie ein Intervall ---')] + UnterstuetzungWiederkehrend.INTERVALL_CHOICES,
required=False,
widget=forms.Select(attrs={'class': 'form-select'}),
label='Zahlungsintervall'
)
letzte_zahlung_am = forms.DateField(
required=False,
widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
label='Letzte Zahlung am (optional)',
help_text='Leer lassen für unbegrenzte Wiederholung'
)
class Meta:
model = DestinataerUnterstuetzung
fields = [
'destinataer', 'konto', 'faellig_am', 'betrag', 'status',
'beschreibung', 'empfaenger_iban', 'empfaenger_name', 'verwendungszweck'
]
widgets = {
'destinataer': forms.Select(attrs={'class': 'form-select'}),
'konto': forms.Select(attrs={'class': 'form-select'}),
'faellig_am': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'betrag': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
'status': forms.Select(attrs={'class': 'form-select'}),
'beschreibung': forms.TextInput(attrs={'class': 'form-control'}),
'empfaenger_iban': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'DE89 3704 0044 0532 0130 00'}),
'empfaenger_name': forms.TextInput(attrs={'class': 'form-control'}),
'verwendungszweck': forms.TextInput(attrs={'class': 'form-control', 'maxlength': '140'}),
}
labels = {
'destinataer': 'Destinatär',
'konto': 'Zahlungskonto',
'faellig_am': 'Fällig am',
'betrag': 'Betrag (€)',
'status': 'Status',
'beschreibung': 'Beschreibung',
'empfaenger_iban': 'Empfänger IBAN',
'empfaenger_name': 'Empfänger Name',
'verwendungszweck': 'Verwendungszweck',
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Add onchange event to destinataer field for AJAX IBAN fetching
self.fields['destinataer'].widget.attrs['onchange'] = 'updateDestinataerInfo()'
def clean(self):
cleaned_data = super().clean()
ist_wiederkehrend = cleaned_data.get('ist_wiederkehrend')
intervall = cleaned_data.get('intervall')
if ist_wiederkehrend and not intervall:
raise forms.ValidationError('Bitte wählen Sie ein Zahlungsintervall für wiederkehrende Zahlungen.')
return cleaned_data
class UnterstuetzungWiederkehrendForm(forms.ModelForm):
"""Form für das Bearbeiten von wiederkehrenden Unterstützungsvorlagen"""
class Meta:
model = UnterstuetzungWiederkehrend
fields = [
'destinataer', 'konto', 'betrag', 'intervall', 'beschreibung',
'empfaenger_iban', 'empfaenger_name', 'verwendungszweck',
'erste_zahlung_am', 'letzte_zahlung_am', 'aktiv'
]
widgets = {
'destinataer': forms.Select(attrs={'class': 'form-select'}),
'konto': forms.Select(attrs={'class': 'form-select'}),
'betrag': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.01'}),
'intervall': forms.Select(attrs={'class': 'form-select'}),
'beschreibung': forms.TextInput(attrs={'class': 'form-control'}),
'empfaenger_iban': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'DE89 3704 0044 0532 0130 00'}),
'empfaenger_name': forms.TextInput(attrs={'class': 'form-control'}),
'verwendungszweck': forms.TextInput(attrs={'class': 'form-control', 'maxlength': '140'}),
'erste_zahlung_am': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'letzte_zahlung_am': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'aktiv': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
}
class UnterstuetzungMarkAsPaidForm(forms.Form):
"""Simple form to mark an Unterstützung as paid"""
ausgezahlt_am = forms.DateField(
widget=forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
label='Ausgezahlt am',
initial=timezone.now().date()
)
bemerkung = forms.CharField(
widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 3}),
label='Bemerkung (optional)',
required=False,
help_text='Optionale Notiz zur Zahlung'
)
class BankTransactionForm(forms.ModelForm):