['except' => ''], 'status' => ['except' => 'all'], 'page' => ['except' => 1], ]; public function mount(): void { $this->selectedTransactionId = Transaction::query() ->orderByDesc('risk_score') ->orderByDesc('executed_at') ->value('id'); } public function with(): array { return [ 'title' => __('Transaktionsprüfung'), ]; } public function selectTransaction(int $transactionId): void { $this->selectedTransactionId = $transactionId; } public function updatingSearch(): void { $this->resetPage(); } public function updatedSearch(): void { $this->refreshSelection(); } public function updatingStatus(): void { $this->resetPage(); } public function updatedStatus(): void { $this->refreshSelection(); } public function updatedPage(): void { $this->refreshSelection(); } protected function refreshSelection(): void { $first = $this->filteredQuery() ->orderByDesc('requires_review') ->orderByDesc('risk_score') ->orderByDesc('executed_at') ->forPage($this->getPage(), $this->perPage) ->first(); $this->selectedTransactionId = $first?->id; } #[Computed] public function statusOptions(): array { return [ 'all' => 'Alle Prüfaufträge', Transaction::STATUS_TRUE_POSITIVE => 'Bestätigte Treffer', Transaction::STATUS_FALSE_POSITIVE => 'Fehlalarme', Transaction::STATUS_CLEARED => 'Freigegebene Vorgänge', ]; } #[Computed] public function transactions(): LengthAwarePaginator { return $this->filteredQuery() ->with('company') ->orderByDesc('requires_review') ->orderByDesc('risk_score') ->orderByDesc('executed_at') ->paginate($this->perPage); } #[Computed] public function metrics(): array { $baseQuery = $this->filteredQuery(); /** @var Collection $grouped */ $grouped = (clone $baseQuery) ->selectRaw('status, COUNT(*) AS total, COALESCE(SUM(amount), 0) AS volume') ->groupBy('status') ->get() ->mapWithKeys(fn ($row) => [ $row->status => [ 'count' => (int) $row->total, 'amount' => (float) $row->volume, ], ]); return [ 'by_status' => $grouped->toArray(), 'total' => [ 'count' => $grouped->sum('count'), 'amount' => $grouped->sum('amount'), ], ]; } #[Computed] public function selectedTransaction(): ?Transaction { $transaction = $this->transactions->firstWhere('id', $this->selectedTransactionId); if (! $transaction && $this->selectedTransactionId) { $transaction = Transaction::query() ->with('company') ->find($this->selectedTransactionId); } return $transaction ?? $this->transactions->first(); } protected function filteredQuery(): Builder { $search = trim($this->search); return Transaction::query() ->when($this->status !== 'all', fn (Builder $query) => $query->where('status', $this->status)) ->when($search !== '', function (Builder $query) use ($search) { $like = '%' . $search . '%'; $query->where(function (Builder $inner) use ($like) { $inner->where('reference', 'like', $like) ->orWhere('counterparty', 'like', $like) ->orWhereHas('company', function (Builder $company) use ($like) { $company->where('name', 'like', $like) ->orWhere('legal_name', 'like', $like) ->orWhere('ticker', 'like', $like); }); }); }); } }; ?> @php /** @var \Illuminate\Contracts\Pagination\LengthAwarePaginator $transactions */ $transactions = $this->transactions; /** @var \App\Models\Transaction|null $selected */ $selected = $this->selectedTransaction; $metrics = $this->metrics; $byStatus = collect($metrics['by_status']); $resolveMetrics = static fn (string $status): array => $byStatus->get($status, ['count' => 0, 'amount' => 0.0]); $formatAmount = static fn (float $value): string => number_format($value, 2, ',', '.') . ' €'; $confirmed = $resolveMetrics(Transaction::STATUS_TRUE_POSITIVE); $falseAlarm = $resolveMetrics(Transaction::STATUS_FALSE_POSITIVE); $cleared = $resolveMetrics(Transaction::STATUS_CLEARED); $total = $metrics['total']; $statusStyles = [ Transaction::STATUS_TRUE_POSITIVE => 'bg-gradient-to-r from-rose-500/25 via-rose-500/10 to-rose-400/25 text-rose-700 dark:text-rose-200 border border-rose-500/30 shadow-[0_0_25px_-14px_rgba(244,63,94,0.85)]', Transaction::STATUS_FALSE_POSITIVE => 'bg-gradient-to-r from-amber-400/25 via-amber-400/10 to-amber-300/25 text-amber-700 dark:text-amber-200 border border-amber-400/30 shadow-[0_0_25px_-14px_rgba(251,191,36,0.85)]', Transaction::STATUS_CLEARED => 'bg-gradient-to-r from-emerald-400/25 via-emerald-400/10 to-emerald-300/25 text-emerald-700 dark:text-emerald-200 border border-emerald-400/30 shadow-[0_0_25px_-14px_rgba(52,211,153,0.85)]', ]; $statusCopy = [ Transaction::STATUS_TRUE_POSITIVE => 'Sofortige Sonderprüfung einleiten und Ermittlungsakte anlegen.', Transaction::STATUS_FALSE_POSITIVE => 'Anomalie begründen, Dokumentation ergänzen und Alarm schließen.', Transaction::STATUS_CLEARED => 'Review-Ergebnis dokumentieren und Kontrollnachweis archivieren.', ]; $statusLegend = [ Transaction::STATUS_TRUE_POSITIVE => [ 'title' => 'Bestätigter Treffer', 'description' => 'Ermittlungsindikatoren bestätigen einen hinreichenden Verdacht. Fallverantwortliche Person informieren, Belege sichern und Maßnahmenplan starten.', 'accent' => 'text-rose-500 dark:text-rose-300', ], Transaction::STATUS_FALSE_POSITIVE => [ 'title' => 'Fehlalarm', 'description' => 'Auslösung plausibel widerlegt (z. B. KYC-Daten, Geschäftslogik). Entscheidungsgrund dokumentieren und Regeloptimierung anstoßen.', 'accent' => 'text-amber-500 dark:text-amber-200', ], Transaction::STATUS_CLEARED => [ 'title' => 'Freigegeben', 'description' => 'Keine verdächtigen Auffälligkeiten. Abschluss mit Vier-Augen-Freigabe und revisionssicherer Ablage des Prüfpfads.', 'accent' => 'text-emerald-500 dark:text-emerald-300', ], ]; $riskExplanation = 'Der Risikowert (0–100) fasst Monitoring-Regeln, KYC-Risiken, Negativmeldungen sowie Verhaltens- und Geodaten zu einer Priorität zusammen. Werte über 80 kennzeichnen Sofortmaßnahmen, 50–79 markieren erhöhte Aufmerksamkeit, alles darunter gilt als Routineprüfung.'; @endphp

AFC-Kontrollzentrum

Finanzkriminalitäts-Workbench

Überwachen Sie verdächtige Transaktionen im DAX-Portfolio, priorisieren Sie Alarme und orchestrieren Sie das manuelle Review im Vier-Augen-Prozess.

Gesamtfälle

{{ $total['count'] }}

Volumen: {{ $formatAmount($total['amount']) }}

Bestätigte Treffer

{{ $confirmed['count'] }}

Volumen: {{ $formatAmount($confirmed['amount']) }}

Fehlalarme

{{ $falseAlarm['count'] }}

Volumen: {{ $formatAmount($falseAlarm['amount']) }}

Freigegeben

{{ $cleared['count'] }}

Volumen: {{ $formatAmount($cleared['amount']) }}

@foreach ($statusLegend as $key => $legend)

{{ $legend['title'] }}

{{ $legend['description'] }}

@endforeach

Aktive Prüfwarteschlange

Alle untenstehenden Meldungen benötigen eine finale Analystenentscheidung.

@foreach ($this->statusOptions as $value => $label) @endforeach
@forelse ($transactions as $transaction) @php $selectedState = $transaction->id === $this->selectedTransactionId; @endphp @empty
Keine Transaktionen für die aktuellen Filterkriterien gefunden. Bitte Seed-Daten neu laden oder Filter anpassen.
@endforelse
@if ($transactions->hasPages())
Seite {{ $transactions->currentPage() }} von {{ $transactions->lastPage() }}
@endif
@if ($selected)

{{ $selected->company->legal_name }}

{{ $selected->company->summary }}

Prüfung erforderlich @php($detailStatusStyle = $statusStyles[$selected->status] ?? 'bg-zinc-500/10 text-zinc-600 border border-zinc-500/20') Status: {{ $selected->statusLabel() }} {{ number_format($selected->amount, 2, ',', '.') }} {{ $selected->currency }}
Risikoscore {{ $selected->risk_score }} {{ $selected->executed_at?->format('d.m.Y, H:i') }}
Gegenpartei
{{ $selected->counterparty }}
{{ $selected->counterparty_country }}
Zahlungskanal & Referenz
{{ $selected->channel }}
{{ $selected->reference }}
Flagging-Engine
{{ $selected->flagged_by }}
{{ $selected->flagged_reason }}
@if (! empty($selected->signals))

Detektionssignale

@foreach ($selected->signals as $signal) {{ data_get($signal, 'type') }} · {{ data_get($signal, 'value') }} @endforeach
@endif

Empfohlene Maßnahme

{{ $statusCopy[$selected->status] ?? 'Review abschließen und vollständigen Audit-Trail dokumentieren.' }}

{{ __('Fallansicht maximieren') }}

Unternehmensprofil

  • Rechtlicher Name {{ $selected->company->legal_name }}
  • Ticker {{ $selected->company->ticker }}
  • Sektor {{ $selected->company->sector }}
  • Hauptsitz {{ $selected->company->headquarters }}
  • Land {{ $selected->company->country }}
  • KYC-Risikostufe {{ Str::title($selected->company->kyc_risk_level) }}
@else
Wählen Sie links einen Alarm aus, um den vollständigen Prüfkontext einzusehen.
@endif