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:
@@ -3,9 +3,11 @@ from django.utils.html import format_html
|
||||
from django.urls import reverse
|
||||
from django.db.models import Sum, Count
|
||||
from django.utils.safestring import mark_safe
|
||||
from . import models
|
||||
from .models import (
|
||||
Person, Paechter, Destinataer, DokumentLink, Foerderung, Land, Verpachtung, CSVImport,
|
||||
Rentmeister, StiftungsKonto, Verwaltungskosten, BankTransaction, AuditLog, BackupJob
|
||||
Person, Paechter, Destinataer, DokumentLink, Foerderung, Land, CSVImport,
|
||||
Rentmeister, StiftungsKonto, Verwaltungskosten, BankTransaction, AuditLog, BackupJob, AppConfiguration,
|
||||
DestinataerUnterstuetzung, UnterstuetzungWiederkehrend
|
||||
)
|
||||
|
||||
@admin.register(CSVImport)
|
||||
@@ -214,66 +216,6 @@ class LandAdmin(admin.ModelAdmin):
|
||||
return f"{obj.get_verpachtungsgrad():.1f}%"
|
||||
verpachtungsgrad_berechnet.short_description = 'Verpachtungsgrad'
|
||||
|
||||
@admin.register(Verpachtung)
|
||||
class VerpachtungAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
'vertragsnummer', 'land', 'paechter', 'pachtbeginn', 'pachtende',
|
||||
'pachtzins_jaehrlich', 'verpachtete_flaeche', 'status', 'restlaufzeit'
|
||||
]
|
||||
list_filter = ['status', 'pachtbeginn', 'pachtende', 'land__gemeinde']
|
||||
search_fields = ['vertragsnummer', 'land__gemeinde', 'paechter__nachname', 'paechter__vorname']
|
||||
ordering = ['-pachtbeginn']
|
||||
readonly_fields = ['id', 'vertragsdauer_tage', 'restlaufzeit_tage', 'is_aktiv_status']
|
||||
|
||||
fieldsets = (
|
||||
('Vertragsdaten', {
|
||||
'fields': ('vertragsnummer', 'land', 'paechter', 'pachtbeginn', 'pachtende', 'verlaengerung')
|
||||
}),
|
||||
('Finanzielle Bedingungen', {
|
||||
'fields': ('pachtzins_pro_qm', 'pachtzins_jaehrlich')
|
||||
}),
|
||||
('Flächenangaben', {
|
||||
'fields': ('verpachtete_flaeche',)
|
||||
}),
|
||||
('Status', {
|
||||
'fields': ('status',)
|
||||
}),
|
||||
('Dokumentation', {
|
||||
'fields': ('verwendungsnachweis', 'bemerkungen')
|
||||
}),
|
||||
('System', {
|
||||
'fields': ('id', 'erstellt_am', 'aktualisiert_am'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
|
||||
def restlaufzeit(self, obj):
|
||||
tage = obj.get_restlaufzeit_tage()
|
||||
if tage > 0:
|
||||
if tage < 30:
|
||||
color = 'red'
|
||||
elif tage < 90:
|
||||
color = 'orange'
|
||||
else:
|
||||
color = 'green'
|
||||
return format_html('<span style="color: {};">{} Tage</span>', color, tage)
|
||||
return 'Abgelaufen'
|
||||
restlaufzeit.short_description = 'Restlaufzeit'
|
||||
|
||||
def vertragsdauer_tage(self, obj):
|
||||
return f"{obj.get_vertragsdauer_tage()} Tage"
|
||||
vertragsdauer_tage.short_description = 'Vertragsdauer'
|
||||
|
||||
def restlaufzeit_tage(self, obj):
|
||||
return f"{obj.get_restlaufzeit_tage()} Tage"
|
||||
restlaufzeit_tage.short_description = 'Restlaufzeit'
|
||||
|
||||
def is_aktiv_status(self, obj):
|
||||
if obj.is_aktiv():
|
||||
return format_html('<span style="color: green;">✓ Aktiv</span>')
|
||||
return format_html('<span style="color: red;">✗ Inaktiv</span>')
|
||||
is_aktiv_status.short_description = 'Aktueller Status'
|
||||
|
||||
@admin.register(DokumentLink)
|
||||
class DokumentLinkAdmin(admin.ModelAdmin):
|
||||
list_display = ['titel', 'kontext', 'paperless_document_id']
|
||||
@@ -541,6 +483,134 @@ class BackupJobAdmin(admin.ModelAdmin):
|
||||
return False # Use the web interface for creating backups
|
||||
|
||||
|
||||
@admin.register(AppConfiguration)
|
||||
class AppConfigurationAdmin(admin.ModelAdmin):
|
||||
list_display = ['display_name', 'key', 'value_display', 'category', 'setting_type', 'is_active', 'updated_at']
|
||||
list_filter = ['category', 'setting_type', 'is_active']
|
||||
search_fields = ['key', 'display_name', 'description']
|
||||
readonly_fields = ['id', 'created_at', 'updated_at']
|
||||
ordering = ['category', 'order', 'display_name']
|
||||
|
||||
fieldsets = (
|
||||
('Basic Information', {
|
||||
'fields': ('key', 'display_name', 'description', 'category', 'setting_type')
|
||||
}),
|
||||
('Value Configuration', {
|
||||
'fields': ('value', 'default_value')
|
||||
}),
|
||||
('Options', {
|
||||
'fields': ('is_active', 'is_system', 'order')
|
||||
}),
|
||||
('Metadata', {
|
||||
'fields': ('created_at', 'updated_at'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
|
||||
def value_display(self, obj):
|
||||
"""Display value with type formatting"""
|
||||
value = obj.value
|
||||
if obj.setting_type == 'boolean':
|
||||
icon = '✅' if obj.get_typed_value() else '❌'
|
||||
return format_html('{} {}', icon, value)
|
||||
elif obj.setting_type == 'url':
|
||||
return format_html('<a href="{}" target="_blank">{}</a>', value, value[:50] + '...' if len(value) > 50 else value)
|
||||
elif len(value) > 100:
|
||||
return value[:100] + '...'
|
||||
return value
|
||||
value_display.short_description = 'Current Value'
|
||||
|
||||
def get_readonly_fields(self, request, obj=None):
|
||||
readonly = list(self.readonly_fields)
|
||||
if obj and obj.is_system:
|
||||
readonly.extend(['key', 'setting_type', 'is_system'])
|
||||
return readonly
|
||||
|
||||
|
||||
@admin.register(DestinataerUnterstuetzung)
|
||||
class DestinataerUnterstuetzungAdmin(admin.ModelAdmin):
|
||||
list_display = ['__str__', 'destinataer', 'betrag', 'faellig_am', 'status', 'wiederkehrend_von', 'ausgezahlt_am']
|
||||
list_filter = ['status', 'faellig_am', 'erstellt_am', 'konto']
|
||||
search_fields = ['destinataer__vorname', 'destinataer__nachname', 'beschreibung', 'empfaenger_name']
|
||||
readonly_fields = ['id', 'erstellt_am', 'aktualisiert_am']
|
||||
|
||||
fieldsets = (
|
||||
('Grundinformationen', {
|
||||
'fields': ('destinataer', 'konto', 'betrag', 'faellig_am', 'status', 'beschreibung')
|
||||
}),
|
||||
('Überweisungsdaten', {
|
||||
'fields': ('empfaenger_iban', 'empfaenger_name', 'verwendungszweck')
|
||||
}),
|
||||
('Zahlungsinformationen', {
|
||||
'fields': ('ausgezahlt_am', 'ausgezahlt_von')
|
||||
}),
|
||||
('Wiederkehrend', {
|
||||
'fields': ('wiederkehrend_von',)
|
||||
}),
|
||||
('Metadaten', {
|
||||
'fields': ('id', 'erstellt_am', 'aktualisiert_am'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@admin.register(UnterstuetzungWiederkehrend)
|
||||
class UnterstuetzungWiederkehrendAdmin(admin.ModelAdmin):
|
||||
list_display = ['__str__', 'destinataer', 'betrag', 'intervall', 'aktiv', 'naechste_generierung']
|
||||
list_filter = ['intervall', 'aktiv', 'erstellt_am']
|
||||
search_fields = ['destinataer__vorname', 'destinataer__nachname', 'beschreibung', 'empfaenger_name']
|
||||
readonly_fields = ['id', 'erstellt_am']
|
||||
|
||||
fieldsets = (
|
||||
('Grundinformationen', {
|
||||
'fields': ('destinataer', 'konto', 'betrag', 'intervall', 'beschreibung', 'aktiv')
|
||||
}),
|
||||
('Überweisungsdaten', {
|
||||
'fields': ('empfaenger_iban', 'empfaenger_name', 'verwendungszweck')
|
||||
}),
|
||||
('Zeitplanung', {
|
||||
'fields': ('erste_zahlung_am', 'letzte_zahlung_am', 'naechste_generierung')
|
||||
}),
|
||||
('Metadaten', {
|
||||
'fields': ('id', 'erstellt_von', 'erstellt_am'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@admin.register(models.HelpBox)
|
||||
class HelpBoxAdmin(admin.ModelAdmin):
|
||||
list_display = ['get_page_display', 'title', 'is_active', 'updated_at', 'updated_by']
|
||||
list_filter = ['page_key', 'is_active', 'updated_at']
|
||||
search_fields = ['title', 'content']
|
||||
|
||||
fieldsets = (
|
||||
('Grundinformationen', {
|
||||
'fields': ('page_key', 'title', 'is_active')
|
||||
}),
|
||||
('Inhalt', {
|
||||
'fields': ('content',),
|
||||
'description': 'Markdown wird unterstützt: **fett**, *kursiv*, `code`, [Link](url), Listen mit - oder 1.'
|
||||
}),
|
||||
('Metadaten', {
|
||||
'fields': ('created_at', 'updated_at', 'created_by', 'updated_by'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
|
||||
readonly_fields = ['created_at', 'updated_at']
|
||||
|
||||
def get_page_display(self, obj):
|
||||
return obj.get_page_key_display()
|
||||
get_page_display.short_description = "Seite"
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
if not change: # Neues Objekt
|
||||
obj.created_by = request.user.username
|
||||
obj.updated_by = request.user.username
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
|
||||
# Customize admin site
|
||||
admin.site.site_header = "Stiftungsverwaltung Administration"
|
||||
admin.site.site_title = "Stiftungsverwaltung Admin"
|
||||
|
||||
Reference in New Issue
Block a user