validate([ 'search' => ['nullable', 'string', 'max:100'], 'category' => ['nullable', 'string', 'max:100'], 'date_from' => ['nullable', 'date'], 'date_to' => ['nullable', 'date', 'after_or_equal:date_from'], ]); return Inertia::render('approvals/index', [ 'reservations' => Reservation::query() ->with([ 'requester:id,name,email,department', 'items.asset:id,name,asset_tag,category_id,category_name', 'approvalActions.actor:id,name', ]) ->whereIn('status', [ReservationStatus::PendingApproval, ReservationStatus::AwaitingInformation]) ->when($filters['search'] ?? null, fn ($query, string $search) => $query ->where(fn ($query) => $query ->where('reference', 'like', "%{$search}%") ->orWhereHas('requester', fn ($query) => $query->where('name', 'like', "%{$search}%")))) ->when($filters['category'] ?? null, fn ($query, string $category) => $query ->whereHas('items.asset', fn ($query) => $query->where('category_name', $category))) ->when($filters['date_from'] ?? null, fn ($query, string $date) => $query ->where('ends_at', '>', CarbonImmutable::parse($date)->startOfDay())) ->when($filters['date_to'] ?? null, fn ($query, string $date) => $query ->where('starts_at', '<', CarbonImmutable::parse($date)->addDay()->startOfDay())) ->oldest('starts_at') ->paginate(20) ->withQueryString(), 'filters' => $filters, 'categories' => SnipeAsset::query() ->whereNotNull('category_name') ->distinct() ->orderBy('category_name') ->pluck('category_name'), 'replacementAssets' => SnipeAsset::query() ->where('active', true) ->where('requestable', true) ->whereNull('assigned_id') ->orderBy('name') ->get(['id', 'name', 'asset_tag', 'category_id', 'category_name']), ]); } public function approve(Request $request, Reservation $reservation, ApprovalService $service): RedirectResponse { $data = $request->validate(['comment' => ['nullable', 'string', 'max:1000']]); $service->approve($reservation, $request->user(), $data['comment'] ?? null); return back()->with('success', "Requisição {$reservation->reference} aprovada."); } public function reject(Request $request, Reservation $reservation, ApprovalService $service): RedirectResponse { $data = $request->validate(['comment' => ['required', 'string', 'min:5', 'max:1000']]); $service->reject($reservation, $request->user(), $data['comment']); return back()->with('success', "Requisição {$reservation->reference} rejeitada."); } public function requestInformation(Request $request, Reservation $reservation, ApprovalService $service): RedirectResponse { $data = $request->validate(['comment' => ['required', 'string', 'min:5', 'max:1000']]); $service->requestInformation($reservation, $request->user(), $data['comment']); return back()->with('success', "Pedido de esclarecimentos enviado para {$reservation->reference}."); } public function substitute(Request $request, Reservation $reservation, ReservationItem $item, ApprovalService $service): RedirectResponse { $data = $request->validate([ 'replacement_asset_id' => ['required', 'integer', 'exists:snipe_assets,id'], 'comment' => ['required', 'string', 'min:5', 'max:1000'], ]); /** @var SnipeAsset $replacement */ $replacement = SnipeAsset::query()->findOrFail($data['replacement_asset_id']); $service->substituteAsset($reservation, $item, $replacement, $request->user(), $data['comment']); return back()->with('success', "Equipamento substituído na requisição {$reservation->reference}."); } }