Files
Investidor-V2/app/Http/Controllers/VirtualDeskInstallationController.php

103 lines
6.5 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Services\DeskServiceAvailability;
use App\Services\DeskServiceEditor;
use App\Services\VirtualDeskInstallation;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
use Inertia\Inertia;
use Inertia\Response;
class VirtualDeskInstallationController extends Controller
{
public function reviewLink(Request $request, string $id): JsonResponse|RedirectResponse
{
$data = $request->validate(['version' => 'required|integer|min:1', 'available' => 'required|boolean',
'evidence' => 'required|string|min:10|max:3000', 'contact' => 'nullable|string|max:255']);
DB::transaction(function () use ($request, $id, $data) {
$link = DB::table('desk_institutional_links')->where('id', $id)->lockForUpdate()->first();
abort_unless($link !== null, 404);
abort_unless((int) $link->version === (int) $data['version'], 409);
abort_unless(filter_var($link->url, FILTER_VALIDATE_URL) && parse_url($link->url, PHP_URL_SCHEME) === 'https', 422);
DB::table('desk_institutional_links')->where('id', $id)->update(['status' => $data['available'] ? 'active' : 'unavailable',
'contact' => $data['contact'] ?? $link->contact, 'verified_at' => now(), 'verified_by' => $request->user()->id,
'version' => $link->version + 1, 'updated_at' => now()]);
DB::table('audit_events')->insert(['source_system' => 'virtual-desk', 'entity_type' => 'desk_institutional_links', 'entity_id' => $id,
'actor_user_id' => $request->user()->id, 'action' => 'institutional_link_checked',
'after_data' => json_encode(['url' => $link->url, 'prior_version' => $link->version, ...$data, 'scope' => 'availability_only_not_legal_approval'])]);
});
return $request->expectsJson() ? response()->json(['checked' => true]) : back()->with('success', 'Conferência de disponibilidade registada por sete dias.');
}
public function sources(Request $request): JsonResponse|Response
{
$read = function (string $name): array {
$file = storage_path('app/private/virtual-desk/'.$name.'.json');
if (! is_file($file)) {
return [];
}
$bytes = file_get_contents($file);
abort_unless(is_string($bytes), 503);
return json_decode($bytes, true, 512, JSON_THROW_ON_ERROR);
};
$inventory = $read('source-inventory');
$forms = $read('form-register');
$data = ['total' => count($inventory), 'attachmentCount' => array_sum(array_map(fn ($item) => count($item['attachments'] ?? []), $inventory)),
'forms' => array_map(fn ($item) => ['identifier' => $item['identifier'], 'sha256' => $item['sha256'], 'size' => $item['size'], 'edition' => $item['edition'],
'provenance' => str_contains($item['path'], DIRECTORY_SEPARATOR.'Scan'.DIRECTORY_SEPARATOR) ? 'Acervo disponibilizado — digitalização' : 'Acervo disponibilizado — fonte de desenho ou template',
'consultation' => $item['consultation'], 'legal_documentary_status' => $item['legal_documentary_status'], 'rule_use' => $item['rule_use'], 'official_confirmation' => $item['official_confirmation'], 'fields_status' => $item['fields_status']], $forms),
'source' => config('virtual-desk.source')];
return $request->expectsJson() ? response()->json($data) : Inertia::render('desk/sources', $data);
}
public function preview(Request $request, VirtualDeskInstallation $installation): JsonResponse|Response
{
$data = $installation->preview();
return $request->expectsJson() ? response()->json($data) : Inertia::render('desk/install', $data);
}
public function apply(Request $request, VirtualDeskInstallation $installation): JsonResponse|RedirectResponse
{
$data = $request->validate(['hash' => 'required|string|size:64', 'confirm' => 'accepted']);
$installation->apply($data['hash'], $request->user());
return $request->expectsJson() ? response()->json(['installed' => true]) : back()->with('success', 'Instalação concluída; serviços ainda exigem publicação explícita.');
}
public function publishService(Request $request): JsonResponse|RedirectResponse
{
$data = $request->validate(['code' => ['required', Rule::in(array_keys(config('virtual-desk.services')))], 'confirm' => 'accepted']);
$row = DB::transaction(function () use ($request, $data) {
DB::select('select pg_advisory_xact_lock(261008, 2)');
$definition = config('virtual-desk.services.'.$data['code']);
$existing = DB::table('desk_service_versions')->where('code', $data['code'])->orderByDesc('version')->first();
if ($existing && $existing->status === 'published' && app(DeskServiceEditor::class)->sameDefinition(json_decode($existing->definition, true, 512, JSON_THROW_ON_ERROR), $definition)) {
return $existing;
}
$id = (string) Str::uuid();
$effective = app(DeskServiceAvailability::class)->scheduled() ? now()->toDateString() : null;
DB::table('desk_service_versions')->insert(['id' => $id, 'code' => $data['code'], 'version' => ($existing->version ?? 0) + 1, 'status' => 'published',
...($effective ? ['effective_from' => $effective] : []),
'definition' => json_encode($definition), 'source' => json_encode(config('virtual-desk.source')), 'author_id' => $request->user()->id,
'published_by' => $request->user()->id, 'published_at' => now(), 'created_at' => now(), 'updated_at' => now()]);
DB::table('audit_events')->insert(['source_system' => 'virtual-desk', 'entity_type' => 'desk_service_versions', 'entity_id' => $id, 'actor_user_id' => $request->user()->id,
'action' => 'internal_service_published', 'after_data' => json_encode(['code' => $data['code'], 'nature' => 'digital_preparation_not_official_form', 'effective_from' => $effective])]);
return DB::table('desk_service_versions')->where('id', $id)->first();
});
return $request->expectsJson() ? response()->json(['id' => $row->id, 'effective_from' => $row->effective_from ?? null], 201)
: back()->with('success', 'Serviço de preparação interna publicado'.(($row->effective_from ?? null) ? ' com entrada em vigor em '.$row->effective_from : '').'.');
}
}