$event */ public function __construct( private readonly Finding $finding, private readonly Tenant $tenant, private readonly array $event, ) {} /** * @return array */ public function via(object $notifiable): array { return ['database']; } /** * @return array */ public function toDatabase(object $notifiable): array { $message = FilamentNotification::make() ->title($this->title()) ->body($this->body()) ->actions([ Action::make('open_finding') ->label('Open finding') ->url(FindingResource::getUrl( 'view', ['record' => $this->finding], panel: 'tenant', tenant: $this->tenant, )), ]) ->getDatabaseMessage(); $message['finding_event'] = [ 'event_type' => (string) ($this->event['event_type'] ?? ''), 'finding_id' => (int) $this->finding->getKey(), 'recipient_reason' => data_get($this->event, 'metadata.recipient_reason'), 'fingerprint_key' => (string) ($this->event['fingerprint_key'] ?? ''), 'due_cycle_key' => $this->event['due_cycle_key'] ?? null, 'tenant_name' => $this->tenant->getFilamentName(), 'severity' => (string) ($this->event['severity'] ?? ''), ]; return $message; } private function title(): string { $title = trim((string) ($this->event['title'] ?? 'Finding update')); return $title !== '' ? $title : 'Finding update'; } private function body(): string { $body = trim((string) ($this->event['body'] ?? 'A finding needs follow-up.')); $recipientReason = $this->recipientReasonCopy((string) data_get($this->event, 'metadata.recipient_reason', '')); return trim($body.' '.$recipientReason); } private function recipientReasonCopy(string $reason): string { return match ($reason) { 'new_assignee' => 'You are the new assignee.', 'current_assignee' => 'You are the current assignee.', 'current_owner' => 'You are the accountable owner.', default => '', }; } }