hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']); } public function mount(): void { $user = Auth::user(); if ($user instanceof User) { $reqStabile = request()->integer('stabile_id'); if ($reqStabile > 0) { $this->selectedStabileId = $reqStabile; } else { $this->selectedStabileId = StabileContext::resolveActiveStabileId($user); } } } public function getStabiliOptionsProperty(): array { $user = Auth::user(); if (! $user instanceof User) { return []; } return StabileContext::accessibleStabili($user) ->mapWithKeys(fn(Stabile $s) => [(int) $s->id => trim((string) ($s->codice_stabile . ' - ' . $s->denominazione))]) ->all(); } public function selectFolder(string $folder): void { $this->currentFolder = $folder; $this->selectedMessageId = null; } public function selectMessage(int $messageId): void { $this->selectedMessageId = $messageId; $msg = CommunicationMessage::find($messageId); if ($msg && $msg->status === 'received') { $msg->update(['status' => 'read']); } } public function closeMessage(): void { $this->selectedMessageId = null; } public function toggleStar(int $messageId): void { $msg = CommunicationMessage::find($messageId); if ($msg) { $meta = is_array($msg->metadata) ? $msg->metadata : []; $meta['is_starred'] = ! ($meta['is_starred'] ?? false); $msg->metadata = $meta; $msg->save(); } } public function deleteMessage(int $messageId): void { $msg = CommunicationMessage::find($messageId); if ($msg) { $msg->delete(); if ($this->selectedMessageId === $messageId) { $this->selectedMessageId = null; } Notification::make()->title('Messaggio PEC eliminato')->success()->send(); } } public function createTicketFromMessage(int $messageId): void { $msg = CommunicationMessage::find($messageId); if (! $msg) { return; } if ($msg->ticket_id) { Notification::make()->title('Ticket già presente')->warning()->send(); return; } $userId = Auth::id() ?: 1; $ticket = Ticket::create([ 'stabile_id' => $msg->stabile_id, 'unita_immobiliare_id' => $msg->metadata['unita_immobiliare_id'] ?? null, 'aperto_da_user_id' => $userId, 'titolo' => Str::limit($msg->metadata['subject'] ?? 'Ticket da PEC', 180, '...'), 'descrizione' => Str::limit($msg->message_text, 1000), 'priorita' => 'Alta', 'stato' => 'Aperto', 'data_apertura' => now(), ]); $msg->update(['ticket_id' => $ticket->id]); Notification::make() ->title('Ticket PEC #' . $ticket->id . ' creato') ->body('Il ticket è stato associato al messaggio e allo stabile con priorità ALTA.') ->success() ->send(); } public function syncNow(): void { $user = Auth::user(); if (! $user instanceof User) { return; } $service = app(ImapMailboxService::class); $stabili = $this->selectedStabileId ? Stabile::where('id', $this->selectedStabileId)->get() : StabileContext::accessibleStabili($user); $totImported = 0; foreach ($stabili as $stabile) { $config = (array) ($stabile->configurazione_avanzata ?? []); $posta = (array) ($config['posta'] ?? []); $caselle = array_values(array_filter((array) ($posta['caselle'] ?? []), 'is_array')); foreach ($caselle as $mailbox) { if (empty($mailbox['enabled'])) { continue; } $mTipo = strtolower((string) ($mailbox['tipo'] ?? 'imap')); if ($mTipo !== 'pec') { continue; } if (! empty($mailbox['host']) && ! empty($mailbox['username'])) { $res = $service->fetchMailbox($stabile, $mailbox, 20); $totImported += (int) ($res['imported'] ?? 0); } } } Notification::make() ->title('Sincronizzazione PEC completata') ->body($totImported > 0 ? "Importati {$totImported} nuovi messaggi PEC (.EML)" : "Nessun nuovo messaggio PEC trovato.") ->success() ->send(); } public function openCompose(): void { $this->isComposing = true; $this->composeTo = ''; $this->composeCc = ''; $this->composeSubject = ''; $this->composeBody = ''; $this->composeStabileId = $this->selectedStabileId; } public function closeCompose(): void { $this->isComposing = false; } public function sendMessage(): void { if (trim($this->composeTo) === '') { Notification::make()->title('Inserisci almeno un destinatario PEC')->warning()->send(); return; } $stabileId = $this->composeStabileId ?: $this->selectedStabileId; if (! $stabileId) { $user = Auth::user(); $stabileId = $user instanceof User ? StabileContext::resolveActiveStabileId($user) : null; } CommunicationMessage::create([ 'channel' => 'pec', 'direction' => 'outbound', 'stabile_id' => $stabileId, 'sender_name' => Auth::user()->name ?? 'Amministrazione Condominiale (PEC)', 'message_text' => $this->composeBody, 'status' => 'sent', 'received_at' => now(), 'metadata' => [ 'subject' => $this->composeSubject ?: '(Nessun oggetto)', 'to' => [['email' => $this->composeTo, 'name' => '']], 'cc' => $this->composeCc ? [['email' => $this->composeCc, 'name' => '']] : [], 'body_html' => nl2br(e($this->composeBody)), 'is_pec' => true, ], ]); $this->isComposing = false; Notification::make()->title('Messaggio PEC registrato e pronto per l\'inoltro certificato')->success()->send(); } public function previewAttachment(string $filename, string $path, string $contentType): void { $this->activeAttachment = [ 'filename' => $filename, 'path' => $path, 'content_type' => $contentType, 'exists' => file_exists($path), ]; $this->showAttachmentModal = true; } public function closeAttachmentModal(): void { $this->showAttachmentModal = false; $this->activeAttachment = null; } public function getMessagesProperty() { $user = Auth::user(); $allowedStabileIds = $user instanceof User ? StabileContext::accessibleStabili($user)->pluck('id')->toArray() : []; $query = CommunicationMessage::with(['stabile', 'ticket']) ->whereIn('stabile_id', $allowedStabileIds) ->where('channel', 'pec'); if ($this->selectedStabileId) { $query->where('stabile_id', $this->selectedStabileId); } if ($this->currentFolder === 'sent') { $query->where('direction', 'outbound'); } elseif ($this->currentFolder === 'starred') { $query->where('metadata->is_starred', true); } elseif ($this->currentFolder === 'attachments') { $query->whereNotNull('attachments')->where('attachments', '!=', '[]'); } else { $query->where('direction', 'inbound'); } if (trim($this->searchQuery) !== '') { $like = '%' . trim($this->searchQuery) . '%'; $query->where(function ($q) use ($like) { $q->where('sender_name', 'like', $like) ->orWhere('message_text', 'like', $like) ->orWhere('metadata->subject', 'like', $like) ->orWhere('metadata->sender_email', 'like', $like); }); } return $query->orderByDesc('received_at')->paginate(25); } public function getSelectedMessageProperty(): ?CommunicationMessage { if (! $this->selectedMessageId) { return null; } return CommunicationMessage::with(['stabile', 'ticket'])->find($this->selectedMessageId); } public function getFolderCountsProperty(): array { $user = Auth::user(); $allowedStabileIds = $user instanceof User ? StabileContext::accessibleStabili($user)->pluck('id')->toArray() : []; $base = CommunicationMessage::whereIn('stabile_id', $allowedStabileIds)->where('channel', 'pec'); if ($this->selectedStabileId) { $base->where('stabile_id', $this->selectedStabileId); } return [ 'inbox' => (clone $base)->where('direction', 'inbound')->count(), 'unread' => (clone $base)->where('direction', 'inbound')->where('status', 'received')->count(), 'sent' => (clone $base)->where('direction', 'outbound')->count(), 'starred' => (clone $base)->where('metadata->is_starred', true)->count(), 'attachments' => (clone $base)->whereNotNull('attachments')->where('attachments', '!=', '[]')->count(), ]; } }