> */ protected $queryString = [ 'status' => ['except' => 'all'], 'channel' => ['except' => 'all'], 'page' => ['except' => 1], 'selectedTransactionId' => ['except' => null, 'as' => 'transaction'], ]; public function mount(Company $company, ?int $transaction = null): void { $this->company = $company; if ($transaction) { $this->selectedTransactionId = $this->baseQuery() ->whereKey($transaction) ->value('id'); } if (! $this->selectedTransactionId) { $this->selectedTransactionId = $this->baseQuery() ->orderByDesc('requires_review') ->orderByDesc('risk_score') ->orderByDesc('executed_at') ->value('id'); } } public function with(): array { return [ 'title' => __('Unternehmenstransaktionen'), ]; } public function selectTransaction(int $transactionId): void { $this->selectedTransactionId = $transactionId; } public function updatingStatus(): void { $this->resetPage(); } public function updatedStatus(): void { $this->refreshSelection(); } public function updatingChannel(): void { $this->resetPage(); } public function updatedChannel(): 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 Status'), Transaction::STATUS_TRUE_POSITIVE => __('Bestätigte Treffer'), Transaction::STATUS_FALSE_POSITIVE => __('Fehlalarme'), Transaction::STATUS_CLEARED => __('Freigegeben'), ]; } #[Computed] public function channelOptions(): array { $channels = $this->baseQuery() ->select('channel') ->distinct() ->orderBy('channel') ->pluck('channel') ->filter() ->values(); $options = [ 'all' => __('Alle Kanäle'), ]; foreach ($channels as $channel) { $options[$channel] = $channel; } return $options; } #[Computed] public function metrics(): array { $baseQuery = $this->baseQuery(); $totalCount = (clone $baseQuery)->count(); $totalVolume = (clone $baseQuery)->sum('amount'); $openAlertsQuery = $this->baseQuery()->where('requires_review', true); $openAlertsCount = (clone $openAlertsQuery)->count(); $openAlertsVolume = (clone $openAlertsQuery)->sum('amount'); $highRiskCount = $totalCount > 0 ? $this->baseQuery()->where('risk_score', '>=', 80)->count() : 0; $last30DaysQuery = $this->baseQuery()->where('executed_at', '>=', now()->subDays(30)); $last30DaysCount = (clone $last30DaysQuery)->count(); $last30DaysVolume = (clone $last30DaysQuery)->sum('amount'); $statusBreakdown = (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, ], ]) ->toArray(); return [ 'total_count' => $totalCount, 'total_volume' => $totalVolume, 'open_alerts' => [ 'count' => $openAlertsCount, 'amount' => $openAlertsVolume, ], 'high_risk_share' => $totalCount > 0 ? (int) round(($highRiskCount / $totalCount) * 100) : 0, 'last_30_days' => [ 'count' => $last30DaysCount, 'amount' => $last30DaysVolume, ], 'by_status' => $statusBreakdown, ]; } #[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 selectedTransaction(): ?Transaction { $transaction = $this->transactions->firstWhere('id', $this->selectedTransactionId); if (! $transaction && $this->selectedTransactionId) { $transaction = $this->baseQuery() ->with('company') ->whereKey($this->selectedTransactionId) ->first(); } return $transaction ?? $this->transactions->first(); } #[Computed] public function counterpartyHistory(): Collection { $selected = $this->selectedTransaction; if (! $selected) { return collect(); } return $this->baseQuery() ->where('counterparty', $selected->counterparty) ->orderByDesc('executed_at') ->limit(6) ->get(); } #[Computed] public function recentAlerts(): Collection { return $this->baseQuery() ->where('requires_review', true) ->orderByDesc('executed_at') ->limit(5) ->get(); } #[Computed] public function actionChecklist(): array { $selected = $this->selectedTransaction; $items = [ [ 'title' => __('KYC- und Screening-Daten abgleichen'), 'description' => __('Prüfen Sie Unternehmens- und Gegenparteidaten gegen Sanktionslisten, PEP-Register und interne Sperrlisten.'), ], [ 'title' => __('Transaktionsverlauf analysieren'), 'description' => __('Bewerten Sie Häufigkeit, Muster und Gegenparteien der letzten Monate, um ungewöhnliche Aktivitäten zu erkennen.'), ], [ 'title' => __('Vier-Augen-Prinzip sicherstellen'), 'description' => __('Organisieren Sie eine Zweitprüfung und dokumentieren Sie alle Entscheidungen revisionssicher.'), ], ]; if ($selected?->status === Transaction::STATUS_TRUE_POSITIVE) { array_unshift($items, [ 'title' => __('Verdachtsmeldung vorbereiten'), 'description' => __('Erstellen Sie den Meldeentwurf für die FIU, sammeln Sie Belege und stellen Sie eine Eskalation sicher.'), ]); } return $items; } protected function filteredQuery(): Builder { return $this->baseQuery() ->when($this->status !== 'all', fn (Builder $query) => $query->where('status', $this->status)) ->when($this->channel !== 'all', fn (Builder $query) => $query->where('channel', $this->channel)); } protected function baseQuery(): Builder { return Transaction::query()->where('company_id', $this->company->id); } }; ?> @php /** @var \Illuminate\Contracts\Pagination\LengthAwarePaginator $transactions */ $transactions = $this->transactions; /** @var \App\Models\Transaction|null $selected */ $selected = $this->selectedTransaction; $metrics = $this->metrics; $statusOptions = $this->statusOptions; $channelOptions = $this->channelOptions; $counterpartyHistory = $this->counterpartyHistory; $recentAlerts = $this->recentAlerts; $actionChecklist = $this->actionChecklist; $formatCurrency = static fn (float $value): string => number_format($value, 2, ',', '.') . ' €'; $formatAmount = static fn (float $value, string $currency): string => number_format($value, 2, ',', '.') . ' ' . $currency; $statusStyles = [ Transaction::STATUS_TRUE_POSITIVE => 'bg-gradient-to-r from-rose-500/25 via-rose-500/10 to-rose-400/20 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/20 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/20 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 => __('Ein schwerwiegender Verdacht liegt vor. Priorisieren Sie die Eskalation und bereiten Sie eine Verdachtsmeldung vor.'), Transaction::STATUS_FALSE_POSITIVE => __('Alarm konnte entkräftet werden. Dokumentieren Sie die Begründung und schließen Sie den Fall.'), Transaction::STATUS_CLEARED => __('Keine Auffälligkeiten. Dokumentieren und archivieren Sie den Prüfschritt.'), ]; @endphp
{{ __('Zurück zur Transaktionsprüfung') }} {{ $company->legal_name }} {{ $company->summary }}
{{ __('Ticker') }} {{ $company->ticker }} {{ $company->sector }} {{ __('KYC-Risiko') }} {{ \Illuminate\Support\Str::title($company->kyc_risk_level) }}

{{ __('Transaktionen gesamt') }}

{{ $metrics['total_count'] }}

{{ __('Volumen') }} {{ $formatCurrency($metrics['total_volume']) }}

{{ __('Offene Alerts') }}

{{ $metrics['open_alerts']['count'] }}

{{ __('Volumen') }} {{ $formatCurrency($metrics['open_alerts']['amount']) }}

{{ __('High-Risk-Anteil') }}

{{ $metrics['high_risk_share'] }}%

{{ __('Letzte 30 Tage') }} {{ $metrics['last_30_days']['count'] }}

{{ __('Transaktionsliste') }}

{{ __('Filtern Sie nach Status und Kanal, um relevante Vorgänge für dieses Unternehmen zu analysieren.') }}

{{ $transactions->total() }} {{ __('Ergebnisse') }}
@foreach ($statusOptions as $value => $label) @endforeach @foreach ($channelOptions as $value => $label) @endforeach
@forelse ($transactions as $transaction) @empty
{{ __('Keine Transaktionen für die aktuellen Filter gefunden.') }}
@endforelse
@if ($transactions->hasPages())
{{ __('Seite') }} {{ $transactions->currentPage() }} {{ __('von') }} {{ $transactions->lastPage() }}
@endif

{{ __('Neueste Alerts') }}

    @forelse ($recentAlerts as $alert)
  • {{ $alert->counterparty }}

    {{ $alert->executed_at?->format('d.m.Y H:i') }} • {{ $alert->channel }}

    {{ $alert->statusLabel() }}
  • @empty
  • {{ __('Aktuell liegen keine offenen Alerts vor.') }}
  • @endforelse
@if ($selected)
{{ __('Case ID') }} {{ $selected->id }}

{{ $selected->counterparty }} — {{ $formatAmount($selected->amount, $selected->currency) }}

{{ __('Ausgeführt am') }} {{ $selected->executed_at?->format('d.m.Y, H:i') }} • {{ $selected->channel }}

@php($badgeStyle = $statusStyles[$selected->status] ?? 'bg-zinc-500/10 text-zinc-600 border border-zinc-500/20') {{ $selected->statusLabel() }} {{ __('Risikowert') }} {{ $selected->risk_score }}

{{ __('Gegenpartei') }}

{{ $selected->counterparty }}

{{ $selected->counterparty_country }}

{{ __('Referenz') }}

{{ $selected->reference }}

{{ $selected->flagged_by }}

{{ __('Flagging-Grund') }}

{{ $selected->flagged_reason }}

{{ __('Empfohlene Maßnahme') }}

{{ $statusCopy[$selected->status] ?? __('Review abschließen und Audit-Trail ergänzen.') }}

@if (! empty($selected->signals))

{{ __('Detektionssignale') }}

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

{{ __('Fallleitlinie') }}

{{ __('Führen Sie eine ganzheitliche Bewertung durch: prüfen Sie Geschäftsbeziehung, Transaktionshistorie und Monitoring-Regeln. Stellen Sie sicher, dass alle Entscheidungswege und Maßnahmen dokumentiert und für Audits nachvollziehbar sind.') }}

{{ __('Aktions-Checkliste') }}

    @foreach ($actionChecklist as $index => $item)
  1. {{ $index + 1 }}

    {{ $item['title'] }}

    {{ $item['description'] }}

  2. @endforeach

{{ __('Historie mit dieser Gegenpartei') }}

@forelse ($counterpartyHistory as $history)

{{ $history->executed_at?->format('d.m.Y H:i') }}

{{ $history->channel }} • {{ $history->reference }}

{{ $formatAmount($history->amount, $history->currency) }} {{ __('Risiko') }} {{ $history->risk_score }}
@empty
{{ __('Keine weiteren Transaktionen mit dieser Gegenpartei gefunden.') }}
@endforelse
@else
{{ __('Wählen Sie links eine Transaktion aus, um die vollständige Fallansicht zu öffnen.') }}
@endif