feat(11-01): create sites table migration, model, and schemas
- Add migration 030 with sites table, RLS policy, and device site_id FK - Add Site SQLAlchemy model with tenant isolation - Add site_id nullable FK and relationship to Device model - Add sites relationship to Tenant model - Register Site in models __init__.py - Add SiteCreate, SiteUpdate, SiteResponse, SiteListResponse schemas Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
74
backend/app/schemas/site.py
Normal file
74
backend/app/schemas/site.py
Normal file
@@ -0,0 +1,74 @@
|
||||
"""Pydantic schemas for Site endpoints."""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, field_validator
|
||||
|
||||
|
||||
class SiteCreate(BaseModel):
|
||||
"""Schema for creating a new site."""
|
||||
|
||||
name: str
|
||||
latitude: Optional[float] = None
|
||||
longitude: Optional[float] = None
|
||||
address: Optional[str] = None
|
||||
elevation: Optional[float] = None
|
||||
notes: Optional[str] = None
|
||||
|
||||
@field_validator("name")
|
||||
@classmethod
|
||||
def validate_name(cls, v: str) -> str:
|
||||
v = v.strip()
|
||||
if len(v) < 1 or len(v) > 255:
|
||||
raise ValueError("Site name must be 1-255 characters")
|
||||
return v
|
||||
|
||||
|
||||
class SiteUpdate(BaseModel):
|
||||
"""Schema for updating an existing site. All fields optional."""
|
||||
|
||||
name: Optional[str] = None
|
||||
latitude: Optional[float] = None
|
||||
longitude: Optional[float] = None
|
||||
address: Optional[str] = None
|
||||
elevation: Optional[float] = None
|
||||
notes: Optional[str] = None
|
||||
|
||||
@field_validator("name")
|
||||
@classmethod
|
||||
def validate_name(cls, v: Optional[str]) -> Optional[str]:
|
||||
if v is None:
|
||||
return v
|
||||
v = v.strip()
|
||||
if len(v) < 1 or len(v) > 255:
|
||||
raise ValueError("Site name must be 1-255 characters")
|
||||
return v
|
||||
|
||||
|
||||
class SiteResponse(BaseModel):
|
||||
"""Site response schema with health rollup stats."""
|
||||
|
||||
id: uuid.UUID
|
||||
name: str
|
||||
latitude: Optional[float] = None
|
||||
longitude: Optional[float] = None
|
||||
address: Optional[str] = None
|
||||
elevation: Optional[float] = None
|
||||
notes: Optional[str] = None
|
||||
device_count: int = 0
|
||||
online_count: int = 0
|
||||
online_percent: float = 0.0
|
||||
alert_count: int = 0
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class SiteListResponse(BaseModel):
|
||||
"""List of sites with unassigned device count."""
|
||||
|
||||
sites: list[SiteResponse]
|
||||
unassigned_count: int
|
||||
Reference in New Issue
Block a user