ConflictDeclaration::query()->visibleTo($request->user()) ->with(['author:id,name', 'supplier:id,name', 'requisition:id,number', 'successor:id,previous_id']) ->latest('id')->paginate(15), // These minimal choices allow personal declarations without granting supplier-management access. 'suppliers' => Supplier::query()->orderBy('name')->get(['id', 'name']), 'requisitions' => Requisition::query()->visibleTo($request->user())->latest()->get(['id', 'number']), ]); } public function store(Request $request, ConflictGuard $guard, RequisitionWorkflow $workflow): RedirectResponse { $data = $request->validate([ 'scope' => ['required', Rule::in(['supplier', 'process', 'process_supplier'])], 'supplier_id' => ['nullable', 'required_if:scope,supplier,process_supplier', 'prohibited_if:scope,process', 'integer', Rule::exists('suppliers', 'id')->where('tenant_id', $request->user()->tenant_id)], 'requisition_id' => ['nullable', 'required_if:scope,process,process_supplier', 'prohibited_if:scope,supplier', 'integer', Rule::exists('requisitions', 'id')->where('tenant_id', $request->user()->tenant_id)], 'has_conflict' => 'required|boolean', 'known_since' => 'required|date_format:Y-m-d|before_or_equal:today', 'reason' => 'required|string|min:10|max:5000', 'user_id' => 'prohibited', 'tenant_id' => 'prohibited', 'declared_at' => 'prohibited', 'root_id' => 'prohibited', 'previous_id' => 'prohibited', ]); DB::transaction(function () use ($request, $guard, $workflow, $data) { $guard->lockCompany($request->user()); if (! empty($data['requisition_id'])) { Requisition::query()->visibleTo($request->user())->findOrFail($data['requisition_id']); } $declaration = ConflictDeclaration::query()->create([ 'tenant_id' => $request->user()->tenant_id, 'user_id' => $request->user()->id, 'supplier_id' => $data['supplier_id'] ?? null, 'requisition_id' => $data['requisition_id'] ?? null, 'has_conflict' => $data['has_conflict'], 'known_since' => $data['known_since'], 'reason' => $data['reason'], 'declared_at' => now(), ]); $workflow->audit($request->user(), 'conflict.declared', null, null, $declaration->toArray()); }); return to_route('conflicts.index'); } public function show(Request $request, ConflictDeclaration $declaration): Response { ConflictDeclaration::query()->visibleTo($request->user())->findOrFail($declaration->id); $rootId = $declaration->root_id ?? $declaration->id; $history = ConflictDeclaration::query()->where(fn ($query) => $query->whereKey($rootId)->orWhere('root_id', $rootId)) ->with(['author:id,name', 'supplier:id,name', 'requisition:id,number'])->orderBy('id')->get(); $latest = $history->last(); return Inertia::render('conflicts/show', ['history' => $history, 'canCorrect' => $latest?->user_id === $request->user()->id]); } public function update(Request $request, ConflictDeclaration $declaration, ConflictGuard $guard, RequisitionWorkflow $workflow): RedirectResponse { abort_unless($declaration->user_id === $request->user()->id, 403); $data = $request->validate([ 'known_since' => 'required|date_format:Y-m-d|before_or_equal:today', 'reason' => 'required|string|min:10|max:5000', 'has_conflict' => 'prohibited', 'supplier_id' => 'prohibited', 'requisition_id' => 'prohibited', 'user_id' => 'prohibited', 'tenant_id' => 'prohibited', 'declared_at' => 'prohibited', 'root_id' => 'prohibited', 'previous_id' => 'prohibited', ]); DB::transaction(function () use ($request, $guard, $workflow, $declaration, $data) { $guard->lockCompany($request->user()); $declaration = ConflictDeclaration::query()->lockForUpdate()->findOrFail($declaration->id); if ($declaration->successor()->exists()) { throw ValidationException::withMessages(['history' => 'Já existe uma correcção mais recente. Reabra o histórico antes de corrigir.']); } $revision = ConflictDeclaration::query()->create([ ...$declaration->only(['tenant_id', 'user_id', 'supplier_id', 'requisition_id', 'has_conflict']), ...$data, 'declared_at' => now(), 'root_id' => $declaration->root_id ?? $declaration->id, 'previous_id' => $declaration->id, ]); $workflow->audit($request->user(), 'conflict.corrected', null, $declaration->toArray(), $revision->toArray()); }); return to_route('conflicts.show', $declaration); } }