fix(autopodbor): дубли по телефону застройщика — снят порог «людного» номера
Кейс «Образцово»: у застройщика (СМ.Сити) один номер отдела продаж легитимно висит на всех его ЖК (277-99-01 на 9 проектах). Прежний порог dropCrowdedKeys (>4 карточек → «рекламный», выкинуть) прятал это, и окно «Найти дубли» не показывало проекты застройщика — systematically (6 таких номеров в данных). Решение владельца 05.07: порог по ТЕЛЕФОНУ (p:) убрать — клиент подтверждает склейку вручную («Это разные»), тихой ложной склейки нет; рекламные-подменыши и так отсекаются на сборе. Порог по АДРЕСУ (a:, бизнес-центр) оставлен. Проверено на AutoMoney: его номер у 3 карточек — все реально Автодом24, группа верная, монстр-группы снятие порога не даёт. Тесты переписаны со старого поведения на новое (unit + feature), 421/421. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -188,10 +188,12 @@ final class AutopodborDedup
|
||||
return [];
|
||||
}
|
||||
|
||||
// Слабые «людные» ключи выкидываем: адрес (a:) бизнес-центра и телефон (p:) — рекламный/общий
|
||||
// номер, висящий у многих фирм (напр. 2ГИС-реклама одного «психа» на чужих карточках). Такой
|
||||
// ключ не опознаёт «одну фирму» → по нему НЕ группируем. Сильные ключи (сайт s:/справочник d:)
|
||||
// не трогаем — они опознают фирму даже у многих филиалов.
|
||||
// Слабый «людный» ключ выкидываем: адрес (a:) бизнес-центра — по одному адресу реально сидят
|
||||
// чужие фирмы. Телефон (p:) с порога СНЯТ (решение владельца 05.07): у застройщика один номер
|
||||
// отдела продаж легитимно висит на всех его ЖК (СМ.Сити: 9 проектов на 277-99-01) — прежний
|
||||
// порог 4 их прятал. Рекламные-подменыши отсекаются раньше (на сборе), а тихой ложной склейки
|
||||
// нет — группу лишь ПОКАЗЫВАЕМ, склейку клиент подтверждает вручную. Сильные ключи (сайт
|
||||
// s:/справочник d:) не трогаем — они опознают фирму даже у многих филиалов.
|
||||
$items = $this->dropCrowdedKeys($items);
|
||||
|
||||
$parent = range(0, $n - 1);
|
||||
@@ -249,9 +251,11 @@ final class AutopodborDedup
|
||||
}
|
||||
|
||||
/**
|
||||
* Выкидывает «людные» СЛАБЫЕ ключи, общие более чем у $cap фирм: адрес (a:) бизнес-центра и
|
||||
* телефон (p:) — рекламный/общий номер. Такой ключ не опознаёт «одну фирму». Сильные ключи
|
||||
* (сайт s:/справочник d:) не трогаем — они опознают фирму даже у многих филиалов.
|
||||
* Выкидывает «людный» СЛАБЫЙ ключ-адрес (a:), общий более чем у $cap фирм: по одному адресу
|
||||
* (бизнес-центр) реально сидят чужие фирмы → адрес их не опознаёт как «одну фирму». Телефон (p:)
|
||||
* с порога СНЯТ (решение владельца 05.07): у застройщика один номер отдела продаж легитимно висит
|
||||
* на всех его ЖК — режущий порог прятал их; ложной тихой склейки нет (клиент подтверждает вручную).
|
||||
* Сильные ключи (сайт s:/справочник d:) не трогаем — они опознают фирму даже у многих филиалов.
|
||||
*
|
||||
* @param array<int, array{id:int, keys?:list<string>}> $items
|
||||
* @return array<int, array{id:int, keys?:list<string>}>
|
||||
@@ -261,7 +265,7 @@ final class AutopodborDedup
|
||||
$count = [];
|
||||
foreach ($items as $it) {
|
||||
foreach (array_unique($it['keys'] ?? []) as $k) {
|
||||
if (str_starts_with((string) $k, 'a:') || str_starts_with((string) $k, 'p:')) {
|
||||
if (str_starts_with((string) $k, 'a:')) {
|
||||
$count[$k] = ($count[$k] ?? 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,15 +126,20 @@ it('группа несёт сайт и ссылки-справочники ка
|
||||
->and($comp['Ломбард Экспресс']['directory_urls'])->toContain('https://yandex.ru/maps/org/le/2');
|
||||
});
|
||||
|
||||
it('предложения: рекламный номер у слишком многих (>4) НЕ группирует (порог людного номера)', function () {
|
||||
it('предложения: единый номер застройщика у многих проектов ГРУППИРУЕТ (порог людного номера снят)', function () {
|
||||
// Кейс «Образцово» (реш. владельца 05.07): у застройщика (СМ.Сити) один номер отдела продаж
|
||||
// висит на всех его ЖК. Прежний порог 4 прятал их как «рекламный номер». Теперь показываем
|
||||
// группу — склейку клиент подтверждает вручную.
|
||||
[$t, $u, $run] = dupSetup();
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
dupProp($t, $run, 'Фирма '.$i, ['79135396546']); // один рекламный номер у пятерых
|
||||
for ($i = 1; $i <= 9; $i++) {
|
||||
dupProp($t, $run, 'ЖК '.$i, ['73912779901']); // единый номер застройщика на 9 проектах
|
||||
}
|
||||
|
||||
$this->actingAs($u)->getJson('/api/autopodbor/field/duplicate-groups?box=proposal')
|
||||
$resp = $this->actingAs($u)->getJson('/api/autopodbor/field/duplicate-groups?box=proposal')
|
||||
->assertOk()
|
||||
->assertJsonCount(0, 'groups');
|
||||
->assertJsonCount(1, 'groups');
|
||||
expect($resp->json('groups.0.competitors'))->toHaveCount(9);
|
||||
expect(mb_strtolower($resp->json('groups.0.reason')))->toContain('телефон');
|
||||
});
|
||||
|
||||
it('GET field/duplicate-groups — группирует по общему адресу источников (слабый сигнал)', function () {
|
||||
|
||||
@@ -271,16 +271,21 @@ it('duplicateGroups: защита от бизнес-центра — адрес
|
||||
expect($groups)->toBe([]);
|
||||
});
|
||||
|
||||
it('duplicateGroups: рекламный/общий телефон у слишком многих фирм НЕ группирует (как бизнес-центр)', function () {
|
||||
// Номер «психа» AutoMoney (реклама) или общая 8-800-линия висит у 6 фирм (порог 4) → это НЕ
|
||||
// «одна фирма», а рекламный/общий номер → такой телефон-ключ выкидываем, ложную группу не строим.
|
||||
it('duplicateGroups: телефон у многих фирм ГРУППИРУЕТ — решение владельца (клиент подтвердит сам)', function () {
|
||||
// Решение владельца 05.07: порог «людного» телефона УБРАН. У застройщика один номер отдела
|
||||
// продаж легитимно висит на всех его ЖК (СМ.Сити: 9 проектов на 277-99-01) — старый порог 4
|
||||
// прятал это. Рекламные-подменыши отсекаются раньше (на сборе), а тихой ложной склейки нет:
|
||||
// группу лишь ПОКАЗЫВАЕМ, склейку клиент подтверждает вручную («Это разные»). Проверено на
|
||||
// AutoMoney: его номер висит у 3 карточек — все реально Автодом24, группа верная.
|
||||
$items = [];
|
||||
for ($i = 1; $i <= 6; $i++) {
|
||||
$items[] = ['id' => $i, 'keys' => ['p:79135396546']];
|
||||
for ($i = 1; $i <= 9; $i++) {
|
||||
$items[] = ['id' => $i, 'keys' => ['p:73912779901']];
|
||||
}
|
||||
$groups = mergeService()->duplicateGroups($items);
|
||||
|
||||
expect($groups)->toBe([]);
|
||||
expect($groups)->toHaveCount(1);
|
||||
expect($groups[0]['ids'])->toBe([1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
expect(mb_strtolower($groups[0]['reason']))->toContain('телефон');
|
||||
});
|
||||
|
||||
it('duplicateGroups: общий телефон у немногих (2 фирмы) ОСТАЁТСЯ — идёт на решение клиента', function () {
|
||||
|
||||
Reference in New Issue
Block a user