feat(tradein/yandex): normalize house_type + promote kitchen/ceiling to columns (#2007) #2016

Merged
lekss361 merged 2 commits from feat/tradein-2007-yandex-house-type-promote into main 2026-06-27 17:45:12 +00:00

2 commits

Author SHA1 Message Date
024fadac73 fix(tradein/yandex): cap ceiling to numeric(3,2) range + backfill 'other'->NULL
All checks were successful
CI / changes (pull_request) Successful in 8s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Pre-push review (#2007):
- ceiling_height_m: clamp to plausible 2.0-6.0 m. yandex SERP emits garbage (seen 18 m)
  -> out-of-range write to ceiling_height numeric(3,2) raised DataError failing the whole
  batch (per-lot SAVEPOINT only catches IntegrityError). Raw value still in raw_payload.
- migration 140: also NULL out legacy 'other' (299 rows) for parity with
  normalize_house_type (unknown->None; NULL neutral in estimator vs 'other' false penalty).
2026-06-27 20:43:31 +03:00
a1ee06ef17 feat(tradein/yandex): normalize house_type + promote kitchen/ceiling to columns (#2007)
house_type-нормализация = реальный фикс estimator soft-penalty: yandex SERP
писал building.buildingType как есть (SCREAMING — MONOLIT/BRICK/PANEL/...),
а estimator штрафует аналог с house_type != target. 'MONOLIT' никогда не равен
каноничному 'monolith' → ~70% yandex-аналогов получали ложный штраф и фактически
выпадали из скоринга. Новый модуль house_type_normalizer.normalize_house_type
приводит yandex SCREAMING и cian camelCase (reuse в #2008) к канону
{panel, brick, monolith, monolith_brick, block, wood}; unknown/'other'/'' → None
(NULL нейтрально для estimator, не штрафуется). Backfill существующих yandex-строк
миграцией 140 (идемпотентный UPDATE под тот же маппинг).

kitchen_area_m2 / ceiling_height_m promote из raw_payload в колонки — для
coverage-дашборда и matching, НЕ valuation-фича (estimator их пока не читает —
отдельный follow-up). ceiling пишется в ОБЕ колонки (ceiling_height 019 — её
читает coverage-дашборд admin.py + yandex_detail/cian_detail; ceiling_height_m
111 — живая avito-колонка) через COALESCE в ON CONFLICT, чтобы SERP re-scrape
без полей не затирал detail-enrichment (avito поведение сохранено).
2026-06-27 20:30:27 +03:00