import uuid from datetime import datetime from pydantic import BaseModel, ConfigDict, model_validator from api.models.intake import IntakeLane, IntakeOutcome, IntakeStatus class IntakeCreate(BaseModel): id: uuid.UUID | None = None topic_id: uuid.UUID | None = None workplan_id: uuid.UUID | None = None repo_id: uuid.UUID | None = None title: str description: str | None = None lane: IntakeLane = IntakeLane.green origin: str | None = None origin_ref: str | None = None source_repo_path: str | None = None @model_validator(mode="after") def scope_required(self) -> "IntakeCreate": if self.topic_id is None and self.workplan_id is None and self.repo_id is None: raise ValueError("At least one of topic_id, workplan_id, or repo_id must be set") return self class IntakeUpdate(BaseModel): title: str | None = None description: str | None = None lane: IntakeLane | None = None status: IntakeStatus | None = None origin: str | None = None origin_ref: str | None = None routed_note: str | None = None class IntakeRoute(BaseModel): """Move an intake from open/vetted into routed — the state that makes it eligible for the promotion transition (CUST-WP-0061-T03).""" routed_note: str | None = None class IntakeClose(BaseModel): outcome: IntakeOutcome promoted_to: str | None = None note: str | None = None @model_validator(mode="after") def promoted_requires_target(self) -> "IntakeClose": if self.outcome == IntakeOutcome.promoted and not self.promoted_to: raise ValueError("outcome=promoted requires promoted_to") return self class IntakeNoteCreate(BaseModel): content: str author: str | None = None class IntakeNoteRead(BaseModel): model_config = ConfigDict(from_attributes=True) id: uuid.UUID author: str | None = None content: str created_at: datetime class IntakeRead(BaseModel): model_config = ConfigDict(from_attributes=True) id: uuid.UUID topic_id: uuid.UUID | None = None workplan_id: uuid.UUID | None = None repo_id: uuid.UUID | None = None title: str description: str | None = None lane: IntakeLane status: IntakeStatus outcome: IntakeOutcome | None = None origin: str | None = None origin_ref: str | None = None promoted_to: str | None = None source_repo_path: str | None = None routed_note: str | None = None closed_at: datetime | None = None created_at: datetime updated_at: datetime notes: list[IntakeNoteRead] = []