Files
Investidor-V2/app/Http/Controllers/InvestorWorkspaceController.php
T
nala 6ddafc95ba
tests / ci (push) Canceled after 0s
oportunidades 4
2026-10-10 07:03:59 +02:00

92 lines
6.0 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\InterestRequest;
use App\Models\Investor;
use App\Models\InvestorJourney;
use App\Services\CountryCatalogue;
use App\Services\InterestSubmission;
use App\Services\PortalAudit;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Inertia\Inertia;
use Inertia\Response;
class InvestorWorkspaceController extends Controller
{
public function index(Request $request): Response
{
$journeys = InvestorJourney::where('user_id', $request->user()->id)->latest()->get()->map(function ($journey) {
$dossier = InvestmentPortfolioController::visible()->find($journey->dossier_id);
$interest = $journey->interest_request_id ? InterestRequest::find($journey->interest_request_id) : null;
return ['id' => $journey->id, 'dossier_id' => $dossier?->id, 'title' => $dossier->title ?? 'Ficha temporariamente indisponível',
'status' => $journey->status, 'reference' => $interest?->reference, 'request_status' => $interest?->status,
'country' => $interest?->country,
'declared_origin' => app(CountryCatalogue::class)->describe($interest?->metadata['declared_origin_country_code'] ?? null)];
});
return Inertia::render('portfolio/workspace', ['journeys' => $journeys, 'countries' => app(CountryCatalogue::class)->all()]);
}
public function start(Request $request, string $id): RedirectResponse
{
$dossier = InvestmentPortfolioController::visible()->findOrFail($id);
$data = $request->validate(['origin_id' => ['nullable', 'uuid']]);
$origin = ! empty($data['origin_id']) ? InvestmentPortfolioController::visible()->whereKey($data['origin_id'])->firstOrFail() : null;
abort_if($origin && ! InvestmentPortfolioController::related($dossier, $origin), 422);
DB::transaction(function () use ($request, $dossier, $origin) {
DB::table('users')->where('id', $request->user()->id)->lockForUpdate()->first();
$account = DB::table('investor_accounts')->where('user_id', $request->user()->id)->first();
$investorId = $account?->investor_id;
if (! $account) {
$investor = Investor::create(['legal_name' => $request->user()->name, 'investor_type' => 'individual',
'status' => 'prospect', 'source_system' => 'portal-account', 'data_classification' => 'confidential']);
DB::table('investor_accounts')->insert(['user_id' => $request->user()->id, 'investor_id' => $investor->id, 'created_at' => now(), 'updated_at' => now()]);
$investorId = $investor->id;
}
$journey = InvestorJourney::firstOrNew(['user_id' => $request->user()->id, 'dossier_id' => $dossier->id]);
if (! $journey->exists) {
PortalAudit::save($journey, ['investor_id' => $investorId, 'status' => 'started', 'origin_dossier_id' => $origin?->id,
'source_system' => 'portal-account', 'data_classification' => 'confidential'], $request->user()->id);
}
});
return redirect('/investidor')->with('success', 'Guardado no seu painel.');
}
public function submit(Request $request, string $id, InterestSubmission $submission): RedirectResponse
{
$data = $request->validate(['message' => ['required', 'string', 'min:20', 'max:5000'], 'country' => ['required', 'string', 'max:100', app(CountryCatalogue::class)->legacyCountryRule()],
'declared_origin_country_code' => ['nullable', app(CountryCatalogue::class)->rule()],
'privacy_consent' => ['accepted'], 'role' => ['required', 'in:investir,financiar,fornecer,operar,parceria'],
'horizon' => ['required', 'string', 'max:100']]);
DB::transaction(function () use ($request, $id, $data, $submission) {
$journey = InvestorJourney::where('user_id', $request->user()->id)->whereKey($id)->lockForUpdate()->firstOrFail();
if ($journey->interest_request_id) {
return; // One expression per saved journey; retry returns its original protocol.
}
$dossier = InvestmentPortfolioController::visible()->whereKey($journey->dossier_id)->lockForUpdate()->firstOrFail();
$origin = $journey->origin_dossier_id ? InvestmentPortfolioController::visible()->find($journey->origin_dossier_id) : null;
$interest = $submission->receive(['email' => $request->user()->email, 'fullName' => $request->user()->name, 'message' => $data['message']], null,
fn () => InterestRequest::create([
'reference' => 'IR-'.now()->year.'-'.Str::ulid(), 'full_name' => $request->user()->name,
'email' => $request->user()->email, 'investor_type' => 'individual', 'country' => $data['country'],
'sector_interest' => Str::limit($dossier->content['sector'] ?? $dossier->title, 150, ''), 'message' => $data['message'],
'privacy_consent' => true, 'consented_at' => now(), 'status' => 'received', 'source_page' => '/carteira/'.$dossier->id,
'metadata' => ['journey_id' => $journey->id, 'dossier_id' => $dossier->id, 'origin_dossier_id' => $journey->origin_dossier_id,
'declared_origin_country_code' => $data['declared_origin_country_code'] ?? null,
'project_id' => $dossier->project_id ?? $origin?->project_id,
'cluster_id' => $dossier->cluster_id ?? $origin?->cluster_id, 'corridor_id' => $dossier->corridor_id ?? $origin?->corridor_id,
'role' => $data['role'], 'horizon' => $data['horizon'], 'purpose' => 'Acompanhamento da manifestação de interesse'],
]));
PortalAudit::save($journey, ['interest_request_id' => $interest->id, 'status' => 'active'], $request->user()->id);
});
return back()->with('success', 'Manifestação recebida. Consulte o protocolo no painel.');
}
}