withoutVite(); $db = DB::selectOne('select current_database() as name, inet_server_port() as port'); $this->assertSame('investor_intent_20261115_test', $db->name); $this->assertSame(55441, (int) $db->port); config(['investor-path.enabled' => true, 'suitecrm.enabled' => false, 'investmoz_ai.enabled' => false]); } private function dossier(User $owner, string $title): string { $id = $this->actingAs($owner)->postJson('/investimentos', ['title' => $title, 'client_key' => (string) Str::uuid(), 'reuse_consent' => true])->assertCreated()->json('id'); $view = $this->getJson('/investimentos/'.$id.'/contexto')->assertOk()->json(); $body = ['version' => $view['case']['version'], 'selection' => [], 'declarations' => ['products_services' => 'SYNTHETIC activity '.$title, 'currency' => 'MZN', 'investment_budget_min' => '1000000', 'investment_budget_max' => '5000000']]; $plan = $this->postJson('/investimentos/'.$id.'/contexto/previa', $body)->assertOk()->json(); $this->postJson('/investimentos/'.$id.'/contexto/confirmar', [...$body, 'preview_hash' => $plan['preview_hash'], 'operation_key' => (string) Str::uuid(), 'confirm' => true])->assertOk(); return $id; } public function test_existing_company_is_reused_without_changing_ownership_or_repeating_the_comparison(): void { $owner = User::factory()->create(); $this->actingAs($owner); $company = $this->postJson('/api/v1/investment/companies', ['version' => 0, 'operation_key' => (string) Str::uuid(), 'payload' => ['name' => 'SYNTHETIC Hotel Company', 'incorporation_country_code' => 'MZ', 'registration' => 'SYNTHETIC-QA-REG', 'role' => 'SYNTHETIC representative', 'legal_form' => 'quotas']])->assertSuccessful()->json('id'); $id = $this->dossier($owner, 'Criar Hotel'); $options = $this->getJson('/investimentos/'.$id.'/contexto/entidade')->assertOk()->assertJsonPath('companies.0.id', $company)->json(); $memberships = DB::table('memberships')->count(); $command = ['version' => $options['version'], 'operation_key' => (string) Str::uuid(), 'kind' => 'company', 'id' => $company, 'source_version' => 1]; $url = '/investimentos/'.$id.'/contexto/entidade'; $this->postJson($url, $command)->assertOk()->assertJsonPath('continue', '/investimentos/'.$id); $this->postJson($url, $command)->assertOk()->assertJsonPath('replayed', true); $case = DB::table('desk_cases')->where('id', $id)->first(); $this->assertSame($owner->id, (int) $case->user_id); $this->assertNull($case->organization_id); $this->assertSame($company, $case->company_id); $this->assertSame($memberships, DB::table('memberships')->count()); $this->assertSame(1, DB::table('investment_company_declarations')->where('user_id', $owner->id)->count()); $this->getJson('/investimentos/'.$id.'/contexto')->assertOk()->assertJsonPath('prefill.simulator.legal_name', 'SYNTHETIC Hotel Company')->assertJsonPath('prefill.simulator.legal_form', 'quotas')->assertJsonPath('prefill.simulator.entity_stage', 'existing')->assertJsonPath('prefill.simulator.investment_budget_max', '5000000'); $preparation = $this->getJson('/investimentos/'.$id.'/preparar-empresa')->assertOk()->assertJsonPath('facts.proposed_name', 'SYNTHETIC Hotel Company')->assertJsonPath('facts.form', 'quotas')->json(); $facts = $preparation['facts']; $facts['notes'] = 'SYNTHETIC deliberate note'; $this->postJson('/investimentos/'.$id.'/preparar-empresa', ['version' => $preparation['case']['version'], 'operation_key' => (string) Str::uuid(), 'facts' => $facts])->assertOk(); $recovered = $this->getJson('/investimentos/'.$id.'/preparar-empresa')->assertOk()->assertJsonPath('facts.notes', 'SYNTHETIC deliberate note')->json(); $facts['form'] = 'anonymous'; $this->postJson('/investimentos/'.$id.'/preparar-empresa', ['version' => $recovered['case']['version'], 'operation_key' => (string) Str::uuid(), 'facts' => $facts])->assertUnprocessable(); $this->getJson('/investimentos/'.$id)->assertOk()->assertJsonPath('tools.simulator', '/simulador-fiscal?context='.$id); $this->actingAs(User::factory()->create())->postJson($url, $command)->assertForbidden(); $otherCase = $this->dossier(auth()->user(), 'Another private idea'); $v = $this->getJson('/investimentos/'.$otherCase.'/contexto/entidade')->assertOk()->assertJsonCount(0, 'companies')->json('version'); $this->postJson('/investimentos/'.$otherCase.'/contexto/entidade', [...$command, 'version' => $v, 'operation_key' => (string) Str::uuid()])->assertNotFound(); } public function test_optional_comparison_can_continue_into_the_same_unconstituted_entity_and_recover_without_creating_a_company(): void { $owner = User::factory()->create(); foreach (['Criar Hotel', 'Agronegocio QA'] as $title) { $id = $this->dossier($owner, $title); $comparison = $this->getJson('/investimentos/'.$id.'/forma-juridica')->assertOk()->json(); $answers = $comparison['answers']; $answers['preferred'] = 'quotas'; $body = ['version' => $comparison['case']['version'], 'operation_key' => (string) Str::uuid(), 'answers' => $answers, 'continue_preparation' => true]; $this->postJson('/investimentos/'.$id.'/forma-juridica', $body)->assertOk(); $this->postJson('/investimentos/'.$id.'/forma-juridica', $body)->assertOk()->assertJsonPath('replayed', true); $this->getJson('/investimentos/'.$id.'/contexto')->assertOk()->assertJsonPath('prefill.simulator.entity_stage', 'being_formed'); $preparation = $this->getJson('/investimentos/'.$id.'/preparar-empresa?form=quotas')->assertOk()->assertJsonPath('facts.form', 'quotas')->assertJsonPath('facts.activities', 'SYNTHETIC activity '.$title)->json(); $facts = $preparation['facts']; $facts['proposed_name'] = 'SYNTHETIC new company '.$title; $this->postJson('/investimentos/'.$id.'/preparar-empresa', ['version' => $preparation['case']['version'], 'operation_key' => (string) Str::uuid(), 'facts' => $facts])->assertOk(); $this->getJson('/investimentos/'.$id.'/preparar-empresa?form=anonymous')->assertOk()->assertJsonPath('facts.form', 'quotas')->assertJsonPath('proposedForm', 'anonymous'); $this->getJson('/investimentos/'.$id)->assertOk()->assertJsonPath('investment_context.promoter_entity.kind', 'being_formed'); $this->assertSame(0, DB::table('investment_company_declarations')->where('user_id', $owner->id)->count()); $this->assertNull(DB::table('desk_cases')->where('id', $id)->value('company_id')); $version = $this->getJson('/investimentos/'.$id.'/contexto/entidade')->json('version'); $this->postJson('/investimentos/'.$id.'/contexto/entidade', ['version' => $version, 'operation_key' => (string) Str::uuid(), 'kind' => 'undetermined'])->assertOk(); $this->getJson('/investimentos/'.$id)->assertOk()->assertJsonPath('investment_context.promoter_entity.kind', 'undetermined')->assertJsonPath('tools.simulator', '/simulador-fiscal?context='.$id); $this->getJson('/investimentos/'.$id.'/preparar-empresa')->assertOk()->assertJsonPath('facts.proposed_name', $facts['proposed_name']); } } public function test_an_authorised_organization_snapshot_does_not_transfer_the_case_or_grant_master_write_access(): void { $owner = User::factory()->create(); $org = (string) Str::uuid(); DB::table('organizations')->insert(['id' => $org, 'name' => 'SYNTHETIC represented organization', 'source_system' => 'unit-qa', 'organization_type' => 'private']); DB::table('memberships')->insert(['user_id' => $owner->id, 'organization_id' => $org, 'role' => 'viewer']); $id = $this->dossier($owner, 'Hotel with existing organization'); $url = '/investimentos/'.$id.'/contexto/entidade'; $options = $this->getJson($url)->assertOk()->assertJsonPath('organizations.0.id', $org)->json(); $command = ['kind' => 'organization', 'id' => $org, 'version' => $options['version'], 'operation_key' => (string) Str::uuid(), 'source_version' => 99]; $this->postJson($url, $command)->assertConflict(); $command['source_version'] = 1; $this->postJson($url, $command)->assertOk(); $case = DB::table('desk_cases')->where('id', $id)->first(); $this->assertNull($case->organization_id); $this->assertNull($case->company_id); $this->assertSame($owner->id, (int) $case->user_id); $this->assertSame('viewer', DB::table('memberships')->where('user_id', $owner->id)->where('organization_id', $org)->value('role')); config(['portal.organization_country_enabled' => true]); $this->putJson('/api/v1/investment/organizations/'.$org.'/country', ['version' => 1, 'country' => 'MZ', 'source_reference' => 'Synthetic QA'])->assertForbidden(); DB::table('memberships')->where('user_id', $owner->id)->where('organization_id', $org)->update(['deleted_at' => now()]); $current = $this->getJson($url)->assertOk()->assertJsonCount(0, 'organizations')->assertJsonPath('selected.snapshot.name', 'SYNTHETIC represented organization')->json(); $this->postJson($url, [...$command, 'version' => $current['version'], 'operation_key' => (string) Str::uuid()])->assertForbidden(); } }