fix: connect documentary anchors to investment preparation and recover accepted territories
tests / ci (push) Canceled after 0s

This commit is contained in:
2026-10-23 19:17:15 +02:00
parent cdf8fcfba4
commit 3fd5128c62
21 changed files with 1668 additions and 33 deletions
@@ -61,8 +61,15 @@ class InvestmentPortfolioController extends Controller
{
$management = $request->routeIs('management.portfolio*');
$filters = $request->validate(['q' => ['nullable', 'string', 'max:120'], 'kind' => ['nullable', 'in:corridor,cluster,project'],
'sector' => ['nullable', 'string', 'max:500'],
'province_id' => ['nullable', 'uuid'], 'district_id' => ['nullable', 'uuid'], 'admin_post_id' => ['nullable', 'uuid'], 'locality_id' => ['nullable', 'uuid']]);
$query = $management ? InvestmentDossier::query() : self::visible();
$sectorOptions = ($management ? InvestmentDossier::query() : self::visible())
->whereNotNull('content->sector')->get()->pluck('content.sector')
->filter(fn ($sector) => is_string($sector) && trim($sector) !== '')->unique()->sort()->values();
if (! empty($filters['sector'])) {
$query->where('content->sector', $filters['sector']);
}
if (! empty($filters['kind'])) {
$query->whereNotNull($filters['kind'].'_id');
}
@@ -76,7 +83,7 @@ class InvestmentPortfolioController extends Controller
}
return Inertia::render('portfolio/index', ['records' => $query->orderBy('title')->paginate(30)->withQueryString(),
'management' => $management, 'filters' => $filters, 'territorySelection' => $territorySelection]);
'management' => $management, 'filters' => $filters, 'sectors' => $sectorOptions, 'territorySelection' => $territorySelection]);
}
public function show(Request $request, string $id): Response
@@ -137,6 +144,13 @@ class InvestmentPortfolioController extends Controller
'origin' => $origin ? ['id' => $origin->id, 'title' => $origin->title] : null, 'opportunities' => $opportunities, 'chains' => $chains]);
}
public function resumeInterest(Request $request, string $id): RedirectResponse
{
self::visible()->findOrFail($id);
$data = $request->validate(['catalogue_query' => ['nullable', 'string', 'max:4000']]);
return redirect('/carteira/'.$id.'?'.http_build_query([...$data, 'prepare_interest' => '1']));
}
public function save(Request $request, InvestmentDossier $dossier): RedirectResponse
{
$data = $request->validate(['version_no' => ['required', 'integer', 'min:1'], 'title' => ['required', 'string', 'max:255'], 'source' => ['required', 'string', 'max:2000'],
@@ -103,12 +103,17 @@ final class InvestorContextController extends Controller
if ($kept && ($kept['territory']['key'] ?? null) !== ($entry['territory']['key'] ?? null)) $differences[] = ['title'=>$entry['opportunity']['title'],'saved'=>$kept['territory']['title']??'Por definir','requested'=>$entry['territory']['title']??'Por definir'];
}
$complements = isset($draft['complements']) ? app(\App\Services\InvestmentComplements::class)->resolve($draft['complements'], $data['context']['complements'] ?? []) : ($data['context']['complements'] ?? []);
$entryTerritory = null;
if (($source['kind'] ?? null) === 'portfolio') {
$path = app(InvestmentGeography::class)->selection($r->validate(['province_id' => 'nullable|uuid', 'district_id' => 'nullable|uuid', 'admin_post_id' => 'nullable|uuid', 'locality_id' => 'nullable|uuid']));
if ($path) $entryTerritory = $context->reference('territory:'.$path[array_key_last($path)]->id);
}
foreach ($this->entryComplements($r) as $entry) {
$tag = 'complement:'.hash('sha256', $entry['key'].'@'.($selectionKey ?? ''));
$entrySources[] = $tag;
if (!in_array($tag, $draft['entry_sources'] ?? [], true)) $complements = collect([...$complements, $entry])->unique('key')->values()->all();
}
return Inertia::render('investor-path/context', ['entryComplements' => $complements, 'entryLocationDifferences'=>$differences,'entrySources'=>$entrySources,'draft' => $draft, 'requestedChoices' => $choices, 'initial' => $data, 'options' => $context->options(), 'source' => $source, 'territorySelection' => isset($data['context']['selection']['territory']) ? app(InvestmentGeography::class)->path($data['context']['selection']['territory']['id']) : []]);
return Inertia::render('investor-path/context', ['entryTerritory' => $entryTerritory, 'entryComplements' => $complements, 'entryLocationDifferences'=>$differences,'entrySources'=>$entrySources,'draft' => $draft, 'requestedChoices' => $choices, 'initial' => $data, 'options' => $context->options(), 'source' => $source, 'territorySelection' => isset($data['context']['selection']['territory']) ? app(InvestmentGeography::class)->path($data['context']['selection']['territory']['id']) : ($entryTerritory ? app(InvestmentGeography::class)->path($entryTerritory['id']) : [])]);
}
public function preview(Request $r, string $id, InvestorContext $context)
@@ -125,9 +130,16 @@ final class InvestorContextController extends Controller
{
$d = $r->validate(['source' => 'nullable|string|max:100', 'step' => ['nullable', 'regex:/^S(0[1-9]|1[0-9])$/']]);
$ref = isset($d['source']) ? $context->reference($d['source']) : null;
$submissionId = $r->validate(['submission' => 'nullable|uuid'])['submission'] ?? null;
$entrySubmission = null;
if ($submissionId) {
$submission = \App\Models\InvestmentSubmission::where('id', $submissionId)->where('user_id', $r->user()->id)->where('status', 'draft')->firstOrFail();
abort_unless(($ref['kind'] ?? null) === 'portfolio' && $submission->dossier_id === $ref['id'], 422, 'Conserve a ficha de origem da manifestação.');
$entrySubmission = ['id' => $submission->id, 'version' => $submission->version];
}
$choices = $this->entryChoices($r, $context);
return Inertia::render('investor-path/context-start', ['entryComplements' => $this->entryComplements($r), 'entryQuery' => $r->only(['complement_origin', 'complement_code', 'complement_target', 'complement_territory', 'from_dossier', 'province_id', 'district_id', 'admin_post_id', 'locality_id']), 'opportunityChoices' => $choices, 'contexts' => $path->contexts($r->user()), 'source' => $ref, 'step' => $d['step'] ?? null]);
return Inertia::render('investor-path/context-start', ['entrySubmission' => $entrySubmission, 'entryComplements' => $this->entryComplements($r), 'entryQuery' => $r->only(['complement_origin', 'complement_code', 'complement_target', 'complement_territory', 'from_dossier', 'province_id', 'district_id', 'admin_post_id', 'locality_id']), 'opportunityChoices' => $choices, 'contexts' => $path->contexts($r->user()), 'source' => $ref, 'step' => $d['step'] ?? null]);
}
public function installation(Request $r, InvestorContextInstallation $install)