geo/backend/app/schemas/lifecycle.py

98 lines
3.0 KiB
Python

import uuid
from datetime import datetime
from pydantic import BaseModel, model_validator
# ---------- Request ----------
class ProjectCreateRequest(BaseModel):
brand_name: str
brand_url: str
description: str | None = None
class StageUpdateRequest(BaseModel):
status: str | None = None
notes: str | None = None
metrics: dict | None = None
# ---------- Response ----------
class StageDetailResponse(BaseModel):
id: uuid.UUID
project_id: uuid.UUID
stage_number: int
status: str
started_at: datetime | None
completed_at: datetime | None
notes: str | None
metrics: dict | None
model_config = {"from_attributes": True}
class ProjectResponse(BaseModel):
id: uuid.UUID
organization_id: uuid.UUID
name: str = "" # alias for brand_name for frontend compatibility
brand_name: str
brand_aliases: list
current_stage: str # mapped from int to string ("diagnosis" etc) for frontend
status: str
owner_id: uuid.UUID | None = None # alias for created_by for frontend
created_by: uuid.UUID | None
created_at: datetime
updated_at: datetime
stages: list[StageDetailResponse] = []
model_config = {"from_attributes": True}
@model_validator(mode="before")
@classmethod
def map_fields(cls, data):
# Handle SQLAlchemy model instance
if hasattr(data, "current_stage"):
stage_int = getattr(data, "current_stage", 1)
stage_map = {1: "diagnosis", 2: "strategy", 3: "content", 4: "publishing", 5: "monitoring"}
if isinstance(stage_int, int):
object.__setattr__(data, "current_stage", stage_map.get(stage_int, "diagnosis"))
# Set name = brand_name for frontend
if not getattr(data, "name", None):
object.__setattr__(data, "name", getattr(data, "brand_name", ""))
# Set owner_id = created_by for frontend
if not getattr(data, "owner_id", None):
object.__setattr__(data, "owner_id", getattr(data, "created_by", None))
elif isinstance(data, dict):
stage_val = data.get("current_stage", 1)
stage_map = {1: "diagnosis", 2: "strategy", 3: "content", 4: "publishing", 5: "monitoring"}
if isinstance(stage_val, int):
data["current_stage"] = stage_map.get(stage_val, "diagnosis")
data.setdefault("name", data.get("brand_name", ""))
data.setdefault("owner_id", data.get("created_by"))
return data
class ProjectStatsResponse(BaseModel):
total_projects: int
active_projects: int
completed_projects: int = 0
contents_produced: int = 0
avg_ai_citation_rate: float | None = None
current_stage_distribution: dict[str, int] = {}
stage_distribution: dict[str, int] = {}
completion_rate: float
class QuickStartResponse(BaseModel):
project: ProjectResponse
message: str
class TimelineEvent(BaseModel):
event_type: str
description: str
timestamp: datetime
stage_number: int | None = None