feat(tradein/rosreestr): импорт ДКП по Москве (77) — canonical_city, raw_payload, wildcard-расписание rosreestr_dkp_import_*, per-source чекпоинт (#3051) #3422

Merged
lekss361 merged 3 commits from feat/3051-rosreestr-import-region-param into main 2026-09-08 20:28:21 +00:00
Owner

Дельта поверх #3421 (уже в main: параметры region_code/doc_types, deals.doc_type, миграция 288). Второй PR трека «Москва» (#2989#3051 п.3/п.6); пара к #3423 (PR-A, регион-фильтр коридора).

Что

  • Region.canonical_city (regions.py: 77 → «Москва», 66 → None). В import_rosreestr_dkp одна SQL-ветка через bind :canonical_city: для Москвы city='Москва', address='Москва, <street>'; фильтр city IS NOT NULL не применяется только когда задан canonical_city (иначе теряется ~10% московских сделок с пустым city источника — там муниципальный округ/поселение, не город). Для 66 SQL по фильтрам совпадает с main.
  • Исходные city/okato/quarter_cad_number/districtdeals.raw_payload (jsonb, колонка из 029); для 66 остаётся NULL, как и раньше.
  • region_code валидируется по реестру REGIONS — неизвестный код падает явно, а не импортирует мусор.
  • Чекпоинт per-source: _dkp_source_for_region()rosreestr_dkp_import (66, байт-в-байт прежнее) / rosreestr_dkp_import_77; _resume_dkp_cursor(source=…) — курсоры регионов не пересекаются.
  • Wildcard-хендлер rosreestr_dkp_import_* в product_handlers.py (по образцу avito_city_sweep_*).
  • Миграция 289: ALTER FOREIGN TABLE gendesign_rosreestr_deals ADD COLUMN IF NOT EXISTS okato/quarter_cad_number/district (существуют в источнике — проверено на проде) + выключенный seed scrape_schedules rosreestr_dkp_import_77 ({"region_code": 77}), идемпотентно, SET LOCAL lock_timeout.
  • deploy/import-rosreestr.sh: валидация REGION_CODE (целое) и DOC_TYPE (без '/;) — оба интерполируются в SQL текстом; шапка честно говорит, что bash-путь не делает canonical_city-подстановку для 77.

Чего НЕ делает

Не включает импорт по 77 (seed enabled=false). Порядок: merge #3423 (PR-A) → merge этого → применить 289 на проде → ручной первый прогон по 77 с проверкой выборки → включить расписание. Тесты трека — после живого прогона (правило от 08.09).

Ревью

code-reviewer APPROVE (исходная ветка), database-expert OK по миграции; после merge main: ruff чисто, pytest dedup/parity/poll — 57 passed.

Refs #3051, #2989. Дизайн ключей: vault decisions/Decision_Moscow_Regional_Keys_Sep08.md.

🤖 Generated with Claude Code

Дельта поверх #3421 (уже в main: параметры `region_code`/`doc_types`, `deals.doc_type`, миграция 288). Второй PR трека «Москва» (#2989 → #3051 п.3/п.6); пара к #3423 (PR-A, регион-фильтр коридора). ## Что - `Region.canonical_city` (`regions.py`: 77 → «Москва», 66 → `None`). В `import_rosreestr_dkp` одна SQL-ветка через bind `:canonical_city`: для Москвы `city='Москва'`, `address='Москва, <street>'`; фильтр `city IS NOT NULL` не применяется только когда задан `canonical_city` (иначе теряется ~10% московских сделок с пустым city источника — там муниципальный округ/поселение, не город). Для 66 SQL по фильтрам совпадает с main. - Исходные `city`/`okato`/`quarter_cad_number`/`district` → `deals.raw_payload` (jsonb, колонка из 029); для 66 остаётся NULL, как и раньше. - `region_code` валидируется по реестру `REGIONS` — неизвестный код падает явно, а не импортирует мусор. - Чекпоинт per-source: `_dkp_source_for_region()` → `rosreestr_dkp_import` (66, байт-в-байт прежнее) / `rosreestr_dkp_import_77`; `_resume_dkp_cursor(source=…)` — курсоры регионов не пересекаются. - Wildcard-хендлер `rosreestr_dkp_import_*` в `product_handlers.py` (по образцу `avito_city_sweep_*`). - **Миграция 289**: `ALTER FOREIGN TABLE gendesign_rosreestr_deals ADD COLUMN IF NOT EXISTS okato/quarter_cad_number/district` (существуют в источнике — проверено на проде) + **выключенный** seed `scrape_schedules` `rosreestr_dkp_import_77` (`{"region_code": 77}`), идемпотентно, `SET LOCAL lock_timeout`. - `deploy/import-rosreestr.sh`: валидация `REGION_CODE` (целое) и `DOC_TYPE` (без `'`/`;`) — оба интерполируются в SQL текстом; шапка честно говорит, что bash-путь не делает canonical_city-подстановку для 77. ## Чего НЕ делает Не включает импорт по 77 (seed `enabled=false`). Порядок: merge #3423 (PR-A) → merge этого → применить 289 на проде → ручной первый прогон по 77 с проверкой выборки → включить расписание. Тесты трека — после живого прогона (правило от 08.09). ## Ревью code-reviewer ✅ APPROVE (исходная ветка), database-expert OK по миграции; после merge main: `ruff` чисто, `pytest` dedup/parity/poll — 57 passed. Refs #3051, #2989. Дизайн ключей: vault `decisions/Decision_Moscow_Regional_Keys_Sep08.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
lekss361 added 2 commits 2026-09-08 20:06:04 +00:00
Трек 2 подготовки Mera к Москве. import_rosreestr_dkp принимает region_code из
params (default 66 — байт-в-байт прежнее поведение), валидирует его через
app.services.regions.REGIONS. Регион с canonical_city (77 — Москва, Росреестр
отдаёт округ/поселение вместо города) подставляет city/address через одну
SQL-ветку на bind-параметре :canonical_city, а не Python if/else на код региона;
city IS NOT NULL не фильтруется для такого региона (иначе теряется ~10% строк),
исходные city/okato/quarter_cad_number/district уходят в raw_payload.

Чекпоинт курсора (_resume_dkp_cursor) стал per-region: source для поиска
предыдущего прогона строится через _dkp_source_for_region (66 сохраняет
легаси-имя 'rosreestr_dkp_import', остальные — суффикс кода) — иначе прогон по
77 либо никогда не резюмился бы (source-литерал не матчил), либо, при более
наивном фиксе, унёс бы курсор чужого региона.

product_handlers регистрирует wildcard rosreestr_dkp_import_* (по образцу
deactivate_stale_*/avito_city_sweep_*), deploy/import-rosreestr.sh получил
REGION_CODE env (bash-путь не region-generic — city-override только в Python).

Migration 288: deals.doc_type + backfill 'ДКП' для source=rosreestr, foreign
table gendesign_rosreestr_deals расширена okato/quarter_cad_number/district
(проверено live на прод-БД), выключенный seed rosreestr_dkp_import_77.
chore(#3051): снять новые тесты до живой проверки; валидация REGION_CODE в deploy-скрипте
All checks were successful
CI Trade-In / changes (pull_request) Successful in 12s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 14s
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 5m13s
1f24f12af9
Тесты трека «Москва» пишутся отдельным заходом после живого прогона импорта по 77 —
правило проекта с 2026-09-08. Правки существующих тестов (bind-параметр вместо
литерала 66, канонический source rosreestr_dkp_import_77) остаются.
REGION_CODE в import-rosreestr.sh подставляется в SQL текстом — допускаем только целое.
lekss361 changed title from feat(tradein/rosreestr): импорт ДКП по региону (77 — Москва), deals.doc_type, wildcard-расписание rosreestr_dkp_import_* (#3051) to feat(tradein/rosreestr): импорт ДКП по Москве (77) — canonical_city, raw_payload, wildcard-расписание rosreestr_dkp_import_*, per-source чекпоинт (#3051) 2026-09-08 20:19:38 +00:00
bot-backend added 1 commit 2026-09-08 20:19:52 +00:00
merge(#3051): main (#3421) в ветку импорта по региону — московская дельта поверх region_code/doc_type
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 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 5m12s
fcf5887225
#3421 въехал в main параллельно с той же миграцией 288 (deals.doc_type,
параметры region_code/doc_types). Разрешение: 288 — целиком версия main;
наша дельта (FDW-колонки okato/quarter_cad_number/district, выключенный seed
rosreestr_dkp_import_77) переехала в 289. scheduler.py — doc_types из main +
canonical_city-маппинг/raw_payload/per-source чекпоинт. deploy-скрипт —
валидация REGION_CODE и DOC_TYPE (интерполируются в SQL текстом).
lekss361 merged commit e2045582ab into main 2026-09-08 20:28:21 +00:00
lekss361 deleted branch feat/3051-rosreestr-import-region-param 2026-09-08 20:28:21 +00:00
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#3422
No description provided.