feat(tradein): fill houses.year_built/material_walls from ДОМ.РФ КР1.1/1.2 + zhkh_year, propagate to listings (#2013) #2476
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2476
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/2013-domrf-year-backfill"
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?
Problem
houses.year_builtis only 38% filled andhouses.material_wallsis 0% filled. The existing ГИС-ЖКХ loader (app/services/zhkh_flats_loader.py, migr. 146/149) already populateshouses.zhkh_year(70% = 5002/7128) andhouses.zhkh_floors(70%), but never copies them intohouses.year_built/total_floors— that is the core gap. The estimator's cohort filter (app/services/estimator.py,year_built BETWEEN ...) directly depends on real years, so this is the real fix for #2013 (supersedes the parked cohort-exclusion PR #2474, which only worked around the symptom on avito).What this adds
app/services/domrf_kapremont_loader.py+ CLI taskapp/tasks/domrf_kapremont_load.py— downloads ДОМ.РФ капремонт open data (free, no auth) for region 66:export/190) —mkd_code, houseguid (ФИАС GUID), address, commission_year, number_floors_max, total_sq.export/275) — long-format (row per construction element permkd_code);wall_materialis populated only on theфасад(facade) element row.verify=False(домрф.рф serves an RU cert not verified by the default trust store — same situation assber_index.py).domrf_kapremont(idempotent,IS DISTINCT FROMgate, chunked SAVEPOINTs mirroringzhkh_flats_loader.py).data/sql/176_domrf_kapremont.sql— creates thedomrf_kapremontstaging table (schema only, no DML onhouses/listings).houses(backfill_houses_from_domrf) — two-step UPDATE:domrf_kapremontviaCOALESCE(gar_house_guid, house_fias_id, zhkh_house_guid) = houseguidgetyear_built = COALESCE(year_built, domrf.commission_year, zhkh_year),material_walls = COALESCE(material_walls, domrf.wall_material),total_floors = COALESCE(total_floors, domrf.number_floors_max, zhkh_floors).year_built/total_floorsfolded in from the already-loadedzhkh_year/zhkh_floorsif still NULL — so houses without a ДОМ.РФ match still benefit from the ГИС-ЖКХ data already on hand.year_built.listings(propagate_listings_year_from_houses) —UPDATE listings SET year_built = houses.year_built WHERE house_id_fklinks andlistings.year_built IS NULL. This is what actually lifts avito's estimator-visible year coverage (avito is 52.5% linked to houses viahouse_id_fkbut has 0%year_builtof its own).Coverage impact (expected, prod)
houses.year_built: 38% → higher (ДОМ.РФ region-66 registry + fold-in of the 70%-filledzhkh_year).houses.material_walls: 0% → non-zero (first source ever for this column).listings.year_builton avito: 0% → up to ~36-52% (bounded by avito's 52.5%house_id_fklink rate × however many of those linked houses gain ayear_built).Tests
tests/test_domrf_kapremont_loader.py(23 tests, all green):фасадrow withwall_material=кирпич).fetch_domrf_csvsdownload+unzip path with HTTP mocked viahttpx.MockTransport(no live network).CAST(:x AS type)discipline,ON CONFLICT ... IS DISTINCT FROMidempotency, COALESCE ordering (year_built, domrf.commission_year, zhkh_year), only-fills-NULL guards, listings propagation predicate.backfill_houses_from_domrf/propagate_listings_year_from_housesdry-run vs real-run branching (MagicMock db).Also ran (all green, unrelated pre-existing failure confirmed out of scope —
tests/test_search_api.py::test_search_cache_hit, RBAC/auth fixture ordering issue reproducible onforgejo/mainbefore this branch, not touched by this PR):tests/test_backtest_regression_gate.pytests/test_estimator*.py(450 tests)tests/test_migrations_manifest.pyDeliberately skipped
_link_listing_to_househook (as hinted in the issue) and found none —house_id_fklinking happens viaapp/services/matching/listings.pyand standalone backfill scripts, not a single save-time hook. Per the issue's own guidance, shipping the standalone backfill script (propagate_listings_year_from_houses, wired into the CLI task) rather than forcing an integration point that doesn't cleanly exist.gar_house_guid → house_fias_id → zhkh_house_guid) per the issue's "keep it simple/safe" guidance — no fuzzy address matching.