70 lines
3.6 KiB
PHP
70 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\InvestmentLegalSource;
|
|
use App\Services\InvestmentZoneAccess;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class InvestmentLegalSourceController extends Controller
|
|
{
|
|
public function index(): JsonResponse
|
|
{
|
|
return response()->json(InvestmentLegalSource::orderByDesc('created_at')->paginate(20));
|
|
}
|
|
|
|
public function store(Request $request): JsonResponse
|
|
{
|
|
$data = $request->validate(['title' => ['required', 'string', 'max:255'], 'url' => ['required', 'url:https', 'max:2000'],
|
|
'diploma' => ['required', 'string', 'max:255'], 'article' => ['required', 'string', 'max:255'],
|
|
'competent_entity' => ['required', 'string', 'max:255'], 'valid_from' => ['required', 'date_format:Y-m-d'],
|
|
'valid_until' => ['nullable', 'date_format:Y-m-d', 'after_or_equal:valid_from']]);
|
|
|
|
return DB::transaction(function () use ($request, $data) {
|
|
$source = InvestmentLegalSource::create([...$data, 'owner_id' => $request->user()->id]);
|
|
$source->refresh();
|
|
$this->audit($source, $request->user()->id, 'created');
|
|
|
|
return response()->json($source->fresh(), 201)
|
|
->header('Location', url('/api/v2/investment/admin/legal-sources/'.$source->id));
|
|
});
|
|
}
|
|
|
|
public function transition(Request $request, string $id, string $action): JsonResponse
|
|
{
|
|
if ($action === 'validate') {
|
|
InvestmentZoneAccess::requireRole($request->user(), 'legal_reviewers');
|
|
}
|
|
$data = $request->validate(['version_no' => ['required', 'integer', 'min:1']]);
|
|
|
|
return DB::transaction(function () use ($request, $id, $action, $data) {
|
|
DB::select('select pg_advisory_xact_lock(261022, hashtext(?))', [$id]);
|
|
$source = InvestmentLegalSource::whereKey($id)->lockForUpdate()->firstOrFail();
|
|
abort_if((int) $source->version_no !== (int) $data['version_no'], 409, 'Versão alterada.');
|
|
if ($action === 'validate') {
|
|
abort_if(str_contains(mb_strtolower($source->article), 'pending') || str_contains(mb_strtolower($source->article), 'pendente')
|
|
|| str_contains(mb_strtolower($source->article), 'a rever'), 422, 'Indique o artigo e confirme o texto oficial antes da validação.');
|
|
abort_if((int) $source->owner_id === $request->user()->id, 403, 'Outra pessoa deve validar a fonte.');
|
|
abort_unless($source->validation_status === 'pending', 422, 'Crie nova referência para substituir fonte revogada.');
|
|
}
|
|
$source->fill(['validation_status' => $action === 'validate' ? 'validated' : 'revoked',
|
|
'version_no' => (int) $source->version_no + 1,
|
|
'validator_id' => $action === 'validate' ? $request->user()->id : $source->validator_id,
|
|
'validated_at' => $action === 'validate' ? now() : $source->validated_at])->save();
|
|
$this->audit($source, $request->user()->id, $action);
|
|
|
|
return response()->json($source);
|
|
});
|
|
}
|
|
|
|
private function audit(InvestmentLegalSource $source, int $actor, string $action): void
|
|
{
|
|
DB::table('audit_events')->insert(['source_system' => 'investment-zones', 'entity_type' => 'investment_legal_sources',
|
|
'entity_id' => $source->getKey(), 'actor_user_id' => $actor, 'action' => $action,
|
|
'after_data' => json_encode(['version_no' => $source->version_no, 'validation_status' => $source->validation_status,
|
|
'sha256' => hash('sha256', $source->toJson())], JSON_THROW_ON_ERROR)]);
|
|
}
|
|
}
|