-- 137_ekb_krt_sites.sql
-- #1060 (Site Finder v2 / GG-форсайт) — реестр КРТ-площадок ЕКБ.
--
-- Источник: https://xn--80acgfbsl1azdqr.xn--p1ai/дляработы/гиз/крт
-- (екатеринбург.рф, SSR-страница, 15+ площадок).
--
-- Реквизиты каждой площадки: застройщик, вид застройки (жилая/нежилая),
-- параметры договора КРТ (номер/дата/цена аукциона), градпотенциал, площадь,
-- список постановлений ПАГЕ. Геометрия отсутствует в источнике — join к
-- opportunity_krt запланирован отдельно.
--
-- Ключ: contract_number — присутствует у площадок с заключённым договором КРТ
-- (большинство). Площадки без договора (ранние стадии «подготовки к аукциону»)
-- используют site_name как резервный ключ (UNIQUE(site_name) + partial UNIQUE
-- по contract_number WHERE contract_number IS NOT NULL реализован через два
-- раздельных индекса + DO-блоки ниже).
--
-- Deploy: auto-applied deploy.yml через _schema_migrations (ровно один раз по NN).
-- Idempotent (CREATE TABLE/INDEX IF NOT EXISTS + guarded DO-блоки по pg_constraint).
-- Без INSERT — данные приходят из ekb_krt_sync Celery-воркера (#1060).
--
-- Параллельный PR берёт номер 138 — этот файл 137 зарезервирован для этого PR.

BEGIN;

-- ── 1. Таблица ekb_krt_sites ─────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS ekb_krt_sites (
    id                   BIGSERIAL PRIMARY KEY,
    site_name            TEXT NOT NULL,            -- «N. КРТ жилой/нежилой застройки в районе ул. X»
    district             TEXT,                     -- район/квартал (извлечён из названия best-effort)
    krt_kind             TEXT,                     -- «жилой застройки» | «нежилой застройки»
    developer_name       TEXT,                     -- застройщик из текста договора
    contract_number      TEXT,                     -- «1-2/21.7-14» (NULL у незавершённых площадок)
    contract_date        DATE,                     -- дата договора КРТ
    auction_start_price  NUMERIC,                  -- начальная стоимость аукциона, руб.
    auction_final_price  NUMERIC,                  -- цена по результатам торгов, руб.
    gradpotential_sqm    NUMERIC,                  -- градостроительный потенциал, кв. м
    area_ha              NUMERIC,                  -- площадь территории, га
    mkd_count            INTEGER,                  -- всего многоквартирных домов (если есть)
    paga_decisions       JSONB,                    -- [{date, number, title}] постановления ПАГЕ
    raw_block            TEXT,                     -- исходный текст блока (для отладки/re-parse)
    source_url           TEXT,                     -- URL страницы-источника
    fetched_at           TIMESTAMPTZ NOT NULL DEFAULT now()
);

COMMENT ON TABLE ekb_krt_sites IS
    'Реестр КРТ-площадок Екатеринбурга (#1060, GG-форсайт). '
    'Источник: екатеринбург.рф/дляработы/гиз/крт. '
    'Обновляется еженедельно воркером ekb_krt_sync. '
    'Геометрия отсутствует — join к opportunity_krt планируется отдельно.';

COMMENT ON COLUMN ekb_krt_sites.contract_number IS
    'Номер договора КРТ («1-2/21.7-14»). NULL у площадок на стадии подготовки к аукциону.';
COMMENT ON COLUMN ekb_krt_sites.paga_decisions IS
    'JSON-массив постановлений ПАГЕ: [{date: «DD.MM.YYYY», number: «NNN», title: «...»}]. '
    'Все постановления из блока, включая об утверждении ППТ/ПМТ.';
COMMENT ON COLUMN ekb_krt_sites.krt_kind IS
    '«жилой застройки» или «нежилой застройки» — вид КРТ из названия площадки.';

-- ── 2. UNIQUE по site_name — надёжный ключ для уникальности (присутствует всегда) ──
-- Служит ON CONFLICT target для UPSERT воркера. contract_number NULL у ранних стадий,
-- поэтому site_name выбран основным дедуп-ключом. Дополнительно: уникальный индекс
-- по contract_number WHERE NOT NULL — для быстрого lookup по номеру договора.
DO $$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM pg_constraint WHERE conname = 'uq_ekb_krt_sites_site_name'
    ) THEN
        ALTER TABLE ekb_krt_sites
            ADD CONSTRAINT uq_ekb_krt_sites_site_name UNIQUE (site_name);
    END IF;
END
$$;

-- ── 3. Partial unique index по contract_number (где не NULL) ─────────────────
-- Не через DO-блок + ALTER (partial UNIQUE через ALTER ADD CONSTRAINT не поддерживает
-- WHERE clause в PostgreSQL). Вместо этого — CREATE UNIQUE INDEX IF NOT EXISTS с WHERE.
CREATE UNIQUE INDEX IF NOT EXISTS uix_ekb_krt_sites_contract_number
    ON ekb_krt_sites (contract_number)
    WHERE contract_number IS NOT NULL;

-- ── 4. Индексы ───────────────────────────────────────────────────────────────
-- Поиск по виду застройки (жилая/нежилая).
CREATE INDEX IF NOT EXISTS idx_ekb_krt_sites_krt_kind
    ON ekb_krt_sites (krt_kind);

-- Поиск по застройщику (JOIN с domrf_kn / анализ по девелоперу).
CREATE INDEX IF NOT EXISTS idx_ekb_krt_sites_developer
    ON ekb_krt_sites (developer_name)
    WHERE developer_name IS NOT NULL;

-- Свежесть данных / ORDER BY fetched_at для мониторинга.
CREATE INDEX IF NOT EXISTS idx_ekb_krt_sites_fetched_at
    ON ekb_krt_sites (fetched_at DESC);

COMMIT;
