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