feat(editorial): stage portfolio base data and territory for atomic publication

This commit is contained in:
2026-11-13 23:47:04 +02:00
parent d2c72f5e13
commit 2459d0ca37
11 changed files with 491 additions and 11 deletions
@@ -11,6 +11,7 @@ use App\Models\ValueChain;
use App\Services\ClusterCompetitiveness;
use App\Services\InvestmentGeography;
use App\Services\PortalAudit;
use App\Services\PortalEditorialWorkflow;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@@ -48,8 +49,12 @@ class InvestmentStructureController extends Controller
{
$model = $this->model($structure);
$record = $id ? $model::findOrFail($id) : null;
$editorialDossier = $id ? app(PortalEditorialWorkflow::class)->structureDossier($structure, $id) : null;
if ($record && $editorialDossier) {
$record = app(PortalEditorialWorkflow::class)->workingStructure($record, $editorialDossier);
}
return Inertia::render('structures/editor', ['structure' => $structure, 'record' => $record,
return Inertia::render('structures/editor', ['editorialDossier' => $editorialDossier?->id, 'structure' => $structure, 'record' => $record,
'projects' => $structure === 'clusters' && $id ? Project::orderBy('name')->get(['id', 'name', 'code']) : [],
'chains' => $structure === 'clusters' && $id ? ValueChain::where('cluster_id', $id)->orderBy('code')->get() : [],
'gaps' => $structure === 'clusters' && $id ? InvestmentGap::where('cluster_id', $id)->orderBy('created_at')->get() : [],
@@ -76,11 +81,15 @@ class InvestmentStructureController extends Controller
$isCorridor = $structure === 'corridors';
$model = $this->model($structure);
$record = $id ? $model::findOrFail($id) : new $model;
$editorialDossier = $id ? app(PortalEditorialWorkflow::class)->structureDossier($structure, $id, true) : null;
$rules = [
'code' => ['required', 'string', 'max:100', Rule::unique($record->getTable(), 'code')->whereNull('deleted_at')->ignore($record->getKey())],
'name' => ['required', 'string', 'max:200'],
'status' => ['required', Rule::in($isProject ? ['draft', 'planned', 'active', 'suspended', 'completed', 'cancelled'] : ($isCluster ? ['planned', 'active', 'inactive'] : ['proposed', 'active', 'closed']))],
];
if ($editorialDossier) {
$rules['editorial_version'] = ['required', 'integer', 'min:1'];
}
if ($isProject || $isCorridor) {
$rules['description'] = ['nullable', 'string', 'max:10000'];
}
@@ -105,6 +114,11 @@ class InvestmentStructureController extends Controller
$data['primary_territory_id'] = $path === [] ? null : $path[array_key_last($path)]->id;
$data['territory_version'] = $path === [] ? 0 : 1;
}
if ($editorialDossier) {
app(PortalEditorialWorkflow::class)->saveStructure($request->user(), $record, $editorialDossier, (int) $data['editorial_version'], $data);
return redirect('/management/'.$structure.'/'.$record->getKey().'/edit')->with('success', 'Dados-base guardados numa edição privada da carteira. A publicação anterior está preservada.');
}
PortalAudit::save($record, $data, $request->user()->id);
return redirect('/management/'.$structure.'/'.$record->getKey().'/edit')->with('success', 'Registo guardado.');