admin: Aktivitäts-Verlauf unter Reports ▸ Verlauf

Chronologisches Protokoll der Systemereignisse als neue Admin-Seite
(/admin/reports/activity) mit Filter nach Ereignistyp, Zeitraum und
Suche. Erfasst ab jetzt fortlaufend:

- Registrierungen inkl. Weg (Formular, Google, Magic-Link)
- Anmeldungen inkl. Weg (Passwort, Google, Magic-Link, Impersonation)
- PM-Statuswechsel mit Ergebnis/Begründung (zentral im Status-Log-Hook;
  KI-/Scheduler-Wechsel erscheinen als „System")
- Zahlungseingänge (Rechnungsspiegelung) und Credit-Aufladungen
- Formular-Eingänge: Kontakt, Rechtsanfrage, Widerruf, Kündigung,
  Newsletter-Anmeldung (Observer auf den Modellen)

Schreiben ist Best-Effort über den ActivityLog-Service — ein
fehlgeschlagener Verlaufseintrag bricht nie den fachlichen Ablauf.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-15 16:00:58 +00:00
parent 5585a26380
commit 991af42d27
19 changed files with 720 additions and 4 deletions

View file

@ -2,6 +2,7 @@
namespace App\Services\PressRelease;
use App\Enums\ActivityType;
use App\Enums\EmailNotificationType;
use App\Enums\PressReleaseClassification;
use App\Enums\PressReleaseStatus;
@ -18,6 +19,7 @@ use App\Models\PressReleaseImage;
use App\Models\PressReleaseStatusLog;
use App\Models\User;
use App\Scopes\PortalScope;
use App\Services\ActivityLog;
use App\Services\Admin\AdminPerformanceCache;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
@ -36,6 +38,7 @@ class PressReleaseService
public function __construct(
private readonly BlacklistService $blacklist,
private readonly AdminPerformanceCache $adminCache,
private readonly ActivityLog $activityLog,
) {}
/**
@ -530,6 +533,30 @@ class PressReleaseService
'created_at' => now(),
]);
// Aktivitäts-Verlauf: ohne eingeloggten Akteur (KI-Jobs, Scheduler)
// erscheint der Wechsel als „System".
$actor = Auth::user();
$actor = $actor instanceof User ? $actor : null;
$this->activityLog->record(
ActivityType::PressReleaseStatus,
sprintf(
'PM „%s“: %s → %s%s',
$pressRelease->title,
$from?->label() ?? 'Neu',
$to->label(),
$reason ? " — {$reason}" : '',
),
user: $actor,
subject: $pressRelease,
actorLabel: $actor?->name ?? 'System',
meta: [
'from' => $from?->value,
'to' => $to->value,
'source' => $source,
],
);
$this->adminCache->forgetPressReleaseStats();
}