feat(tradein): схема «доли квартир дома в продаже» — gar_house_flats + houses.gar_* + v_building_sale_share (143) #2053

Merged
lekss361 merged 1 commit from feat/tradein-sale-share-schema into main 2026-06-28 13:48:42 +00:00
Owner

Summary

Schema-фундамент новой страницы gendsgn.ru/trade-in/sale-share — список домов вторичного рынка, где active_vtorichka_listings / total_apartments_in_building >= порог%, с адресами и картой.

Числитель (активные вторичные объявления на дом) уже есть в listings (house_id_fk + is_active + listing_segment='vtorichka'). Знаменатель («сколько всего квартир в доме») на проде пуст (total_units/flat_count/entrances = 0) → будет заполнен отдельной задачей из self-parsed ГАР/ФИАС-дампа (регион 66), матч к houses по нормализованному адресу.

Этот PR — только схема (миграция 143):

  • gar_house_flats — приёмник «квартир на дом» из ГАР (PK house_guid, flat_count, norm_address + btree/GIN-trgm индексы, region_code). pg_trgm создаётся IF NOT EXISTS.
  • houses.gar_* provenance-колонки: gar_house_guid, gar_flat_count, gar_matched_at, gar_match_method + partial index по gar_flat_count.
  • v_building_sale_share — per-building rollup вторички: эффективный знаменатель COALESCE(gar_flat_count, NULLIF(total_units,0), NULLIF(flat_count,0)), sale_share_pct (только при denom>0, иначе NULL — строка сохраняется для coverage), медианы цены/₽m² + средний срок экспозиции. Фильтр: geom NOT NULL AND active_secondary>0 (отсекает псевдо-дома без гео; новостройки отсекаются listing_segment).

Идемпотентно (CREATE … IF NOT EXISTS / ADD COLUMN IF NOT EXISTS / CREATE OR REPLACE VIEW), BEGIN/COMMIT. Чисто аддитивно — никаких DROP/ALTER TYPE.

Test plan

  • Прогнал тело миграции на проде tradein дважды внутри одной транзакции с ON_ERROR_STOP=1 → 0 ошибок, второй прогон полный no-op (idempotency доказана), ROLLBACK (ничего не персистится).
  • Smoke-select из v_building_sale_share вернул реальные строки (house 7560 = 341 активных вторичных); flat_count_effective/sale_share_pct = NULL при пустом знаменателе — NULL-строки сохраняются для coverage.
  • Авто-apply на деплое (миграция гонится _schema_migrations, strict).

Часть серии: PR1/4 (schema). Дальше — API (/buildings/sale-share), страница с картой, и ГАР-loader (заполняет знаменатель).

## Summary Schema-фундамент новой страницы `gendsgn.ru/trade-in/sale-share` — список домов **вторичного** рынка, где `active_vtorichka_listings / total_apartments_in_building >= порог%`, с адресами и картой. Числитель (активные вторичные объявления на дом) уже есть в `listings` (`house_id_fk` + `is_active` + `listing_segment='vtorichka'`). Знаменатель («сколько всего квартир в доме») на проде пуст (`total_units`/`flat_count`/`entrances` = 0) → будет заполнен отдельной задачей из self-parsed ГАР/ФИАС-дампа (регион 66), матч к `houses` по нормализованному адресу. Этот PR — **только схема** (миграция `143`): - **`gar_house_flats`** — приёмник «квартир на дом» из ГАР (PK `house_guid`, `flat_count`, `norm_address` + btree/GIN-trgm индексы, `region_code`). `pg_trgm` создаётся `IF NOT EXISTS`. - **`houses.gar_*`** provenance-колонки: `gar_house_guid`, `gar_flat_count`, `gar_matched_at`, `gar_match_method` + partial index по `gar_flat_count`. - **`v_building_sale_share`** — per-building rollup вторички: эффективный знаменатель `COALESCE(gar_flat_count, NULLIF(total_units,0), NULLIF(flat_count,0))`, `sale_share_pct` (только при denom>0, иначе NULL — строка сохраняется для coverage), медианы цены/₽m² + средний срок экспозиции. Фильтр: `geom NOT NULL AND active_secondary>0` (отсекает псевдо-дома без гео; новостройки отсекаются `listing_segment`). Идемпотентно (CREATE … IF NOT EXISTS / ADD COLUMN IF NOT EXISTS / CREATE OR REPLACE VIEW), BEGIN/COMMIT. Чисто аддитивно — никаких DROP/ALTER TYPE. ## Test plan - [x] Прогнал тело миграции на проде `tradein` дважды внутри одной транзакции с `ON_ERROR_STOP=1` → 0 ошибок, второй прогон полный no-op (idempotency доказана), `ROLLBACK` (ничего не персистится). - [x] Smoke-select из `v_building_sale_share` вернул реальные строки (house 7560 = 341 активных вторичных); `flat_count_effective`/`sale_share_pct` = NULL при пустом знаменателе — NULL-строки сохраняются для coverage. - [ ] Авто-apply на деплое (миграция гонится `_schema_migrations`, strict). Часть серии: PR1/4 (schema). Дальше — API (`/buildings/sale-share`), страница с картой, и ГАР-loader (заполняет знаменатель).
lekss361 added 1 commit 2026-06-28 13:47:12 +00:00
feat(tradein): схема «доли квартир дома в продаже» — gar_house_flats + houses.gar_* + v_building_sale_share (143)
All checks were successful
CI / changes (pull_request) Successful in 7s
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
fa3ae581ee
lekss361 merged commit 9e2d9ddbea into main 2026-06-28 13:48:42 +00:00
lekss361 deleted branch feat/tradein-sale-share-schema 2026-06-28 13:48:42 +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#2053
No description provided.