assertSame('simulator_fiscal_delta_20261021_test', $identity->name); $this->assertSame(55441, (int) $identity->port); $this->withoutVite(); $this->withoutMiddleware(ThrottleRequests::class); config(['investor-path.enabled' => true, 'investor-path.private_preparation' => true, 'suitecrm.enabled' => false, 'investmoz_ai.enabled' => false]); $this->actor = User::factory()->create(); } public function test_documented_sector_filter_is_explicit_and_preserves_the_catalogue_scope(): void { $anchor = InvestmentPortfolioController::visible()->where('content->code', 'A06')->firstOrFail(); $sector = $anchor->content['sector']; $this->get('/carteira?'.http_build_query(['kind' => 'project', 'sector' => $sector]))->assertOk() ->assertInertia(fn (Assert $p) => $p->where('filters.sector', $sector)->has('records.data', 1)->where('records.data.0.id', $anchor->id)->has('sectors')); $this->get('/carteira?sector=sector-inexistente')->assertOk()->assertInertia(fn (Assert $p) => $p->has('records.data', 0)); $this->get('/carteira')->assertOk()->assertInertia(fn (Assert $p) => $p->where('records.total', InvestmentPortfolioController::visible()->count())); } public function test_accepted_territories_are_recovered_by_identity_with_citations_and_idempotence(): void { $service = app(ApprovedAnchorTerritories::class); $before = DB::table('investment_dossiers')->orderBy('id')->get()->toJson(); $plan = $service->plan(); $this->assertCount(28, $plan['links']); $this->assertCount(13, $plan['projects']); $result = $service->apply($plan); $this->assertSame(count(array_filter($plan['links'], fn ($link) => ! $link['already_present'])), $result['relations_restored']); $this->assertSame(0, $result['publication_changes']); $this->assertSame($before, DB::table('investment_dossiers')->orderBy('id')->get()->toJson()); $second = $service->apply($service->plan()); $this->assertSame(0, $second['relations_restored']); $this->assertSame(0, $second['projects_updated']); $anchor = InvestmentPortfolioController::visible()->where('content->code', 'A06')->firstOrFail(); $locations = app(InvestmentRelations::class)->projectLocations($anchor->project_id); $this->assertCount(4, $locations); $this->assertNotEmpty($locations[0]['source_quote']); $this->assertSame('secondary', $locations[0]['role']); $province = $locations[0]['id']; $this->get('/carteira?'.http_build_query(['kind' => 'project', 'sector' => $anchor->content['sector'], 'province_id' => $province]))->assertOk() ->assertInertia(fn (Assert $p) => $p->has('records.data', 1)->where('records.data.0.id', $anchor->id)); $this->assertCount(0, app(InvestmentRelations::class)->projectLocations(InvestmentPortfolioController::visible()->where('content->code', 'A01')->firstOrFail()->project_id)); } public function test_anchor_without_offer_survives_login_dossier_and_simulator_as_documentary_origin(): void { $anchor = InvestmentPortfolioController::visible()->where('content->code', 'A06')->firstOrFail(); $source = 'portfolio:'.$anchor->id; $entry = '/investimentos/iniciar?'.http_build_query(['source' => $source]); $this->get($entry)->assertRedirect(route('login')); $this->assertStringEndsWith($entry, session('url.intended')); $this->actingAs($this->actor); $this->get($entry)->assertOk()->assertInertia(fn (Assert $p) => $p->where('source.key', $source)->has('opportunityChoices', 0)); $reference = app(InvestorContext::class)->reference($source); $this->assertArrayNotHasKey('province_id', $reference['fields']); $this->assertFalse($reference['analysis']['available_opportunity']); $id = $this->postJson('/investimentos', ['title' => 'SYNTHETIC QA - ideia propria', 'client_key' => (string) Str::uuid(), 'reuse_consent' => true])->assertCreated()->json('id'); $body = ['version' => $this->getJson('/investimentos/'.$id.'/contexto')->json('case.version'), 'selection' => ['portfolio' => $source]]; $preview = $this->postJson('/investimentos/'.$id.'/contexto/previa', $body)->assertOk()->json(); $this->assertSame('SYNTHETIC QA - ideia propria', $preview['fields']['project_title']); $this->postJson('/investimentos/'.$id.'/contexto/confirmar', [...$body, 'preview_hash' => $preview['preview_hash'], 'operation_key' => (string) Str::uuid(), 'confirm' => true])->assertOk(); $view = $this->getJson('/investimentos/'.$id.'/contexto')->assertOk()->json(); $this->assertSame($source, $view['context']['selection']['portfolio']['key']); $this->assertSame([], $view['context']['opportunity_choices']); $snapshot = json_decode($view['prefill']['simulator']['context_applicability_snapshot'], true); $this->assertSame($source, $snapshot['portfolio_origin']['key']); $draft = $this->postJson('/api/v1/simulation-drafts', ['context' => $id, 'personal_snapshot' => [], 'economic_snapshot' => ['purpose' => 'simulate_only', 'project_title' => 'SYNTHETIC QA - titulo proprio', 'context_applicability_snapshot' => json_encode($snapshot)]], ['Idempotency-Key' => (string) Str::uuid()])->assertCreated()->json('data.id'); $saved = $this->getJson('/api/v1/simulation-drafts/'.$draft.'?context='.$id)->assertOk()->json('data.economic_snapshot'); $this->assertSame($source, json_decode($saved['context_applicability_snapshot'], true)['portfolio_origin']['key']); $this->assertSame('SYNTHETIC QA - titulo proprio', $saved['project_title']); $anchor->publication_status = 'draft'; $anchor->save(); $this->get($entry)->assertNotFound(); } public function test_interest_resumption_keeps_the_same_anchor_and_filters_without_creating_a_request_on_get(): void { $anchor = InvestmentPortfolioController::visible()->where('content->code', 'A06')->firstOrFail(); $query = http_build_query(['sector' => $anchor->content['sector'], 'kind' => 'project']); $entry = '/carteira/'.$anchor->id.'/interesse?'.http_build_query(['catalogue_query' => $query]); $before = DB::table('investment_submissions')->count(); $this->get($entry)->assertRedirect(route('login')); $this->assertStringEndsWith($entry, session('url.intended')); $this->actingAs($this->actor); $this->get($entry)->assertRedirect('/carteira/'.$anchor->id.'?'.http_build_query(['catalogue_query' => $query, 'prepare_interest' => '1'])); $this->assertSame($before, DB::table('investment_submissions')->count()); $response = $this->postJson('/investidor/manifestacoes', ['dossier_id' => $anchor->id])->assertCreated(); $row = DB::table('investment_submissions')->where('id', $response->json('id'))->first(); $this->assertSame($anchor->id, $row->dossier_id); $start = '/investimentos/iniciar?'.http_build_query(['source' => 'portfolio:'.$anchor->id, 'submission' => $row->id]); $this->get($start)->assertOk()->assertInertia(fn (Assert $p) => $p->where('entrySubmission.id', $row->id)->where('entrySubmission.version', (int) $row->version)); $other = InvestmentPortfolioController::visible()->where('id', '!=', $anchor->id)->firstOrFail(); $this->get('/investimentos/iniciar?'.http_build_query(['source' => 'portfolio:'.$other->id, 'submission' => $row->id]))->assertUnprocessable(); $case = $this->postJson('/investimentos', ['title' => 'SYNTHETIC QA - manifesto e ancora', 'client_key' => (string) Str::uuid(), 'reuse_consent' => true])->assertCreated()->json('id'); $version = $this->getJson('/investimentos/'.$case.'/contexto')->json('case.version'); $this->postJson('/investidor/manifestacoes/'.$row->id.'/contexto', ['case_id' => $case, 'case_version' => $version, 'version' => (int) $row->version])->assertOk(); $this->assertSame($row->id, DB::table('desk_cases')->where('id', $case)->value('submission_id')); $this->assertSame($anchor->id, DB::table('investment_submissions')->where('id', $row->id)->value('dossier_id')); $this->actingAs(User::factory()->create()); $this->get($start)->assertNotFound(); } }