Files
portal/app/tests/Unit/Autopodbor/AutopodborMergeTest.php
T
Дмитрий 64d6703bb3 feat(автоподбор): шаг1 E — сильное слияние конкурентов (union-find + вычет клиента)
AutopodborDedup::mergeCompetitors — склейка одного конкурента из 3 каналов под разными
написаниями, доменом-vs-именем или общим телефоном (union-find по корню имени/домена/номеру).
Объединяет ссылки справочников и телефоны, is_federal — местная карточка перевешивает.
Вычитает самого клиента (его имя/сайт не попадают в конкурентов). Усиливает §12.11.

Размещено в существующем backend-дедупе (§7.2 «дедуп на стороне бэкенда»), а не дублем
в движке. Старый dedupCompetitors и его тесты не тронуты.

Нормалайзер: nameKey/domainRoot (alnum-ключ, ё→е) — имя «Драйв займ» сцепляется с «драйвзайм.рф».

Тесты: merge 6/6; модуль Автоподбора unit 81/81; feature dedup 3/3; Pint чисто.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 17:36:59 +03:00

78 lines
3.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
use App\Services\Autopodbor\AutopodborDedup;
use App\Services\Autopodbor\AutopodborNormalizer;
function mergeService(): AutopodborDedup
{
return new AutopodborDedup(new AutopodborNormalizer);
}
it('склеивает конкурента, попавшего и по имени, и по домену (одна группа)', function () {
$merged = mergeService()->mergeCompetitors([
['name' => 'Драйв займ'], // только имя (из канала В)
['name' => 'Драйв Займ', 'site_url' => 'https://драйвзайм.рф/'], // имя + домен (из канала А)
]);
// имя «драйвзайм» = корень домена «драйвзайм» → одна карточка
expect($merged)->toHaveCount(1);
expect($merged[0]['site_url'])->toBe('https://драйвзайм.рф/');
});
it('склеивает по общему домену при разном написании имени', function () {
$merged = mergeService()->mergeCompetitors([
['name' => 'Окна Комфорт', 'site_url' => 'https://okna-komfort.ru/contacts'],
['name' => 'ОКНА-КОМФОРТ', 'site_url' => 'okna-komfort.ru'],
]);
expect($merged)->toHaveCount(1);
});
it('склеивает по общему телефону', function () {
$merged = mergeService()->mergeCompetitors([
['name' => 'Фирма А', 'phones' => ['73912920000']],
['name' => 'Фирма Б', 'phones' => ['73912920000', '79991112233']],
]);
expect($merged)->toHaveCount(1);
expect($merged[0]['phones'])->toContain('73912920000')->toContain('79991112233');
});
it('объединяет ссылки справочников и телефоны внутри группы', function () {
$merged = mergeService()->mergeCompetitors([
['name' => 'X', 'site_url' => 'x.ru', 'directory_urls' => ['https://2gis.ru/firm/1'], 'phones' => ['71112223344']],
['name' => 'X', 'site_url' => 'https://x.ru/', 'directory_urls' => ['https://yandex.ru/maps/org/x/2'], 'phones' => ['75556667788']],
]);
expect($merged)->toHaveCount(1);
expect($merged[0]['directory_urls'])->toContain('https://2gis.ru/firm/1')->toContain('https://yandex.ru/maps/org/x/2');
expect($merged[0]['phones'])->toContain('71112223344')->toContain('75556667788');
});
it('не склеивает разных конкурентов', function () {
$merged = mergeService()->mergeCompetitors([
['name' => 'Окна Комфорт', 'site_url' => 'okna-komfort.ru'],
['name' => 'Пластика Окон', 'site_url' => 'plastika.ru'],
]);
expect($merged)->toHaveCount(2);
});
it('вычитает самого клиента (по домену и по имени)', function () {
$merged = mergeService()->mergeCompetitors(
[
['name' => 'Мой Бизнес', 'site_url' => 'moy-biznes.ru'], // это сам клиент по домену
['name' => 'Драйв займ', 'site_url' => 'драйвзайм.рф'],
['name' => 'Мой Бизнес Плюс'], // сам клиент по имени
],
clientKeys: ['https://moy-biznes.ru', 'Мой Бизнес Плюс'],
);
$names = array_column($merged, 'name');
expect($names)->not->toContain('Мой Бизнес');
expect($names)->not->toContain('Мой Бизнес Плюс');
expect($names)->toContain('Драйв займ');
});