From 2b7dcb6ab71ef7e84ae9a075a801b6a68ad58822 Mon Sep 17 00:00:00 2001 From: michele Date: Thu, 12 Mar 2026 08:25:34 +0000 Subject: [PATCH] feat(ticket-postit): supplier progress, timestamped notes, reopen flow --- .../Pages/Strumenti/PostItGestione.php | 63 +++++++++++++++++++ .../Pages/Supporto/TicketGestione.php | 50 ++++++++++++--- .../strumenti/post-it-gestione.blade.php | 8 +++ .../pages/supporto/ticket-gestione.blade.php | 15 ++++- 4 files changed, 127 insertions(+), 9 deletions(-) diff --git a/app/Filament/Pages/Strumenti/PostItGestione.php b/app/Filament/Pages/Strumenti/PostItGestione.php index f60b129..0fd24bd 100644 --- a/app/Filament/Pages/Strumenti/PostItGestione.php +++ b/app/Filament/Pages/Strumenti/PostItGestione.php @@ -30,6 +30,9 @@ class PostItGestione extends Page protected string $view = 'filament.pages.strumenti.post-it-gestione'; + /** @var array */ + public array $riaperturaNote = []; + public function getPostItInserimentoUrl(): string { return PostIt::getUrl(panel: 'admin-filament'); @@ -106,6 +109,66 @@ public function chiudiPostIt(int $postItId): void ->send(); } + public function riapriPostIt(int $postItId): void + { + if (! $this->isPostItTableReady()) { + return; + } + + $postIt = ChiamataPostIt::query()->find($postItId); + if (! $postIt) { + return; + } + + $noteInput = trim((string) ($this->riaperturaNote[$postItId] ?? '')); + $stamp = now()->format('d/m/Y H:i'); + $noteLine = $noteInput !== '' + ? '[' . $stamp . '] Riapertura: ' . $noteInput + : '[' . $stamp . '] Riapertura da gestione Post-it'; + + $existing = trim((string) ($postIt->nota ?? '')); + $postIt->nota = $existing !== '' ? ($existing . "\n" . $noteLine) : $noteLine; + $postIt->stato = $postIt->ticket_id ? 'ticket' : 'post_it'; + + if (Schema::hasColumn('chiamate_post_it', 'chiusa_il')) { + $postIt->chiusa_il = null; + } + + $postIt->save(); + + if ($postIt->ticket_id) { + $ticket = Ticket::query()->find((int) $postIt->ticket_id); + if ($ticket && in_array((string) $ticket->stato, ['Chiuso', 'Risolto'], true)) { + $ticket->stato = 'Preso in Carico'; + + if (Schema::hasColumn('tickets', 'data_chiusura_effettiva')) { + $ticket->data_chiusura_effettiva = null; + } + + if (Schema::hasColumn('tickets', 'data_risoluzione_effettiva')) { + $ticket->data_risoluzione_effettiva = null; + } + + $ticket->save(); + + if (method_exists($ticket, 'messages') && Schema::hasTable('ticket_messages')) { + $ticket->messages()->create([ + 'user_id' => Auth::id(), + 'messaggio' => $noteLine, + ]); + } + } + } + + unset($this->riaperturaNote[$postItId]); + + Notification::make() + ->title('Post-it riaperto') + ->body('Riapertura completata con nota di tracciamento.') + ->success() + ->send(); + } + public function getRecentiProperty() { if (! $this->isPostItTableReady()) { diff --git a/app/Filament/Pages/Supporto/TicketGestione.php b/app/Filament/Pages/Supporto/TicketGestione.php index 7047bc4..77b6b0a 100644 --- a/app/Filament/Pages/Supporto/TicketGestione.php +++ b/app/Filament/Pages/Supporto/TicketGestione.php @@ -281,9 +281,10 @@ public function aggiungiNotaInterna(): void 'notaInterna' => ['required', 'string', 'max:5000'], ]); + $stamp = now()->format('d/m/Y H:i'); $ticket->messages()->create([ 'user_id' => Auth::id(), - 'messaggio' => trim((string) $this->notaInterna), + 'messaggio' => '[' . $stamp . '] ' . trim((string) $this->notaInterna), ]); $this->notaInterna = null; @@ -417,24 +418,56 @@ private function refreshFornitoriAttiviRows(): void $ticketApertiStati = ['Aperto', 'Preso in Carico', 'In Lavorazione', 'In Attesa Approvazione', 'In Attesa Ricambi']; - $assignedByFornitore = Ticket::query() + $assignedTickets = Ticket::query() ->where('stabile_id', $stabileId) ->whereIn('stato', $ticketApertiStati) ->whereNotNull('assegnato_a_fornitore_id') - ->selectRaw('assegnato_a_fornitore_id as fornitore_id, COUNT(*) as ticket_attivi') + ->get(['id', 'assegnato_a_fornitore_id', 'stato', 'updated_at']); + + $assignedByFornitore = $assignedTickets ->groupBy('assegnato_a_fornitore_id') - ->pluck('ticket_attivi', 'fornitore_id'); + ->map(fn($rows) => $rows->count()); + + $ticketSummaries = $assignedTickets + ->groupBy('assegnato_a_fornitore_id') + ->map(function ($rows) { + return $rows->sortByDesc('updated_at')->take(6)->map(function ($ticket): string { + return '#' . ((int) $ticket->id) . ' (' . (string) $ticket->stato . ')'; + })->values()->all(); + }); $openInterventiByFornitore = collect(); + $interventoStatiByFornitore = collect(); + $lastInterventoAtByFornitore = collect(); if (Schema::hasTable('ticket_interventi')) { - $openInterventiByFornitore = TicketIntervento::query() + $openInterventi = TicketIntervento::query() ->whereIn('stato', ['assegnato', 'in_corso', 'in_verifica']) ->whereHas('ticket', function ($q) use ($stabileId, $ticketApertiStati): void { $q->where('stabile_id', $stabileId)->whereIn('stato', $ticketApertiStati); }) - ->selectRaw('fornitore_id, COUNT(*) as interventi_aperti') + ->orderByDesc('updated_at') + ->get(['fornitore_id', 'stato', 'updated_at']); + + $openInterventiByFornitore = $openInterventi ->groupBy('fornitore_id') - ->pluck('interventi_aperti', 'fornitore_id'); + ->map(fn($rows) => $rows->count()); + + $interventoStatiByFornitore = $openInterventi + ->groupBy('fornitore_id') + ->map(function ($rows): string { + return $rows->pluck('stato') + ->map(fn($stato) => str_replace('_', ' ', (string) $stato)) + ->unique() + ->take(3) + ->implode(', '); + }); + + $lastInterventoAtByFornitore = $openInterventi + ->groupBy('fornitore_id') + ->map(function ($rows): ?string { + $last = $rows->sortByDesc('updated_at')->first(); + return $last && $last->updated_at ? $last->updated_at->format('d/m/Y H:i') : null; + }); } $fornitoriIds = collect($assignedByFornitore->keys()) @@ -458,6 +491,9 @@ private function refreshFornitoriAttiviRows(): void 'telefono' => (string) ($fornitore->telefono ?: $fornitore->cellulare), 'ticket_attivi' => (int) ($assignedByFornitore->get((string) $fornitore->id) ?? $assignedByFornitore->get((int) $fornitore->id) ?? 0), 'interventi_aperti' => (int) ($openInterventiByFornitore->get((string) $fornitore->id) ?? $openInterventiByFornitore->get((int) $fornitore->id) ?? 0), + 'ticket_focus' => (array) ($ticketSummaries->get((string) $fornitore->id) ?? $ticketSummaries->get((int) $fornitore->id) ?? []), + 'intervento_stati' => (string) ($interventoStatiByFornitore->get((string) $fornitore->id) ?? $interventoStatiByFornitore->get((int) $fornitore->id) ?? ''), + 'ultimo_aggiornamento' => (string) ($lastInterventoAtByFornitore->get((string) $fornitore->id) ?? $lastInterventoAtByFornitore->get((int) $fornitore->id) ?? ''), ]; } diff --git a/resources/views/filament/pages/strumenti/post-it-gestione.blade.php b/resources/views/filament/pages/strumenti/post-it-gestione.blade.php index 4ea2917..1d9230c 100644 --- a/resources/views/filament/pages/strumenti/post-it-gestione.blade.php +++ b/resources/views/filament/pages/strumenti/post-it-gestione.blade.php @@ -55,6 +55,14 @@ Chiudi @endif + @php($ticketClosed = $riga->ticket && in_array((string) $riga->ticket->stato, ['Chiuso', 'Risolto'], true)) + @if($riga->stato === 'chiusa' || $ticketClosed) +
+ + Riapri post-it/ticket +
+ @endif + @if($riga->ticket_id) Apri Ticket (#{{ $riga->ticket_id }}) @endif diff --git a/resources/views/filament/pages/supporto/ticket-gestione.blade.php b/resources/views/filament/pages/supporto/ticket-gestione.blade.php index 975ff13..a03de2f 100644 --- a/resources/views/filament/pages/supporto/ticket-gestione.blade.php +++ b/resources/views/filament/pages/supporto/ticket-gestione.blade.php @@ -89,7 +89,7 @@
Fornitori attivi su ticket aperti
-
Elenco dinamico dei fornitori che stanno gestendo almeno un ticket/intervento aperto nello stabile attivo.
+
Mostra solo fornitori con ticket/interventi in corso, con stato operativo e ultimo aggiornamento.
@@ -99,6 +99,7 @@ + @@ -109,6 +110,15 @@ + @empty - + @endforelse @@ -170,6 +180,7 @@
Nota interna
+
Puoi aggiungere piu note: ogni nota viene salvata con data/ora automatica.
Contatti Ticket attivi Interventi apertiCome procede Azioni
{{ $f['email'] ?: '-' }}
{{ $f['telefono'] ?: '-' }}
{{ (int) $f['ticket_attivi'] }} {{ (int) $f['interventi_aperti'] }} +
+
Stati intervento: {{ $f['intervento_stati'] ?: 'N/D' }}
+
Ultimo aggiornamento: {{ $f['ultimo_aggiornamento'] ?: '-' }}
+ @if(!empty($f['ticket_focus'])) +
{{ implode(', ', $f['ticket_focus']) }}
+ @endif +
+
Scheda operativa @@ -118,7 +128,7 @@
Nessun fornitore attivo su ticket aperti.Nessun fornitore attivo su ticket aperti.