gendesign/tradein-mvp/backend/app/schemas/buildings.py
lekss361 f3e10a04ad
All checks were successful
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m39s
Deploy Trade-In / build-backend (push) Successful in 8m5s
Deploy Trade-In / deploy (push) Successful in 52s
feat(tradein): API домов «доли квартир в продаже» — /buildings/sale-share (+ listings, summary) (#2055)
2026-06-28 14:14:18 +00:00

78 lines
2.5 KiB
Python
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.

"""Pydantic-схемы страницы «доля квартир дома в продаже» (мигр. 143).
Источник данных — view v_building_sale_share + базовая таблица listings.
Список домов вторичного рынка, где active_secondary / flat_count_effective >= threshold%.
"""
from __future__ import annotations
from datetime import date
from pydantic import BaseModel, ConfigDict
class BuildingSaleShare(BaseModel):
"""Один дом из v_building_sale_share для списка /buildings/sale-share."""
model_config = ConfigDict(from_attributes=True)
house_id: int
address: str | None = None
lat: float | None = None
lon: float | None = None
sale_share_pct: float | None = None
# implausible-матч (active_secondary > знаменателя) — скорее всего коллизия
# адреса при ГАР-матче; не прячем, а маркируем для UI.
over_100: bool = False
active_secondary: int | None = None
flat_count_effective: int | None = None
gar_match_method: str | None = None
median_price_rub: int | None = None
median_price_per_m2: int | None = None
avg_days_on_market: float | None = None
year_built: int | None = None
house_type: str | None = None
total_floors: int | None = None
series_name: str | None = None
is_emergency: bool | None = None
class BuildingListing(BaseModel):
"""Активное вторичное объявление в доме (click-through drawer)."""
model_config = ConfigDict(from_attributes=True)
listing_id: int
source: str
source_url: str | None = None
price_rub: int | None = None
price_per_m2: int | None = None
rooms: int | None = None
area_m2: float | None = None
floor: int | None = None
total_floors: int | None = None
days_on_market: int | None = None
listing_date: date | None = None
address: str | None = None
class HistogramBucket(BaseModel):
"""Корзина гистограммы распределения sale_share_pct."""
bucket: str
count: int
class SaleShareSummary(BaseModel):
"""Сводка для слайдера % + баннера покрытия (/buildings/sale-share/summary)."""
total_secondary_buildings: int
buildings_with_denominator: int
coverage_pct: float
max_pct: float | None = None
p95_pct: float | None = None
histogram: list[HistogramBucket]