c9383788de
Co-authored-by: Copilot <copilot@github.com>
130 lines
4.0 KiB
Python
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
|