gendesign/data/sql/72_objective_sync_config.sql
lekss361 7c05d0a0d8 feat(objective): full sync pipeline + dynamic admin config
Objective API (api.objctv.ru) интегрирован как новый source of truth для
per-flat данных по новостройкам УрФО. Заменяет промежуточный Anton-SQLite
(legacy bootstrap-ETL остался как fallback в свёрнутом блоке UI).

Schema (data/sql/68_v2 — applied на проде, 6 таблиц):
- objective_lots          (UPSERT по lot_id; 303 677 rows)
- objective_corpus_room_month (long-формат месяц×корпус×room_bucket; 19 738 rows)
- objective_lots_history  (append-only weekly snapshots для elasticity)
- objective_complex_mapping (Objective ComplexName ↔ domrf_kn_objects.obj_id)
- objective_raw_reports   (jsonb страховка на смену схемы API)
- objective_scrape_runs   (журнал прогонов)
+ data/sql/72_objective_sync_config (single-row динамический конфиг)

Backend:
- services/scrapers/objective.py: ObjectiveClient — Bearer-токен (Redis +
  in-memory fallback), retry на 401/429/5xx, Retry-After header support
- services/objective_etl.py: ETL SQLite Антона → PG (legacy)
- services/objective_sync_config.py: read/update single-row config
- workers/tasks/scrape_objective.py:
  * sync_objective_group: 2 рабочих отчёта (corp_sum, lots_pf), inline-парсинг
  * sync_all_groups: wrapper, перебирает группы из БД-конфига с
    inter-group паузой; PATCH-merge explicit args > DB config
- workers/tasks/objective_etl.py: Celery task для legacy bootstrap
- workers/celery_app.py: beat читает cron из БД при старте (fallback на env)
- api/v1/admin_scrape.py: 5 новых endpoints для /objective/*

Frontend (frontend/src/app/admin/scrape/objective/page.tsx):
- PRIMARY blue блок «🌐 Наш sync» с input для override групп
- Collapsible «⚙️ Настройки» с формой (cron + 8 параметров) → PUT в БД
- Coverage-панель с PG counts + строка про SQLite Антона как legacy
- Collapsible «🛠 Bootstrap ETL» — legacy-инструмент

Beat schedule: вторник 06:00 МСК, ~10-15 мин на 4 группы (Свердл.обл +
Челябинск + Тюмень + Пермь = ~700K квартир УрФО). Расписание и параметры
меняются через админку без редеплоя (cron требует restart beat).

Эмпирические находки об API (probe 2026-05-10):
- 13 из 21 проверенных group_name доступны на тарифе (включая «Свердловская
  область», «Челябинск», «Тюмень», «Пермь», но НЕ «Свердловская обл» —
  формат имени строгий)
- ComplexName требует БЕЗ префикса «ЖК» и БЕЗ кавычек
- Поле «Банк» для всех 303k = NULL (тариф не отдаёт), но «Тип обременения»
  работает (36% строк = ипотека) → ipoteka_share возможен, банковская
  атрибуция — нет

Docker:
- bind-mount /opt/gendesign/site-finder:/data/anton-sqlite:ro в worker

GitHub backlog: добавлены #22-25 (recommend_mix v3 — 4 сабтаска по
улучшению алгоритма на основе фидбэка про POI / границы районов /
конкурентов / окно данных / success-driven mix).

Knowledge graph (memory/memory-gendesign.jsonl): обновлены entities
Objective_Integration_May07_2026, Schema_Objective_v2_May07,
Objective_API_Findings_May07, Module_Objective_Client + новый
Session_End_May07_2026.

TODO для прода: прописать OBJECTIVE_API_KEY=<key> в backend/.env +
docker compose restart worker beat.
2026-05-10 19:54:15 +03:00

46 lines
3.4 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- Динамическая конфигурация Objective sync — single-row settings.
--
-- Зачем нужна:
-- 1. В админке /admin/scrape/objective можно менять параметры запроса
-- (groups, use_ddu/dkp, period_months_back, inter_group_delay) без редеплоя.
-- 2. Cron-расписание тоже хранится здесь — Celery beat читает его при старте.
-- Изменение требует restart beat-контейнера (это указано в UI как hint).
--
-- Pattern: single-row (id=1), UPSERT для безопасных обновлений.
-- Если строки нет — task/beat падают на settings.* env как fallback.
CREATE TABLE IF NOT EXISTS objective_sync_config (
id SMALLINT PRIMARY KEY DEFAULT 1 CHECK (id = 1),
-- Cron-расписание для Celery beat (5-полевой формат: 'minute hour dom month dow').
-- Celery beat перечитывает это поле только при старте — после изменения
-- нужен `docker compose restart beat`.
cron_schedule TEXT NOT NULL DEFAULT '0 6 * * tue',
-- Группы для sync (csv). Эмпирически проверены на тарифе:
-- 'Свердловская область', 'Челябинск', 'Тюмень', 'Пермь',
-- 'Екатеринбург', 'Верхняя Пышма', 'Берёзовский', 'Нижний Тагил',
-- 'Каменск-Уральский', 'Первоуральск', 'Новоуральск', 'Сысерть'.
groups_csv TEXT NOT NULL DEFAULT 'Свердловская область,Челябинск,Тюмень,Пермь',
-- Параметры запроса /v2/Report/GetReport.
use_ddu BOOLEAN NOT NULL DEFAULT TRUE,
use_dkp BOOLEAN NOT NULL DEFAULT TRUE,
-- Сколько месяцев назад тянуть для Сводных отчётов (corp_sum).
-- 1 = только последний полный месяц (default). 12 = весь год.
-- Поквартирные/Лоты не имеют дат — всегда snapshot.
period_months_back SMALLINT NOT NULL DEFAULT 1 CHECK (period_months_back BETWEEN 1 AND 24),
-- Пауза между группами в одном task'е (секунды). Защита от 429.
inter_group_delay_s SMALLINT NOT NULL DEFAULT 30 CHECK (inter_group_delay_s BETWEEN 0 AND 300),
-- Пауза между HTTP-запросами в client (мс). Передаётся в ObjectiveClient(rate_ms=…).
rate_ms SMALLINT NOT NULL DEFAULT 3000 CHECK (rate_ms BETWEEN 0 AND 10000),
-- Сколько ретраев на 429/5xx.
retries SMALLINT NOT NULL DEFAULT 2 CHECK (retries BETWEEN 0 AND 5),
updated_at timestamptz NOT NULL DEFAULT NOW(),
updated_by TEXT
);
COMMENT ON TABLE objective_sync_config IS
'Single-row динамическая конфигурация Objective sync. Все task-ы и beat '
'читают отсюда. Если строки нет — fallback на settings.* env.';
-- Засеваем единственную строку с дефолтами (если ещё не создана).
INSERT INTO objective_sync_config (id) VALUES (1)
ON CONFLICT (id) DO NOTHING;