426 lines
15 KiB
PHP
426 lines
15 KiB
PHP
<?php
|
|
namespace App\Filament\Pages\Strumenti;
|
|
|
|
use App\Models\ChiamataPostIt;
|
|
use App\Models\RubricaUniversale;
|
|
use App\Models\Stabile;
|
|
use App\Models\Ticket;
|
|
use App\Models\User;
|
|
use App\Support\PhoneNumber;
|
|
use BackedEnum;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Pages\Page;
|
|
use Illuminate\Database\QueryException;
|
|
use Illuminate\Support\Collection;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use UnitEnum;
|
|
|
|
class PostIt extends Page
|
|
{
|
|
protected static ?string $title = 'Post-it';
|
|
|
|
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-document-text';
|
|
|
|
protected static ?string $slug = 'strumenti/post-it';
|
|
|
|
protected static bool $shouldRegisterNavigation = true;
|
|
|
|
protected static UnitEnum|string|null $navigationGroup = 'Strumenti';
|
|
|
|
protected static ?int $navigationSort = 10;
|
|
|
|
protected string $view = 'filament.pages.strumenti.post-it';
|
|
|
|
public ?string $telefono = null;
|
|
public ?string $nomeChiamante = null;
|
|
public ?string $ricercaChiamante = null;
|
|
public string $direzione = 'in_arrivo';
|
|
public ?string $esito = null;
|
|
public ?string $oggetto = null;
|
|
public ?string $nota = null;
|
|
public string $priorita = 'Media';
|
|
public ?int $rubricaId = null;
|
|
public ?int $stabileId = null;
|
|
|
|
public ?int $selectedSuggerimentoId = null;
|
|
|
|
/** @var \Illuminate\Support\Collection<int, RubricaUniversale> */
|
|
public $suggerimentiRubrica;
|
|
|
|
public function mount(): void
|
|
{
|
|
$this->priorita = 'Media';
|
|
$this->direzione = 'in_arrivo';
|
|
$this->suggerimentiRubrica = collect();
|
|
}
|
|
|
|
public function getGestionePostItUrl(): string
|
|
{
|
|
return PostItGestione::getUrl(panel: 'admin-filament');
|
|
}
|
|
|
|
public function getGestioneTicketUrl(): string
|
|
{
|
|
return \App\Filament\Pages\Supporto\TicketGestione::getUrl(panel: 'admin-filament');
|
|
}
|
|
|
|
public function isPostItTableReady(): bool
|
|
{
|
|
return Schema::hasTable('chiamate_post_it');
|
|
}
|
|
|
|
public function updatedRicercaChiamante(?string $value): void
|
|
{
|
|
$query = trim((string) $value);
|
|
if ($query === '') {
|
|
$this->suggerimentiRubrica = collect();
|
|
$this->selectedSuggerimentoId = null;
|
|
return;
|
|
}
|
|
|
|
$this->suggerimentiRubrica = $this->searchRubrica($query);
|
|
if ($this->selectedSuggerimentoId && ! $this->suggerimentiRubrica->contains('id', $this->selectedSuggerimentoId)) {
|
|
$this->selectedSuggerimentoId = null;
|
|
}
|
|
}
|
|
|
|
public function updatedTelefono(?string $value): void
|
|
{
|
|
$input = trim((string) $value);
|
|
if ($input === '') {
|
|
$this->rubricaId = null;
|
|
$this->stabileId = null;
|
|
return;
|
|
}
|
|
|
|
$match = $this->findRubricaByPhone($input);
|
|
if (! $match) {
|
|
return;
|
|
}
|
|
|
|
$this->rubricaId = $match->id;
|
|
$this->selectedSuggerimentoId = $match->id;
|
|
if (blank($this->nomeChiamante)) {
|
|
$this->nomeChiamante = $match->nome_completo ?: $match->ragione_sociale;
|
|
}
|
|
|
|
$stabile = Stabile::query()->where('rubrica_id', $match->id)->first();
|
|
if ($stabile) {
|
|
$this->stabileId = $stabile->id;
|
|
}
|
|
|
|
if (blank($this->ricercaChiamante)) {
|
|
$this->ricercaChiamante = $match->nome_completo ?: $match->ragione_sociale;
|
|
}
|
|
}
|
|
|
|
public function selezionaSuggerimentoRubrica(int $rubricaId): void
|
|
{
|
|
$match = $this->suggerimentiRubrica->firstWhere('id', $rubricaId);
|
|
if (! $match) {
|
|
$match = RubricaUniversale::query()->find($rubricaId);
|
|
}
|
|
|
|
if (! $match) {
|
|
return;
|
|
}
|
|
|
|
$this->selectedSuggerimentoId = (int) $match->id;
|
|
$this->rubricaId = (int) $match->id;
|
|
$this->nomeChiamante = $match->nome_completo ?: $match->ragione_sociale;
|
|
$this->telefono = $match->telefono_cellulare ?: ($match->telefono_ufficio ?: $match->telefono_casa);
|
|
$this->ricercaChiamante = $match->nome_completo ?: ($match->ragione_sociale ?: '');
|
|
|
|
$stabile = Stabile::query()->where('rubrica_id', $match->id)->first();
|
|
$this->stabileId = $stabile?->id;
|
|
|
|
$this->suggerimentiRubrica = $this->searchRubrica((string) $this->ricercaChiamante);
|
|
}
|
|
|
|
public function salvaPostIt(): void
|
|
{
|
|
if (! $this->isPostItTableReady()) {
|
|
Notification::make()
|
|
->title('Tabella chiamate non pronta')
|
|
->body('Esegui prima le migrazioni per usare il nuovo Post-it chiamate.')
|
|
->danger()
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
$this->validate([
|
|
'telefono' => ['nullable', 'string', 'max:32'],
|
|
'nomeChiamante' => ['nullable', 'string', 'max:255'],
|
|
'direzione' => ['required', 'in:in_arrivo,in_uscita,persa'],
|
|
'esito' => ['nullable', 'string', 'max:255'],
|
|
'oggetto' => ['required', 'string', 'max:255'],
|
|
'nota' => ['required', 'string'],
|
|
'priorita' => ['required', 'in:Bassa,Media,Alta,Urgente'],
|
|
'rubricaId' => ['nullable', 'integer', 'exists:rubrica_universale,id'],
|
|
'stabileId' => ['nullable', 'integer', 'exists:stabili,id'],
|
|
]);
|
|
|
|
try {
|
|
$this->createPostItRecord();
|
|
} catch (QueryException $e) {
|
|
Notification::make()
|
|
->title('Tabella chiamate non pronta')
|
|
->body('Esegui prima le migrazioni per usare il nuovo Post-it chiamate.')
|
|
->danger()
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
$this->resetFormState();
|
|
|
|
Notification::make()
|
|
->title('Post-it salvato')
|
|
->success()
|
|
->send();
|
|
}
|
|
|
|
public function salvaEConvertiInTicket(): void
|
|
{
|
|
if (! $this->isPostItTableReady()) {
|
|
$this->creaTicketDirettoDaForm();
|
|
return;
|
|
}
|
|
|
|
$this->validate([
|
|
'telefono' => ['nullable', 'string', 'max:32'],
|
|
'nomeChiamante' => ['nullable', 'string', 'max:255'],
|
|
'direzione' => ['required', 'in:in_arrivo,in_uscita,persa'],
|
|
'esito' => ['nullable', 'string', 'max:255'],
|
|
'oggetto' => ['required', 'string', 'max:255'],
|
|
'nota' => ['required', 'string'],
|
|
'priorita' => ['required', 'in:Bassa,Media,Alta,Urgente'],
|
|
'rubricaId' => ['nullable', 'integer', 'exists:rubrica_universale,id'],
|
|
'stabileId' => ['required', 'integer', 'exists:stabili,id'],
|
|
]);
|
|
|
|
try {
|
|
$postIt = $this->createPostItRecord();
|
|
} catch (QueryException) {
|
|
Notification::make()
|
|
->title('Tabella chiamate non pronta')
|
|
->body('Esegui prima le migrazioni per usare il nuovo Post-it chiamate.')
|
|
->danger()
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
$this->convertiInTicket((int) $postIt->id);
|
|
$this->resetFormState();
|
|
}
|
|
|
|
public function convertiInTicket(int $postItId): void
|
|
{
|
|
if (! $this->isPostItTableReady()) {
|
|
Notification::make()
|
|
->title('Tabella chiamate non pronta')
|
|
->body('Esegui prima le migrazioni per usare la gestione Post-it.')
|
|
->danger()
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
$postIt = ChiamataPostIt::query()->find($postItId);
|
|
if (! $postIt) {
|
|
return;
|
|
}
|
|
|
|
if ($postIt->ticket_id) {
|
|
Notification::make()->title('Gia convertito in ticket')->warning()->send();
|
|
return;
|
|
}
|
|
|
|
if (! $postIt->stabile_id) {
|
|
Notification::make()
|
|
->title('Stabile mancante')
|
|
->body('Associa prima uno stabile al Post-it per poter creare il ticket.')
|
|
->danger()
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
$ticket = Ticket::query()->create([
|
|
'stabile_id' => $postIt->stabile_id,
|
|
'aperto_da_user_id' => Auth::id(),
|
|
'titolo' => $postIt->oggetto ?: ('Chiamata da ' . ($postIt->nome_chiamante ?: 'Contatto sconosciuto')),
|
|
'descrizione' => trim(($postIt->nota ?? '') . "\n\nRiferimento chiamata: #{$postIt->id}"),
|
|
'data_apertura' => now(),
|
|
'stato' => 'Aperto',
|
|
'priorita' => $postIt->priorita,
|
|
]);
|
|
|
|
$postIt->ticket_id = $ticket->id;
|
|
$postIt->stato = 'ticket';
|
|
$postIt->save();
|
|
|
|
Notification::make()
|
|
->title('Ticket creato')
|
|
->body("Ticket #{$ticket->id} creato dal Post-it #{$postIt->id}")
|
|
->success()
|
|
->send();
|
|
}
|
|
|
|
public function chiudiPostIt(int $postItId): void
|
|
{
|
|
if (! $this->isPostItTableReady()) {
|
|
return;
|
|
}
|
|
|
|
$postIt = ChiamataPostIt::query()->find($postItId);
|
|
if (! $postIt) {
|
|
return;
|
|
}
|
|
|
|
$postIt->stato = 'chiusa';
|
|
$postIt->save();
|
|
|
|
Notification::make()
|
|
->title('Post-it chiuso')
|
|
->success()
|
|
->send();
|
|
}
|
|
|
|
public function getRecentiProperty()
|
|
{
|
|
if (! $this->isPostItTableReady()) {
|
|
return collect();
|
|
}
|
|
|
|
try {
|
|
return ChiamataPostIt::query()
|
|
->with(['rubrica', 'stabile', 'ticket', 'creatoDa'])
|
|
->orderByDesc('chiamata_il')
|
|
->limit(25)
|
|
->get();
|
|
} catch (QueryException) {
|
|
return collect();
|
|
}
|
|
}
|
|
|
|
private function creaTicketDirettoDaForm(): void
|
|
{
|
|
$this->validate([
|
|
'telefono' => ['nullable', 'string', 'max:32'],
|
|
'nomeChiamante' => ['nullable', 'string', 'max:255'],
|
|
'oggetto' => ['required', 'string', 'max:255'],
|
|
'nota' => ['required', 'string'],
|
|
'priorita' => ['required', 'in:Bassa,Media,Alta,Urgente'],
|
|
'stabileId' => ['required', 'integer', 'exists:stabili,id'],
|
|
]);
|
|
|
|
$ticket = Ticket::query()->create([
|
|
'stabile_id' => $this->stabileId,
|
|
'aperto_da_user_id' => Auth::id(),
|
|
'titolo' => $this->oggetto ?: ('Chiamata da ' . ($this->nomeChiamante ?: 'Contatto sconosciuto')),
|
|
'descrizione' => trim(($this->nota ?? '') . "\n\nOrigine: Ticket diretto da Post-it (tabella chiamate non disponibile)"),
|
|
'data_apertura' => now(),
|
|
'stato' => 'Aperto',
|
|
'priorita' => $this->priorita,
|
|
]);
|
|
|
|
Notification::make()
|
|
->title('Ticket creato senza tabella Post-it')
|
|
->body('Ticket #' . $ticket->id . ' creato. Appena pronta la tabella chiamate, potrai usare la gestione Post-it completa.')
|
|
->warning()
|
|
->send();
|
|
|
|
$this->resetFormState();
|
|
}
|
|
|
|
private function findRubricaByPhone(string $value): ?RubricaUniversale
|
|
{
|
|
$normalized = PhoneNumber::normalizeForMatch($value);
|
|
if ($normalized === '') {
|
|
return null;
|
|
}
|
|
|
|
return RubricaUniversale::query()
|
|
->where(function ($q) use ($normalized): void {
|
|
$q->where('telefono_cellulare', $normalized)
|
|
->orWhere('telefono_ufficio', $normalized)
|
|
->orWhere('telefono_casa', $normalized)
|
|
->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_cellulare, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", ['%' . preg_replace('/\D+/', '', $normalized) . '%'])
|
|
->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_ufficio, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", ['%' . preg_replace('/\D+/', '', $normalized) . '%'])
|
|
->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_casa, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", ['%' . preg_replace('/\D+/', '', $normalized) . '%']);
|
|
})
|
|
->first();
|
|
}
|
|
|
|
private function createPostItRecord(): ChiamataPostIt
|
|
{
|
|
return ChiamataPostIt::query()->create([
|
|
'telefono' => $this->telefono ? PhoneNumber::toE164Italy($this->telefono) ?? $this->telefono : null,
|
|
'nome_chiamante' => $this->nomeChiamante,
|
|
'direzione' => $this->direzione,
|
|
'esito' => $this->esito,
|
|
'oggetto' => $this->oggetto,
|
|
'nota' => $this->nota,
|
|
'priorita' => $this->priorita,
|
|
'stato' => 'post_it',
|
|
'rubrica_id' => $this->rubricaId,
|
|
'stabile_id' => $this->stabileId,
|
|
'creato_da_user_id' => Auth::id(),
|
|
'chiamata_il' => now(),
|
|
]);
|
|
}
|
|
|
|
private function resetFormState(): void
|
|
{
|
|
$this->telefono = null;
|
|
$this->nomeChiamante = null;
|
|
$this->ricercaChiamante = null;
|
|
$this->direzione = 'in_arrivo';
|
|
$this->esito = null;
|
|
$this->oggetto = null;
|
|
$this->nota = null;
|
|
$this->priorita = 'Media';
|
|
$this->rubricaId = null;
|
|
$this->stabileId = null;
|
|
$this->selectedSuggerimentoId = null;
|
|
$this->suggerimentiRubrica = collect();
|
|
}
|
|
|
|
/**
|
|
* @return Collection<int, RubricaUniversale>
|
|
*/
|
|
private function searchRubrica(string $value): Collection
|
|
{
|
|
$query = trim($value);
|
|
if ($query === '') {
|
|
return collect();
|
|
}
|
|
|
|
$digits = preg_replace('/\D+/', '', $query) ?: '';
|
|
$needleText = '%' . mb_strtolower($query) . '%';
|
|
$needleDigits = '%' . $digits . '%';
|
|
|
|
return RubricaUniversale::query()
|
|
->where(function ($q) use ($needleText, $needleDigits, $digits): void {
|
|
$q->orWhereRaw("LOWER(COALESCE(nome, '')) LIKE ?", [$needleText])
|
|
->orWhereRaw("LOWER(COALESCE(cognome, '')) LIKE ?", [$needleText])
|
|
->orWhereRaw("LOWER(COALESCE(ragione_sociale, '')) LIKE ?", [$needleText])
|
|
->orWhereRaw("LOWER(COALESCE(email, '')) LIKE ?", [$needleText]);
|
|
|
|
if ($digits !== '') {
|
|
$q->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_cellulare, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", [$needleDigits])
|
|
->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_ufficio, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", [$needleDigits])
|
|
->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_casa, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') LIKE ?", [$needleDigits]);
|
|
}
|
|
})
|
|
->limit(8)
|
|
->get();
|
|
}
|
|
|
|
public static function canAccess(): bool
|
|
{
|
|
$user = Auth::user();
|
|
return $user instanceof User
|
|
&& $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']);
|
|
}
|
|
}
|