create(); config(['portal.managers' => [$manager->email], 'portal.opportunity_specialized_drafts_enabled' => true]); $payload = ['creation_key' => (string) Str::uuid(), 'opportunity_category' => 'real_estate', 'title' => 'QA imóvel incompleto', 'real_estate' => ['transaction_type' => 'lease', 'land_area' => 250.5, 'area_unit' => 'sqm'], 'reason' => 'Rascunho imobiliário incompleto sem decisão externa']; $draft = $this->actingAs($manager)->postJson('/management/opportunities/drafts', $payload)->assertCreated()->json(); $this->postJson('/management/opportunities/drafts', $payload)->assertCreated()->assertJsonPath('id', $draft['id']); $this->assertSame(1, Opportunity::count()); $path = '/management/opportunities/'.$draft['id'].'/edit'; $this->get($path)->assertInertia(fn (Assert $page) => $page->where('values.real_estate.land_area', 250.5)->where('record.status', 'draft')); $this->putJson('/management/opportunities/'.$draft['id'].'/draft', ['etag' => $draft['etag'], 'real_estate' => ['rent' => 1000, 'rent_periodicity' => 'monthly'], 'reason' => 'Complemento de renda no mesmo rascunho imobiliário'])->assertOk(); $this->get($path)->assertInertia(fn (Assert $page) => $page->where('values.real_estate.land_area', 250.5)->where('values.real_estate.rent', 1000)); $record = Opportunity::findOrFail($draft['id']); $before = $record->getRawOriginal(); foreach ([['price' => 0], ['price' => '100'], ['transaction_type' => 'sell_duat'], ['id' => (string) Str::uuid()], ['utilities' => ['invalid scalar']], ['planning_permit_document_id' => 'not-uuid']] as $invalid) { $this->putJson('/management/opportunities/'.$draft['id'].'/draft', ['etag' => app(OpportunityManagement::class)->etag($record), 'real_estate' => $invalid, 'reason' => 'Negativo contratual que deve conservar o rascunho'])->assertUnprocessable(); $this->assertSame($before, $record->fresh()->getRawOriginal()); } $this->actingAs(User::factory()->create())->get($path)->assertForbidden(); $this->assertSame(0, Opportunity::published()->count()); } public function test_specialized_draft_never_changes_published_version_and_is_disabled_by_default(): void { $manager = User::factory()->create(); config(['portal.managers' => [$manager->email]]); $this->actingAs($manager)->postJson('/management/opportunities/drafts', ['creation_key' => (string) Str::uuid(), 'opportunity_category' => 'real_estate', 'real_estate' => ['transaction_type' => 'sale'], 'reason' => 'Incremento desativado mantém compatibilidade ativa'])->assertUnprocessable(); $this->assertSame(0, Opportunity::count()); config(['portal.opportunity_specialized_drafts_enabled' => true]); $sector = Sector::create(['name' => 'QA imóveis', 'slug' => 'qa-real-estate', 'is_active' => true, 'sort_order' => 1]); $record = Opportunity::create(['title' => 'QA published original', 'reference' => 'QA-RE-PUBLISHED', 'slug' => 'qa-re-published', 'sector_id' => $sector->id, 'status' => 'published', 'published_at' => now(), 'opportunity_category' => 'real_estate', 'management_version' => 1]); $record->forceFill(['opportunity_category' => 'real_estate'])->save(); $this->putJson('/management/opportunities/'.$record->id.'/draft', ['etag' => app(OpportunityManagement::class)->etag($record), 'real_estate' => ['transaction_type' => 'sale', 'price' => 50000], 'reason' => 'Nova proposta privada sem alteração da ficha publicada'])->assertOk(); $this->assertSame('QA published original', $record->fresh()->title); $this->assertSame('published', $record->fresh()->status); $this->getJson('/api/v1/opportunities/qa-re-published')->assertOk()->assertJsonMissingPath('data.real_estate')->assertJsonMissingPath('data.management_draft'); $this->assertSame(50000, json_decode($record->fresh()->management_draft, true)['real_estate']['price']); } }