173 lines
4.6 KiB
Python
173 lines
4.6 KiB
Python
from pydantic import BaseModel, Field
|
|
from typing import Optional
|
|
from datetime import datetime
|
|
|
|
|
|
# -----------------------------
|
|
# Owner Response Schema
|
|
# -----------------------------
|
|
|
|
class OwnerResponse(BaseModel):
|
|
|
|
owner_id: str = Field(..., example="OWN_9001")
|
|
|
|
full_name: str = Field(..., example="Michael Anderson")
|
|
|
|
email: Optional[str] = Field(None, example="michael.anderson@email.com")
|
|
|
|
phone: Optional[str] = Field(None, example="+14155552671")
|
|
|
|
entity_type: str = Field(..., example="Individual")
|
|
|
|
mailing_address: Optional[str] = Field(
|
|
None,
|
|
example="742 Evergreen Terrace, San Diego, CA 92101"
|
|
)
|
|
|
|
credit_score_est: Optional[int] = Field(None, ge=300, le=850, example=780)
|
|
|
|
income_bracket: Optional[str] = Field(None, example="$100k+")
|
|
|
|
net_worth_est: Optional[int] = Field(None, example=1250000)
|
|
|
|
portfolio_size: Optional[int] = Field(None, example=3)
|
|
|
|
min_price_expectation: Optional[int] = Field(None, example=650000)
|
|
|
|
preferred_close_days: Optional[int] = Field(None, example=30)
|
|
|
|
urgency_score: Optional[int] = Field(None, ge=0, le=100, example=72)
|
|
|
|
is_absentee: Optional[bool] = Field(None, example=True)
|
|
|
|
willing_to_sell: Optional[bool] = Field(None, example=True)
|
|
|
|
willing_to_partner: Optional[bool] = Field(None, example=False)
|
|
|
|
# ⚠ Recommended: Do not expose in public APIs
|
|
tax_id_hash: Optional[str] = Field(
|
|
None,
|
|
example="HASHX9921",
|
|
description="Hashed tax identifier (masked)"
|
|
)
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# -----------------------------
|
|
# Property Response Schema
|
|
# -----------------------------
|
|
|
|
class PropertyResponse(BaseModel):
|
|
|
|
property_id: str = Field(..., example="PROP_1001")
|
|
|
|
internal_asset_code: str = Field(..., example="ASSET-LA-7782")
|
|
|
|
structure_type: str = Field(..., example="SingleFamily")
|
|
|
|
listing_status: str = Field(..., example="ForSale")
|
|
|
|
occupancy_status: str = Field(..., example="OwnerOccupied")
|
|
|
|
property_grade: str = Field(..., example="A")
|
|
|
|
energy_rating: Optional[str] = Field(None, example="B+")
|
|
|
|
year_built: int = Field(..., example=2006)
|
|
|
|
floors_count: int = Field(..., example=2)
|
|
|
|
bedrooms: int = Field(..., example=4)
|
|
|
|
bathrooms: int = Field(..., example=3)
|
|
|
|
total_built_sqft: int = Field(..., example=2480)
|
|
|
|
lot_size_sqft: Optional[int] = Field(None, example=6200)
|
|
|
|
garage_spaces: Optional[int] = Field(None, example=2)
|
|
|
|
purchase_price: Optional[int] = Field(None, example=590000)
|
|
|
|
expected_sale_price: Optional[int] = Field(None, example=740000)
|
|
|
|
market_value_est: Optional[int] = Field(None, example=685000)
|
|
|
|
current_rent: Optional[int] = Field(None, example=0)
|
|
|
|
rental_yield_percent: Optional[float] = Field(None, example=6.2)
|
|
|
|
vacancy_days: Optional[int] = Field(None, example=0)
|
|
|
|
tenant_present: Optional[bool] = Field(None, example=False)
|
|
|
|
# Structural / Condition
|
|
|
|
exterior_condition: Optional[str] = Field(None, example="Good")
|
|
|
|
foundation_type: Optional[str] = Field(None, example="Slab")
|
|
|
|
roof_type: Optional[str] = Field(None, example="Gable")
|
|
|
|
roof_material: Optional[str] = Field(None, example="Asphalt Shingle")
|
|
|
|
roof_condition: Optional[str] = Field(None, example="Good")
|
|
|
|
roof_pitch: Optional[str] = Field(None, example="Medium")
|
|
|
|
roof_age_years: Optional[int] = Field(None, example=7)
|
|
|
|
siding_material: Optional[str] = Field(None, example="Hardie Board")
|
|
|
|
gutter_status: Optional[str] = Field(None, example="Functional")
|
|
|
|
hvac_type: Optional[str] = Field(None, example="Central")
|
|
|
|
electric_type: Optional[str] = Field(None, example="Copper")
|
|
|
|
plumbing_type: Optional[str] = Field(None, example="PEX")
|
|
|
|
solar_installed: Optional[bool] = Field(None, example=False)
|
|
|
|
# Risk Indicators
|
|
|
|
mold_risk_level: Optional[str] = Field(None, example="Low")
|
|
|
|
termite_risk_level: Optional[str] = Field(None, example="Low")
|
|
|
|
structural_risk_level: Optional[str] = Field(None, example="Low")
|
|
|
|
fire_damage_flag: Optional[bool] = Field(None, example=False)
|
|
|
|
water_damage_flag: Optional[bool] = Field(None, example=False)
|
|
|
|
# Timestamps
|
|
|
|
created_at: Optional[datetime] = Field(
|
|
None,
|
|
example="2026-01-29T16:43:44.285Z"
|
|
)
|
|
|
|
updated_at: Optional[datetime] = Field(
|
|
None,
|
|
example="2026-01-29T16:43:44.285Z"
|
|
)
|
|
|
|
class Config:
|
|
from_attributes = True
|
|
|
|
|
|
# -----------------------------
|
|
# Final Nearest Asset Response
|
|
# -----------------------------
|
|
|
|
class NearestAssetResponse(BaseModel):
|
|
|
|
owner: OwnerResponse
|
|
|
|
property: PropertyResponse
|
|
|
|
distanceMeters: float = Field(..., example=342.55)
|