from __future__ import annotations from .shared import * from ...services.sstc.entity_lookup import _ensure_charter, _ensure_project, _parse_due_date from ...services.sstc.governance import _assert_charter_aligned, _require_manager from ...services.sstc.signal_core import _parse_node_id, _parse_project_id, _sync_pmflow_rag_async router = APIRouter(tags=["sstc"]) class TaskCreateRequest(BaseModel): title: str description: Optional[str] = None required_skill_tag_ids: Optional[list[int]] = None priority: str = "medium" estimated_hours: Optional[float] = None due_date: Optional[str] = None @router.post("/projects/{project_id}/charters/{charter_id}/tasks") async def create_task( project_id: str, charter_id: str, body: TaskCreateRequest, permission_user: User = Depends(require_project_member_or_manager), db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user), ): _ = permission_user _require_manager(current_user) pid = _parse_project_id(project_id) cid = _parse_node_id(charter_id, "charter_id") tenant_id = int(current_user.tenant_id) await _ensure_project(SSTCService(db, tenant_id=tenant_id), pid) charter = await _ensure_charter(db, tenant_id=tenant_id, project_id=pid, charter_id=cid) _assert_charter_aligned(charter) due_date = _parse_due_date(body.due_date) task = await persist_task( db, tenant_id=tenant_id, truth_node_id=cid, project_id=pid, draft=build_task_create_draft( title=body.title, description=body.description, required_skill_tag_ids=body.required_skill_tag_ids or [], priority=body.priority, status="todo", estimated_hours=body.estimated_hours, due_date=due_date, ), actor_user_id=int(current_user.id), action="task.create", remark="sstc.create_task", commit=False, refresh_workload=False, ) await db.commit() await db.refresh(task) if task.assignee_id is not None: await workload_service.refresh_user_assigned_hours_from_tasks( db, tenant_id=tenant_id, user_id=int(task.assignee_id), ) _sync_pmflow_rag_async( tenant_id=tenant_id, record_type="task", record_id=int(task.id), project_id=pid, title=task.title, content=task.description or "", ) return success_response( { "id": str(task.id), "title": task.title, "status": task.status, "priority": task.priority, "charter_id": str(cid), } )