-- 017_house_placement_history.sql -- CREATE TABLE house_placement_history — архив размещений из IMV API -- (исторические объявления в конкретном доме, уже снятые с продажи) -- -- Dependencies: 009_houses.sql (houses table — FK house_id, nullable) -- Apply after: 016_listings_snapshots.sql -- Apply before: 018_avito_imv_evaluations.sql -- -- Source: decisions/Schema_Avito_Houses_Listings_History.md sec 6 (UPDATE 2026-05-23) -- Key notes: -- - photo_url НЕ сохраняем (требование 2026-05-23 "без картинок") -- - removed_date заполняется ТОЛЬКО из IMV API (в widget housePlacementHistory его НЕТ) -- - source = 'avito_imv' для данных из IMV API, 'avito' для данных из Houses Catalog widget -- -- Идемпотентно: безопасно запускать повторно. BEGIN; CREATE TABLE IF NOT EXISTS house_placement_history ( id bigserial PRIMARY KEY, source text NOT NULL, -- 'avito_imv' / 'avito' house_id bigint REFERENCES houses(id), -- NULL если дом ещё не в houses table -- Старый item ID (объявление уже снято → 404 на Avito) ext_item_id text NOT NULL, -- e.g. '7489769108' -- Описание (raw text + parsed fields) title text, -- "1-к. квартира, 27,1 м², 2/5 эт." rooms int, area_m2 numeric(8,2), floor int, total_floors int, -- Эволюция цены start_price bigint, -- начальная ask price start_price_date date, -- из unix timestamp startPriceDate last_price bigint, -- финальная ask price (при снятии) last_price_date date, -- из unix timestamp lastPriceDate -- Дата снятия (ТОЛЬКО из IMV API — в widget housePlacementHistory отсутствует) removed_date date, -- лучший proxy для deal_date -- Точный days_on_market (от Avito, точнее нашего вычисления) exposure_days int, -- photo_url НЕ сохраняем (raw_payload содержит itemImage URL для retrofit) raw_payload jsonb, -- полный объект из API scraped_at timestamptz NOT NULL DEFAULT NOW(), UNIQUE (source, ext_item_id) ); CREATE INDEX IF NOT EXISTS hph_house_idx ON house_placement_history (house_id, last_price_date DESC) WHERE house_id IS NOT NULL; CREATE INDEX IF NOT EXISTS hph_source_item_idx ON house_placement_history (source, ext_item_id); -- Для "comparable sales в заданный период" CREATE INDEX IF NOT EXISTS hph_removed_idx ON house_placement_history (removed_date DESC) WHERE removed_date IS NOT NULL; COMMENT ON TABLE house_placement_history IS 'Архив снятых объявлений (proxy для сделок) из IMV API + Houses Catalog. ' 'removed_date заполняется только из IMV API. photo_url не сохраняется.'; COMMENT ON COLUMN house_placement_history.removed_date IS 'Дата снятия объявления с продажи. Лучший proxy для deal_date. ' 'ТОЛЬКО из IMV API (из widget housePlacementHistory это поле отсутствует).'; COMMENT ON COLUMN house_placement_history.house_id IS 'FK на houses.id. NULL если при scrape дом ещё не был в houses table. ' 'Backfill через UPDATE ... WHERE ext_item_id IN (...) при первом scrape дома.'; COMMIT;