fix(tradein/houses): camelCase-типы домов приводятся к канону у источника (#2678) #2719
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#2719
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2678-house-type-canon"
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?
Что чинит
Хвост #2675 (пункты 1 и 6 из #2678). Миграция 141 привела тип дома к канону только в объявлениях; в таблице домов camelCase-вокабуляр Циана остался, и каждый читатель чинил его у себя — #2675 починил домовую оценку, остальные потребители продолжали сравнивать
monolithBrickсmonolith_brickи не совпадать (ложный штраф при подборе аналогов, пропуск оценки на поштучном пути).Замер прода 2026-08-06 (
SELECT source, house_type, count(*) FROM houses GROUP BY 1,2)monolithBrickotherstalinaerocreteBlock/gasSilicateBlock/wireframeЧисла совпали с оценкой в #2674 (там «75 домов с camelCase» — фактически 56 camelCase + 3 stalin + 18 other + 1 wireframe = 78 неканоничных, из них мапится 61).
Проверка смысла ПЕРЕД склейкой (контрольная группа в своих же данных)
Для каждой неканоничной строки взяты типы её ЖЕ объявлений (
listings.house_id_fk), уже нормализованных миграцией 141:monolithBrick×56monolith_brickприсутствует у всех 56stalin×3brickaerocreteBlock×1blockgasSilicateBlock×1blockother×18wireframe×1wireframeи у объявленийЧто сделано
houses):monolithBrick→monolith_brick,gasSilicateBlock/aerocreteBlock/foamConcreteBlock→block,stalin→brick. Ожидаемо тронута 61 строка (56+3+1+1+0, счётчики сняты на проде до применения). Идемпотентна: повторный прогон 0 строк. ПлюсCOMMENT ON COLUMNс каноном и с тем, что осталось вне его намеренно.housesнет — у всех 80 неканоничных строк одна и та же меткаlast_scraped_at = 2026-05-24 14:04:20.012209, т.е. единственный прогон backfill'а 063 (промоут из listings ДО 141). Единственный живой писательhouses.house_type— avito-каталог домов (providers/avito/houses.py), и он был вторым источником неканона: незнакомую подпись превращал в'other'. Теперь идёт через общийnormalize_house_type, неизвестное → NULL._RAW_TO_CANONдобавлен канонический токенmonolith_brick— единственный, у которого не было регистронезависимой страховки.Третьего словаря не заводим: тест сверяет
CASEмиграции с картой кода.Чего тут НЕТ (и почему)
monolithicvsmonolith_brickв запросах к Авито) — закрывается зондирующим запросом к площадке; живые запросы к площадкам в этой сессии запрещены. Остаётся открытым в #2678.Test plan
tests/test_2678_house_type_canon.py— каждый ФАКТИЧЕСКИЙ вариант с прода → канон/честный None; писатель avito больше не изобретает'other'; регистр канона; CASE миграции == карта кода; WHERE не задеваетother/wireframetest_search_cache_hit)SELECT house_type, count(*) FROM houses GROUP BY 1— camelCase 0,monolith_brick+56,brick+3,block+2Refs #2678