hasAnyRole(['super-admin', 'admin', 'amministratore'])) { $fornitoreId = $forcedFornitoreId ?: (int) request()->query('fornitore', 0); if ($fornitoreId <= 0) { $interventoRoute = request()->route('intervento'); if ($interventoRoute instanceof TicketIntervento) { $fornitoreId = (int) ($interventoRoute->fornitore_id ?? 0); } } if ($fornitoreId > 0) { $fornitore = Fornitore::query()->find($fornitoreId); abort_unless($fornitore instanceof Fornitore, 404); return [$fornitore, null]; } if ($allowAdminWithoutSupplier) { return [null, null]; } } $requestedFornitoreId = $forcedFornitoreId ?: (int) request()->query('fornitore', 0); $currentSupplier = $this->resolveCurrentUserSupplier($user); if ($requestedFornitoreId > 0) { $collaboratore = $this->resolveCollaboratoreForUser($requestedFornitoreId, $currentSupplier?->id); if ($collaboratore instanceof FornitoreDipendente) { $fornitore = Fornitore::query()->find($requestedFornitoreId); abort_unless($fornitore instanceof Fornitore, 404); $collaboratore->ultimo_accesso_at = now(); $collaboratore->save(); return [$fornitore, $collaboratore]; } if ($currentSupplier instanceof Fornitore && (int) $currentSupplier->id === $requestedFornitoreId) { return [$currentSupplier, null]; } } $dipendente = null; $fornitore = $currentSupplier; if (! $fornitore && $user) { $dipendente = $this->resolveCollaboratoreForUser(null, null); if ($dipendente instanceof FornitoreDipendente) { $fornitore = Fornitore::query()->find((int) $dipendente->fornitore_id); $dipendente->ultimo_accesso_at = now(); $dipendente->save(); } } abort_unless($fornitore instanceof Fornitore, 403, 'Profilo fornitore non collegato.'); return [$fornitore, $dipendente]; } protected function resolveCurrentUserSupplier($user): ?Fornitore { if (! $user) { return null; } $email = mb_strtolower(trim((string) $user->email)); if ($email === '') { return null; } return Fornitore::query() ->whereRaw('LOWER(email) = ?', [$email]) ->withCount(['ticketInterventi', 'dipendenti']) ->orderByDesc('ticket_interventi_count') ->orderByDesc('dipendenti_count') ->orderByDesc('id') ->first(); } protected function resolveCollaboratoreForUser(?int $fornitoreId = null, ?int $currentSupplierId = null): ?FornitoreDipendente { $user = Auth::user(); if (! $user) { return null; } $query = FornitoreDipendente::query() ->where('attivo', true) ->when($fornitoreId, fn($builder) => $builder->where('fornitore_id', $fornitoreId)) ->where(function ($builder) use ($user, $currentSupplierId): void { $builder->where('user_id', (int) $user->id) ->orWhereRaw('LOWER(email) = ?', [mb_strtolower((string) $user->email)]); if (($currentSupplierId ?? 0) > 0) { $builder->orWhere('fornitore_esterno_id', (int) $currentSupplierId); } }) ->orderByRaw('CASE WHEN user_id = ? THEN 0 ELSE 1 END', [(int) $user->id]) ->orderByRaw('CASE WHEN fornitore_esterno_id IS NULL THEN 1 ELSE 0 END') ->orderByDesc('id'); return $query->first(); } protected function authorizeIntervento(TicketIntervento $intervento, Fornitore $fornitore): void { abort_unless((int) $intervento->fornitore_id === (int) $fornitore->id, 403); } protected function authorizeDipendenteIntervento(TicketIntervento $intervento, ?FornitoreDipendente $dipendente): void { if (! $dipendente instanceof FornitoreDipendente) { return; } $assignedDipendenteId = (int) ($intervento->eseguito_da_dipendente_id ?? 0); abort_if($assignedDipendenteId > 0 && $assignedDipendenteId !== (int) $dipendente->id, 403, 'Intervento assegnato a un altro operatore del fornitore.'); } /** * @return array{ingresso:string,contatto:string,telefono:string,problema:string,apparato:string} */ protected function buildInterventoRow(TicketIntervento $intervento): array { $ticket = $intervento->ticket; $descrizione = (string) ($ticket->descrizione ?? ''); $caller = $this->extractCallerData($descrizione); if (($caller['contatto'] ?? '-') === '-' || trim((string) ($caller['contatto'] ?? '')) === '') { $titleContact = $this->extractCallerNameFromTitle((string) ($ticket->titolo ?? '')); if ($titleContact !== '') { $caller['contatto'] = $titleContact; } } if ($ticket?->soggettoRichiedente) { $soggetto = $ticket->soggettoRichiedente; $label = trim((string) ($soggetto->ragione_sociale ?: trim(($soggetto->nome ?? '') . ' ' . ($soggetto->cognome ?? '')))); if ($label !== '') { $caller['contatto'] = $label; } $telefono = trim((string) ($soggetto->telefono ?? '')); if ($telefono !== '') { $caller['telefono'] = $telefono; } } $rubrica = $this->resolveCallerRubricaFromTicket($ticket, (string) ($caller['contatto'] ?? '')); if ($rubrica instanceof RubricaUniversale) { if (($caller['contatto'] ?? '-') === '-' || trim((string) ($caller['contatto'] ?? '')) === '') { $caller['contatto'] = trim((string) ($rubrica->nome_completo ?: $rubrica->ragione_sociale ?: '-')) ?: '-'; } if (($caller['telefono'] ?? '') === '') { $caller['telefono'] = trim((string) ($rubrica->telefono_cellulare ?: $rubrica->telefono_ufficio ?: $rubrica->telefono_casa ?: '')); } } return [ 'ingresso' => optional($intervento->created_at)->format('d/m/Y H:i') ?: '-', 'contatto' => $caller['contatto'], 'telefono' => $caller['telefono'], 'problema' => $caller['problema'] !== '' ? $caller['problema'] : ((string) ($intervento->ticket->titolo ?? '-')), 'apparato' => $this->extractApparato((string) ($intervento->rapporto_fornitore ?? '')), ]; } /** * @return array{contatto:string,telefono:string,problema:string,email:string,riferimento:string} */ protected function extractCallerData(string $descrizione): array { $contatto = '-'; $telefono = ''; $problema = ''; $email = ''; $riferimento = ''; $lines = preg_split('/\r\n|\r|\n/', $descrizione) ?: []; foreach ($lines as $line) { $trim = trim($line); if ($problema === '' && $trim !== '') { $problema = $trim; } if (str_starts_with($trim, 'Chiamante selezionato:')) { $contatto = trim((string) str_replace('Chiamante selezionato:', '', $trim)); } if (str_starts_with($trim, 'Contatto associato:')) { $contatto = trim((string) str_replace('Contatto associato:', '', $trim)); } if (str_starts_with($trim, 'Telefono:')) { $telefono = trim((string) str_replace('Telefono:', '', $trim)); } if (str_starts_with($trim, 'Telefono richiamabile:')) { $telefono = trim((string) str_replace('Telefono richiamabile:', '', $trim)); } if (str_starts_with($trim, 'Email richiedente:')) { $email = trim((string) str_replace('Email richiedente:', '', $trim)); } if (str_starts_with($trim, 'Riferimento stabile:')) { $riferimento = trim((string) str_replace('Riferimento stabile:', '', $trim)); } if (str_starts_with($trim, 'Riferimento unità:')) { $unita = trim((string) str_replace('Riferimento unità:', '', $trim)); $riferimento = $riferimento !== '' ? ($riferimento . ' · ' . $unita) : $unita; } } return [ 'contatto' => $contatto, 'telefono' => $telefono, 'problema' => $problema, 'email' => $email, 'riferimento' => $riferimento, ]; } protected function extractApparato(string $rapporto): string { foreach ((preg_split('/\r\n|\r|\n/', $rapporto) ?: []) as $line) { $trim = trim($line); if (str_starts_with(mb_strtolower($trim), 'apparato:')) { return trim((string) substr($trim, strlen('apparato:'))); } } return '-'; } protected function extractCallerNameFromTitle(string $title): string { $title = trim($title); if ($title === '') { return ''; } if (preg_match('/^Segnalazione da\s+(.+)$/iu', $title, $matches)) { return trim((string) ($matches[1] ?? '')); } return ''; } protected function resolveCallerRubricaFromTicket(?Ticket $ticket, string $fallbackName = ''): ?RubricaUniversale { if (! $ticket instanceof Ticket) { return null; } $adminId = (int) ($ticket->stabile?->amministratore_id ?? 0); $soggetto = $ticket->soggettoRichiedente; $queries = []; if ($soggetto && filled($soggetto->codice_fiscale)) { $queries[] = fn() => RubricaUniversale::query()->where('codice_fiscale', strtoupper(trim((string) $soggetto->codice_fiscale))); } if ($soggetto && filled($soggetto->email)) { $queries[] = fn() => RubricaUniversale::query()->whereRaw('LOWER(email) = ?', [mb_strtolower(trim((string) $soggetto->email))]); } if ($soggetto && filled($soggetto->telefono)) { $phone = preg_replace('/\D+/', '', (string) $soggetto->telefono) ?: ''; if ($phone !== '') { $queries[] = fn() => RubricaUniversale::query()->where(function ($builder) use ($phone): void { $builder->whereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_cellulare, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') = ?", [$phone]) ->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_ufficio, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') = ?", [$phone]) ->orWhereRaw("REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(COALESCE(telefono_casa, ''), ' ', ''), '+', ''), '-', ''), '(', ''), ')', '') = ?", [$phone]); }); } } $name = trim($fallbackName); if ($name !== '' && $name !== '-') { $queries[] = fn() => RubricaUniversale::query()->where(function ($builder) use ($name): void { $builder->whereRaw("LOWER(COALESCE(ragione_sociale, '')) = ?", [mb_strtolower($name)]) ->orWhereRaw("LOWER(TRIM(CONCAT(COALESCE(nome, ''), ' ', COALESCE(cognome, '')))) = ?", [mb_strtolower($name)]); }); } foreach ($queries as $factory) { $query = $factory(); if ($adminId > 0) { $query->where(function ($builder) use ($adminId): void { $builder->where('amministratore_id', $adminId) ->orWhereNull('amministratore_id'); }); } $match = $query->orderByDesc('updated_at')->orderBy('id')->first(); if ($match instanceof RubricaUniversale) { return $match; } } return null; } protected function buildApparatoSummary(string $marca, string $modello, string $seriale): string { $marca = trim($marca); $modello = trim($modello); $seriale = trim($seriale); if ($marca === '' && $modello === '' && $seriale === '') { return ''; } return 'Apparato: ' . ($marca !== '' ? ('marca=' . $marca . ' ') : '') . ($modello !== '' ? ('modello=' . $modello . ' ') : '') . ($seriale !== '' ? ('seriale=' . $seriale) : ''); } protected function getFornitoreLabel(Fornitore $fornitore): string { $label = trim((string) ($fornitore->ragione_sociale ?: trim(($fornitore->nome ?? '') . ' ' . ($fornitore->cognome ?? '')))); return $label !== '' ? $label : ('Fornitore #' . (int) $fornitore->id); } }