109 lines
2.9 KiB
Python
109 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from .shared import *
|
|
|
|
def _parse_due_date(value: Optional[str]) -> Optional[datetime]:
|
|
if not value:
|
|
return None
|
|
try:
|
|
return datetime.fromisoformat(value.replace("Z", "+00:00")).replace(tzinfo=None)
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=400, detail="Invalid due_date") from exc
|
|
|
|
async def _ensure_project(
|
|
svc: SSTCService,
|
|
project_id: int,
|
|
):
|
|
project = await svc.get_project(project_id)
|
|
if not project:
|
|
raise HTTPException(status_code=404, detail="Project not found")
|
|
return project
|
|
|
|
async def _ensure_charter(
|
|
db: AsyncSession,
|
|
*,
|
|
tenant_id: int,
|
|
project_id: int,
|
|
charter_id: int,
|
|
) -> TruthNode:
|
|
result = await db.execute(
|
|
select(TruthNode).where(
|
|
and_(
|
|
TruthNode.id == charter_id,
|
|
TruthNode.project_id == project_id,
|
|
TruthNode.tenant_id == tenant_id,
|
|
TruthNode.node_type == "charter",
|
|
)
|
|
)
|
|
)
|
|
charter = result.scalar_one_or_none()
|
|
if not charter:
|
|
raise HTTPException(status_code=404, detail="Charter not found")
|
|
return charter
|
|
|
|
async def _ensure_task(
|
|
db: AsyncSession,
|
|
*,
|
|
tenant_id: int,
|
|
project_id: int,
|
|
task_id: int,
|
|
) -> Task:
|
|
result = await db.execute(
|
|
select(Task).where(
|
|
and_(
|
|
Task.id == task_id,
|
|
Task.project_id == project_id,
|
|
Task.tenant_id == tenant_id,
|
|
)
|
|
)
|
|
)
|
|
task = result.scalar_one_or_none()
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail="Task not found")
|
|
return task
|
|
|
|
async def _ensure_release(
|
|
db: AsyncSession,
|
|
*,
|
|
tenant_id: int,
|
|
project_id: int,
|
|
release_node_id: int,
|
|
) -> TruthNode:
|
|
result = await db.execute(
|
|
select(TruthNode).where(
|
|
and_(
|
|
TruthNode.id == release_node_id,
|
|
TruthNode.project_id == project_id,
|
|
TruthNode.tenant_id == tenant_id,
|
|
TruthNode.node_type == "release",
|
|
)
|
|
)
|
|
)
|
|
release_node = result.scalar_one_or_none()
|
|
if not release_node:
|
|
raise HTTPException(status_code=404, detail="Release plan not found")
|
|
return release_node
|
|
|
|
async def _ensure_review(
|
|
db: AsyncSession,
|
|
*,
|
|
tenant_id: int,
|
|
project_id: int,
|
|
review_node_id: int,
|
|
) -> TruthNode:
|
|
result = await db.execute(
|
|
select(TruthNode).where(
|
|
and_(
|
|
TruthNode.id == review_node_id,
|
|
TruthNode.project_id == project_id,
|
|
TruthNode.tenant_id == tenant_id,
|
|
TruthNode.node_type == "review",
|
|
)
|
|
)
|
|
)
|
|
review_node = result.scalar_one_or_none()
|
|
if not review_node:
|
|
raise HTTPException(status_code=404, detail="Review not found")
|
|
return review_node
|
|
|