initial
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
"""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(serializers={datetime: lambda v: v.isoformat()})
|
||||
|
||||
|
||||
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_vector: str | None = None
|
||||
fetched_at: datetime = Field(default_factory=lambda: datetime.now(UTC))
|
||||
|
||||
model_config = ConfigDict(serializers={datetime: lambda v: v.isoformat()})
|
||||
|
||||
|
||||
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(serializers={datetime: lambda v: v.isoformat() if v else None})
|
||||
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user