diff --git a/backend/app/dtos/house_create_request.py b/backend/app/dtos/house_create_request.py index 0f7fc7c..ca07085 100644 --- a/backend/app/dtos/house_create_request.py +++ b/backend/app/dtos/house_create_request.py @@ -21,3 +21,14 @@ class HouseCreateRequest(BaseModel): description="Description of the house", examples=["A beautiful 3-bedroom house"], ) + square_feet: float = Field( + ..., + description="Square footage of the house", + examples=[1500.00], + ) + bedrooms: int = Field( + ..., description="Number of bedrooms in the house", examples=[3] + ) + bathrooms: float = Field( + ..., description="Number of bathrooms in the house", examples=[2.5] + ) diff --git a/backend/app/models/house.py b/backend/app/models/house.py index 9bd08df..84ce0bf 100644 --- a/backend/app/models/house.py +++ b/backend/app/models/house.py @@ -11,3 +11,6 @@ class House(SQLModel, table=True): price: float = Field() description: str = Field() owner_user_id: UUID = Field(foreign_key="owner.user_id") + square_feet: float = Field() + bedrooms: int = Field() + bathrooms: float = Field() diff --git a/backend/app/repositories/house_repository.py b/backend/app/repositories/house_repository.py index 65d06e2..21c2338 100644 --- a/backend/app/repositories/house_repository.py +++ b/backend/app/repositories/house_repository.py @@ -1,9 +1,9 @@ -from typing import Annotated +from typing import Annotated, Literal from uuid import UUID from fastapi import Depends from sqlalchemy.ext.asyncio.session import AsyncSession -from sqlmodel import select +from sqlmodel import asc, desc, select from ..models.house import House from ..providers.db_provider import get_session @@ -13,8 +13,19 @@ class HouseRepository: def __init__(self, session: Annotated[AsyncSession, Depends(get_session)]) -> None: self.session = session - async def get_all(self, limit: int = 100, offset: int = 0) -> list[House]: - statement = select(House).offset(offset).limit(limit) + async def get_all( + self, + limit: int = 100, + offset: int = 0, + order_by: Literal["PRICE"] = "PRICE", + sort_order: Literal["ASC", "DESC"] = "DESC", + ) -> list[House]: + sorter = desc if sort_order == "DESC" else asc + + statement = ( + select(House).offset(offset).limit(limit).order_by(sorter(House.price)) + ) + result = await self.session.execute(statement) return result.scalars().all() diff --git a/backend/app/routers/houses.py b/backend/app/routers/houses.py index f05ca11..a9bc95c 100644 --- a/backend/app/routers/houses.py +++ b/backend/app/routers/houses.py @@ -1,4 +1,4 @@ -from typing import Annotated +from typing import Annotated, Literal from fastapi import APIRouter, Depends @@ -35,6 +35,9 @@ async def create_house( country=body.country, price=body.price, description=body.description, + square_feet=body.square_feet, + bedrooms=body.bedrooms, + bathrooms=body.bathrooms, ) await house_repository.save(house) @@ -45,10 +48,14 @@ async def create_house( @router.get("") async def get_all_houses( house_repository: Annotated[HouseRepository, Depends()], + order_by: Literal["PRICE"] = "PRICE", + sort_order: Literal["ASC", "DESC"] = "DESC", limit: int = 100, offset: int = 0, ) -> HousesListResponse: - all_houses = await house_repository.get_all(offset=offset, limit=limit) + all_houses = await house_repository.get_all( + offset=offset, limit=limit, order_by=order_by, sort_order=sort_order + ) house_responses = [ HouseResponse( @@ -61,6 +68,5 @@ async def get_all_houses( ) for house in all_houses ] - print(house_responses) return HousesListResponse(houses=house_responses) diff --git a/backend/app/services/house_price_predictor.py b/backend/app/services/house_price_predictor.py index bb23d33..6243ff8 100644 --- a/backend/app/services/house_price_predictor.py +++ b/backend/app/services/house_price_predictor.py @@ -1,45 +1,16 @@ -import random -from dataclasses import dataclass -from typing import List - - -@dataclass -class Prediction: - predicted_price: float - confidence_score: float - similar_listings: List[float] - - class HousePricePredictor: """ Mock ML model that predicts house prices. In a real scenario, this would load a trained model. """ - def __init__(self): - # Mock initialization - in reality would load model weights - pass - - def predict( + async def predict( self, square_feet: float, bedrooms: int, bathrooms: float - ) -> Prediction: - """ - Mock prediction method that returns: - - predicted price - - confidence score - - similar listing prices - """ - # Mock prediction logic + ) -> float: base_price = square_feet * 200 bedroom_value = bedrooms * 25000 bathroom_value = bathrooms * 15000 predicted_price = base_price + bedroom_value + bathroom_value - # Add some randomness to make it interesting - confidence_score = random.uniform(0.8, 0.99) - similar_listings = [ - predicted_price * random.uniform(0.9, 1.1) for _ in range(3) - ] - - return Prediction(predicted_price, confidence_score, similar_listings) + return predicted_price diff --git a/backend/app/services/investor_predictor.py b/backend/app/services/investor_predictor.py index 4ceec16..a1ad54b 100644 --- a/backend/app/services/investor_predictor.py +++ b/backend/app/services/investor_predictor.py @@ -1,5 +1,7 @@ import random +from ..models import User + class InvestorPredictor: def is_investor(user: User) -> bool: