feat(scraper): добавить domrf catalog-квартир API — 91% квартир сейчас без цены (P0) #297

Closed
opened 2026-05-17 14:16:28 +00:00 by lekss361 · 5 comments
Owner

Severity: P0-critical

Наш domrf_kn скрапер использует kn-API который отдаёт только метаданные квартир без цены. Цены лежат в отдельном API «каталог-квартир» (/сервисы/каталог-квартир/квартира/{hash}), куда мы не ходим.

Результат: 91% квартир в domrf_kn_flats без price_rub / price_per_m2 → блокер для любой ценовой аналитики, TradeIn estimator, рекомендаций.

Live evidence (obj_id=65136 ЖК «РАЗУМ на Малышева»)

Метрика Значение
Всего квартир в БД 1 232
Из них с price_rub 113 (9%)
Без price_rub / status 1 119 (91%)
flat_number заполнен 0% (никогда не парсится)

При этом на сайте DOM.РФ конкретная квартира видна с ценой:

  • URL: https://дом.рф/сервисы/каталог-квартир/квартира/d8c7a8103f26c52e427ace5a996706ba
  • 1-к, 36.22 м², 7 890 000 ₽ (217 838 ₽/м²)
  • У нас 10 квартир с такими параметрами (obj 65136, area 36.22, rooms 1) — все NULL по цене

Root cause

DOM.РФ имеет два разных API:

API URL Что отдаёт Используем
kn-API /services/api/object/{obj_id}/... obj meta + flats meta (rooms/area/floor) без цены еженедельный sweep
Catalog-квартир /сервисы/каталог-квартир/квартира/{hash} (SSR HTML + JSON?) Цены, статусы продажи, ипотечные программы не используем

Hash в URL (d8c7a8103f26c52e427ace5a996706ba) — это flat_id каталога, не связан с нашим ods_id (формат 65136/1/1.3.3).

Impact

  • Любая ценовая аналитика на основе domrf_kn_flats.price_per_m2 — на 9% выборки
  • mv_layout_velocity.avg_price_thousand_rub_per_m2 после fix #295 (weighted AVG) — всё равно неверная из-за data sparsity
  • TradeIn Estimator (vault code/patterns/TradeIn_Estimator_Brief_May17.md) полностью блокирован — без цен с DOM.РФ нет ground truth для сданных квартир
  • BestLayoutsBlock.tsx рекомендации использует фейковые / отсутствующие цены

Fix — план

  1. Reverse-engineer catalog-квартир endpoint:
    • Через playwright/devtools на странице obj 65136 на сайте дом.рф → найти endpoint списка квартир (вероятно /сервисы/api/catalog-flats/?obj_id={id} или подобный)
    • Если API закрыт — парсить SSR HTML страницы /каталог-квартир/квартира/{hash} (хеш в URL)
  2. Новая таблица data/sql/NN_add_domrf_catalog_flats.sql:
    CREATE TABLE domrf_catalog_flats (
      flat_hash text PRIMARY KEY,
      obj_id bigint REFERENCES domrf_kn_objects (obj_id) на самом деле без FK,
      price_rub bigint,
      price_per_m2 numeric(12,2),
      status text,           -- в продаже / снято / продано
      mortgage_programs jsonb,
      total_area numeric(10,2),  -- для match с kn-API flats
      rooms int,
      floor int,
      snapshot_date date NOT NULL,
      scraped_at timestamptz DEFAULT now()
    );
    
  3. Scraper backend/app/services/scrapers/domrf_catalog.py:
    • Использовать services/scrapers/stealth.py Playwright pattern для антибот
    • Iterate obj_id из активных ЖК → получить flat list → скачать каждую страницу/JSON
  4. Celery beat backend/app/workers/tasks/scrape_catalog.py:
    • Task tasks.scrape_catalog.scrape_catalog_obj(obj_id)
    • Запускается после scrape_kn для каждого активного obj_id (chain)
    • Rate-limit ~3 секунды между запросами
  5. Match с domrf_kn_flats:
    • LEFT JOIN на (obj_id, total_area, rooms, floor) (combinatorial)
    • При множественных совпадениях по площади — использовать flat_hash как PK
    • Опционально — записать flat_hash обратно в domrf_kn_flats (новая колонка catalog_hash)
  6. Frontend deep-link:
    • В BestLayoutsBlock.tsx каждую planning row сделать clickable → https://дом.рф/сервисы/каталог-квартир/квартира/{hash}
    • В CompetitorTable.tsx — ссылка на страницу ЖК на DOM.РФ

Verification

После завершения:

  • SELECT COUNT(*) FROM domrf_catalog_flats WHERE obj_id = 65136 → ~1232 (как в kn flats)
  • SELECT obj_id, COUNT(*) FILTER (WHERE price_rub IS NOT NULL) FROM domrf_catalog_flats GROUP BY obj_id → ≥80% покрытие для активных
  • Open Site Finder для 66:41:0204016:10 → в Анализе планировок цены близки к реальным (110-220 тыс ₽/м² для эконом-комфорт Екб)

Estimated effort

3-4 дня: reverse-engineer API (1d) + scraper (1d) + table + match logic (1d) + tests (0.5d) + frontend deep-link (0.5d).

References

  • Vault FixList: audits/SiteFinder_FixList_May17.md (этот баг — #22)
  • Связанный баг weighted AVG: #295
  • TradeIn Estimator brief: vault code/patterns/TradeIn_Estimator_Brief_May17.md (блокер для него)
  • Существующий scraper: backend/app/services/scrapers/domrf_kn.py
  • Playwright stealth pattern: backend/app/services/scrapers/stealth.py

Discovered: 2026-05-17 live walkthrough by Ghost (квартира d8c7a8103f26c52e427ace5a996706ba в obj 65136).

## Severity: P0-critical Наш `domrf_kn` скрапер использует **kn-API** который отдаёт только **метаданные квартир без цены**. Цены лежат в **отдельном API «каталог-квартир»** (`/сервисы/каталог-квартир/квартира/{hash}`), куда мы не ходим. Результат: **91% квартир в `domrf_kn_flats` без `price_rub` / `price_per_m2`** → блокер для любой ценовой аналитики, TradeIn estimator, рекомендаций. ## Live evidence (obj_id=65136 ЖК «РАЗУМ на Малышева») | Метрика | Значение | |---|---| | Всего квартир в БД | **1 232** | | Из них с `price_rub` | **113 (9%)** | | Без `price_rub` / `status` | **1 119 (91%)** | | `flat_number` заполнен | **0%** (никогда не парсится) | При этом на сайте DOM.РФ конкретная квартира видна с ценой: - URL: `https://дом.рф/сервисы/каталог-квартир/квартира/d8c7a8103f26c52e427ace5a996706ba` - 1-к, 36.22 м², **7 890 000 ₽** (217 838 ₽/м²) - У нас 10 квартир с такими параметрами (obj 65136, area 36.22, rooms 1) — все NULL по цене ## Root cause DOM.РФ имеет два разных API: | API | URL | Что отдаёт | Используем | |---|---|---|---| | **kn-API** | `/services/api/object/{obj_id}/...` | obj meta + flats meta (rooms/area/floor) **без цены** | ✅ еженедельный sweep | | **Catalog-квартир** | `/сервисы/каталог-квартир/квартира/{hash}` (SSR HTML + JSON?) | **Цены, статусы продажи, ипотечные программы** | ❌ не используем | Hash в URL (`d8c7a8103f26c52e427ace5a996706ba`) — это flat_id каталога, не связан с нашим `ods_id` (формат `65136/1/1.3.3`). ## Impact - Любая ценовая аналитика на основе `domrf_kn_flats.price_per_m2` — на 9% выборки - `mv_layout_velocity.avg_price_thousand_rub_per_m2` после fix #295 (weighted AVG) — всё равно неверная из-за data sparsity - **TradeIn Estimator** (vault `code/patterns/TradeIn_Estimator_Brief_May17.md`) полностью блокирован — без цен с DOM.РФ нет ground truth для сданных квартир - `BestLayoutsBlock.tsx` рекомендации использует фейковые / отсутствующие цены ## Fix — план 1. **Reverse-engineer catalog-квартир endpoint**: - Через playwright/devtools на странице obj 65136 на сайте дом.рф → найти endpoint списка квартир (вероятно `/сервисы/api/catalog-flats/?obj_id={id}` или подобный) - Если API закрыт — парсить SSR HTML страницы `/каталог-квартир/квартира/{hash}` (хеш в URL) 2. **Новая таблица** `data/sql/NN_add_domrf_catalog_flats.sql`: ```sql CREATE TABLE domrf_catalog_flats ( flat_hash text PRIMARY KEY, obj_id bigint REFERENCES domrf_kn_objects (obj_id) на самом деле без FK, price_rub bigint, price_per_m2 numeric(12,2), status text, -- в продаже / снято / продано mortgage_programs jsonb, total_area numeric(10,2), -- для match с kn-API flats rooms int, floor int, snapshot_date date NOT NULL, scraped_at timestamptz DEFAULT now() ); ``` 3. **Scraper** `backend/app/services/scrapers/domrf_catalog.py`: - Использовать `services/scrapers/stealth.py` Playwright pattern для антибот - Iterate `obj_id` из активных ЖК → получить flat list → скачать каждую страницу/JSON 4. **Celery beat** `backend/app/workers/tasks/scrape_catalog.py`: - Task `tasks.scrape_catalog.scrape_catalog_obj(obj_id)` - Запускается **после** `scrape_kn` для каждого активного obj_id (chain) - Rate-limit ~3 секунды между запросами 5. **Match с `domrf_kn_flats`**: - LEFT JOIN на `(obj_id, total_area, rooms, floor)` (combinatorial) - При множественных совпадениях по площади — использовать `flat_hash` как PK - Опционально — записать `flat_hash` обратно в `domrf_kn_flats` (новая колонка `catalog_hash`) 6. **Frontend deep-link**: - В `BestLayoutsBlock.tsx` каждую planning row сделать clickable → `https://дом.рф/сервисы/каталог-квартир/квартира/{hash}` - В `CompetitorTable.tsx` — ссылка на страницу ЖК на DOM.РФ ## Verification После завершения: - `SELECT COUNT(*) FROM domrf_catalog_flats WHERE obj_id = 65136` → ~1232 (как в kn flats) - `SELECT obj_id, COUNT(*) FILTER (WHERE price_rub IS NOT NULL) FROM domrf_catalog_flats GROUP BY obj_id` → ≥80% покрытие для активных - Open Site Finder для 66:41:0204016:10 → в Анализе планировок цены **близки к реальным** (110-220 тыс ₽/м² для эконом-комфорт Екб) ## Estimated effort 3-4 дня: reverse-engineer API (1d) + scraper (1d) + table + match logic (1d) + tests (0.5d) + frontend deep-link (0.5d). ## References - Vault FixList: `audits/SiteFinder_FixList_May17.md` (этот баг — #22) - Связанный баг weighted AVG: #295 - TradeIn Estimator brief: vault `code/patterns/TradeIn_Estimator_Brief_May17.md` (блокер для него) - Существующий scraper: `backend/app/services/scrapers/domrf_kn.py` - Playwright stealth pattern: `backend/app/services/scrapers/stealth.py` Discovered: 2026-05-17 live walkthrough by Ghost (квартира `d8c7a8103f26c52e427ace5a996706ba` в obj 65136).
lekss361 added the
data
site-finder
bug
labels 2026-05-17 14:16:28 +00:00
Author
Owner

Update 2026-05-17 — расширенный scope после verification конкретной квартиры

Проверил https://дом.рф/сервисы/каталог-квартир/квартира/d8c7a8103f26c52e427ace5a996706ba. Картина шире чем казалось.

Уточнения первоначального плана

  1. Hash в URL НЕ нужен — ID на странице DOM.РФ = 65136/1/1.4.3 — это наш формат ods_id. Match уже есть, отдельная таблица domrf_catalog_flats НЕ нужна — только расширение существующих.

  2. Эта квартира В БД С ЦЕНОЙ (7 890 000 ₽, 217 835 ₽/м², status=free). То есть скрапер ИНОГДА получает цены. Проблема — почему только 0.3% жилых ЕКБ (849 из 335 519) имеют price_rub. Это не gap скрапера, а избирательность endpoint'а kn-API.

  3. На странице квартиры DOM.РФ есть ~15 полей, которых у нас нет.

Полный gap-list полей

Flat-level (расширить domrf_kn_flats)

  • section_no (подъезд 1)
  • finishing_type (Отделка: Предчистовая / Чистовая / Без отделки)
  • ceiling_height_m (2,7 м)
  • key_handover_dt (30 июня 2029)
  • catalog_updated_at (17.04.2026 — last sync с DOM.РФ)
  • catalog_url_hash (для deep-link)

Plans — новая таблица domrf_kn_flat_plans

  • ods_id PK, plan_image_url, local_path, width_px, height_px, downloaded_at
  • Скачивать аналогично photos (domrf_kn_photos)

Obj-level (расширить domrf_kn_objects)

  • dev_group_name (Группа компаний Разум) — сейчас в dev_name только СЗ
  • spz_name (СЗ РАЗУМ НА ВИШНЕВОЙ)
  • metro_nearest_name (Площадь 1905 года) — denormalize из infrastructure
  • metro_nearest_walk_minutes (27)
  • domrf_score_location (6) — score от DOM.РФ
  • domrf_score_transport (10)
  • domrf_score_infrastructure (10)
  • playground_kids_count (6)
  • playground_sport_count (5)
  • info_updated_at (17.05.2026)

Checks — новая таблица domrf_obj_checks

  • 6 чекбоксов «Проверено на наш.дом.рф»: документы / сроки / фото актуальны / не банкрот / декларация обновлена
  • obj_id, check_type, passed bool, checked_at

Developer-level (расширить domrf_developers)

  • houses_building (43)
  • houses_building_delayed (8)
  • houses_delivered (12)
  • houses_delivered_delayed (3)

Real coverage цен (текущий БД)

Категория Total С price_rub %
Жилое (ЕКБ) 335 519 849 0.3%
Нежилое (ЕКБ) 22 018 0 0%
Жилое obj 65136 413 58 14% (лучше среднего)

Уточнённый план (подзадачи 22a..22g)

ID Что Effort
22a Reverse-engineer почему 99.7% жилых ЕКБ без цены 1d
22b +6 колонок в domrf_kn_flats (section, finishing, ceiling, keys, catalog_updated_at, hash) 1d
22c Новая таблица domrf_kn_flat_plans + download 2d
22d Catalog scraper main loop (для всех flat без catalog_updated_at >30 days) 2d
22e +9 колонок в domrf_kn_objects (dev_group, spz, metro_nearest, scores, площадки) 1d
22f Новая таблица domrf_obj_checks (6 проверок) 0.5d
22g +4 колонки в domrf_developers (houses metrics) 0.5d

Total: 8 дней. Можно split на 2 PR: flat-level (22a-d) и obj+dev-level (22e-g).

Скриншот для контекста

Title страницы: «Купить 1-комнатную квартиру площадью 36.22м² в ЖК «РАЗУМ на Малышева» 1 этап по адресу Город Екатеринбург. Цена продажи — 7890000 руб.»

Полный текст полей зафиксирован в audits/SiteFinder_FixList_May17.md (Update 2).

## Update 2026-05-17 — расширенный scope после verification конкретной квартиры Проверил `https://дом.рф/сервисы/каталог-квартир/квартира/d8c7a8103f26c52e427ace5a996706ba`. Картина шире чем казалось. ### Уточнения первоначального плана 1. **Hash в URL НЕ нужен** — ID на странице DOM.РФ = `65136/1/1.4.3` — это **наш формат `ods_id`**. Match уже есть, отдельная таблица `domrf_catalog_flats` НЕ нужна — только расширение существующих. 2. **Эта квартира В БД С ЦЕНОЙ** (7 890 000 ₽, 217 835 ₽/м², status=`free`). То есть скрапер ИНОГДА получает цены. Проблема — почему **только 0.3% жилых ЕКБ** (849 из 335 519) имеют price_rub. Это не gap скрапера, а **избирательность endpoint'а** kn-API. 3. **На странице квартиры DOM.РФ есть ~15 полей, которых у нас нет**. ### Полный gap-list полей #### Flat-level (расширить `domrf_kn_flats`) - `section_no` (подъезд 1) - `finishing_type` (Отделка: Предчистовая / Чистовая / Без отделки) - `ceiling_height_m` (2,7 м) - `key_handover_dt` (30 июня 2029) - `catalog_updated_at` (17.04.2026 — last sync с DOM.РФ) - `catalog_url_hash` (для deep-link) #### Plans — новая таблица `domrf_kn_flat_plans` - `ods_id PK`, `plan_image_url`, `local_path`, `width_px`, `height_px`, `downloaded_at` - Скачивать аналогично photos (`domrf_kn_photos`) #### Obj-level (расширить `domrf_kn_objects`) - `dev_group_name` (Группа компаний Разум) — сейчас в `dev_name` только СЗ - `spz_name` (СЗ РАЗУМ НА ВИШНЕВОЙ) - `metro_nearest_name` (Площадь 1905 года) — denormalize из infrastructure - `metro_nearest_walk_minutes` (27) - `domrf_score_location` (6) — score от DOM.РФ - `domrf_score_transport` (10) - `domrf_score_infrastructure` (10) - `playground_kids_count` (6) - `playground_sport_count` (5) - `info_updated_at` (17.05.2026) #### Checks — новая таблица `domrf_obj_checks` - 6 чекбоксов «Проверено на наш.дом.рф»: документы / сроки / фото актуальны / не банкрот / декларация обновлена - `obj_id`, `check_type`, `passed bool`, `checked_at` #### Developer-level (расширить `domrf_developers`) - `houses_building` (43) - `houses_building_delayed` (8) - `houses_delivered` (12) - `houses_delivered_delayed` (3) ### Real coverage цен (текущий БД) | Категория | Total | С price_rub | % | |---|---|---|---| | Жилое (ЕКБ) | 335 519 | 849 | **0.3%** | | Нежилое (ЕКБ) | 22 018 | 0 | **0%** | | Жилое obj 65136 | 413 | 58 | **14%** (лучше среднего) | ### Уточнённый план (подзадачи 22a..22g) | ID | Что | Effort | |---|---|---| | **22a** | Reverse-engineer почему 99.7% жилых ЕКБ без цены | 1d | | **22b** | `+6` колонок в `domrf_kn_flats` (section, finishing, ceiling, keys, catalog_updated_at, hash) | 1d | | **22c** | Новая таблица `domrf_kn_flat_plans` + download | 2d | | **22d** | Catalog scraper main loop (для всех flat без catalog_updated_at >30 days) | 2d | | **22e** | `+9` колонок в `domrf_kn_objects` (dev_group, spz, metro_nearest, scores, площадки) | 1d | | **22f** | Новая таблица `domrf_obj_checks` (6 проверок) | 0.5d | | **22g** | `+4` колонки в `domrf_developers` (houses metrics) | 0.5d | **Total: 8 дней.** Можно split на 2 PR: flat-level (22a-d) и obj+dev-level (22e-g). ### Скриншот для контекста Title страницы: «Купить 1-комнатную квартиру площадью 36.22м² в ЖК «РАЗУМ на Малышева» 1 этап по адресу Город Екатеринбург. Цена продажи — 7890000 руб.» Полный текст полей зафиксирован в `audits/SiteFinder_FixList_May17.md` (Update 2).
Author
Owner

Дополнение по метро — sub-task 22h

Проверка БД (2026-05-17)

Запрос: все poi_category в domrf_kn_infrastructure по всей БД.

Категория Строк Уникальных ЖК
Новостройки 136 158 1 493
Продукты 124 957 1 505
Спорт 116 848 1 494
Образование 103 139 1 458
Медицина 11 311 1 272
Развлечения 3 740 740

Категории «Метро» в нашей БД НЕТ (единственное совпадение %метро%Метроfitness спорт-клуб).

Что у нас сейчас работает

Score участка в Site Finder считает доступность метро через наш OSM-based POI loader (backend/app/services/site_finder/poi_loader.py + weight_profiles.py, категории metro_stop/tram_stop/bus_stop) + OpenRouteService изохроны. Это альт-источник, работает.

Что добавить (22h)

Парсить ещё одно поле с DOM.РФ — их собственное «ближайшее метро + время пешком»:

  • На странице квартиры в блоке «Метро»: metro_nearest_name (Площадь 1905 года), metro_nearest_walk_minutes (27)
  • Скорее всего в payload kn-API есть отдельная секция metro/transport (отдельно от infrastructure 6 категорий)

Цель — НЕ заменить наш OSM-расчёт, а показывать DOM.РФ-оценку рядом для cross-reference (если DOM.РФ показывает 27 мин, а мы 18 мин — это сигнал что наш OSM роутинг неточен или у DOM.РФ другая отправная точка).

Подзадача 22h

ID Что Effort
22h Audit kn-API payload на отдельный metro/transport endpoint + denormalize в domrf_kn_objects.metro_nearest_name и metro_nearest_walk_minutes 0.5d

Можно склеить с 22e (расширение domrf_kn_objects). Total effort issue теперь — 8.5 дней.

## Дополнение по метро — sub-task 22h ### Проверка БД (2026-05-17) Запрос: все `poi_category` в `domrf_kn_infrastructure` по всей БД. | Категория | Строк | Уникальных ЖК | |---|---:|---:| | Новостройки | 136 158 | 1 493 | | Продукты | 124 957 | 1 505 | | Спорт | 116 848 | 1 494 | | Образование | 103 139 | 1 458 | | Медицина | 11 311 | 1 272 | | Развлечения | 3 740 | 740 | **Категории «Метро» в нашей БД НЕТ** (единственное совпадение `%метро%` — `Метроfitness` спорт-клуб). ### Что у нас сейчас работает Score участка в Site Finder считает доступность метро через **наш OSM-based POI loader** (`backend/app/services/site_finder/poi_loader.py` + `weight_profiles.py`, категории `metro_stop`/`tram_stop`/`bus_stop`) + OpenRouteService изохроны. Это альт-источник, работает. ### Что добавить (22h) Парсить ещё одно поле с DOM.РФ — **их собственное «ближайшее метро + время пешком»**: - На странице квартиры в блоке «Метро»: `metro_nearest_name` (Площадь 1905 года), `metro_nearest_walk_minutes` (27) - Скорее всего в payload kn-API есть отдельная секция metro/transport (отдельно от infrastructure 6 категорий) **Цель** — НЕ заменить наш OSM-расчёт, а **показывать DOM.РФ-оценку рядом** для cross-reference (если DOM.РФ показывает 27 мин, а мы 18 мин — это сигнал что наш OSM роутинг неточен или у DOM.РФ другая отправная точка). ### Подзадача 22h | ID | Что | Effort | |---|---|---| | **22h** | Audit kn-API payload на отдельный metro/transport endpoint + denormalize в `domrf_kn_objects.metro_nearest_name` и `metro_nearest_walk_minutes` | **0.5d** | Можно склеить с 22e (расширение `domrf_kn_objects`). Total effort issue теперь — **8.5 дней**.
Author
Owner

Update 2 — audit страницы ЖК (obj_id=65136) vs БД

Прошёлся по странице /каталог-новостроек/объект/65136. Картина: много данных уже есть, но не выводится в Site Finder. И ~10 полей не хватает.

УЖЕ хранится в БД (но не показано в Site Finder UI)

Поле / Блок на сайте Где в БД Verified для obj 65136
Динамика продаж по месяцам (график) domrf_kn_sale_graph (report_month, type, realised, contracted, area_sq, price_avg) 36 строк за 2025-04 .. 2026-04
Распроданность % (apartments/nonliv/parking) domrf_kn_sales_agg (type, total, realised, perc) 6 строк (31% / 20% / 0%)
Ход строительства (фото по месяцам) domrf_kn_photos (period_dt, photo_url, local_path) 50 фото
Инфраструктура с координатами domrf_kn_infrastructure (POI + lat/lon + distance) 374 POI
Эскроу domrf_kn_objects.escrow TRUE
Сдача дома domrf_kn_objects.ready_dt 2028-12-31
Этажность domrf_kn_objects.floor_max проверить

Action для frontend: добавить блоки «Динамика продаж» и «Распроданность» в objects/[id]/page.tsx — данные уже в API.

Что НЕТ в БД — обновлённый gap-list

Уровень объекта (расширить domrf_kn_objects — было 9 колонок в 22e, теперь +5)

  • obj_class — на сайте «Комфорт», у нас NULL (uplink скрапера, не отсутствие колонки)
  • wall_type — на сайте «Монолит-кирпич», у нас NULL → verify
  • flat_area_min, flat_area_max (24.99 — 93.22 м²)
  • price_min_rub, price_max_rub (7 900 000 — 14 800 000)
  • price_per_m2_min, price_per_m2_max (160 000 — 259 000)
  • parking_provision_pct (Обеспеченность машиноместами 60%) — новое
  • project_published_at (31.03.2025)
  • project_declaration_num (66-001686)
  • domrf_score_location, _transport, _infrastructure (уже в 22e)
  • metro_nearest_name, metro_nearest_walk_minutes (уже в 22e+22h)
  • metro_top3 jsonb (Площадь 1905 года 27 мин, Уральская 29, Геологическая 32) — новое
  • dev_group_name (Группа компаний Разум) — уже в 22e
  • playground_kids_count, playground_sport_count — уже в 22e

Sub-task 22i — НОВАЯ таблица domrf_kn_documents (PDF документы ЖК)

На странице видим 5+ типов документов:

  • Проектные декларации (6 версий за 1.5 месяца)
  • Разрешительная документация
  • Проектная документация
  • Отчётность застройщика
  • Прочие документы

Колонки: obj_id, doc_type, doc_num, posted_at, file_url, size_bytes, local_path, downloaded_at. Effort: 1d.

POI gap (audit вне scope этого issue, но findings)

Категория На сайте DOM.РФ В нашей БД (obj 65136)
Все 192 374
Продукты 50 98
Образование 48 102
Спорт 50 98
Новостройки 32 56
Медицина 9 14
Развлечения 3 6

У нас POI В 2 РАЗА БОЛЬШЕ — вероятно дубликаты по snapshot_date (не дедуплицируются при сохранении). Возможный bug domrf_kn_infrastructure scraper'а. → отдельный sub-task 22j: DEDUP infrastructure (0.5d).

Квартирография по дому — на основе domrf_kn_flats

На странице сайта:

  • 1-комнатные: 243 шт, от 24.99 м², 7.9-9.6 млн ₽, 12 в продаже
  • 2-комнатные: 139 шт, от 37.59 м², 9.5-14.8 млн ₽, 35 в продаже
  • 3-комнатные: 31 шт, от 67.76 м², 12-12.9 млн ₽, 6 в продаже
  • Нежилые: 314 помещений, от 2.21 м²

Source: domrf_kn_flats уже содержит всё (rooms / total_area / price_rub / status). SQL:

SELECT rooms, COUNT(*) AS total, MIN(total_area), MAX(total_area),
       MIN(price_rub) FILTER (WHERE status='free'), MAX(price_rub) FILTER (WHERE status='free'),
       COUNT(*) FILTER (WHERE status='free') AS for_sale
FROM domrf_kn_flats WHERE obj_id=65136 GROUP BY rooms;

Action для frontend: добавить блок «Квартирография по дому» в objects/[id]/page.tsx. SQL уже работает (но status 9% покрытие → нужен #22a fix).

Обновлённый план — total 11 дней

ID Что Effort
22a Reverse-engineer price coverage 0.3% 1d
22b Flat-level +6 колонок 1d
22c domrf_kn_flat_plans (планировки) 2d
22d Catalog scraper main loop 2d
22e Obj-level +14 колонок (было 9, добавил 5 + metro_top3) 1.5d
22f domrf_obj_checks (6 проверок) 0.5d
22g Developer +4 metrics 0.5d
22h metro_nearest_name + walk_minutes 0.5d
22i domrf_kn_documents PDF docs 1d
22j DEDUP domrf_kn_infrastructure (×2 raw) 0.5d
22k Frontend objects/[id]/page.tsx — добавить блоки Sales/Layouts/Photos timeline 1.5d

Frontend work (22k) — отдельный кусок, можно отдать frontend-engineer параллельно. Backend (22a-j) — sequential.

Главное insight

Большинство «недостающих» данных уже есть в БД — нужна экспозиция в Site Finder. Скрапер расширять надо только для:

  • цен (фундаментальный bug 0.3% coverage)
  • планировок (новая таблица)
  • 3 scores + 3 metros + ряд obj-метрик (~15 колонок в objects)
  • документов (PDF, новая таблица)
  • DEDUP infrastructure

Полный текст fields фиксирован в vault audits/SiteFinder_FixList_May17.md.

## Update 2 — audit страницы ЖК (obj_id=65136) vs БД Прошёлся по странице `/каталог-новостроек/объект/65136`. Картина: **много данных уже есть, но не выводится в Site Finder**. И ~10 полей не хватает. ### ✅ УЖЕ хранится в БД (но не показано в Site Finder UI) | Поле / Блок на сайте | Где в БД | Verified для obj 65136 | |---|---|---| | **Динамика продаж по месяцам** (график) | `domrf_kn_sale_graph` (`report_month, type, realised, contracted, area_sq, price_avg`) | 36 строк за 2025-04 .. 2026-04 ✅ | | **Распроданность %** (apartments/nonliv/parking) | `domrf_kn_sales_agg` (`type, total, realised, perc`) | 6 строк (31% / 20% / 0%) ✅ | | **Ход строительства** (фото по месяцам) | `domrf_kn_photos` (`period_dt, photo_url, local_path`) | 50 фото ✅ | | **Инфраструктура с координатами** | `domrf_kn_infrastructure` (POI + lat/lon + distance) | 374 POI ✅ | | **Эскроу** | `domrf_kn_objects.escrow` | TRUE ✅ | | **Сдача дома** | `domrf_kn_objects.ready_dt` | 2028-12-31 ✅ | | **Этажность** | `domrf_kn_objects.floor_max` | проверить | **Action для frontend**: добавить блоки «Динамика продаж» и «Распроданность» в `objects/[id]/page.tsx` — данные уже в API. ### ❌ Что НЕТ в БД — обновлённый gap-list #### Уровень объекта (расширить `domrf_kn_objects` — было 9 колонок в 22e, теперь +5) - `obj_class` — на сайте «Комфорт», у нас NULL (uplink скрапера, не отсутствие колонки) - `wall_type` — на сайте «Монолит-кирпич», у нас NULL → verify - `flat_area_min`, `flat_area_max` (24.99 — 93.22 м²) - `price_min_rub`, `price_max_rub` (7 900 000 — 14 800 000) - `price_per_m2_min`, `price_per_m2_max` (160 000 — 259 000) - `parking_provision_pct` (Обеспеченность машиноместами 60%) — **новое** - `project_published_at` (31.03.2025) - `project_declaration_num` (66-001686) - `domrf_score_location`, `_transport`, `_infrastructure` (уже в 22e) - `metro_nearest_name`, `metro_nearest_walk_minutes` (уже в 22e+22h) - `metro_top3` jsonb (Площадь 1905 года 27 мин, Уральская 29, Геологическая 32) — **новое** - `dev_group_name` (Группа компаний Разум) — уже в 22e - `playground_kids_count`, `playground_sport_count` — уже в 22e #### Sub-task 22i — НОВАЯ таблица `domrf_kn_documents` (PDF документы ЖК) На странице видим 5+ типов документов: - Проектные декларации (6 версий за 1.5 месяца) - Разрешительная документация - Проектная документация - Отчётность застройщика - Прочие документы Колонки: `obj_id`, `doc_type`, `doc_num`, `posted_at`, `file_url`, `size_bytes`, `local_path`, `downloaded_at`. **Effort: 1d**. #### POI gap (audit вне scope этого issue, но findings) | Категория | На сайте DOM.РФ | В нашей БД (obj 65136) | |---|---|---| | Все | 192 | **374** | | Продукты | 50 | 98 | | Образование | 48 | 102 | | Спорт | 50 | 98 | | Новостройки | 32 | 56 | | Медицина | 9 | 14 | | Развлечения | 3 | 6 | **У нас POI В 2 РАЗА БОЛЬШЕ** — вероятно дубликаты по snapshot_date (не дедуплицируются при сохранении). Возможный bug `domrf_kn_infrastructure` scraper'а. → **отдельный sub-task 22j: DEDUP infrastructure** (0.5d). ### Квартирография по дому — на основе `domrf_kn_flats` На странице сайта: - 1-комнатные: 243 шт, от 24.99 м², 7.9-9.6 млн ₽, **12 в продаже** - 2-комнатные: 139 шт, от 37.59 м², 9.5-14.8 млн ₽, **35 в продаже** - 3-комнатные: 31 шт, от 67.76 м², 12-12.9 млн ₽, **6 в продаже** - Нежилые: 314 помещений, от 2.21 м² **Source**: `domrf_kn_flats` уже содержит всё (rooms / total_area / price_rub / status). SQL: ```sql SELECT rooms, COUNT(*) AS total, MIN(total_area), MAX(total_area), MIN(price_rub) FILTER (WHERE status='free'), MAX(price_rub) FILTER (WHERE status='free'), COUNT(*) FILTER (WHERE status='free') AS for_sale FROM domrf_kn_flats WHERE obj_id=65136 GROUP BY rooms; ``` **Action для frontend**: добавить блок «Квартирография по дому» в `objects/[id]/page.tsx`. SQL уже работает (но `status` 9% покрытие → нужен #22a fix). ### Обновлённый план — total 11 дней | ID | Что | Effort | |---|---|---| | 22a | Reverse-engineer price coverage 0.3% | 1d | | 22b | Flat-level +6 колонок | 1d | | 22c | `domrf_kn_flat_plans` (планировки) | 2d | | 22d | Catalog scraper main loop | 2d | | 22e | Obj-level +14 колонок (было 9, добавил 5 + metro_top3) | 1.5d | | 22f | `domrf_obj_checks` (6 проверок) | 0.5d | | 22g | Developer +4 metrics | 0.5d | | 22h | metro_nearest_name + walk_minutes | 0.5d | | **22i** | **`domrf_kn_documents` PDF docs** | **1d** | | **22j** | **DEDUP `domrf_kn_infrastructure`** (×2 raw) | **0.5d** | | **22k** | **Frontend `objects/[id]/page.tsx` — добавить блоки Sales/Layouts/Photos timeline** | **1.5d** | **Frontend work (22k)** — отдельный кусок, можно отдать frontend-engineer параллельно. Backend (22a-j) — sequential. ### Главное insight Большинство «недостающих» данных **уже есть в БД** — нужна экспозиция в Site Finder. Скрапер расширять надо только для: - цен (фундаментальный bug 0.3% coverage) - планировок (новая таблица) - 3 scores + 3 metros + ряд obj-метрик (~15 колонок в objects) - документов (PDF, новая таблица) - DEDUP infrastructure Полный текст fields фиксирован в vault `audits/SiteFinder_FixList_May17.md`.
Author
Owner

Update 3 — категория багов «колонка есть, NULL для всех» (mapping gap)

При проверке energy_eff обнаружено: колонка в domrf_kn_objects существует, но 0% заполнено (0 из 1516 объектов). Скорее всего, scraper domrf_kn.py не делает mapping этого поля из payload (либо payload его не содержит — нужен audit).

Полный список «пустых» колонок схемы (для категории mapping-fix)

Колонка Тип Coverage сейчас На сайте DOM.РФ obj 65136 Severity
energy_eff text 0% (на сайте видно) 🟠 P1
wall_type text 0% (для obj 65136) «Монолит-кирпич» 🟠 P1
obj_class text NULL для 52% «Комфорт» 🔴 P0 (использует для рекомендаций)
flat_number text 0% в domrf_kn_flats (виден в карточке квартиры через ods_id) 🟢 P2
living_area numeric ~30% NULL «10,11 м²» 🟡 P1

Это подзадача 22a (reverse-engineer kn-API payload)

В предыдущих updates я фокусировал 22a на ценовом покрытии (0.3%). На самом деле scope шире — audit всех NULL-fields на предмет «есть ли в payload, но scraper не маппит»:

  1. Запросить raw payload через /services/api/object/{obj_id} (или из domrf_raw_endpoints если хранится)
  2. Сравнить response JSON с тем, что мы пишем в domrf_kn_objects / domrf_kn_flats
  3. Зафиксировать missing mappings → fix scraper за 1 проход

Action: расширить 22a

Было: «Reverse-engineer почему 0.3% жилых ЕКБ без цены» — 1d
Стало: «Audit всех NULL-fields в domrf_kn_objects и domrf_kn_flats — что есть в kn-API payload, но мы не маппим»1.5d

Включает поля:

  • energy_eff, wall_type, obj_class, flat_number, living_area (улучшить coverage)
  • price_rub, price_per_m2, status (главный bug 0.3%)

Эффект после fix 22a

Без работы со scraper kn-API payload'ом — добавим 5+ полей без новых миграций (schema уже готова). Это самый дешёвый win в issue: 1.5d даёт 5 полей.

Updated total

11d → 11.5d (расширил 22a на 0.5d).

## Update 3 — категория багов «колонка есть, NULL для всех» (mapping gap) При проверке `energy_eff` обнаружено: **колонка в `domrf_kn_objects` существует, но 0% заполнено** (0 из 1516 объектов). Скорее всего, scraper `domrf_kn.py` не делает mapping этого поля из payload (либо payload его не содержит — нужен audit). ### Полный список «пустых» колонок схемы (для категории mapping-fix) | Колонка | Тип | Coverage сейчас | На сайте DOM.РФ obj 65136 | Severity | |---|---|---|---|---| | `energy_eff` | text | **0%** | (на сайте видно) | 🟠 P1 | | `wall_type` | text | 0% (для obj 65136) | «Монолит-кирпич» | 🟠 P1 | | `obj_class` | text | NULL для 52% | «Комфорт» | 🔴 P0 (использует для рекомендаций) | | `flat_number` | text | **0%** в `domrf_kn_flats` | (виден в карточке квартиры через ods_id) | 🟢 P2 | | `living_area` | numeric | ~30% NULL | «10,11 м²» | 🟡 P1 | ### Это **подзадача 22a** (reverse-engineer kn-API payload) В предыдущих updates я фокусировал 22a на ценовом покрытии (0.3%). На самом деле scope шире — **audit всех NULL-fields на предмет «есть ли в payload, но scraper не маппит»**: 1. Запросить raw payload через `/services/api/object/{obj_id}` (или из `domrf_raw_endpoints` если хранится) 2. Сравнить response JSON с тем, что мы пишем в `domrf_kn_objects` / `domrf_kn_flats` 3. Зафиксировать missing mappings → fix scraper за 1 проход ### Action: расширить 22a Было: «Reverse-engineer почему 0.3% жилых ЕКБ без цены» — 1d Стало: **«Audit всех NULL-fields в `domrf_kn_objects` и `domrf_kn_flats` — что есть в kn-API payload, но мы не маппим»** — **1.5d** Включает поля: - `energy_eff`, `wall_type`, `obj_class`, `flat_number`, `living_area` (улучшить coverage) - `price_rub`, `price_per_m2`, `status` (главный bug 0.3%) ### Эффект после fix 22a Без работы со scraper kn-API payload'ом — добавим **5+ полей** без новых миграций (schema уже готова). Это самый дешёвый win в issue: **1.5d даёт 5 полей**. ### Updated total 11d → **11.5d** (расширил 22a на 0.5d).
Author
Owner

Update 4 — блок «Все характеристики» (22 поля)

При проверке блока «Все характеристики» на странице ЖК (obj 65136) обнаружено ещё 14 новых полей + 2 mapping-fix.

Verified для obj 65136

# Поле на сайте Значение DOM.РФ Наша БД Действие
1 Класс энергоэффективности B energy_eff NULL mapping fix → 22a
2 Первый этаж Нежилой НЕТ NEW first_floor_type text
3 Количество подъездов 1 НЕТ NEW section_count int
4 Количество квартир 413 flat_count OK
5 Среднее кв на этаже 14 computable (413/32≈13) denormalize или вычислять
6 Жилая площадь 19 089 м² square_living OK
7 Пассажирских лифтов Нет НЕТ NEW elevators_passenger_count int (nullable)
8 Грузовых лифтов 4 НЕТ NEW elevators_cargo_count int
9 Машиномест в паркинге 246 через sales_agg WHERE type='parking' denormalize as parking_total_slots
10 Гостевые места на придомовой 43 НЕТ NEW guest_parking_inside_count int
11 Гостевые места вне придомовой Нет НЕТ NEW guest_parking_outside_count int
12 Тип отделки 1 вариант НЕТ NEW finishing_variants_count int
13 Свободная планировка Нет НЕТ NEW has_free_planning bool
14 Средняя площадь квартир 46,2 м² computable computable (avg by rooms='Квартира')
15 Высота потолков 2,7 м НЕТ NEW ceiling_height_m numeric (уже на flat-level в 22b — нужно и obj-level)
16 Материал стен Монолит-кирпич wall_type NULL mapping fix → 22a
17 Класс объекта Комфорт obj_class (теперь заполнен!) OK
18 Детские площадки 6 НЕТ NEW playground_kids_count (уже в 22e)
19 Спортивные площадки 5 НЕТ NEW playground_sport_count (уже в 22e)
20 Велосипедные дорожки Нет НЕТ NEW has_bike_paths bool
21 Площадки сбора мусора 3 НЕТ NEW trash_areas_count int
22 Наличие пандуса Нет НЕТ NEW has_ramp bool
23 Понижающие площадки (ОВЗ) Есть НЕТ NEW has_low_platforms bool
24 Инвалидные подъемники Нет НЕТ NEW has_wheelchair_lift bool

Сводка по категориям

Категория Колонок Поля
Уже есть и заполнено 5 flat_count, square_living, floor_max, obj_class, escrow
Есть в БД, denormalize из других таблиц 3 parking_total_slots, apts_total, avg_flat_area_m2 (computable)
🟠 Mapping fix (schema готова, NULL для всех) 2 energy_eff, wall_type
🔴 NEW колонки (специфика дома) 8 first_floor_type, section_count, elevators_passenger_count, elevators_cargo_count, ceiling_height_m, finishing_variants_count, has_free_planning
🔴 NEW колонки (парковка детально) 2 guest_parking_inside_count, guest_parking_outside_count
🔴 NEW колонки (придомовая инфра) 4 playground_kids_count, playground_sport_count, has_bike_paths, trash_areas_count
🔴 NEW колонки (accessibility / ОВЗ) 3 has_ramp, has_low_platforms, has_wheelchair_lift

Обновлённый 22e — domrf_kn_objects расширение

Было в 22e: 9 колонок (1.5d)
Стало:

-- Building specs (8)
ALTER TABLE domrf_kn_objects ADD COLUMN
  first_floor_type text,
  section_count int,
  elevators_passenger_count int,        -- NULL = "Нет"
  elevators_cargo_count int,
  parking_total_slots int,              -- denormalize from sales_agg
  guest_parking_inside_count int,
  guest_parking_outside_count int,
  ceiling_height_m numeric(3,2),

-- Apartment specs (3)
  finishing_variants_count int,
  has_free_planning bool,
  avg_flat_area_m2 numeric(5,1),        -- denormalize from flats AVG

-- Yard infrastructure (4)
  playground_kids_count int,
  playground_sport_count int,
  has_bike_paths bool,
  trash_areas_count int,

-- Accessibility / ОВЗ (3)
  has_ramp bool,
  has_low_platforms bool,
  has_wheelchair_lift bool,

-- Catalog/UI (9, из предыдущих updates)
  flat_area_min numeric(8,2),
  flat_area_max numeric(8,2),
  price_min_rub bigint,
  price_max_rub bigint,
  price_per_m2_min numeric(12,2),
  price_per_m2_max numeric(12,2),
  parking_provision_pct numeric(5,1),
  project_published_at date,
  project_declaration_num text,

-- Metro & scores (5)
  metro_nearest_name text,
  metro_nearest_walk_minutes int,
  metro_top3 jsonb,
  domrf_score_location int,
  domrf_score_transport int,
  domrf_score_infrastructure int,

-- Developer split (1)
  dev_group_name text;

Итого ~30 новых колонок в domrf_kn_objects. Effort 22e теперь:

  • Было: 1.5d
  • Стало: 3d (migration + scraper mapping для 18 «специфика» полей + verify all coverage)

Обновлённый total

11.5d → 13d

ID Effort
22a 1.5d (mapping fix energy_eff, wall_type, obj_class, flat_number, living_area, price_rub)
22b 1d (flat-level +6 cols)
22c 2d (flat plans)
22d 2d (catalog scraper loop)
22e 3d (obj-level +30 cols — building specs + accessibility + catalog/UI)
22f 0.5d (obj_checks)
22g 0.5d (developer metrics)
22h 0.5d (metro_top3 already в 22e)
22i 1d (documents)
22j 0.5d (DEDUP infrastructure)
22k 1.5d (frontend exposure)

Special note: accessibility — маркетинговый дифференциатор

Поля has_ramp / has_low_platforms / has_wheelchair_lift редко учитываются конкурентами. Если показать «пандус + подъёмник» как фильтр в Site Finder — топовый USP для социального жилья / семей с ОВЗ родственниками. Стоит выделить в отдельную UI-секцию объекта.

## Update 4 — блок «Все характеристики» (22 поля) При проверке блока «Все характеристики» на странице ЖК (obj 65136) обнаружено ещё **14 новых полей** + 2 mapping-fix. ### Verified для obj 65136 | # | Поле на сайте | Значение DOM.РФ | Наша БД | Действие | |---|---|---|---|---| | 1 | Класс энергоэффективности | **B** | `energy_eff` NULL | mapping fix → 22a | | 2 | Первый этаж | Нежилой | НЕТ | NEW `first_floor_type` text | | 3 | Количество подъездов | 1 | НЕТ | NEW `section_count` int | | 4 | Количество квартир | 413 | ✅ `flat_count` | OK | | 5 | Среднее кв на этаже | 14 | computable (413/32≈13) | denormalize или вычислять | | 6 | Жилая площадь | 19 089 м² | ✅ `square_living` | OK | | 7 | Пассажирских лифтов | Нет | НЕТ | NEW `elevators_passenger_count` int (nullable) | | 8 | Грузовых лифтов | 4 | НЕТ | NEW `elevators_cargo_count` int | | 9 | Машиномест в паркинге | 246 | ✅ через `sales_agg WHERE type='parking'` | denormalize as `parking_total_slots` | | 10 | Гостевые места на придомовой | 43 | НЕТ | NEW `guest_parking_inside_count` int | | 11 | Гостевые места вне придомовой | Нет | НЕТ | NEW `guest_parking_outside_count` int | | 12 | Тип отделки | 1 вариант | НЕТ | NEW `finishing_variants_count` int | | 13 | Свободная планировка | Нет | НЕТ | NEW `has_free_planning` bool | | 14 | Средняя площадь квартир | 46,2 м² | computable | computable (avg by rooms='Квартира') | | 15 | Высота потолков | 2,7 м | НЕТ | NEW `ceiling_height_m` numeric (уже на flat-level в 22b — нужно и obj-level) | | 16 | Материал стен | Монолит-кирпич | `wall_type` NULL | mapping fix → 22a | | 17 | Класс объекта | Комфорт | ✅ `obj_class` (теперь заполнен!) | OK | | 18 | Детские площадки | 6 | НЕТ | NEW `playground_kids_count` (уже в 22e) | | 19 | Спортивные площадки | 5 | НЕТ | NEW `playground_sport_count` (уже в 22e) | | 20 | Велосипедные дорожки | Нет | НЕТ | NEW `has_bike_paths` bool | | 21 | Площадки сбора мусора | 3 | НЕТ | NEW `trash_areas_count` int | | 22 | Наличие пандуса | Нет | НЕТ | NEW `has_ramp` bool | | 23 | Понижающие площадки (ОВЗ) | Есть | НЕТ | NEW `has_low_platforms` bool | | 24 | Инвалидные подъемники | Нет | НЕТ | NEW `has_wheelchair_lift` bool | ### Сводка по категориям | Категория | Колонок | Поля | |---|---|---| | ✅ Уже есть и заполнено | 5 | flat_count, square_living, floor_max, obj_class, escrow | | ✅ Есть в БД, denormalize из других таблиц | 3 | parking_total_slots, apts_total, avg_flat_area_m2 (computable) | | 🟠 Mapping fix (schema готова, NULL для всех) | 2 | energy_eff, wall_type | | 🔴 NEW колонки (специфика дома) | 8 | first_floor_type, section_count, elevators_passenger_count, elevators_cargo_count, ceiling_height_m, finishing_variants_count, has_free_planning | | 🔴 NEW колонки (парковка детально) | 2 | guest_parking_inside_count, guest_parking_outside_count | | 🔴 NEW колонки (придомовая инфра) | 4 | playground_kids_count, playground_sport_count, has_bike_paths, trash_areas_count | | 🔴 NEW колонки (accessibility / ОВЗ) | 3 | has_ramp, has_low_platforms, has_wheelchair_lift | ### Обновлённый 22e — `domrf_kn_objects` расширение Было в 22e: **9 колонок** (1.5d) Стало: ``` -- Building specs (8) ALTER TABLE domrf_kn_objects ADD COLUMN first_floor_type text, section_count int, elevators_passenger_count int, -- NULL = "Нет" elevators_cargo_count int, parking_total_slots int, -- denormalize from sales_agg guest_parking_inside_count int, guest_parking_outside_count int, ceiling_height_m numeric(3,2), -- Apartment specs (3) finishing_variants_count int, has_free_planning bool, avg_flat_area_m2 numeric(5,1), -- denormalize from flats AVG -- Yard infrastructure (4) playground_kids_count int, playground_sport_count int, has_bike_paths bool, trash_areas_count int, -- Accessibility / ОВЗ (3) has_ramp bool, has_low_platforms bool, has_wheelchair_lift bool, -- Catalog/UI (9, из предыдущих updates) flat_area_min numeric(8,2), flat_area_max numeric(8,2), price_min_rub bigint, price_max_rub bigint, price_per_m2_min numeric(12,2), price_per_m2_max numeric(12,2), parking_provision_pct numeric(5,1), project_published_at date, project_declaration_num text, -- Metro & scores (5) metro_nearest_name text, metro_nearest_walk_minutes int, metro_top3 jsonb, domrf_score_location int, domrf_score_transport int, domrf_score_infrastructure int, -- Developer split (1) dev_group_name text; ``` **Итого ~30 новых колонок в `domrf_kn_objects`**. Effort 22e теперь: - Было: 1.5d - Стало: **3d** (migration + scraper mapping для 18 «специфика» полей + verify all coverage) ### Обновлённый total 11.5d → **13d** | ID | Effort | |---|---| | 22a | 1.5d (mapping fix energy_eff, wall_type, obj_class, flat_number, living_area, price_rub) | | 22b | 1d (flat-level +6 cols) | | 22c | 2d (flat plans) | | 22d | 2d (catalog scraper loop) | | **22e** | **3d** (obj-level +30 cols — building specs + accessibility + catalog/UI) | | 22f | 0.5d (obj_checks) | | 22g | 0.5d (developer metrics) | | 22h | 0.5d (metro_top3 already в 22e) | | 22i | 1d (documents) | | 22j | 0.5d (DEDUP infrastructure) | | 22k | 1.5d (frontend exposure) | ### Special note: accessibility — маркетинговый дифференциатор Поля `has_ramp` / `has_low_platforms` / `has_wheelchair_lift` редко учитываются конкурентами. Если показать «пандус + подъёмник» как фильтр в Site Finder — топовый USP для социального жилья / семей с ОВЗ родственниками. Стоит выделить в отдельную UI-секцию объекта.
Sign in to join this conversation.
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#297
No description provided.