netgescon-day0/app/Filament/Pages/Strumenti/PostItGestione.php

349 lines
11 KiB
PHP

<?php
namespace App\Filament\Pages\Strumenti;
use App\Filament\Pages\Gescon\RubricaUniversaleScheda;
use App\Models\ChiamataPostIt;
use App\Models\CommunicationMessage;
use App\Models\RubricaUniversale;
use App\Models\Ticket;
use App\Models\User;
use BackedEnum;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Schema;
use UnitEnum;
class PostItGestione extends Page
{
protected static ?string $title = 'Post-it Gestione';
protected static ?string $navigationLabel = 'Post-it Gestione';
protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-clipboard-document-list';
protected static ?string $slug = 'strumenti/post-it-gestione';
protected static bool $shouldRegisterNavigation = true;
protected static UnitEnum|string|null $navigationGroup = 'Strumenti';
protected static ?int $navigationSort = 11;
protected string $view = 'filament.pages.strumenti.post-it-gestione';
public string $activeTab = 'storico';
/** @var array<int,string> */
public array $riaperturaNote = [];
/** @var array<string, int|null> */
private array $rubricaPhoneCache = [];
public function getPostItInserimentoUrl(): string
{
return PostIt::getUrl(panel: 'admin-filament');
}
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 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()) {
return collect();
}
try {
return ChiamataPostIt::query()
->with(['rubrica', 'stabile', 'ticket', 'creatoDa'])
->orderByDesc('chiamata_il')
->limit(50)
->get();
} catch (QueryException) {
return collect();
}
}
public function getChiamateTecnicheProperty()
{
if (! Schema::hasTable('communication_messages')) {
return collect();
}
try {
return CommunicationMessage::query()
->with(['assignedUser:id,name', 'stabile:id,denominazione'])
->where('channel', 'smdr')
->latest('id')
->limit(250)
->get();
} catch (QueryException) {
return collect();
}
}
public function creaPostItDaMessaggio(int $messageId): void
{
if (! $this->isPostItTableReady()) {
Notification::make()->title('Tabella post-it non pronta')->danger()->send();
return;
}
$message = CommunicationMessage::query()->find($messageId);
if (! $message) {
return;
}
if (! empty($message->post_it_id)) {
Notification::make()->title('Post-it già associato')->warning()->send();
return;
}
$smdr = (array) data_get($message->metadata, 'smdr', []);
$line = trim((string) ($message->message_text ?? ''));
$postIt = ChiamataPostIt::query()->create([
'stabile_id' => $message->stabile_id,
'creato_da_user_id' => Auth::id(),
'telefono' => $message->phone_number,
'nome_chiamante' => 'SMDR ' . strtoupper((string) $message->direction),
'direzione' => $this->normalizePostItDirection((string) $message->direction),
'origine' => 'smdr_table',
'origine_id' => (string) $message->id,
'durata_secondi' => is_numeric($smdr['duration_seconds'] ?? null) ? (int) $smdr['duration_seconds'] : null,
'oggetto' => 'Chiamata da pannello tecnico SMDR',
'nota' => $line !== '' ? $line : 'Evento SMDR senza testo riga',
'priorita' => 'Media',
'stato' => 'post_it',
'chiamata_il' => $message->received_at ?? now(),
]);
$message->post_it_id = $postIt->id;
$message->save();
Notification::make()
->title('Post-it creato da riga tecnica')
->body('Post-it #' . $postIt->id . ' collegato al messaggio #' . $message->id)
->success()
->send();
}
private function normalizePostItDirection(string $direction): string
{
$d = strtolower(trim($direction));
if ($d === 'inbound') {
return 'in_arrivo';
}
if ($d === 'outbound' || $d === 'internal') {
return 'in_uscita';
}
return 'in_arrivo';
}
public function isPostItTableReady(): bool
{
return Schema::hasTable('chiamate_post_it');
}
public function getRubricaUrlByPhone(?string $phone): ?string
{
$rubricaId = $this->resolveRubricaIdByPhone($phone);
if (! $rubricaId) {
return null;
}
return RubricaUniversaleScheda::getUrl(['record' => $rubricaId], panel: 'admin-filament');
}
public function getRubricaNomeByPhone(?string $phone): ?string
{
$rubricaId = $this->resolveRubricaIdByPhone($phone);
if (! $rubricaId) {
return null;
}
$rubrica = RubricaUniversale::query()->find($rubricaId, ['id', 'ragione_sociale', 'nome', 'cognome']);
if (! $rubrica) {
return null;
}
$nome = trim((string) ($rubrica->ragione_sociale ?: ((string) ($rubrica->nome ?? '') . ' ' . (string) ($rubrica->cognome ?? ''))));
return $nome !== '' ? $nome : null;
}
private function resolveRubricaIdByPhone(?string $phone): ?int
{
$digits = preg_replace('/\D+/', '', (string) $phone);
if (! is_string($digits) || $digits === '') {
return null;
}
if (array_key_exists($digits, $this->rubricaPhoneCache)) {
return $this->rubricaPhoneCache[$digits];
}
$adminId = (int) (Auth::user()?->amministratore?->id ?? 0);
$query = RubricaUniversale::query();
if ($adminId > 0 && Schema::hasColumn('rubrica_universale', 'amministratore_id')) {
$query->where(function ($q) use ($adminId): void {
$q->where('amministratore_id', $adminId)
->orWhereNull('amministratore_id');
});
}
$rubricaId = $query
->where(function ($q) use ($digits): void {
$q->orWhereRaw("REPLACE(REPLACE(REPLACE(COALESCE(telefono_ufficio,''), ' ', ''), '+', ''), '-', '') LIKE ?", ['%' . $digits . '%'])
->orWhereRaw("REPLACE(REPLACE(REPLACE(COALESCE(telefono_cellulare,''), ' ', ''), '+', ''), '-', '') LIKE ?", ['%' . $digits . '%'])
->orWhereRaw("REPLACE(REPLACE(REPLACE(COALESCE(telefono_casa,''), ' ', ''), '+', ''), '-', '') LIKE ?", ['%' . $digits . '%']);
})
->orderByDesc('id')
->value('id');
$result = is_numeric($rubricaId) ? (int) $rubricaId : null;
$this->rubricaPhoneCache[$digits] = $result;
return $result;
}
public static function canAccess(): bool
{
$user = Auth::user();
return $user instanceof User
&& $user->hasAnyRole(['super-admin', 'admin', 'amministratore', 'collaboratore']);
}
}