FallenBirdyForm/app/reports/admin.py
2025-07-09 19:59:29 +02:00

239 lines
8.7 KiB
Python

from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from django.utils.html import format_html
from django.urls import reverse
from django.contrib import messages
from django.http import HttpResponseRedirect
from datetime import date, timedelta
from .models import AutomaticReport, ReportLog
from .services import ReportGenerator
@admin.register(AutomaticReport)
class AutomaticReportAdmin(admin.ModelAdmin):
list_display = [
'name',
'frequency',
'is_active',
'last_sent',
'created_by',
'created_at',
'email_count'
]
list_filter = ['frequency', 'is_active', 'created_at', 'include_naturschutzbehoerde', 'include_jagdbehoerde']
search_fields = ['name', 'description']
readonly_fields = ['created_by', 'created_at', 'updated_at']
actions = ['send_report_now']
fieldsets = (
(None, {
'fields': ('name', 'description', 'is_active')
}),
(_('E-Mail-Einstellungen'), {
'fields': ('email_addresses',)
}),
(_('Filter-Einstellungen'), {
'fields': ('include_naturschutzbehoerde', 'include_jagdbehoerde')
}),
(_('Zeitplan'), {
'fields': ('frequency',)
}),
(_('Metadaten'), {
'fields': ('created_by', 'created_at', 'updated_at', 'last_sent'),
'classes': ('collapse',)
}),
)
def save_model(self, request, obj, form, change):
if not change: # Creating new object
obj.created_by = request.user
super().save_model(request, obj, form, change)
def email_count(self, obj):
"""Show number of email addresses."""
count = obj.email_addresses.count()
return f"{count} E-Mail-Adresse(n)"
email_count.short_description = _("E-Mail-Adressen")
def send_report_now(self, request, queryset):
"""Send selected reports immediately."""
sent_count = 0
error_count = 0
skipped_count = 0
for report in queryset:
if not report.is_active:
messages.warning(
request,
f"Report '{report.name}' ist deaktiviert und wurde übersprungen."
)
skipped_count += 1
continue
if not report.email_addresses.exists():
messages.warning(
request,
f"Report '{report.name}' hat keine E-Mail-Adressen und wurde übersprungen."
)
skipped_count += 1
continue
# Get email addresses
email_addresses = [addr.email_address for addr in report.email_addresses.all()]
# Calculate date range based on frequency
today = date.today()
if report.frequency == 'weekly':
date_from = today - timedelta(days=7)
range_description = "letzte 7 Tage"
elif report.frequency == 'monthly':
# Go back one month
if today.month == 1:
date_from = today.replace(year=today.year-1, month=12, day=1)
else:
date_from = today.replace(month=today.month-1, day=1)
range_description = "letzter Monat"
elif report.frequency == 'quarterly':
# Go back three months
if today.month <= 3:
date_from = today.replace(year=today.year-1, month=today.month+9, day=1)
else:
date_from = today.replace(month=today.month-3, day=1)
range_description = "letztes Quartal"
else:
date_from = today - timedelta(days=30) # Default to 30 days
range_description = "letzte 30 Tage"
# Generate and send report
try:
generator = ReportGenerator(
date_from=date_from,
date_to=today,
include_naturschutzbehoerde=report.include_naturschutzbehoerde,
include_jagdbehoerde=report.include_jagdbehoerde
)
report_log, success, error_msg = generator.send_email_report(
email_addresses=email_addresses,
automatic_report=report
)
if success:
# Update last_sent timestamp
report.last_sent = today
report.save(update_fields=['last_sent'])
sent_count += 1
# Success message with details
messages.success(
request,
f"Report '{report.name}' erfolgreich gesendet "
f"({range_description}, {report_log.patient_count} Patienten, "
f"{len(email_addresses)} Empfänger)."
)
else:
error_count += 1
messages.error(
request,
f"Fehler beim Senden von '{report.name}': {error_msg}"
)
except Exception as e:
error_count += 1
messages.error(
request,
f"Unerwarteter Fehler bei '{report.name}': {str(e)}"
)
# Show summary message
if sent_count > 0:
messages.success(
request,
f"Zusammenfassung: {sent_count} Report(s) erfolgreich gesendet"
+ (f", {skipped_count} übersprungen" if skipped_count > 0 else "")
+ (f", {error_count} Fehler" if error_count > 0 else "") + "."
)
elif skipped_count > 0 and error_count == 0:
messages.info(
request,
f"Alle {skipped_count} ausgewählten Reports wurden übersprungen (deaktiviert oder keine E-Mail-Adressen)."
)
elif error_count > 0 and sent_count == 0:
messages.error(
request,
f"Alle {error_count} Reports konnten nicht gesendet werden."
)
send_report_now.short_description = _("Ausgewählte Reports sofort senden")
@admin.register(ReportLog)
class ReportLogAdmin(admin.ModelAdmin):
list_display = [
'created_at',
'get_report_type',
'date_range',
'patient_count',
'has_email_recipients',
'filters_used'
]
list_filter = [
'automatic_report',
'include_naturschutzbehörde',
'include_jagdbehörde',
'created_at'
]
search_fields = ['automatic_report__name']
readonly_fields = [
'automatic_report', 'date_from', 'date_to', 'include_naturschutzbehörde',
'include_jagdbehörde', 'patient_count', 'email_sent_to',
'created_at', 'csv_file'
]
def get_report_type(self, obj):
"""Show report type."""
if obj.automatic_report:
return format_html(
'<span style="color: #007bff;"><i class="fas fa-clock"></i> Automatisch</span>'
)
return format_html(
'<span style="color: #6c757d;"><i class="fas fa-hand-paper"></i> Manuell</span>'
)
get_report_type.short_description = _("Typ")
def date_range(self, obj):
"""Show date range."""
return f"{obj.date_from} - {obj.date_to}"
date_range.short_description = _("Zeitraum")
def has_email_recipients(self, obj):
"""Show if email was sent."""
if obj.email_sent_to:
return format_html(
'<span style="color: #28a745;"><i class="fas fa-envelope"></i> {} Empfänger</span>',
len(obj.email_sent_to)
)
return format_html(
'<span style="color: #17a2b8;"><i class="fas fa-download"></i> Download</span>'
)
has_email_recipients.short_description = _("Versendung")
def filters_used(self, obj):
"""Show which filters were used."""
filters = []
if obj.include_naturschutzbehörde:
filters.append("Naturschutzbehörde")
if obj.include_jagdbehörde:
filters.append("Jagdbehörde")
return ", ".join(filters) if filters else _("Keine Filter")
filters_used.short_description = _("Filter")
def has_add_permission(self, request):
"""Disable manual creation of logs."""
return False
# Custom admin site configuration
admin.site.site_header = "Django FBF Administration"
admin.site.site_title = "Django FBF Admin"
admin.site.index_title = "Willkommen zur Django FBF Administration"