Files
ole c9383788de update
Co-authored-by: Copilot <copilot@github.com>
2026-05-18 21:31:52 +00:00

130 lines
4.0 KiB
Python

"""Pydantic models for FINN ads and Eiendom.no units."""
from datetime import UTC, datetime
from pydantic import BaseModel, ConfigDict, Field
class FinnSearchCard(BaseModel):
"""FINN search result card (minimal fields from search listing)."""
finnkode: str
url: str
title: str | None = None
address: str | None = None
area_m2: int | None = None
asking_price: int | None = None
total_price: int | None = None
common_costs: int | None = None
property_type: str | None = None
ownership_type: str | None = None
bedrooms: int | None = None
floor: str | None = None
broker_company: str | None = None
class FinnAd(BaseModel):
"""FINN listing detail with all available fields."""
finnkode: str
url: str
title: str | None = None
address: str | None = None
postal_area: str | None = None
district: str | None = None
property_type: str | None = None
ownership_type: str | None = None
asking_price: int | None = None
total_price: int | None = None
shared_debt: int | None = None
common_costs: int | None = None
municipal_fee: int | None = None
other_fees: int | None = None
area_m2: int | None = None
rooms: int | None = None
bedrooms: int | None = None
floor: str | None = None
construction_year: int | None = None
energy_rating: str | None = None
heating: str | None = None
has_balcony: bool | None = None
has_terrace: bool | None = None
has_elevator: bool | None = None
has_parking: bool | None = None
has_garage: bool | None = None
listing_description: str | None = None
broker_name: str | None = None
broker_company: str | None = None
first_seen_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
last_seen_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
detail_fetched_at: datetime | None = None
eiendom_unit_code: str | None = None
model_config = ConfigDict()
class EiendomUnit(BaseModel):
"""Eiendom.no unit detail with market data."""
unit_code: str
address: str | None = None
lat: float | None = None
lng: float | None = None
property_type: str | None = None
floor: int | None = None
rooms: int | None = None
construction_year: int | None = None
usable_area: int | None = None
estimated_selling_price: int | None = None
estimated_selling_price_lower: int | None = None
estimated_selling_price_upper: int | None = None
listing_price: int | None = None
listing_sqm_price: int | None = None
common_costs: int | None = None
days_on_market: int | None = None
sale_status: str | None = None
market_placement_score: str | None = None
unit_images: list[str] | None = None
unit_vector: str | None = None
fetched_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
model_config = ConfigDict()
class SimilarUnit(BaseModel):
"""Eiendom.no similar unit (comp) result."""
unit_code: str
address: str | None = None
lat: float | None = None
lng: float | None = None
property_type: str | None = None
floor: int | None = None
rooms: int | None = None
construction_year: int | None = None
usable_area: int | None = None
listing_price: int | None = None
selling_price: int | None = None
shared_debt: int | None = None
common_costs: int | None = None
sqm_price: int | None = None
days_on_market: int | None = None
sale_status: str | None = None
finalized_at: datetime | None = None
listing_status: str = Field(default="RECENTLY_SOLD")
model_config = ConfigDict()
class UnitVector(BaseModel):
"""Unit vector payload for similar-units API."""
lon: float
lat: float
ptype: str # property type: APARTMENT, HOUSE, etc.
floor: int | None = None
rooms: int | None = None
built: int | None = None # construction year
area: int | None = None # usable area
price: int | None = None # listing or estimated price