inner = new FakeCompetitorAgent; } public function findCompetitors(FindCompetitorsRequest $r): FindCompetitorsResult { return new FindCompetitorsResult($this->competitors); } public function studyCompetitor(StudyCompetitorRequest $r): StudyCompetitorResult { return $this->inner->studyCompetitor($r); } public function resolveByName(ResolveByNameRequest $r): ResolveByNameResult { return $this->inner->resolveByName($r); } }; } function groupsTestSettings(): void { SystemSetting::updateOrCreate(['key' => 'autopodbor_price_search_rub'], ['value' => '300', 'type' => 'decimal']); SystemSetting::updateOrCreate(['key' => 'autopodbor_max_competitors'], ['value' => '15', 'type' => 'int']); } function mkSearchRun(int $tenantId): AutopodborRun { return AutopodborRun::create([ 'tenant_id' => $tenantId, 'kind' => 'search', 'status' => 'queued', 'region_code' => 16, 'params' => ['examples' => [], 'about_self' => ['ломбард'], 'include_federal' => false], ]); } it('находка, совпавшая с АРХИВОМ, сохраняется в предложения (не прячется на записи)', function () { Mail::fake(); $tenant = Tenant::factory()->create(['balance_rub' => '100000.00']); DB::statement('SET app.current_tenant_id = '.$tenant->id); groupsTestSettings(); // В архиве — ранее удалённый «Яричъ» с сайтом yarich.ru AutopodborCompetitor::create([ 'tenant_id' => $tenant->id, 'name' => 'Яричъ', 'origin' => 'auto', 'box' => 'archived', 'site_url' => 'yarich.ru', 'dedup_key' => 'site:yarich.ru', ]); app()->bind(CompetitorAgent::class, fn () => agentReturning([ ['name' => 'Яричъ', 'site_url' => 'yarich.ru', 'description' => 'ломбард', 'is_federal' => false, 'directory_urls' => [], 'relevance_pct' => 90, 'provenance' => []], ])); $run = mkSearchRun($tenant->id); app()->call([new RunAutopodborSearchJob($run->id), 'handle']); expect(AutopodborCompetitor::where('tenant_id', $tenant->id)->where('box', 'proposal')->where('name', 'Яричъ')->exists()) ->toBeTrue(); }); it('находка — полный дубль АКТИВНОЙ фирмы поля — на записи выкидывается (пусто)', function () { Mail::fake(); $tenant = Tenant::factory()->create(['balance_rub' => '100000.00']); DB::statement('SET app.current_tenant_id = '.$tenant->id); groupsTestSettings(); AutopodborCompetitor::create([ 'tenant_id' => $tenant->id, 'name' => 'Яричъ', 'origin' => 'auto', 'box' => 'field', 'site_url' => 'yarich.ru', 'dedup_key' => 'site:yarich.ru', ]); app()->bind(CompetitorAgent::class, fn () => agentReturning([ ['name' => 'Яричъ', 'site_url' => 'yarich.ru', 'description' => 'ломбард', 'is_federal' => false, 'directory_urls' => [], 'relevance_pct' => 90, 'provenance' => []], ])); $run = mkSearchRun($tenant->id); app()->call([new RunAutopodborSearchJob($run->id), 'handle']); expect(AutopodborCompetitor::where('tenant_id', $tenant->id)->where('box', 'proposal')->exists())->toBeFalse() ->and($run->fresh()->status)->toBe('empty'); }); it('GET /proposals раскладывает по группам; bulk убирает всю группу «ранее удалённые»', function () { $tenant = Tenant::factory()->create(); $user = User::factory()->create(['tenant_id' => $tenant->id]); DB::statement('SET app.current_tenant_id = '.$tenant->id); // в поле — Alpha (a.ru); в архиве — Beta (b.ru) AutopodborCompetitor::create(['tenant_id' => $tenant->id, 'name' => 'Alpha', 'origin' => 'auto', 'box' => 'field', 'site_url' => 'a.ru', 'dedup_key' => 'site:a.ru']); AutopodborCompetitor::create(['tenant_id' => $tenant->id, 'name' => 'Beta', 'origin' => 'auto', 'box' => 'archived', 'site_url' => 'b.ru', 'dedup_key' => 'site:b.ru']); // предложения: Gamma (новый), «Beta заново» (совпал с архивом b.ru → ранее удалён) $new = AutopodborCompetitor::create(['tenant_id' => $tenant->id, 'name' => 'Gamma', 'origin' => 'auto', 'box' => 'proposal', 'site_url' => 'g.ru', 'dedup_key' => 'site:g.ru']); $del = AutopodborCompetitor::create(['tenant_id' => $tenant->id, 'name' => 'Beta заново', 'origin' => 'auto', 'box' => 'proposal', 'site_url' => 'b.ru', 'dedup_key' => 'site:b.ru']); $groups = $this->actingAs($user)->getJson('/api/autopodbor/proposals')->assertOk()->json('groups'); expect($groups['new'][0]['name'])->toBe('Gamma') ->and($groups['archived'][0]['name'])->toBe('Beta заново'); // bulk: убрать всю группу «ранее удалённые» $this->actingAs($user)->postJson('/api/autopodbor/proposals/dismiss-archived')->assertOk(); expect(AutopodborCompetitor::find($del->id)->box)->toBe('archived') // ранее удалённый снова в архив ->and(AutopodborCompetitor::find($new->id)->box)->toBe('proposal'); // новых не трогаем });