feat(tradein): SQL migrations 030-032 — Yandex schema (listings/houses/history) #453

Merged
lekss361 merged 1 commit from feat/tradein-yandex-migrations into main 2026-05-23 13:00:55 +00:00
3 changed files with 117 additions and 0 deletions

View file

@ -0,0 +1,45 @@
-- 030_listings_alter_yandex.sql
-- Purpose: Add Yandex Realty-specific columns to listings table (SERP + detail fields).
-- Dependencies: listings table created in 002_core_tables.sql / 011_listings_alter.sql
-- 019_listings_alter_cian.sql already adds views_total (int) for Cian.
-- Yandex gets a parallel column views_total_yandex to preserve source attribution —
-- a single shared column cannot distinguish which scraper wrote the value when both
-- are active concurrently (conflict-resolution ambiguity).
-- Deploy order: Apply after 029_extend_matching_valuation_dynamics.sql
--
-- Sources:
-- - decisions/Schema_YandexRealty_Recon.md sec 10.1 (SERP offer card)
-- - decisions/Schema_YandexRealty_Recon.md sec 12.3 (OfferCardAuthorInfo agency block)
-- - YandexRealtyScraper_v1_Implementation_Plan Stage 1
--
-- Idempotent: all ALTER TABLE uses ADD COLUMN IF NOT EXISTS; all CREATE INDEX use IF NOT EXISTS.
BEGIN;
ALTER TABLE listings
-- Yandex Realty offer identification
ADD COLUMN IF NOT EXISTS yandex_offer_id text, -- numeric string (e.g. '7567094292504417257'), kept as text
-- Yandex SERP/detail stats
ADD COLUMN IF NOT EXISTS views_total_yandex int, -- "N просмотров" из OfferCardSummary; views_total already used by Cian
ADD COLUMN IF NOT EXISTS publish_date_relative text, -- "6 часов назад" / "вчера" / "N дней назад" raw text
-- Yandex sale type (text form differs from Cian sale_type enum)
ADD COLUMN IF NOT EXISTS sale_type_text text, -- 'свободная продажа' / 'альтернативная' (raw RU phrase)
-- Yandex agency block (OfferCardAuthorInfo)
ADD COLUMN IF NOT EXISTS agency_name text, -- 'Агентство «Диал»'
ADD COLUMN IF NOT EXISTS agency_founded_year int, -- "Год основания N" parsed
ADD COLUMN IF NOT EXISTS agency_objects_count int; -- "N объектов" parsed
-- Partial index on yandex_offer_id for fast lookup by Yandex identifier
CREATE INDEX IF NOT EXISTS listings_yandex_offer_id_idx
ON listings (yandex_offer_id)
WHERE yandex_offer_id IS NOT NULL;
-- Partial index on agency_name for analytics queries filtered by agency
CREATE INDEX IF NOT EXISTS listings_agency_name_idx
ON listings (agency_name)
WHERE agency_name IS NOT NULL;
COMMIT;

View file

@ -0,0 +1,41 @@
-- 031_houses_alter_yandex.sql
-- Purpose: Add Yandex Realty-specific columns to houses table (ЖК landing + valuation enrichment).
-- Dependencies:
-- - houses table: 009_houses.sql
-- - 020_houses_alter_cian.sql (prior Cian columns must exist; no FK dependency, column-level only)
-- Deploy order: Apply after 030_listings_alter_yandex.sql
--
-- Sources:
-- - decisions/Schema_YandexRealty_Recon.md sec 11.2 (Newbuilding ЖК landing fields)
-- - decisions/Schema_YandexRealty_Recon.md sec 13.1 (Yandex Valuation tool enrichment)
-- - YandexRealtyScraper_v1_Implementation_Plan Stage 1
--
-- Idempotent: all ALTER TABLE uses ADD COLUMN IF NOT EXISTS; all CREATE INDEX use IF NOT EXISTS.
BEGIN;
ALTER TABLE houses
-- Yandex Newbuilding (ЖК) landing
ADD COLUMN IF NOT EXISTS yandex_jk_id text, -- '1592987'
ADD COLUMN IF NOT EXISTS yandex_jk_slug text, -- 'tatlin'
ADD COLUMN IF NOT EXISTS commission_year int, -- 2023
ADD COLUMN IF NOT EXISTS commission_month text, -- 'июнь' (raw RU month)
ADD COLUMN IF NOT EXISTS total_area_ha numeric(6,2), -- 1.50
ADD COLUMN IF NOT EXISTS corpus_count int, -- 3 (parsed from "три башни")
-- Yandex Valuation tool enrichment
ADD COLUMN IF NOT EXISTS yandex_validated_at timestamptz, -- last enrichment timestamp
ADD COLUMN IF NOT EXISTS yandex_total_listings int, -- "N объектов" в истории дома
ADD COLUMN IF NOT EXISTS has_panorama boolean; -- Yandex Panorama 3D view available
-- Partial index on yandex_jk_id for fast lookup by Yandex newbuilding identifier
CREATE INDEX IF NOT EXISTS houses_yandex_jk_idx
ON houses (yandex_jk_id)
WHERE yandex_jk_id IS NOT NULL;
-- Partial index on commission_year for filtering by year of commissioning
CREATE INDEX IF NOT EXISTS houses_commission_year_idx
ON houses (commission_year)
WHERE commission_year IS NOT NULL;
COMMIT;

View file

@ -0,0 +1,31 @@
-- 032_yandex_history.sql
-- Purpose: Enable source='yandex_valuation' on existing house_placement_history table by
-- updating the column COMMENT to document the new value and adding analytics-friendly
-- indexes for efficient filtered queries on the new source.
-- Dependencies: 017_house_placement_history.sql (table must already exist)
-- Deploy order: Apply after 031_houses_alter_yandex.sql
--
-- Sources:
-- - decisions/Schema_YandexRealty_Recon.md sec 12.5 + 13.2
-- - YandexRealtyScraper_v1_Implementation_Plan Stage 1
--
-- Note: Idempotent — does NOT alter table schema (no ADD/DROP COLUMN).
-- Only updates COMMENT metadata and creates indexes with IF NOT EXISTS.
-- Safe to re-run; COMMENT ON COLUMN is always an overwrite (no-error on repeat).
BEGIN;
-- Update column comment to document the new source enum value
COMMENT ON COLUMN house_placement_history.source IS
'Source of history record: avito / avito_imv / cian / yandex_valuation';
-- Partial index for analytics queries filtered by source (mostly yandex_valuation)
CREATE INDEX IF NOT EXISTS hph_source_idx
ON house_placement_history (source);
-- Composite index for "all history for a house from a specific source"
CREATE INDEX IF NOT EXISTS hph_house_source_idx
ON house_placement_history (house_id, source, last_price_date DESC)
WHERE house_id IS NOT NULL;
COMMIT;