2025-06-04 21:09:29 +00:00
|
|
|
from dataclasses import dataclass
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
import enum
|
2025-06-07 13:56:00 +00:00
|
|
|
from pathlib import Path
|
2025-06-04 21:09:29 +00:00
|
|
|
from typing import Any, Dict, List
|
2025-06-07 13:56:00 +00:00
|
|
|
from sqlmodel import JSON, Column, Enum, SQLModel, Field, String, TypeDecorator
|
2025-06-03 20:00:30 +00:00
|
|
|
|
|
|
|
|
|
2025-06-04 21:09:29 +00:00
|
|
|
@dataclass
|
|
|
|
|
class PriceHistoryItem:
|
|
|
|
|
first_seen: datetime
|
|
|
|
|
last_seen: datetime
|
|
|
|
|
price: float
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ListingSite(enum.StrEnum):
|
|
|
|
|
RIGHTMOVE = "rightmove"
|
|
|
|
|
# ZOOPLA = "zoopla"
|
|
|
|
|
# ... add more
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Listing(SQLModel, table=False):
|
2025-06-03 20:00:30 +00:00
|
|
|
id: int = Field(primary_key=True)
|
2025-06-04 21:09:29 +00:00
|
|
|
price: float = Field(nullable=False)
|
|
|
|
|
number_of_bedrooms: int = Field(nullable=False)
|
|
|
|
|
square_meters: float | None = Field(default=None, nullable=True)
|
|
|
|
|
agency: str | None = Field(default=None, nullable=True)
|
|
|
|
|
council_tax_band: str | None = Field(default=None, nullable=True)
|
|
|
|
|
longtitude: float = Field(nullable=False)
|
|
|
|
|
latitude: float = Field(nullable=False)
|
|
|
|
|
price_history: List[Dict[str, Any]] = Field(default_factory=list, sa_type=JSON)
|
|
|
|
|
listing_site: ListingSite = Field(nullable=False)
|
|
|
|
|
last_seen: datetime = Field(default_factory=datetime.now, nullable=False)
|
|
|
|
|
photo_thumbnail: str | None = Field(default=None, nullable=True)
|
2025-06-07 13:56:00 +00:00
|
|
|
floorplan_image_paths: List[str] = Field(
|
|
|
|
|
default_factory=list, sa_type=JSON, nullable=False
|
|
|
|
|
)
|
2025-06-06 19:57:50 +00:00
|
|
|
additional_info: Dict[str, Any] = Field(
|
|
|
|
|
default_factory=dict, sa_type=JSON, nullable=False
|
|
|
|
|
)
|
2025-06-04 21:09:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class FurnishType(enum.StrEnum):
|
|
|
|
|
FURNISHED = "furnished"
|
|
|
|
|
UNFURNISHED = "unfurnished"
|
|
|
|
|
PART_FURNISHED = "partFurnished"
|
2025-06-04 21:56:26 +00:00
|
|
|
UNKNOWN = "unknown"
|
2025-06-04 21:09:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class RentListing(Listing, table=True):
|
|
|
|
|
available_from: datetime | None = Field(default=None, nullable=True)
|
|
|
|
|
furnish_type: FurnishType | None = Field(nullable=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BuyListing(Listing, table=True):
|
|
|
|
|
service_charge: float | None = Field(default=None, nullable=True)
|
|
|
|
|
lease_left: int | None = Field(
|
|
|
|
|
default=None, nullable=True
|
|
|
|
|
) # in years, e.g., 90, 80, etc.
|