create(); $user = User::factory()->create(['tenant_id' => $tenant->id]); DB::statement('SET app.current_tenant_id = '.$tenant->id); $run = AutopodborRun::create(['tenant_id' => $tenant->id, 'kind' => 'study', 'status' => 'done', 'region_code' => 16, 'params' => []]); // конкурент в поле $fieldComp = AutopodborCompetitor::create([ 'tenant_id' => $tenant->id, 'search_run_id' => $run->id, 'name' => 'Окна Комфорт', 'dedup_key' => 'okna', 'box' => 'field', 'relevance_pct' => 90, ]); // конкурент в предложениях — НЕ должен попасть AutopodborCompetitor::create([ 'tenant_id' => $tenant->id, 'search_run_id' => $run->id, 'name' => 'Предложенный', 'dedup_key' => 'prop', 'box' => 'proposal', ]); // активный проект для источника A $project = Project::factory()->create([ 'tenant_id' => $tenant->id, 'is_active' => true, 'preflight_blocked_at' => null, ]); // источник A — в поле, с активным проектом AutopodborSource::create([ 'tenant_id' => $tenant->id, 'competitor_id' => $fieldComp->id, 'study_run_id' => $run->id, 'signal_type' => 'site', 'identifier' => 'okna-a.ru', 'dedup_key' => 'site:okna-a.ru', 'box' => 'field', 'created_project_id' => $project->id, ]); // источник B — в поле, без проекта AutopodborSource::create([ 'tenant_id' => $tenant->id, 'competitor_id' => $fieldComp->id, 'study_run_id' => $run->id, 'signal_type' => 'site', 'identifier' => 'okna-b.ru', 'dedup_key' => 'site:okna-b.ru', 'box' => 'field', ]); // источник C — в предложениях, не считаем в поле AutopodborSource::create([ 'tenant_id' => $tenant->id, 'competitor_id' => $fieldComp->id, 'study_run_id' => $run->id, 'signal_type' => 'site', 'identifier' => 'okna-c.ru', 'dedup_key' => 'site:okna-c.ru', 'box' => 'proposal', ]); $resp = $this->actingAs($user)->getJson('/api/autopodbor/field') ->assertOk() ->assertJsonStructure([ 'competitors' => [[ 'id', 'name', 'box', 'counters' => ['sources', 'projects_created', 'projects_in_work'], 'sources' => [['id', 'identifier', 'box', 'project']], ]], ]); $data = $resp->json('competitors'); expect($data)->toHaveCount(1) ->and($data[0]['name'])->toBe('Окна Комфорт'); // счётчики: 2 источника в поле, 1 проект создан, 1 в работе expect($data[0]['counters']['sources'])->toBe(2) ->and($data[0]['counters']['projects_created'])->toBe(1) ->and($data[0]['counters']['projects_in_work'])->toBe(1); // источник A несёт статус проекта, источник B — null $ids = collect($data[0]['sources'])->keyBy('identifier'); expect($ids['okna-a.ru']['project'])->not->toBeNull() ->and($ids['okna-a.ru']['project']['is_active'])->toBeTrue() ->and($ids['okna-b.ru']['project'])->toBeNull(); }); it('GET /api/autopodbor/field — заблокированный по балансу проект не считается «в работе»', function () { $tenant = Tenant::factory()->create(); $user = User::factory()->create(['tenant_id' => $tenant->id]); DB::statement('SET app.current_tenant_id = '.$tenant->id); $run = AutopodborRun::create(['tenant_id' => $tenant->id, 'kind' => 'study', 'status' => 'done', 'region_code' => 16, 'params' => []]); $comp = AutopodborCompetitor::create([ 'tenant_id' => $tenant->id, 'search_run_id' => $run->id, 'name' => 'X', 'dedup_key' => 'x', 'box' => 'field', ]); $blocked = Project::factory()->create([ 'tenant_id' => $tenant->id, 'is_active' => true, 'preflight_blocked_at' => now(), ]); AutopodborSource::create([ 'tenant_id' => $tenant->id, 'competitor_id' => $comp->id, 'study_run_id' => $run->id, 'signal_type' => 'site', 'identifier' => 'x.ru', 'dedup_key' => 'site:x.ru', 'box' => 'field', 'created_project_id' => $blocked->id, ]); $data = $this->actingAs($user)->getJson('/api/autopodbor/field')->assertOk()->json('competitors'); expect($data[0]['counters']['projects_created'])->toBe(1) ->and($data[0]['counters']['projects_in_work'])->toBe(0); }); it('GET /api/autopodbor/field — чужой тенант своих в поле не видит', function () { $tenant = Tenant::factory()->create(); $user = User::factory()->create(['tenant_id' => $tenant->id]); DB::statement('SET app.current_tenant_id = '.$tenant->id); $run = AutopodborRun::create(['tenant_id' => $tenant->id, 'kind' => 'study', 'status' => 'done', 'region_code' => 16, 'params' => []]); AutopodborCompetitor::create([ 'tenant_id' => $tenant->id, 'search_run_id' => $run->id, 'name' => 'Чужой', 'dedup_key' => 'alien', 'box' => 'field', ]); $other = User::factory()->create(['tenant_id' => Tenant::factory()->create()->id]); $data = $this->actingAs($other)->getJson('/api/autopodbor/field')->assertOk()->json('competitors'); expect($data)->toHaveCount(0); });