281 lines
8.5 KiB
PHP
281 lines
8.5 KiB
PHP
<?php
|
|
namespace App\Filament\Pages\Supporto;
|
|
|
|
use App\Models\Fornitore;
|
|
use App\Models\Ticket;
|
|
use App\Models\TicketAttachment;
|
|
use App\Models\TicketIntervento;
|
|
use App\Models\User;
|
|
use App\Services\Support\TicketAttachmentUploadService;
|
|
use App\Support\StabileContext;
|
|
use BackedEnum;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Livewire\WithFileUploads;
|
|
use UnitEnum;
|
|
|
|
class TicketScheda extends Page
|
|
{
|
|
use WithFileUploads;
|
|
|
|
protected static ?string $navigationLabel = 'Ticket Scheda';
|
|
|
|
protected static ?string $title = 'Scheda Ticket';
|
|
|
|
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-ticket';
|
|
|
|
protected static UnitEnum|string|null $navigationGroup = 'Supporto';
|
|
|
|
protected static ?int $navigationSort = 27;
|
|
|
|
protected static ?string $slug = 'supporto/ticket-scheda';
|
|
|
|
protected static bool $shouldRegisterNavigation = true;
|
|
|
|
protected string $view = 'filament.pages.supporto.ticket-scheda';
|
|
|
|
public ?int $ticketId = null;
|
|
|
|
public ?string $notaInterna = null;
|
|
|
|
public ?int $fornitoreId = null;
|
|
|
|
public ?string $noteAssegnazione = null;
|
|
|
|
/** @var array<int,mixed> */
|
|
public array $nuoviAllegati = [];
|
|
|
|
public ?string $descrizioneAllegati = null;
|
|
|
|
/** @var array<int,array{id:int,nome:string}> */
|
|
public array $fornitoriOptions = [];
|
|
|
|
public static function canAccess(): bool
|
|
{
|
|
$user = Auth::user();
|
|
|
|
return $user instanceof User
|
|
&& $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']);
|
|
}
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->ticketId = (int) request()->query('ticket', 0) ?: null;
|
|
$this->redirect(
|
|
TicketGestione::getUrl(
|
|
parameters: [
|
|
'ticket' => $this->ticketId,
|
|
'tab' => 'scheda',
|
|
],
|
|
panel: 'admin-filament'
|
|
),
|
|
navigate: true
|
|
);
|
|
}
|
|
|
|
public function getTicketGestioneUrl(): string
|
|
{
|
|
return TicketGestione::getUrl(panel: 'admin-filament');
|
|
}
|
|
|
|
public function getTicketMobileUrl(): string
|
|
{
|
|
return TicketMobile::getUrl(panel: 'admin-filament');
|
|
}
|
|
|
|
public function getTicketProperty(): ?Ticket
|
|
{
|
|
if (! $this->ticketId) {
|
|
return null;
|
|
}
|
|
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
return null;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
return null;
|
|
}
|
|
|
|
return Ticket::query()
|
|
->with([
|
|
'stabile:id,denominazione',
|
|
'categoriaTicket:id,nome',
|
|
'assegnatoAFornitore:id,ragione_sociale,nome,cognome',
|
|
'attachments.user:id,name',
|
|
'messages.user:id,name',
|
|
'interventi.fornitore:id,ragione_sociale,nome,cognome',
|
|
'interventi.creatoDaUser:id,name',
|
|
])
|
|
->where('stabile_id', $stabileId)
|
|
->find($this->ticketId);
|
|
}
|
|
|
|
public function assegnaFornitore(): void
|
|
{
|
|
$ticket = $this->ticket;
|
|
if (! $ticket) {
|
|
Notification::make()->title('Ticket non trovato')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$this->validate([
|
|
'fornitoreId' => ['required', 'integer', 'exists:fornitori,id'],
|
|
'noteAssegnazione' => ['nullable', 'string', 'max:4000'],
|
|
]);
|
|
|
|
$ticket->update([
|
|
'assegnato_a_fornitore_id' => $this->fornitoreId,
|
|
'stato' => in_array($ticket->stato, ['Aperto'], true) ? 'Preso in Carico' : $ticket->stato,
|
|
]);
|
|
|
|
if (Schema::hasTable('ticket_interventi')) {
|
|
$ultimo = TicketIntervento::query()
|
|
->where('ticket_id', $ticket->id)
|
|
->where('fornitore_id', $this->fornitoreId)
|
|
->latest('id')
|
|
->first();
|
|
|
|
if (! $ultimo) {
|
|
TicketIntervento::query()->create([
|
|
'ticket_id' => $ticket->id,
|
|
'fornitore_id' => $this->fornitoreId,
|
|
'creato_da_user_id' => Auth::id(),
|
|
'stato' => 'assegnato',
|
|
'note_amministratore' => $this->noteAssegnazione,
|
|
]);
|
|
}
|
|
}
|
|
|
|
if (filled($this->noteAssegnazione)) {
|
|
$ticket->messages()->create([
|
|
'user_id' => Auth::id(),
|
|
'messaggio' => 'Assegnazione fornitore: ' . trim((string) $this->noteAssegnazione),
|
|
]);
|
|
}
|
|
|
|
Notification::make()
|
|
->title('Fornitore assegnato')
|
|
->success()
|
|
->send();
|
|
|
|
$this->noteAssegnazione = null;
|
|
}
|
|
|
|
public function aggiungiNotaInterna(): void
|
|
{
|
|
$ticket = $this->ticket;
|
|
if (! $ticket) {
|
|
Notification::make()->title('Ticket non trovato')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
$this->validate([
|
|
'notaInterna' => ['required', 'string', 'max:5000'],
|
|
]);
|
|
|
|
$ticket->messages()->create([
|
|
'user_id' => Auth::id(),
|
|
'messaggio' => trim((string) $this->notaInterna),
|
|
]);
|
|
|
|
$this->notaInterna = null;
|
|
|
|
Notification::make()
|
|
->title('Nota aggiunta')
|
|
->success()
|
|
->send();
|
|
}
|
|
|
|
public function caricaAllegati(): void
|
|
{
|
|
$ticket = $this->ticket;
|
|
if (! $ticket) {
|
|
Notification::make()->title('Ticket non trovato')->danger()->send();
|
|
return;
|
|
}
|
|
|
|
if (! Schema::hasTable('ticket_attachments')) {
|
|
Notification::make()
|
|
->title('Tabella allegati non pronta')
|
|
->danger()
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
$this->validate([
|
|
'nuoviAllegati' => ['required', 'array', 'max:8'],
|
|
'nuoviAllegati.*' => ['file', 'max:10240', 'mimes:jpg,jpeg,png,webp,pdf,doc,docx,xls,xlsx,txt'],
|
|
'descrizioneAllegati' => ['nullable', 'string', 'max:500'],
|
|
]);
|
|
|
|
$saved = 0;
|
|
foreach ($this->nuoviAllegati as $file) {
|
|
if (! is_object($file) || ! method_exists($file, 'store')) {
|
|
continue;
|
|
}
|
|
|
|
$stored = app(TicketAttachmentUploadService::class)->store($file, 'ticket-scheda/' . $ticket->id);
|
|
|
|
TicketAttachment::query()->create([
|
|
'ticket_id' => $ticket->id,
|
|
'ticket_update_id' => null,
|
|
'user_id' => Auth::id(),
|
|
'file_path' => $stored['path'],
|
|
'original_file_name' => $stored['original_name'],
|
|
'mime_type' => $stored['mime'],
|
|
'size' => $stored['size'],
|
|
'description' => $this->descrizioneAllegati ?: 'Allegato da scheda ticket',
|
|
]);
|
|
|
|
$saved++;
|
|
}
|
|
|
|
$this->nuoviAllegati = [];
|
|
$this->descrizioneAllegati = null;
|
|
|
|
Notification::make()
|
|
->title('Allegati caricati')
|
|
->body('Caricati ' . $saved . ' allegati.')
|
|
->success()
|
|
->send();
|
|
}
|
|
|
|
private function loadFornitoriOptions(): void
|
|
{
|
|
$user = Auth::user();
|
|
if (! $user instanceof User) {
|
|
$this->fornitoriOptions = [];
|
|
return;
|
|
}
|
|
|
|
$stabileId = StabileContext::resolveActiveStabileId($user);
|
|
if (! $stabileId) {
|
|
$this->fornitoriOptions = [];
|
|
return;
|
|
}
|
|
|
|
$stabile = \App\Models\Stabile::query()->find($stabileId);
|
|
$adminId = (int) ($stabile->amministratore_id ?? 0);
|
|
|
|
$query = Fornitore::query()->orderBy('ragione_sociale')->orderBy('cognome')->orderBy('nome');
|
|
if ($adminId > 0) {
|
|
$query->where(function ($q) use ($adminId): void {
|
|
$q->where('amministratore_id', $adminId)->orWhereNull('amministratore_id');
|
|
});
|
|
}
|
|
|
|
$this->fornitoriOptions = $query->limit(400)->get()->map(function (Fornitore $f): array {
|
|
$label = trim((string) ($f->ragione_sociale ?: trim(($f->nome ?? '') . ' ' . ($f->cognome ?? ''))));
|
|
return [
|
|
'id' => (int) $f->id,
|
|
'nome' => $label !== '' ? $label : ('Fornitore #' . $f->id),
|
|
];
|
|
})->all();
|
|
}
|
|
}
|