add manual report
This commit is contained in:
parent
67a49aa193
commit
56164b2f47
2 changed files with 224 additions and 0 deletions
108
MANUAL_SEND_DOCUMENTATION.md
Normal file
108
MANUAL_SEND_DOCUMENTATION.md
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
# Manuelle "Sofort senden" Funktion für Automatische Reports
|
||||||
|
|
||||||
|
## Übersicht
|
||||||
|
|
||||||
|
Die neue "Sofort senden" Aktion im Django Admin ermöglicht es Administratoren, automatische Reports manuell und sofort zu versenden, ohne auf den geplanten Zeitpunkt warten zu müssen.
|
||||||
|
|
||||||
|
## Verwendung
|
||||||
|
|
||||||
|
1. **Admin-Bereich öffnen**: Navigieren Sie zu `/admin/reports/automaticreport/`
|
||||||
|
2. **Reports auswählen**: Wählen Sie einen oder mehrere automatische Reports aus der Liste aus
|
||||||
|
3. **Aktion ausführen**: Wählen Sie aus dem Aktions-Dropdown "Ausgewählte Reports sofort senden"
|
||||||
|
4. **Bestätigen**: Klicken Sie auf "Ausführen"
|
||||||
|
|
||||||
|
## Funktionalität
|
||||||
|
|
||||||
|
### Automatische Zeitraumberechnung
|
||||||
|
Die Aktion berechnet automatisch den Zeitraum basierend auf der Frequenz des Reports:
|
||||||
|
|
||||||
|
- **Wöchentlich**: Letzte 7 Tage
|
||||||
|
- **Monatlich**: Letzter Monat (vom 1. des Vormonats bis heute)
|
||||||
|
- **Vierteljährlich**: Letztes Quartal (3 Monate zurück)
|
||||||
|
|
||||||
|
### Validierung und Filterung
|
||||||
|
Vor dem Versenden wird überprüft:
|
||||||
|
|
||||||
|
- ✅ **Aktivierung**: Report muss aktiv sein (`is_active = True`)
|
||||||
|
- ✅ **E-Mail-Adressen**: Mindestens eine E-Mail-Adresse muss konfiguriert sein
|
||||||
|
- ✅ **Filter**: Die konfigurierten Filter (Naturschutz-/Jagdbehörde) werden angewendet
|
||||||
|
|
||||||
|
### Rückmeldungen
|
||||||
|
Das System gibt detaillierte Rückmeldungen:
|
||||||
|
|
||||||
|
- ✅ **Erfolgreich**: Anzahl gesendeter E-Mails, Zeitraum, Patientenzahl
|
||||||
|
- ⚠️ **Übersprungen**: Grund für das Überspringen (deaktiviert, keine E-Mail-Adressen)
|
||||||
|
- ❌ **Fehler**: Detaillierte Fehlermeldungen bei Problemen
|
||||||
|
|
||||||
|
### Protokollierung
|
||||||
|
- Alle versendeten Reports werden in `ReportLog` protokolliert
|
||||||
|
- Das `last_sent` Feld des AutomaticReport wird aktualisiert
|
||||||
|
- CSV-Dateien werden gespeichert und können später heruntergeladen werden
|
||||||
|
|
||||||
|
## Technische Details
|
||||||
|
|
||||||
|
### Implementierung
|
||||||
|
- **Datei**: `/app/reports/admin.py`
|
||||||
|
- **Methode**: `send_report_now()`
|
||||||
|
- **Service**: Verwendet `ReportGenerator` aus `reports.services`
|
||||||
|
|
||||||
|
### Sicherheit
|
||||||
|
- Nur Administratoren mit entsprechenden Berechtigungen können diese Aktion ausführen
|
||||||
|
- Deaktivierte Reports werden automatisch übersprungen
|
||||||
|
- Umfassende Fehlerbehandlung verhindert Systemausfälle
|
||||||
|
|
||||||
|
## Beispiel-Ausgaben
|
||||||
|
|
||||||
|
### Erfolgreicher Versand
|
||||||
|
```
|
||||||
|
✅ Report 'Monatlicher Naturschutzbericht' erfolgreich gesendet (letzter Monat, 15 Patienten, 3 Empfänger).
|
||||||
|
✅ Zusammenfassung: 1 Report(s) erfolgreich gesendet.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Übersprungener Report
|
||||||
|
```
|
||||||
|
⚠️ Report 'Deaktivierter Report' ist deaktiviert und wurde übersprungen.
|
||||||
|
ℹ️ Alle 1 ausgewählten Reports wurden übersprungen (deaktiviert oder keine E-Mail-Adressen).
|
||||||
|
```
|
||||||
|
|
||||||
|
### Fehler beim Versand
|
||||||
|
```
|
||||||
|
❌ Fehler beim Senden von 'Fehlerhafter Report': SMTP-Server nicht erreichbar.
|
||||||
|
❌ Alle 1 Reports konnten nicht gesendet werden.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Häufige Probleme
|
||||||
|
|
||||||
|
1. **"Report ist deaktiviert"**
|
||||||
|
- Lösung: Report in der Detail-Ansicht aktivieren (`is_active = True`)
|
||||||
|
|
||||||
|
2. **"Keine E-Mail-Adressen"**
|
||||||
|
- Lösung: E-Mail-Adressen im Report konfigurieren
|
||||||
|
|
||||||
|
3. **"'Emailadress' object has no attribute 'email'"**
|
||||||
|
- Technischer Fehler: Das Emailadress-Model verwendet `email_address` statt `email`
|
||||||
|
- Lösung: Wurde in Version 1.1 behoben
|
||||||
|
|
||||||
|
4. **"SMTP-Fehler"**
|
||||||
|
- Lösung: E-Mail-Konfiguration in `settings.py` überprüfen
|
||||||
|
|
||||||
|
5. **"Keine Patienten gefunden"**
|
||||||
|
- Normal: Report wird trotzdem versendet, zeigt 0 Patienten an
|
||||||
|
|
||||||
|
### Log-Überprüfung
|
||||||
|
- Alle Versandaktivitäten werden in `/admin/reports/reportlog/` protokolliert
|
||||||
|
- Bei Fehlern die Django-Logs überprüfen
|
||||||
|
|
||||||
|
## Entwickler-Hinweise
|
||||||
|
|
||||||
|
### Anpassungen
|
||||||
|
- Zeitraumberechnung kann in der `send_report_now()` Methode angepasst werden
|
||||||
|
- Zusätzliche Validierungen können hinzugefügt werden
|
||||||
|
- E-Mail-Templates befinden sich in `/templates/reports/email/`
|
||||||
|
|
||||||
|
### Erweiterungen
|
||||||
|
- Mögliche Erweiterung: Benutzerdefinierte Zeiträume
|
||||||
|
- Mögliche Erweiterung: Vorschau vor dem Versand
|
||||||
|
- Mögliche Erweiterung: Stapelverarbeitung mit Fortschrittsanzeige
|
|
@ -2,7 +2,11 @@ from django.contrib import admin
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
from django.urls import reverse
|
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 .models import AutomaticReport, ReportLog
|
||||||
|
from .services import ReportGenerator
|
||||||
|
|
||||||
|
|
||||||
@admin.register(AutomaticReport)
|
@admin.register(AutomaticReport)
|
||||||
|
@ -19,6 +23,7 @@ class AutomaticReportAdmin(admin.ModelAdmin):
|
||||||
list_filter = ['frequency', 'is_active', 'created_at', 'include_naturschutzbehoerde', 'include_jagdbehoerde']
|
list_filter = ['frequency', 'is_active', 'created_at', 'include_naturschutzbehoerde', 'include_jagdbehoerde']
|
||||||
search_fields = ['name', 'description']
|
search_fields = ['name', 'description']
|
||||||
readonly_fields = ['created_by', 'created_at', 'updated_at']
|
readonly_fields = ['created_by', 'created_at', 'updated_at']
|
||||||
|
actions = ['send_report_now']
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, {
|
(None, {
|
||||||
|
@ -50,6 +55,117 @@ class AutomaticReportAdmin(admin.ModelAdmin):
|
||||||
return f"{count} E-Mail-Adresse(n)"
|
return f"{count} E-Mail-Adresse(n)"
|
||||||
email_count.short_description = _("E-Mail-Adressen")
|
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)
|
@admin.register(ReportLog)
|
||||||
class ReportLogAdmin(admin.ModelAdmin):
|
class ReportLogAdmin(admin.ModelAdmin):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue