120 lines
5.1 KiB
PHP
120 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Http\Requests\StoreRequisitionRequest;
|
|
use App\Models\AuditLog;
|
|
use App\Models\CostCenter;
|
|
use App\Models\Requisition;
|
|
use App\Models\Tenant;
|
|
use App\Services\ConflictGuard;
|
|
use App\Services\RequisitionWorkflow;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Validation\Rule;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
|
|
class RequisitionController extends Controller
|
|
{
|
|
public function index(Request $request): Response
|
|
{
|
|
$filters = $request->validate(['search' => 'nullable|string|max:100', 'status' => ['nullable', Rule::in(['draft', 'pending', 'approved', 'rejected'])]]);
|
|
$query = Requisition::query()->visibleTo($request->user())->with(['requester:id,name', 'department:id,name', 'steps']);
|
|
if (! empty($filters['search'])) {
|
|
$query->where('number', 'like', '%'.$filters['search'].'%');
|
|
}
|
|
if (! empty($filters['status'])) {
|
|
$query->where('status', $filters['status']);
|
|
}
|
|
|
|
return Inertia::render('requisitions/index', [
|
|
'requisitions' => $query->latest()->paginate(15)->withQueryString(),
|
|
'filters' => $filters,
|
|
]);
|
|
}
|
|
|
|
public function create(Request $request): Response
|
|
{
|
|
return Inertia::render('requisitions/form', [
|
|
'costCenters' => CostCenter::query()->where('department_id', $request->user()->department_id)->orderBy('code')->get(),
|
|
'requisition' => null,
|
|
]);
|
|
}
|
|
|
|
public function store(StoreRequisitionRequest $request, RequisitionWorkflow $workflow): RedirectResponse
|
|
{
|
|
$requisition = $workflow->save($request->user(), $request->validated());
|
|
|
|
return to_route('requisitions.show', $requisition);
|
|
}
|
|
|
|
public function show(Request $request, Requisition $requisition): Response
|
|
{
|
|
Requisition::query()->visibleTo($request->user())->findOrFail($requisition->id);
|
|
$requisition->load(['items', 'steps', 'requester:id,name', 'department:id,name', 'costCenter']);
|
|
|
|
return Inertia::render('requisitions/show', [
|
|
'requisition' => $requisition,
|
|
'canEdit' => $requisition->requester_id === $request->user()->id && $requisition->status === 'draft',
|
|
'canDecide' => $requisition->canDecide($request->user()),
|
|
'conflictBlocked' => app(ConflictGuard::class)->participationBlocked($request->user(), $requisition),
|
|
'audit' => AuditLog::query()->where('requisition_id', $requisition->id)->orderBy('id')->get(['id', 'action', 'user_id', 'created_at']),
|
|
]);
|
|
}
|
|
|
|
public function edit(Request $request, Requisition $requisition): Response
|
|
{
|
|
abort_unless($requisition->requester_id === $request->user()->id && $requisition->status === 'draft', 403);
|
|
|
|
return Inertia::render('requisitions/form', [
|
|
'requisition' => $requisition->load('items'),
|
|
'costCenters' => CostCenter::query()->where('department_id', $request->user()->department_id)->orderBy('code')->get(),
|
|
]);
|
|
}
|
|
|
|
public function update(StoreRequisitionRequest $request, Requisition $requisition, RequisitionWorkflow $workflow): RedirectResponse
|
|
{
|
|
$workflow->save($request->user(), $request->validated(), $requisition);
|
|
|
|
return to_route('requisitions.show', $requisition);
|
|
}
|
|
|
|
public function submit(Request $request, Requisition $requisition, RequisitionWorkflow $workflow): RedirectResponse
|
|
{
|
|
$workflow->submit($request->user(), $requisition);
|
|
|
|
return back();
|
|
}
|
|
|
|
public function decide(Request $request, Requisition $requisition, RequisitionWorkflow $workflow): RedirectResponse
|
|
{
|
|
$data = $request->validate([
|
|
'decision' => ['required', Rule::in(['approved', 'rejected'])],
|
|
'comment' => ['nullable', 'required_if:decision,rejected', 'string', 'max:2000'],
|
|
]);
|
|
$workflow->decide($request->user(), $requisition, $data['decision'], $data['comment'] ?? null);
|
|
|
|
return back();
|
|
}
|
|
|
|
public function dashboard(Request $request): Response
|
|
{
|
|
$visible = Requisition::query()->visibleTo($request->user());
|
|
$pending = (clone $visible)->where('status', 'pending')->with('steps')->get();
|
|
|
|
return Inertia::render('dashboard', [
|
|
'company' => $request->user()->tenant_id ? Tenant::query()->find($request->user()->tenant_id) : null,
|
|
'stats' => [
|
|
'total' => (clone $visible)->count(),
|
|
'pending' => $pending->count(),
|
|
'approved' => (clone $visible)->where('status', 'approved')->count(),
|
|
'approvedMinor' => (clone $visible)->where('status', 'approved')->sum('total_minor'),
|
|
'awaitingMe' => $pending->filter(fn (Requisition $r) => $r->canDecide($request->user()))->count(),
|
|
],
|
|
'recent' => (clone $visible)->with(['requester:id,name', 'department:id,name'])->latest()->limit(6)->get(),
|
|
'approvals' => $pending->filter(fn (Requisition $r) => $r->canDecide($request->user()))->take(5)->values(),
|
|
]);
|
|
}
|
|
}
|