98 lines
3.0 KiB
Python
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
|