feat(#3051): deals.doc_type + регион и тип документа как параметры импорта Росреестра #3421

Merged
lekss361 merged 3 commits from feat/3051-deals-doc-type-region-param into main 2026-09-08 20:04:29 +00:00
Owner

Summary

Пункты 3 и 6 из #3051 (эпик #2989). Тип документа терялся при загрузке, а фильтр ДКП и регион 66 стояли литералами в двух местах — на них упирается расширение на регион 77.

Для Москвы это не косметика: в источнике за 2024 по region_code=77 лежит 30 627 ДДУ с медианой 112 743 ₽/м² против 107 005 ДКП с медианой 256 250 ₽/м². Это цены котлована, и без различимого признака они развалят любой ценовой коридор.

  • 288_deals_doc_type.sql — колонка doc_type text (idempotent), бэкфилл 'ДКП' для source='rosreestr' (всё, что там лежит, прошло фильтр ДКП на импорте — не эвристика), явный region_code=66 в default_params расписания. Индекса нет: селективность 2-3 значения, живые выборки идут по region_code/deal_date/geom.
  • scheduler.import_rosreestr_dkpregion_code и doc_types из params, дефолты 66 / ['ДКП'] воспроизводят текущее прод-поведение байт-в-байт. Фильтры через bind-параметры (CAST(:region_code AS int), ANY(CAST(:doc_types AS text[]))), doc_type теперь пишется в deals.
  • dedup_hash оставлен как 'ros:dkp:' || idid уникален в источнике независимо от типа документа, а смена формы ключа осиротила бы все уже загруженные строки (ровно то, что чинила миграция 077). Причина записана комментарием.
  • deploy/import-rosreestr.sh — те же два параметра как env со старыми дефолтами, doc_type протащен через staging.

Test plan

  • Pushdown в FDW проверен на проде EXPLAIN (VERBOSE): Remote SQL ... WHERE ((doc_type = ANY ('{ДКП}'::text[]))) ... AND ((region_code = 66)) ... LIMIT 2000 — оба предиката и LIMIT уезжают на удалённую сторону, регрессии плана нет
  • uv run pytest tests/test_rosreestr_dedup_key.py -q → 10 passed (обновлён под уход литералов из SQL живого импорта)
  • uv run ruff check + ruff format --check по изменённым файлам
  • bash -n deploy/import-rosreestr.sh
  • Стоимость бэкфилла на проде: deals = 108 623 строки / 49 MB, все source='rosreestr' — разовый UPDATE на деплое дёшев
  • Живой прогон импорта после мержа (миграции tradein применяются автоматически, strict)

Новые тесты не писались — до живой проверки функционала.

Часть #3051 (п. 3 и 6), эпик #2989.

## Summary Пункты 3 и 6 из #3051 (эпик #2989). Тип документа терялся при загрузке, а фильтр ДКП и регион 66 стояли литералами в двух местах — на них упирается расширение на регион 77. Для Москвы это не косметика: в источнике за 2024 по `region_code=77` лежит 30 627 ДДУ с медианой 112 743 ₽/м² против 107 005 ДКП с медианой 256 250 ₽/м². Это цены котлована, и без различимого признака они развалят любой ценовой коридор. - `288_deals_doc_type.sql` — колонка `doc_type text` (idempotent), бэкфилл `'ДКП'` для `source='rosreestr'` (всё, что там лежит, прошло фильтр ДКП на импорте — не эвристика), явный `region_code=66` в `default_params` расписания. Индекса нет: селективность 2-3 значения, живые выборки идут по `region_code`/`deal_date`/`geom`. - `scheduler.import_rosreestr_dkp` — `region_code` и `doc_types` из `params`, дефолты `66` / `['ДКП']` воспроизводят текущее прод-поведение байт-в-байт. Фильтры через bind-параметры (`CAST(:region_code AS int)`, `ANY(CAST(:doc_types AS text[]))`), `doc_type` теперь пишется в `deals`. - `dedup_hash` оставлен как `'ros:dkp:' || id` — `id` уникален в источнике независимо от типа документа, а смена формы ключа осиротила бы все уже загруженные строки (ровно то, что чинила миграция 077). Причина записана комментарием. - `deploy/import-rosreestr.sh` — те же два параметра как env со старыми дефолтами, `doc_type` протащен через staging. ## Test plan - [x] Pushdown в FDW проверен на проде `EXPLAIN (VERBOSE)`: `Remote SQL ... WHERE ((doc_type = ANY ('{ДКП}'::text[]))) ... AND ((region_code = 66)) ... LIMIT 2000` — оба предиката и LIMIT уезжают на удалённую сторону, регрессии плана нет - [x] `uv run pytest tests/test_rosreestr_dedup_key.py -q` → 10 passed (обновлён под уход литералов из SQL живого импорта) - [x] `uv run ruff check` + `ruff format --check` по изменённым файлам - [x] `bash -n deploy/import-rosreestr.sh` - [x] Стоимость бэкфилла на проде: `deals` = 108 623 строки / 49 MB, все `source='rosreestr'` — разовый UPDATE на деплое дёшев - [ ] Живой прогон импорта после мержа (миграции tradein применяются автоматически, strict) Новые тесты не писались — до живой проверки функционала. Часть #3051 (п. 3 и 6), эпик #2989.
lekss361 added 2 commits 2026-09-08 19:55:41 +00:00
ПОЧЕМУ: расширение на Москву упирается в два литерала. В источнике за 2024 по региону 77
лежат 30 627 ДДУ с медианой 112 743 против 107 005 ДКП с медианой 256 250 — это цены
котлована, и без различимого признака в deals они развалят любую оценку. При этом тип
сделки терялся при загрузке вовсе (в deals колонки не было), а фильтры region_code = 66
и doc_type = 'ДКП' стояли литералами в scheduler.import_rosreestr_dkp и в двойнике
deploy/import-rosreestr.sh — сменить регион было нельзя, не правя код.

ЧТО:
- миграция 288: deals.doc_type text (idempotent) + бэкфилл 'ДКП' для source='rosreestr'
  (корректен, а не эвристика: всё загруженное прошло фильтр ДКП — и в импорте, и в 077)
  + явный region_code=66 в default_params расписания rosreestr_dkp_import вместо неявного
  дефолта в коде. Индекс НЕ добавлен: 2-3 значения, живые выборки идут по
  region_code/deal_date/geom — заведём частичный, когда появится режущий запрос;
- import_rosreestr_dkp: region_code (default 66) и doc_types (default ['ДКП']) из params,
  фильтры через bind-параметры CAST(:region_code AS int) / ANY(CAST(:doc_types AS text[])),
  doc_type едет из SELECT в INSERT и в ON CONFLICT DO UPDATE. Дефолты сохраняют текущее
  прод-поведение байт-в-байт;
- dedup_hash оставлен как 'ros:dkp:' || id: id уникален в источнике независимо от типа
  документа, а смена формы ключа осиротила бы уже загруженные строки (ровно то, что
  разгребала миграция 077);
- deploy/import-rosreestr.sh: REGION_CODE / DOC_TYPE как env со старыми дефолтами,
  doc_type протащен через staging в deals; шапка про «ЕКБ квартиры» переписана честно —
  city-фильтр снят давно, скоуп = весь регион;
- тесты: test_rosreestr_dedup_key переведён с ассертов на литералы на проверку
  «параметр + дефолт = скоуп 077»; новый test_3051_* проверяет bind-параметры реальным
  вызовом с моком Session, дефолты 66/['ДКП'], doc_type в колонках INSERT и текст 288.
chore(#3051): снять новые тесты — до живой проверки функционала тесты не пишем
Some checks failed
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Failing after 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
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
CI Trade-In / backend-tests (pull_request) Successful in 5m7s
476fb9b77a
В существующем test_rosreestr_dedup_key оставлена только правка, без которой
он падает после параметризации (литералы region_code=66 / doc_type='ДКП'
ушли из SQL живого импорта). Новый тест-файл и добавленная функция сняты:
поведение ещё не проверено на живом импорте, тест зафиксировал бы догадку.
bot-backend added 1 commit 2026-09-08 19:58:44 +00:00
fix(#3051): lock_timeout в миграции 288 — гейт CI #2752
All checks were successful
CI / changes (pull_request) Successful in 10s
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 5m11s
e9370818ea
ALTER TABLE deals ADD COLUMN без SET LOCAL lock_timeout встаёт в очередь за
чужой сессией и уводит за собой запросы приложения. Лучше упасть по таймауту
и повторить деплой.
lekss361 merged commit 541c4ff28d into main 2026-09-08 20:04:29 +00:00
lekss361 deleted branch feat/3051-deals-doc-type-region-param 2026-09-08 20:04:30 +00:00
Author
Owner

Уточнение: на момент этого комментария PR уже был смержен другой сессией (20:04:29 UTC, 541c4ff2) — закрывать нечего. Ветка feat/3051-rosreestr-import-region-param (PR #3422) перебазируется поверх main как дельта: маппинг city='Москва'/address для 77 без потери сделок с пустым city, исходный округ в raw_payload, колонки okato/quarter_cad_number/district у foreign table, wildcard-расписание rosreestr_dkp_import_* с выключенным seed 77, чекпоинт per-source.

Уточнение: на момент этого комментария PR уже был смержен другой сессией (20:04:29 UTC, 541c4ff2) — закрывать нечего. Ветка `feat/3051-rosreestr-import-region-param` (PR #3422) перебазируется поверх main как дельта: маппинг `city='Москва'`/`address` для 77 без потери сделок с пустым city, исходный округ в `raw_payload`, колонки `okato`/`quarter_cad_number`/`district` у foreign table, wildcard-расписание `rosreestr_dkp_import_*` с выключенным seed 77, чекпоинт per-source.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3421
No description provided.