"""Milestone API — AP0.8d.""" from __future__ import annotations from datetime import date from typing import Literal, Optional from capabilities import require_capability from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel, Field from services import milestones as milestone_service from tenant_context import TenantContext router = APIRouter(prefix="/api/milestones", tags=["milestones"]) class MilestoneCreateRequest(BaseModel): title: str = Field(min_length=1, max_length=255) goal_description: str = "" status: Literal["planned", "active", "at_risk", "reached", "moved", "discarded"] = "planned" target_date: Optional[date] = None class MilestoneUpdateRequest(BaseModel): title: Optional[str] = Field(default=None, min_length=1, max_length=255) goal_description: Optional[str] = None status: Optional[ Literal["planned", "active", "at_risk", "reached", "moved", "discarded"] ] = None target_date: Optional[date] = None clear_target_date: bool = False @router.get("/{milestone_id}") def get_milestone( milestone_id: str, ctx: TenantContext = Depends(require_capability("kairo.milestone.read")), ): item = milestone_service.get_milestone(tenant_id=ctx.tenant_id, milestone_id=milestone_id) if not item: raise HTTPException(status_code=404, detail="Meilenstein nicht gefunden") return item @router.patch("/{milestone_id}") def update_milestone( milestone_id: str, body: MilestoneUpdateRequest, ctx: TenantContext = Depends(require_capability("kairo.milestone.manage")), ): try: item = milestone_service.update_milestone( tenant_id=ctx.tenant_id, milestone_id=milestone_id, user_id=ctx.user_id, title=body.title, goal_description=body.goal_description, status=body.status, target_date=body.target_date, clear_target_date=body.clear_target_date, ) except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc if not item: raise HTTPException(status_code=404, detail="Meilenstein nicht gefunden") return item @router.delete("/{milestone_id}", status_code=204) def delete_milestone( milestone_id: str, ctx: TenantContext = Depends(require_capability("kairo.milestone.manage")), ): if not milestone_service.delete_milestone( tenant_id=ctx.tenant_id, milestone_id=milestone_id, user_id=ctx.user_id ): raise HTTPException(status_code=404, detail="Meilenstein nicht gefunden")