Kairo-Jinkendo/backend/services/milestones.py
Lars 09433b5d28
Some checks failed
Deploy Development / deploy (push) Successful in 46s
Test Suite / pytest-backend (push) Failing after 1m30s
Test Suite / k6 /api/health Baseline (push) Has been skipped
Test Suite / playwright-smoke (push) Has been skipped
Test Suite / lint-backend (push) Successful in 2s
Test Suite / compose-smoke (push) Has been skipped
AP1.2 + AP1.4: Signals konsolidieren, RoadmapItem mit Gate-Verify
Entfernt operating_phase aus dem Snapshot zugunsten von Lifecycle + signals.
Führt methodenneutrale RoadmapItems (Migration 010), Verify-Pfad und Plan-UI ein.
Milestone-API bleibt als Compat-Wrapper; Version 0.13.0-ap1.4.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-05 18:45:36 +02:00

104 lines
3.0 KiB
Python

"""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
)