netgescon-day0/app/Http/Controllers/Fornitore/TicketOperativoController.php

191 lines
6.7 KiB
PHP

<?php
namespace App\Http\Controllers\Fornitore;
use App\Http\Controllers\Controller;
use App\Models\Fornitore;
use App\Models\FornitoreDipendente;
use App\Models\TicketIntervento;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class TicketOperativoController extends Controller
{
public function index(Request $request)
{
[$fornitore] = $this->resolveOperatoreContext();
$stato = (string) $request->query('stato', 'aperti');
$query = TicketIntervento::query()
->with(['ticket.stabile'])
->where('fornitore_id', $fornitore->id)
->orderByDesc('created_at');
if ($stato === 'chiusi') {
$query->whereIn('stato', ['chiuso', 'fatturato']);
} elseif ($stato === 'fatturabili') {
$query->whereIn('stato', ['fatturabile', 'fatturato']);
} else {
$query->whereNotIn('stato', ['chiuso']);
}
$interventi = $query->paginate(15)->withQueryString();
$fatturabili = TicketIntervento::query()
->where('fornitore_id', $fornitore->id)
->whereIn('stato', ['fatturabile', 'fatturato'])
->orderByDesc('updated_at')
->limit(100)
->get();
return view('fornitore.tickets.index', [
'fornitore' => $fornitore,
'interventi' => $interventi,
'stato' => $stato,
'fatturabili' => $fatturabili,
]);
}
public function show(TicketIntervento $intervento)
{
[$fornitore] = $this->resolveOperatoreContext();
$this->authorizeIntervento($intervento, $fornitore);
$intervento->load(['ticket.stabile', 'ticket.messages.user', 'eseguitoDaDipendente']);
return view('fornitore.tickets.show', [
'fornitore' => $fornitore,
'intervento' => $intervento,
]);
}
public function start(TicketIntervento $intervento)
{
[$fornitore, $dipendente] = $this->resolveOperatoreContext();
$this->authorizeIntervento($intervento, $fornitore);
$intervento->update([
'stato' => 'in_corso',
'preso_in_carico_da_user_id' => Auth::id(),
'eseguito_da_dipendente_id' => $dipendente?->id,
'iniziato_at' => $intervento->iniziato_at ?? now(),
]);
$intervento->ticket->update(['stato' => 'In Lavorazione']);
return redirect()->route('fornitore.tickets.show', $intervento)
->with('success', 'Intervento preso in carico.');
}
public function complete(Request $request, TicketIntervento $intervento)
{
[$fornitore, $dipendente] = $this->resolveOperatoreContext();
$this->authorizeIntervento($intervento, $fornitore);
$validated = $request->validate([
'rapporto_fornitore' => 'required|string|max:5000',
'tempo_minuti' => 'nullable|integer|min:1|max:1440',
'articoli_utilizzati' => 'nullable|array',
'articoli_utilizzati.*' => 'nullable|string|max:120',
'foto_lavoro' => 'nullable|image|max:5120',
'qr_token' => 'nullable|string|max:40',
]);
$payload = [
'rapporto_fornitore' => $validated['rapporto_fornitore'],
'tempo_minuti' => $validated['tempo_minuti'] ?? null,
'terminato_at' => now(),
'stato' => 'in_verifica',
'eseguito_da_dipendente_id' => $dipendente?->id ?? $intervento->eseguito_da_dipendente_id,
];
$articoli = collect($validated['articoli_utilizzati'] ?? [])
->map(fn($item) => trim((string) $item))
->filter()
->values()
->all();
if ($articoli !== []) {
$payload['articoli_utilizzati'] = $articoli;
}
if ($request->hasFile('foto_lavoro')) {
$payload['foto_path'] = $request->file('foto_lavoro')
->store('ticket-interventi/foto/' . $intervento->id, 'public');
}
$tokenInserito = trim((string) ($validated['qr_token'] ?? ''));
if ($tokenInserito !== '' && strcasecmp($tokenInserito, (string) $intervento->qr_token) === 0) {
$payload['qr_scansionato_at'] = now();
}
$intervento->update($payload);
$intervento->ticket->messages()->create([
'user_id' => Auth::id(),
'messaggio' => 'Rapporto intervento caricato dal fornitore.',
'canale' => 'interno',
'direzione' => 'inbound',
'inviato_il' => now(),
]);
return redirect()->route('fornitore.tickets.show', $intervento)
->with('success', 'Intervento inviato in verifica amministratore.');
}
/**
* @return array{0:Fornitore,1:?FornitoreDipendente}
*/
private function resolveOperatoreContext(): array
{
$user = Auth::user();
if ($user && $user->hasAnyRole(['super-admin', 'admin', 'amministratore'])) {
$fornitoreId = (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) {
$fornitoreAdmin = Fornitore::query()->find($fornitoreId);
abort_unless($fornitoreAdmin, 404);
return [$fornitoreAdmin, null];
}
}
$dipendente = null;
$fornitore = Fornitore::query()
->where('email', (string) $user->email)
->first();
if (! $fornitore && $user) {
$dipendente = FornitoreDipendente::query()
->where('attivo', true)
->where(function ($q) use ($user): void {
$q->where('user_id', (int) $user->id)
->orWhereRaw('LOWER(email) = ?', [mb_strtolower((string) $user->email)]);
})
->orderByDesc('id')
->first();
if ($dipendente) {
$fornitore = Fornitore::query()->find((int) $dipendente->fornitore_id);
$dipendente->ultimo_accesso_at = now();
$dipendente->save();
}
}
abort_unless($fornitore, 403, 'Profilo fornitore non collegato.');
return [$fornitore, $dipendente];
}
private function authorizeIntervento(TicketIntervento $intervento, Fornitore $fornitore): void
{
abort_unless((int) $intervento->fornitore_id === (int) $fornitore->id, 403);
}
}