gendesign/tradein-mvp/backend/data/sql/011_listings_alter.sql
lekss361 a2147872ed
All checks were successful
Deploy Trade-In / build-backend (push) Successful in 23s
Deploy Trade-In / deploy (push) Successful in 27s
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / build-frontend (push) Has been skipped
feat(tradein): SQL migrations 009-018 — houses + listings extension + IMV cache (#440)
2026-05-23 11:41:44 +00:00

96 lines
6.9 KiB
PL/PgSQL
Raw 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.

-- 011_listings_alter.sql
-- ALTER TABLE listings — добавить ~30 полей для Avito detail page + domoteka (Росреестр)
--
-- Dependencies:
-- 002_core_tables.sql (listings table)
-- 009_houses.sql (houses table — FK house_id_fk)
--
-- Apply after: 009_houses.sql
-- Apply before: 012_sellers.sql, 013_listings_alter_seller.sql
--
-- Sources:
-- decisions/Schema_Avito_Houses_Listings_History.md sec 13 (listings ALTER)
-- decisions/Schema_Avito_Houses_Listings_History.md sec 29 (owners_count/owners_at_least)
--
-- Note: owners_2plus (boolean) из sec 13 заменён на owners_count + owners_at_least (sec 29).
-- Идемпотентно: ADD COLUMN IF NOT EXISTS безопасен при повторном запуске.
BEGIN;
ALTER TABLE listings
-- ── House linking ──────────────────────────────────────────────────────
ADD COLUMN IF NOT EXISTS house_source text, -- 'avito' / 'cian'
ADD COLUMN IF NOT EXISTS house_ext_id text, -- Avito's '3171365'
ADD COLUMN IF NOT EXISTS house_url text, -- /catalog/houses/<slug>/<id>
ADD COLUMN IF NOT EXISTS house_id_fk bigint REFERENCES houses(id),
ADD COLUMN IF NOT EXISTS listing_segment text, -- 'vtorichka' / 'novostroyki'
-- ── Характеристики квартиры (из detail page "О квартире") ─────────────
ADD COLUMN IF NOT EXISTS kitchen_area_m2 numeric(6,2),
ADD COLUMN IF NOT EXISTS balcony_loggia text, -- balcony/loggia/both/none
-- (заменяет has_balcony boolean для detail)
ADD COLUMN IF NOT EXISTS room_layout text, -- isolated/adjacent/mixed
ADD COLUMN IF NOT EXISTS bathroom_type text, -- combined/separate/both/multi
ADD COLUMN IF NOT EXISTS windows_view text, -- yard/street/both/park
-- ── Условия продажи ────────────────────────────────────────────────────
ADD COLUMN IF NOT EXISTS sale_type text, -- free/alternative/auction
ADD COLUMN IF NOT EXISTS mortgage_available boolean,
-- ── Метрики просмотров (Avito tracks viewership) ──────────────────────
ADD COLUMN IF NOT EXISTS views_total int,
ADD COLUMN IF NOT EXISTS views_today int,
ADD COLUMN IF NOT EXISTS publish_date date, -- "18 мая в 13:40" → 2025-05-18
-- ── Текстовое описание ─────────────────────────────────────────────────
ADD COLUMN IF NOT EXISTS description text, -- 1000+ chars обычно
-- ── Domoteka / Росреестр verification badges ──────────────────────────
-- Note: owners_2plus (boolean из sec 13) заменён на owners_count + owners_at_least (sec 29)
ADD COLUMN IF NOT EXISTS owners_count int, -- 1 = точно 1; 2 = '2 или больше'
ADD COLUMN IF NOT EXISTS owners_at_least boolean, -- true если Avito выдал "X или больше"
ADD COLUMN IF NOT EXISTS last_owner_change_date date, -- "Последняя смена собственника YYYY-MM-DD"
ADD COLUMN IF NOT EXISTS encumbrances_clean boolean, -- "Не найдены ограничения и обременения"
ADD COLUMN IF NOT EXISTS registry_match boolean, -- "Совпадают площадь, адрес и этаж"
-- ── Metro + location internal IDs ─────────────────────────────────────
ADD COLUMN IF NOT EXISTS metro_stations jsonb DEFAULT '[]'::jsonb,
-- [{"name":"Чкаловская","minutes":"11-15","mode":"walk"},...]
ADD COLUMN IF NOT EXISTS avito_location_id int, -- 654070 (ЕКБ internal ID)
-- ── Detail-page enrichment tracking ───────────────────────────────────
ADD COLUMN IF NOT EXISTS detail_enriched_at timestamptz; -- когда обогатили с detail page
-- Индексы для аналитических запросов
CREATE INDEX IF NOT EXISTS listings_house_ext_id_idx ON listings (house_source, house_ext_id)
WHERE house_ext_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS listings_house_id_fk_idx ON listings (house_id_fk)
WHERE house_id_fk IS NOT NULL;
CREATE INDEX IF NOT EXISTS listings_kitchen_idx ON listings (kitchen_area_m2)
WHERE kitchen_area_m2 IS NOT NULL;
CREATE INDEX IF NOT EXISTS listings_views_idx ON listings (views_total DESC)
WHERE views_total IS NOT NULL;
-- Partial index для фильтра "без обременений" — используется estimator
CREATE INDEX IF NOT EXISTS listings_encumbrances_idx ON listings (encumbrances_clean)
WHERE encumbrances_clean = true;
-- Partial index для очереди detail-enrichment (пустой = нужно обогатить)
CREATE INDEX IF NOT EXISTS listings_detail_enrich_idx ON listings (detail_enriched_at)
WHERE detail_enriched_at IS NULL;
-- Partial index для "только с одним собственником" (clean title filter)
CREATE INDEX IF NOT EXISTS listings_owners_idx ON listings (owners_count)
WHERE owners_count IS NOT NULL;
COMMENT ON COLUMN listings.house_ext_id IS
'Avito house ID из /catalog/houses/<slug>/<id>. NULL для ~18% карточек без ссылки на дом.';
COMMENT ON COLUMN listings.balcony_loggia IS
'Тип балкона: balcony/loggia/both/none. Детальнее чем has_balcony (boolean). Из detail page.';
COMMENT ON COLUMN listings.owners_count IS
'Кол-во собственников из domoteka badge. 1=точно один; 2=''2 или больше'' (Avito скрывает точное для privacy).';
COMMENT ON COLUMN listings.owners_at_least IS
'true если badge содержит "X или больше" — значит owners_count является нижней границей.';
COMMENT ON COLUMN listings.metro_stations IS
'Список станций метро: [{"name":"Чкаловская","minutes":"11-15","mode":"walk"},...]. Из detail page.';
COMMENT ON COLUMN listings.detail_enriched_at IS
'Timestamp обогащения с detail page. NULL = ещё не обогащено (используется как queue flag).';
COMMIT;