Kairo-Jinkendo/backend/services/milestones.py

104 lines
3.0 KiB
Python
Raw Normal View History

"""Milestone service — Kompatibilitäts-Wrapper auf RoadmapItems (AP0.8d → AP1.4)."""
from __future__ import annotations
from datetime import date
from typing import Any, Literal, Optional
from services import roadmap as roadmap_service
MilestoneStatus = Literal[
"planned", "active", "at_risk", "reached", "moved", "discarded"
]
MILESTONE_STATUSES = roadmap_service.ROADMAP_ITEM_STATUSES
def _as_milestone(item: dict[str, Any]) -> dict[str, Any]:
return {
"id": item["id"],
"tenant_id": item["tenant_id"],
"initiative_id": item["initiative_id"],
"title": item["title"],
"goal_description": item.get("goal_description", ""),
"status": item["status"],
"target_date": item.get("target_date"),
"created_at": item["created_at"],
"updated_at": item["updated_at"],
}
def create_milestone(
*,
tenant_id: str,
initiative_id: str,
title: str,
goal_description: str = "",
status: MilestoneStatus = "planned",
target_date: Optional[date] = None,
user_id: Optional[str] = None,
) -> dict[str, Any]:
item = roadmap_service.create_roadmap_item(
tenant_id=tenant_id,
initiative_id=initiative_id,
title=title,
item_type="milestone",
goal_description=goal_description,
status=status,
target_date=target_date,
user_id=user_id,
)
return _as_milestone(item)
def list_milestones_for_initiative(*, tenant_id: str, initiative_id: str) -> list[dict[str, Any]]:
items = roadmap_service.list_roadmap_items_for_initiative(
tenant_id=tenant_id, initiative_id=initiative_id
)
return [_as_milestone(i) for i in items if i["item_type"] == "milestone"]
def get_milestone(*, tenant_id: str, milestone_id: str) -> Optional[dict[str, Any]]:
item = roadmap_service.get_roadmap_item(tenant_id=tenant_id, item_id=milestone_id)
if not item or item["item_type"] != "milestone":
return None
return _as_milestone(item)
def update_milestone(
*,
tenant_id: str,
milestone_id: str,
user_id: Optional[str] = None,
title: Optional[str] = None,
goal_description: Optional[str] = None,
status: Optional[MilestoneStatus] = None,
target_date: Optional[date] = None,
clear_target_date: bool = False,
) -> Optional[dict[str, Any]]:
item = roadmap_service.update_roadmap_item(
tenant_id=tenant_id,
item_id=milestone_id,
user_id=user_id,
title=title,
goal_description=goal_description,
status=status,
target_date=target_date,
clear_target_date=clear_target_date,
)
return _as_milestone(item) if item else None
def delete_milestone(
*,
tenant_id: str,
milestone_id: str,
user_id: Optional[str] = None,
) -> bool:
item = roadmap_service.get_roadmap_item(tenant_id=tenant_id, item_id=milestone_id)
if not item or item["item_type"] != "milestone":
return False
return roadmap_service.delete_roadmap_item(
tenant_id=tenant_id, item_id=milestone_id, user_id=user_id
)