fix(tradein): sanitize ДКП deal outliers (floor / ppm²) (#699) #733
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#733
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/699-deals-outlier-sanitize"
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?
Summary
actual_dealscarried non-market / broken Rosreestr rows (floor:100, ~39.7 K/m² for 125 m²) that feddkp_corridor+expected_soldwith noise — hurting the demo "killer factor" (price-range accuracy).Fix
Absolute guard-bands for EKB vtorichka (
_is_plausible_deal):[50K, 800K]— market is ~100–400K (cf._band_haircut180/350K), premium up to ~680K; below/above is not arms-length (shares, encumbered, typos). Drops the39 700report case.[1, 60]andfloor ≤ total_floors— dropsfloor:100and physically-impossible floors (30th floor in a 5-storey). A real high floor in a tall building (30/30) is kept.Applied in two places:
_fetch_deals→ filters rows via_is_plausible_deal(coversactual_dealsdisplay + anything downstream)._fetch_dkp_corridor→ adds the ppm² band to its SQLWHERE(coversexpected_soldcorridor).The existing relative Tukey outlier filter on listings is unchanged. None fields aren't judged (None-safe).
Test plan
tests/test_deals_sanitize.py(8 cases): dropsfloor:100,39.7K/m²,floor>total_floors, over-band ppm²; keeps normal deals, real high floors, band edges, null fields.ruff checkclean.Refs #699
✅ APPROVE
Demo-critical fix #699 (Praktika milestone, точность ценового диапазона). Корректно и end-to-end.
Correctness
_fetch_dealsSELECT отдаётfloor, total_floors, price_per_m2(стр. 3012–3013) → фильтр читает реальные колонки,floor ≤ total_floors-guard не вырождается в no-op._is_plausible_deal: None-safe, каждое поле судится независимо (тестtest_null_fields_not_judgedэто покрывает); floor[1,60]ловитfloor:100независимо от total_floors._fetch_dkp_corridor: ppm²-band через bound-params:ppm_min/:ppm_max— без инъекции, psycopg-safe.Bands — абсолютные guard-bands (не статистические) с документированным EKB-обоснованием (рынок ~100–400К, премиум ~680К). Правильный инструмент для битых строк (floor:100, 39.7К/м²) — не искажает легитимное распределение, нижний 50К отсекает не-arms-length.
Tests — 8 кейсов: репорт-кейсы + edges + None-independent-judgment. 226 regression pass, ruff clean.
Scope/security — только estimator.py + новый тест; listings Tukey-фильтр нетронут; нет миграции, нет secrets, нет self-extending триггера. Coverage/accuracy validation → qa.