fix: reconcile accepted source classifications for protected investor aggregates
tests / ci (push) Waiting to run

This commit is contained in:
2026-11-15 23:25:51 +02:00
parent c8957ecb9d
commit b60c231ddc
14 changed files with 11171 additions and 26 deletions
+57 -1
View File
@@ -214,7 +214,63 @@ final class ProtectedSupplyAggregateTest extends TestCase
$after = $this->getJson('/investimentos/'.$id)->assertOk()->json();
$this->assertSame($before['case']['version'], $after['case']['version']);
$this->assertSame([], $after['supply_aggregates']);
$this->assertSame([], $after['supply_activity_options']);
$this->assertContains('ebau:979', array_column($after['supply_activity_options'], 'id'));
}
public function test_accepted_source_classification_works_by_code_or_exact_label_without_public_numeric_catalogue(): void
{
$sector = Sector::create(['name' => 'SYNTHETIC general tourism', 'slug' => 'qa-'.Str::lower(Str::random(16)), 'is_active' => true]);
$this->sectors['source_only'] = $sector->id;
$id = $this->dossier('source_only');
DB::table('proactive_supply_observations')->where('source_hash', $this->sourceHash)->where('cae', '55110')->update(['cae' => '55111', 'activity' => 'HOTÉIS COM RESTAURANTE']);
$coded = $this->aggregateSnapshot($id, ['classification_key' => 'ebau:979']);
$this->assertSame('55', $coded['groups'][0]['code']);
$this->assertSame('5–9', $coded['groups'][0]['entities_band']);
$this->assertSame('ebau:979', $coded['filters']['classification_key']);
$this->assertSame($sector->id, $coded['filters']['sector_id']);
DB::table('proactive_supply_observations')->where('source_hash', $this->sourceHash)->where('cae', '55111')->update(['cae' => '']);
$labelled = $this->aggregateSnapshot($id, ['classification_key' => 'ebau:979']);
$this->assertSame($coded['groups'], $labelled['groups']);
for ($i = 0; $i < 6; $i++) {
$row = $this->observation($this->sourceHash, '56', 'restaurant-'.$i, $this->geo['large']);
DB::table('proactive_supply_observations')->where('id', $row)->update(['cae' => '', 'activity' => 'RESTAURANTES (INCLUI ACTIVIDADES DE RESTAURAÇÃO EM MEIOS MÓVEIS)']);
}
$restaurant = $this->aggregateSnapshot($id, ['classification_key' => 'ebau:345']);
$this->assertSame('56', $restaurant['groups'][0]['code']);
$this->assertSame('5–9', $restaurant['groups'][0]['entities_band']);
$after = $this->getJson('/investimentos/'.$id)->assertOk()->json();
$this->assertCount(3, $after['supply_aggregates']);
$this->assertSame('ebau:345', $after['supply_aggregates'][2]['filters']['classification_key']);
$this->assertStringNotContainsString('PRIVATE-', json_encode($after['supply_aggregates'], JSON_THROW_ON_ERROR));
$this->assertSame('1000000', $after['investment_context']['fields']['investment_budget_min']);
}
public function test_conflicting_and_unidentified_source_classifications_are_not_invented_matches(): void
{
$id = $this->dossier('hotel');
DB::table('proactive_supply_observations')->where('source_hash', $this->sourceHash)->where('cae', '55110')->update(['cae' => '01', 'activity' => 'HOTÉIS COM RESTAURANTE']);
$a = $this->aggregateSnapshot($id, ['classification_key' => 'ebau:979']);
$this->assertSame([], $a['groups']);
$v = $this->getJson('/investimentos/'.$id)->json('case.version');
$this->postJson('/investimentos/'.$id.'/contexto/oferta-agregada', ['version' => $v, 'operation_key' => (string) Str::uuid(), 'classification_key' => 'ebau:99999999'])->assertUnprocessable();
$this->postJson('/investimentos/'.$id.'/contexto/oferta-agregada', ['version' => $v, 'operation_key' => (string) Str::uuid(), 'classification_key' => 'ebau:979', 'activity_id' => $this->activities['hotel']])->assertUnprocessable();
$this->actingAs(User::factory()->create())->postJson('/investimentos/'.$id.'/contexto/oferta-agregada', ['version' => $v, 'operation_key' => (string) Str::uuid(), 'classification_key' => 'ebau:979'])->assertForbidden();
}
public function test_previously_accepted_tourism_scope_is_accommodation_without_inventing_a_specific_subtype(): void
{
$source = 'f02e086ed4973ef17234aa6cc54b98fbb7a6952ffb16ec4dc4f7d0c72af6400c';
$this->assertFalse(DB::table('proactive_supply_sources')->where('sha256', $source)->exists(), 'Only isolated synthetic source allowed');
DB::table('proactive_supply_sources')->insert(['sha256' => $source, 'name' => 'SYNTHETIC accepted tourism contract', 'period' => '2024', 'limitations' => 'SYNTHETIC', 'receipt' => json_encode(['candidate' => 'a022ed9848b41ba342b4209414c2bbf2ebd0a7a3', 'access' => 'internal', 'synthetic' => true], JSON_THROW_ON_ERROR), 'imported_at' => now()]);
for ($i = 0; $i < 6; $i++) {
$row = $this->observation($source, '55', 'tourism-broad-'.$i, $this->geo['large']);
DB::table('proactive_supply_observations')->where('id', $row)->update(['cae' => '', 'activity' => 'Alojamento (âmbito do exemplar; categoria por conferir)']);
}
$id = $this->dossier('hotel');
$a = $this->aggregateSnapshot($id, ['classification_key' => 'ebau:158']);
$this->assertSame('ALOJAMENTO', $a['groups'][0]['label']);
$this->assertSame('5–9', $a['groups'][0]['entities_band']);
$this->assertStringNotContainsString('HOTÉIS COM RESTAURANTE', $a['groups'][0]['label']);
}
public function test_unresolved_observation_keys_conflicts_duplicates_and_unknown_import_contracts_do_not_form_a_publishable_cohort(): void