migrate immoweb exporter to use models

This commit is contained in:
Viktor Barzin 2025-06-08 18:18:38 +00:00
parent e317d2ec54
commit 3785d01009
No known key found for this signature in database
GPG key ID: 4056458DBDBF8863
5 changed files with 94 additions and 22 deletions

View file

@ -10,12 +10,19 @@ from rec import routing
from sqlmodel import JSON, SQLModel, Field, String
@dataclass
@dataclass(frozen=True)
class PriceHistoryItem:
first_seen: datetime
last_seen: datetime
price: float
def to_dict(self) -> Dict[str, float | str]:
return {
"first_seen": self.first_seen.isoformat(),
"last_seen": self.last_seen.isoformat(),
"price": self.price,
}
@dataclass(frozen=True)
class Route:
@ -54,7 +61,8 @@ class Listing(SQLModel, table=False):
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)
# price_history: List[Dict[str, Any]] = Field(default_factory=list, sa_type=JSON)
price_history_json: str = Field(sa_type=String)
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)
@ -72,6 +80,56 @@ class Listing(SQLModel, table=False):
def is_removed(self) -> bool:
return not self.additional_info["property"]["visible"]
@property
def price_per_square_meter(self) -> float | None:
"""
Returns the price per square meter.
"""
if self.square_meters is None or self.square_meters == 0:
return None
return round(self.price / self.square_meters, 2)
@property
def url(self):
return f"https://www.rightmove.co.uk/properties/{self.id}"
@property
def price_history(self) -> List[PriceHistoryItem]:
"""
Returns a list of PriceHistoryItem objects from the price_history_json.
"""
if not self.price_history_json:
return []
parsed: list = json.loads(str(self.price_history_json))
for item in parsed:
item["first_seen"] = datetime.fromisoformat(item["first_seen"])
item["last_seen"] = datetime.fromisoformat(item["last_seen"])
return [
PriceHistoryItem(
first_seen=item["first_seen"],
last_seen=item["last_seen"],
price=item["price"],
)
for item in parsed
]
@staticmethod
def serialize_price_history(price_history: List[PriceHistoryItem]) -> str:
"""
Serializes the price history to a JSON string.
"""
serialized = json.dumps(
[
{
"first_seen": item.first_seen.isoformat(),
"last_seen": item.last_seen.isoformat(),
"price": item.price,
}
for item in price_history
]
)
return serialized
@property
def routing_info(self) -> dict[DestinationMode, List[Route]]:
"""