fix(ptica): «не продана» перестаёт означать «продана» (#2464) #2979
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2979
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2464-status-negation"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Дефект
Регекс статусов каталога ДОМ.РФ искал ключевые слова без защиты от отрицания. Русские отрицательные формы содержат положительные как подстроку, поэтому статус получался обратный:
Статус: нереализованареализованаКвартира не проданапроданаНе реализовано ни одной квартирыреализованоне забронированазабронированане в продажев продажеСвободная квартира уехала бы в
domrf_kn_flats.statusпроданной.Правка
Отрицание гасит токен, а не переворачивает его.
не забронированане означает ни sold, ни free, ане продана → free— это вывод, а не факт со страницы. Лучше отсутствие статуса, чем неверный.Заодно вылечен второй дефект того же места: разбор брал первое совпадение в блоке.
Квартира не продана. Статус: в продажена main даётsold— новый_status_in_textперебирает все вхождения и берёт первое неотрицаемое, так что настоящий статус в блоке больше не теряется.Граница слова (
\bне) не даёт зацепиться за хвост чужого слова:Цене снижена, квартира проданапо-прежнемуsold.Текущий эффект на проде — нулевой, и это проверено
Не «вероятно не влияет», а измерено:
Каталожный скрапер не записал ни одной строки: он всегда ставит
catalog_updated_atвместе соstatus, а этот столбец пуст поголовно. Существующие статусы пришли из kn-API — среди нихbooked, которого нет в константах этого модуля (STATUS_RESERVED = "reserved").То есть правка предупредительная: сегодня инвертировать нечего, но при включении пути статусы поехали бы молча и неотличимо от правильных.
Как проверено
origin/main7 тестов красные, каждый с конкретным неверным значением в сообщении («Нереализована» классифицировано как 'sold',assert 'sold' != 'sold') — краснота от значения, а не от отсутствующего символа.Продана,Реализована,Забронирована,Бронь,В продаже,Свободна,Продано) и случай«не» в хвосте слова. Они ловят «починку» через грубое гашение всего рядом со словом «не».parse_catalog_flat(полный разбор HTML), а не через хелпер — красное значение это ровно то, что доехало бы до БД.pytest backend/tests/services/scrapers/— 320 passed, 6 skipped. Существующие 15 тестов статусов не тронуты.Часть эпика #2464.
Регекс статусов каталога ДОМ.РФ искал ключевые слова без защиты от отрицания, поэтому русские отрицательные формы давали ОБРАТНЫЙ статус: «нереализована» → содержит «реализована» → sold «не продана» → содержит «продана» → sold «не забронирована» → содержит «забронирована» → reserved «не в продаже» → содержит «в продаже» → free Свободная квартира попадала бы в domrf_kn_flats.status проданной. Отрицание теперь гасит токен, а не переворачивает его. «Не забронирована» не означает ни sold, ни free; «не продана → free» — это вывод, а не факт со страницы. Лучше отсутствие статуса, чем неверный. Заодно вылечен второй дефект того же места: разбор брал ПЕРВОЕ совпадение в блоке, поэтому «Квартира не продана. Статус: в продаже» на main даёт sold. Новый _status_in_text перебирает все вхождения и берёт первое неотрицаемое — настоящий статус в блоке больше не теряется. Текущий эффект на проде НУЛЕВОЙ, и это проверено, а не предположено: catalog_updated_at пуст у всех 983 088 строк domrf_kn_flats (скрапер не записал ни одной), таска scrape_kn_catalog_flats закомментирована в beat_schedule.py из-за WAF-cooldown. Существующие значения status (free 25 656 / sold 3 122 / booked 641) пришли из kn-API — среди них 'booked', которого нет в константах этого модуля. Правка предупредительная: при включении пути дефект инвертировал бы статусы молча. Двусторонне: против origin/main 7 тестов красные, каждый с конкретным неверным значением («Нереализована» → 'sold'). Контроли (7 обычных форм и «не» в хвосте слова «Цене») зелёные с обеих сторон. Старая сюита парсера — 320 passed, регрессий нет. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>