70 lines
3.9 KiB
PL/PgSQL
70 lines
3.9 KiB
PL/PgSQL
-- 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;
|