netgescon-day0/app/Filament/Pages/Fornitore/Concerns/ResolvesOperatoreContext.php

222 lines
7.8 KiB
PHP

<?php
namespace App\Filament\Pages\Fornitore\Concerns;
use App\Models\Fornitore;
use App\Models\FornitoreDipendente;
use App\Models\TicketIntervento;
use Illuminate\Support\Facades\Auth;
trait ResolvesOperatoreContext
{
/**
* @return array{0:?Fornitore,1:?FornitoreDipendente}
*/
protected function resolveOperatoreContext(?int $forcedFornitoreId = null, bool $allowAdminWithoutSupplier = false): array
{
$user = Auth::user();
if ($user && $user->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
{
$descrizione = (string) ($intervento->ticket->descrizione ?? '');
$caller = $this->extractCallerData($descrizione);
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}
*/
protected function extractCallerData(string $descrizione): array
{
$contatto = '-';
$telefono = '';
$problema = '';
$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, 'Telefono:')) {
$telefono = trim((string) str_replace('Telefono:', '', $trim));
}
}
return [
'contatto' => $contatto,
'telefono' => $telefono,
'problema' => $problema,
];
}
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 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);
}
}