feat(site-finder): детерминированная атрибуция застройщика в analyze (#1088) #1302

Merged
bot-backend merged 1 commit from feat/developer-attribution-1088 into main 2026-06-13 11:21:58 +00:00
Collaborator

Summary

Детерминированная атрибуция застройщика для Site Finder analyze (#1088, GG-форсайт future-supply).

Связывает «пятно земли ↔ застройщик»: ekburg_construction_permits (РНС ЕКБ, 4059 строк, есть developer_inn/cadastral_number/geom) ⋈ domrf_kn_objects (10699, dev_inn/cad_quarter) по нормализованному ИНН + spatial/quarter fallback. Закрывает дыру: WFS/НСПД дают геометрию+статус, но не имя застройщика.

Что добавлено (additive, 0 удалений)

  • data/sql/149_developer_attribution.sqlfn_normalize_inn, matview developer_registry (1024 застройщика, канон-имя + track-record + unique-idx для REFRESH CONCURRENTLY), developer_attribution view, fn_developer_for_parcel(cad, radius) резолвер (exact_cadastral → spatial_150m → quarter), fn_refresh_developer_registry. Проверена на prod BEGIN/ROLLBACK.
  • services/site_finder/developer_attribution.pyget_developer_attribution(), дедуп по ИНН, graceful→None (OperationalError/ProgrammingError/DataError, pre-migration safe).
  • workers/tasks/developer_registry_refresh.py + beat-entry (1-го числа 05:30 МСК, после ekburg-permits).
  • Pydantic-схемы + wire в analyze payload (ключ developer_attribution, только при наличии застройщика).
  • 18 тестов.

Prod-факты

68% domrf-застройщиков имеют РНС; 80% domrf-объектов принадлежат застройщику с РНС. EXPLAIN: point-lookup 0.06ms, резолвер ~30ms.

Test plan

  • ruff clean (E F I B UP N RUF ASYNC, line 100)
  • 18 unit-тестов green (happy-path, дедуп, nearby-фильтр, nullable, graceful 3 класса ошибок)
  • psycopg v3: CAST(:x AS type), pre-check пуст
  • миграция idempotent + additive (code-reviewer APPROVE)
  • post-deploy: миграция 149 auto-apply + analyze отдаёт developer_attribution для ЕКБ-кадастра (qa-tester)

Деплой-порядок

Миграция 149 auto-apply через _schema_migrations ПЕРЕД backend-кодом (sql.md). До применения сервис graceful→None.

Closes #1088

## Summary Детерминированная атрибуция застройщика для Site Finder analyze (#1088, GG-форсайт future-supply). Связывает «пятно земли ↔ застройщик»: `ekburg_construction_permits` (РНС ЕКБ, 4059 строк, есть developer_inn/cadastral_number/geom) ⋈ `domrf_kn_objects` (10699, dev_inn/cad_quarter) по **нормализованному ИНН** + spatial/quarter fallback. Закрывает дыру: WFS/НСПД дают геометрию+статус, но не имя застройщика. ### Что добавлено (additive, 0 удалений) - **`data/sql/149_developer_attribution.sql`** — `fn_normalize_inn`, matview `developer_registry` (1024 застройщика, канон-имя + track-record + unique-idx для REFRESH CONCURRENTLY), `developer_attribution` view, `fn_developer_for_parcel(cad, radius)` резолвер (exact_cadastral → spatial_150m → quarter), `fn_refresh_developer_registry`. Проверена на prod BEGIN/ROLLBACK. - **`services/site_finder/developer_attribution.py`** — `get_developer_attribution()`, дедуп по ИНН, graceful→None (OperationalError/ProgrammingError/DataError, pre-migration safe). - **`workers/tasks/developer_registry_refresh.py`** + beat-entry (1-го числа 05:30 МСК, после ekburg-permits). - Pydantic-схемы + wire в analyze payload (ключ `developer_attribution`, только при наличии застройщика). - 18 тестов. ### Prod-факты 68% domrf-застройщиков имеют РНС; 80% domrf-объектов принадлежат застройщику с РНС. EXPLAIN: point-lookup 0.06ms, резолвер ~30ms. ## Test plan - [x] ruff clean (E F I B UP N RUF ASYNC, line 100) - [x] 18 unit-тестов green (happy-path, дедуп, nearby-фильтр, nullable, graceful 3 класса ошибок) - [x] psycopg v3: CAST(:x AS type), pre-check пуст - [x] миграция idempotent + additive (code-reviewer ✅ APPROVE) - [ ] post-deploy: миграция 149 auto-apply + analyze отдаёт developer_attribution для ЕКБ-кадастра (qa-tester) ## Деплой-порядок Миграция 149 auto-apply через `_schema_migrations` ПЕРЕД backend-кодом (sql.md). До применения сервис graceful→None. Closes #1088
bot-backend added 1 commit 2026-06-13 11:14:17 +00:00
feat(site-finder): детерминированная атрибуция застройщика в analyze (#1088)
All checks were successful
CI / changes (pull_request) Successful in 6s
CI / changes (push) Successful in 8s
CI / frontend-tests (push) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (push) Successful in 6m33s
CI / backend-tests (pull_request) Successful in 6m33s
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m44s
Deploy / build-worker (push) Successful in 5m24s
Deploy / deploy (push) Successful in 1m30s
b211183940
Сервис get_developer_attribution поверх fn_developer_for_parcel (миграция 149):
топ-1 застройщик участка + track-record (РНС/РВЭ + домрф) + nearby_developers.
Дедуп по норм-ИНН (лучший match_method первым). Wire в analyze additive без флага
(чистый DB-резолвер по индексам, graceful → None). Beat-refresh developer_registry
ежемесячно 05:30 МСК после ekburg-permits. Pydantic-схемы + 18 тестов.

Источники: ekburg_construction_permits (РНС, ИНН) ⋈ domrf_kn_objects по
нормализованному ИНН + spatial/quarter fallback. 68% domrf-застройщиков имеют РНС.
EXPLAIN: point-lookup 0.06ms, резолвер ~30ms (functional/GIST индексы в миграции).

Closes #1088
bot-backend merged commit b211183940 into main 2026-06-13 11:21:58 +00:00
bot-backend deleted branch feat/developer-attribution-1088 2026-06-13 11:21:58 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#1302
No description provided.