feat: add tasks/supports/meetings endpoints with project_code paths

This commit is contained in:
Zhi
2026-03-12 22:09:39 +00:00
parent 5a76f61692
commit 724be87a04

View File

@@ -486,3 +486,270 @@ def dashboard_stats(project_id: int = None, db: Session = Depends(get_db)):
by_priority = {p: query.filter(models.Issue.priority == p).count()
for p in ["low", "medium", "high", "critical"]}
return {"total": total, "by_status": by_status, "by_type": by_type, "by_priority": by_priority}
# ============ Tasks ============
@router.get("/tasks/{project_code}/{milestone_id}", tags=["Tasks"])
def list_tasks(project_code: str, milestone_id: int, db: Session = Depends(get_db)):
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")
issues = db.query(models.Issue).filter(
models.Issue.project_id == project.id,
models.Issue.milestone_id == milestone_id,
models.Issue.issue_type == "task"
).all()
return [{
"id": i.id,
"title": i.title,
"description": i.description,
"status": i.status.value if hasattr(i.status, 'value') else i.status,
"priority": i.priority.value if hasattr(i.priority, 'value') else i.priority,
"task_code": i.task_code,
"task_status": i.task_status,
"estimated_effort": i.estimated_effort,
"estimated_working_time": str(i.estimated_working_time) if i.estimated_working_time else None,
"started_on": i.started_on,
"finished_on": i.finished_on,
"depend_on": i.depend_on,
"related_tasks": i.related_tasks,
"assignee_id": i.assignee_id,
"created_at": i.created_at,
} for i in issues]
@router.post("/tasks/{project_code}/{milestone_id}", status_code=status.HTTP_201_CREATED, tags=["Tasks"])
def create_task(project_code: str, milestone_id: int, task_data: dict, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)):
from datetime import datetime, time
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")
ms = db.query(MilestoneModel).filter(MilestoneModel.id == milestone_id).first()
if not ms:
raise HTTPException(status_code=404, detail="Milestone not found")
if ms.status and hasattr(ms.status, 'value') and ms.status.value == "progressing":
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is in_progress")
max_issue = db.query(models.Issue).filter(models.Issue.project_id == project.id).order_by(models.Issue.id.desc()).first()
next_id = (max_issue.id + 1) if max_issue else 1
task_code = f"i_{project_code}_{next_id:06x}"
est_time = None
if task_data.get("estimated_working_time"):
try:
est_time = datetime.strptime(task_data["estimated_working_time"], "%H:%M").time()
except:
pass
issue = models.Issue(
title=task_data.get("title"),
description=task_data.get("description"),
issue_type="task",
status=models.IssueStatus.OPEN,
priority=models.IssuePriority.MEDIUM,
project_id=project.id,
milestone_id=milestone_id,
reporter_id=current_user.id,
task_code=task_code,
estimated_effort=task_data.get("estimated_effort"),
estimated_working_time=est_time,
task_status="open",
created_by_id=current_user.id,
)
db.add(issue)
db.commit()
db.refresh(issue)
return {
"id": issue.id,
"title": issue.title,
"description": issue.description,
"task_code": issue.task_code,
"status": issue.status.value if hasattr(issue.status, 'value') else issue.status,
"priority": issue.priority.value if hasattr(issue.priority, 'value') else issue.priority,
"created_at": issue.created_at,
}
@router.get("/tasks/{project_code}/{milestone_id}/{task_id}", tags=["Tasks"])
def get_task(project_code: str, milestone_id: int, task_id: int, db: Session = Depends(get_db)):
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")
issue = db.query(models.Issue).filter(
models.Issue.id == task_id,
models.Issue.project_id == project.id,
models.Issue.milestone_id == milestone_id,
models.Issue.issue_type == "task"
).first()
if not issue:
raise HTTPException(status_code=404, detail="Task not found")
return {
"id": issue.id,
"title": issue.title,
"description": issue.description,
"status": issue.status.value if hasattr(issue.status, 'value') else issue.status,
"priority": issue.priority.value if hasattr(issue.priority, 'value') else issue.priority,
"task_code": issue.task_code,
"task_status": issue.task_status,
"estimated_effort": issue.estimated_effort,
"estimated_working_time": str(issue.estimated_working_time) if issue.estimated_working_time else None,
"started_on": issue.started_on,
"finished_on": issue.finished_on,
"depend_on": issue.depend_on,
"related_tasks": issue.related_tasks,
"assignee_id": issue.assignee_id,
"created_at": issue.created_at,
}
@router.patch("/tasks/{project_code}/{milestone_id}/{task_id}", tags=["Tasks"])
def update_task(project_code: str, milestone_id: int, task_id: int, task_data: dict, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)):
from datetime import datetime
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")
issue = db.query(models.Issue).filter(
models.Issue.id == task_id,
models.Issue.project_id == project.id,
models.Issue.milestone_id == milestone_id,
models.Issue.issue_type == "task"
).first()
if not issue:
raise HTTPException(status_code=404, detail="Task not found")
if "title" in task_data:
issue.title = task_data["title"]
if "description" in task_data:
issue.description = task_data["description"]
if "task_status" in task_data:
issue.task_status = task_data["task_status"]
if task_data["task_status"] == "progressing" and not issue.started_on:
issue.started_on = datetime.now()
if task_data["task_status"] == "closed" and not issue.finished_on:
issue.finished_on = datetime.now()
if "estimated_effort" in task_data:
issue.estimated_effort = task_data["estimated_effort"]
if "assignee_id" in task_data:
issue.assignee_id = task_data["assignee_id"]
if "status" in task_data:
issue.status = models.IssueStatus[task_data["status"].upper()] if task_data["status"].upper() in [s.name for s in models.IssueStatus] else models.IssueStatus.OPEN
db.commit()
db.refresh(issue)
return issue
# ============ Supports ============
@router.get("/supports/{project_code}/{milestone_id}", tags=["Supports"])
def list_supports(project_code: str, milestone_id: int, db: Session = Depends(get_db)):
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")
issues = db.query(models.Issue).filter(
models.Issue.project_id == project.id,
models.Issue.milestone_id == milestone_id,
models.Issue.issue_type == "support"
).all()
return [{
"id": i.id,
"title": i.title,
"description": i.description,
"status": i.status.value if hasattr(i.status, 'value') else i.status,
"priority": i.priority.value if hasattr(i.priority, 'value') else i.priority,
"created_at": i.created_at,
} for i in issues]
@router.post("/supports/{project_code}/{milestone_id}", status_code=status.HTTP_201_CREATED, tags=["Supports"])
def create_support(project_code: str, milestone_id: int, support_data: dict, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)):
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")
ms = db.query(MilestoneModel).filter(MilestoneModel.id == milestone_id).first()
if not ms:
raise HTTPException(status_code=404, detail="Milestone not found")
if ms.status and hasattr(ms.status, 'value') and ms.status.value == "progressing":
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is in_progress")
issue = models.Issue(
title=support_data.get("title"),
description=support_data.get("description"),
issue_type="support",
status=models.IssueStatus.OPEN,
priority=models.IssuePriority.MEDIUM,
project_id=project.id,
milestone_id=milestone_id,
reporter_id=current_user.id,
)
db.add(issue)
db.commit()
db.refresh(issue)
return issue
# ============ Meetings ============
@router.get("/meetings/{project_code}/{milestone_id}", tags=["Meetings"])
def list_meetings(project_code: str, milestone_id: int, db: Session = Depends(get_db)):
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")
issues = db.query(models.Issue).filter(
models.Issue.project_id == project.id,
models.Issue.milestone_id == milestone_id,
models.Issue.issue_type == "meeting"
).all()
return [{
"id": i.id,
"title": i.title,
"description": i.description,
"status": i.status.value if hasattr(i.status, 'value') else i.status,
"priority": i.priority.value if hasattr(i.priority, 'value') else i.priority,
"created_at": i.created_at,
} for i in issues]
@router.post("/meetings/{project_code}/{milestone_id}", status_code=status.HTTP_201_CREATED, tags=["Meetings"])
def create_meeting(project_code: str, milestone_id: int, meeting_data: dict, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)):
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")
ms = db.query(MilestoneModel).filter(MilestoneModel.id == milestone_id).first()
if not ms:
raise HTTPException(status_code=404, detail="Milestone not found")
if ms.status and hasattr(ms.status, 'value') and ms.status.value == "progressing":
raise HTTPException(status_code=400, detail="Cannot add items to a milestone that is in_progress")
issue = models.Issue(
title=meeting_data.get("title"),
description=meeting_data.get("description"),
issue_type="meeting",
status=models.IssueStatus.OPEN,
priority=models.IssuePriority.MEDIUM,
project_id=project.id,
milestone_id=milestone_id,
reporter_id=current_user.id,
)
db.add(issue)
db.commit()
db.refresh(issue)
return issue