Files
compras/app/Http/Controllers/ConflictDeclarationController.php
T
nala 4d42f083ce
tests / ci (push) Canceled after 0s
commit
2026-10-28 12:06:05 +02:00

96 lines
5.4 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\ConflictDeclaration;
use App\Models\Requisition;
use App\Models\Supplier;
use App\Services\ConflictGuard;
use App\Services\RequisitionWorkflow;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Inertia\Inertia;
use Inertia\Response;
class ConflictDeclarationController extends Controller
{
public function index(Request $request): Response
{
return Inertia::render('conflicts/index', [
'declarations' => 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);
}
}