refactor: split tasks/supports/meetings into separate tables
This commit is contained in:
@@ -17,6 +17,9 @@ from app.models import models
|
||||
from app.models.apikey import APIKey
|
||||
from app.models.activity import ActivityLog
|
||||
from app.models.milestone import Milestone as MilestoneModel
|
||||
from app.models.task import Task, TaskStatus, TaskPriority
|
||||
from app.models.support import Support, SupportStatus, SupportPriority
|
||||
from app.models.meeting import Meeting, MeetingStatus, MeetingPriority
|
||||
from app.models.notification import Notification as NotificationModel
|
||||
from app.models.worklog import WorkLog
|
||||
from app.schemas import schemas
|
||||
@@ -487,6 +490,7 @@ def dashboard_stats(project_id: int = None, db: Session = Depends(get_db)):
|
||||
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"])
|
||||
@@ -495,34 +499,32 @@ def list_tasks(project_code: str, milestone_id: int, db: Session = Depends(get_d
|
||||
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"
|
||||
tasks = db.query(Task).filter(
|
||||
Task.project_id == project.id,
|
||||
Task.milestone_id == milestone_id
|
||||
).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]
|
||||
"id": t.id,
|
||||
"title": t.title,
|
||||
"description": t.description,
|
||||
"status": t.status.value if hasattr(t.status, "value") else t.status,
|
||||
"priority": t.priority.value if hasattr(t.priority, "value") else t.priority,
|
||||
"task_code": t.task_code,
|
||||
"estimated_effort": t.estimated_effort,
|
||||
"estimated_working_time": str(t.estimated_working_time) if t.estimated_working_time else None,
|
||||
"started_on": t.started_on,
|
||||
"finished_on": t.finished_on,
|
||||
"depend_on": t.depend_on,
|
||||
"related_tasks": t.related_tasks,
|
||||
"assignee_id": t.assignee_id,
|
||||
"created_at": t.created_at,
|
||||
} for t in tasks]
|
||||
|
||||
|
||||
@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
|
||||
from datetime import datetime
|
||||
|
||||
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
|
||||
if not project:
|
||||
@@ -532,11 +534,11 @@ def create_task(project_code: str, milestone_id: int, task_data: dict, db: Sessi
|
||||
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":
|
||||
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
|
||||
max_task = db.query(Task).filter(Task.project_id == project.id).order_by(Task.id.desc()).first()
|
||||
next_id = (max_task.id + 1) if max_task else 1
|
||||
task_code = f"i_{project_code}_{next_id:06x}"
|
||||
|
||||
est_time = None
|
||||
@@ -546,33 +548,31 @@ def create_task(project_code: str, milestone_id: int, task_data: dict, db: Sessi
|
||||
except:
|
||||
pass
|
||||
|
||||
issue = models.Issue(
|
||||
task = Task(
|
||||
title=task_data.get("title"),
|
||||
description=task_data.get("description"),
|
||||
issue_type="task",
|
||||
status=models.IssueStatus.OPEN,
|
||||
priority=models.IssuePriority.MEDIUM,
|
||||
status=TaskStatus.OPEN,
|
||||
priority=TaskPriority.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.add(task)
|
||||
db.commit()
|
||||
db.refresh(issue)
|
||||
db.refresh(task)
|
||||
|
||||
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,
|
||||
"id": task.id,
|
||||
"title": task.title,
|
||||
"description": task.description,
|
||||
"task_code": task.task_code,
|
||||
"status": task.status.value,
|
||||
"priority": task.priority.value,
|
||||
"created_at": task.created_at,
|
||||
}
|
||||
|
||||
|
||||
@@ -582,31 +582,29 @@ def get_task(project_code: str, milestone_id: int, task_id: int, db: Session = D
|
||||
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"
|
||||
task = db.query(Task).filter(
|
||||
Task.id == task_id,
|
||||
Task.project_id == project.id,
|
||||
Task.milestone_id == milestone_id
|
||||
).first()
|
||||
if not issue:
|
||||
if not task:
|
||||
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,
|
||||
"id": task.id,
|
||||
"title": task.title,
|
||||
"description": task.description,
|
||||
"status": task.status.value,
|
||||
"priority": task.priority.value,
|
||||
"task_code": task.task_code,
|
||||
"estimated_effort": task.estimated_effort,
|
||||
"estimated_working_time": str(task.estimated_working_time) if task.estimated_working_time else None,
|
||||
"started_on": task.started_on,
|
||||
"finished_on": task.finished_on,
|
||||
"depend_on": task.depend_on,
|
||||
"related_tasks": task.related_tasks,
|
||||
"assignee_id": task.assignee_id,
|
||||
"created_at": task.created_at,
|
||||
}
|
||||
|
||||
|
||||
@@ -618,36 +616,37 @@ def update_task(project_code: str, milestone_id: int, task_id: int, task_data: d
|
||||
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"
|
||||
task = db.query(Task).filter(
|
||||
Task.id == task_id,
|
||||
Task.project_id == project.id,
|
||||
Task.milestone_id == milestone_id
|
||||
).first()
|
||||
if not issue:
|
||||
if not task:
|
||||
raise HTTPException(status_code=404, detail="Task not found")
|
||||
|
||||
if "title" in task_data:
|
||||
issue.title = task_data["title"]
|
||||
task.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"]
|
||||
task.description = task_data["description"]
|
||||
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
|
||||
new_status = task_data["status"]
|
||||
if new_status == "progressing" and not task.started_on:
|
||||
task.started_on = datetime.now()
|
||||
if new_status == "closed" and not task.finished_on:
|
||||
task.finished_on = datetime.now()
|
||||
task.status = TaskStatus[new_status.upper()] if new_status.upper() in [s.name for s in TaskStatus] else TaskStatus.OPEN
|
||||
if "priority" in task_data:
|
||||
task.priority = TaskPriority[task_data["priority"].upper()] if task_data["priority"].upper() in [s.name for s in TaskPriority] else TaskPriority.MEDIUM
|
||||
if "estimated_effort" in task_data:
|
||||
task.estimated_effort = task_data["estimated_effort"]
|
||||
if "assignee_id" in task_data:
|
||||
task.assignee_id = task_data["assignee_id"]
|
||||
|
||||
db.commit()
|
||||
db.refresh(issue)
|
||||
db.refresh(task)
|
||||
|
||||
return issue
|
||||
return task
|
||||
|
||||
|
||||
# ============ Supports ============
|
||||
|
||||
@@ -657,20 +656,20 @@ def list_supports(project_code: str, milestone_id: int, db: Session = Depends(ge
|
||||
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"
|
||||
supports = db.query(Support).filter(
|
||||
Support.project_id == project.id,
|
||||
Support.milestone_id == milestone_id
|
||||
).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]
|
||||
"id": s.id,
|
||||
"title": s.title,
|
||||
"description": s.description,
|
||||
"status": s.status.value,
|
||||
"priority": s.priority.value,
|
||||
"assignee_id": s.assignee_id,
|
||||
"created_at": s.created_at,
|
||||
} for s in supports]
|
||||
|
||||
|
||||
@router.post("/supports/{project_code}/{milestone_id}", status_code=status.HTTP_201_CREATED, tags=["Supports"])
|
||||
@@ -683,23 +682,22 @@ def create_support(project_code: str, milestone_id: int, support_data: dict, db:
|
||||
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":
|
||||
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(
|
||||
support = Support(
|
||||
title=support_data.get("title"),
|
||||
description=support_data.get("description"),
|
||||
issue_type="support",
|
||||
status=models.IssueStatus.OPEN,
|
||||
priority=models.IssuePriority.MEDIUM,
|
||||
status=SupportStatus.OPEN,
|
||||
priority=SupportPriority.MEDIUM,
|
||||
project_id=project.id,
|
||||
milestone_id=milestone_id,
|
||||
reporter_id=current_user.id,
|
||||
)
|
||||
db.add(issue)
|
||||
db.add(support)
|
||||
db.commit()
|
||||
db.refresh(issue)
|
||||
return issue
|
||||
db.refresh(support)
|
||||
return support
|
||||
|
||||
|
||||
# ============ Meetings ============
|
||||
@@ -710,24 +708,27 @@ def list_meetings(project_code: str, milestone_id: int, db: Session = Depends(ge
|
||||
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"
|
||||
meetings = db.query(Meeting).filter(
|
||||
Meeting.project_id == project.id,
|
||||
Meeting.milestone_id == milestone_id
|
||||
).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]
|
||||
"id": m.id,
|
||||
"title": m.title,
|
||||
"description": m.description,
|
||||
"status": m.status.value,
|
||||
"priority": m.priority.value,
|
||||
"scheduled_at": m.scheduled_at,
|
||||
"duration_minutes": m.duration_minutes,
|
||||
"created_at": m.created_at,
|
||||
} for m in meetings]
|
||||
|
||||
|
||||
@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)):
|
||||
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")
|
||||
@@ -736,20 +737,28 @@ def create_meeting(project_code: str, milestone_id: int, meeting_data: dict, db:
|
||||
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":
|
||||
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(
|
||||
scheduled_at = None
|
||||
if meeting_data.get("scheduled_at"):
|
||||
try:
|
||||
scheduled_at = datetime.fromisoformat(meeting_data["scheduled_at"].replace("Z", "+00:00"))
|
||||
except:
|
||||
pass
|
||||
|
||||
meeting = Meeting(
|
||||
title=meeting_data.get("title"),
|
||||
description=meeting_data.get("description"),
|
||||
issue_type="meeting",
|
||||
status=models.IssueStatus.OPEN,
|
||||
priority=models.IssuePriority.MEDIUM,
|
||||
status=MeetingStatus.SCHEDULED,
|
||||
priority=MeetingPriority.MEDIUM,
|
||||
project_id=project.id,
|
||||
milestone_id=milestone_id,
|
||||
reporter_id=current_user.id,
|
||||
scheduled_at=scheduled_at,
|
||||
duration_minutes=meeting_data.get("duration_minutes"),
|
||||
)
|
||||
db.add(issue)
|
||||
db.add(meeting)
|
||||
db.commit()
|
||||
db.refresh(issue)
|
||||
return issue
|
||||
db.refresh(meeting)
|
||||
return meeting
|
||||
|
||||
Reference in New Issue
Block a user