feat(sitefinder): rosreestr cadastral-value loader + 0.7x denoise of quarter price index #2068
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#2068
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/rosreestr-cadastral-value-denoise"
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?
What / why
Adds a quarterly Rosreestr cadastral-value loader and uses it to denoise the
deals price index. The open dataset
dataset_КАДАСТРСТОИМОСТЬgives a per-cad-quartercadastral ₽/m² (
cost_per_area). Registered deals priced below 0.7× the cadastralmedian for their quarter are dropped from
mv_quarter_price_per_m2as noise(data-entry junk / non-arm's-length deals that drag medians down).
Chain (consumers unchanged):
rosreestr_deals→mv_quarter_price_per_m2(95) →mv_quarter_price_index(99a)→ tradein FDW
quarter_price_index.Files
data/sql/178_schema_cadastral_value.sql—rosreestr_cadastral_value(+_staging),region-66-scoped, idempotent (
CREATE TABLE/INDEX IF NOT EXISTS,BEGIN/COMMIT).data/sql/178b_load_cadastral_value.py— psycopg v3 loader, mirrors02b_load_via_tunnel.py: stagingcur.copy()(UTF-8,~delimiter) → typed INSERTfiltering
region_code='66'with regex-guarded numeric casts; idempotent skip-if-loaded.data/sql/179_mv_quarter_price_cadastral_floor.sql— recreates both MVs(
DROP ... mv_quarter_price_per_m2 CASCADEalso drops the dependent index MV). Adds acad_floorCTE +LEFT JOINfloor predicate tomv_quarter_price_per_m2;mv_quarter_price_indexrecreated verbatim from 99a to restore the FDW contract.Safety — no-op when cadastral table is empty
179auto-applies on prod (via_schema_migrations) before any cadastral data isloaded. The table exists (178) but is empty →
cad_floorhas zero rows → theLEFT JOINyieldsfloor_ppm2 IS NULLfor every quarter → the predicatecf.floor_ppm2 IS NULL OR price_m2 >= cf.floor_ppm2keeps all deals → the rebuiltmv_quarter_price_per_m2is byte-identical to the pre-floor (95) definition.The floor only activates after an operator loads cadastral data and REFRESHes the MVs.
Dry-run (rolled back, against prod data — nothing mutated)
Used the existing experiment table
cad_value_66_2026q1(70 340 apartment rows, region 66)as a stand-in cadastral source.
cad_value_66_2026q1(quarter, deals_count, median)EXCEPTboth directions =0 / 0(byte-identical to live for the66:%scope).HAVING ≥ 3, 470 got a higher median). Samples:66:41:0401048252→199 deals, median 120 883→134 783;66:41:0705005326→279, median 115 294→122 388.NOTE — data load is manual
The cadastral CSV is not auto-loaded. Deploy order:
178+179auto-apply (MVs rebuilt, no behaviour change — cad table empty).data/raw/and runsuv run python ../data/sql/178b_load_cadastral_value.py 2026Q1.REFRESH MATERIALIZED VIEW CONCURRENTLY mv_quarter_price_per_m2;then
... mv_quarter_price_index;to activate the floor.Deviation from spec
Migration numbers bumped 172/173 → 178/178b/179:
172–177already exist onmain(spec assumed max=171). NN = next sequential per
.claude/rules/sql.md.🤖 Generated with Claude Code