Compare commits
1 Commits
43af5b29f6
...
96cbe109ec
| Author | SHA1 | Date | |
|---|---|---|---|
| 96cbe109ec |
@@ -13,7 +13,7 @@ from pydantic import BaseModel
|
|||||||
|
|
||||||
from app.core.config import get_db
|
from app.core.config import get_db
|
||||||
from app.api.deps import get_current_user_or_apikey
|
from app.api.deps import get_current_user_or_apikey
|
||||||
from app.api.rbac import ensure_can_edit_milestone
|
from app.api.rbac import check_project_role, ensure_can_edit_milestone
|
||||||
from app.models import models
|
from app.models import models
|
||||||
from app.models.apikey import APIKey
|
from app.models.apikey import APIKey
|
||||||
from app.models.activity import ActivityLog
|
from app.models.activity import ActivityLog
|
||||||
@@ -484,6 +484,46 @@ def create_milestone_task(project_code: str, milestone_id: int, task_data: dict,
|
|||||||
|
|
||||||
# ============ Supports ============
|
# ============ Supports ============
|
||||||
|
|
||||||
|
|
||||||
|
def _find_support_by_id_or_code(db: Session, identifier: str) -> Support | None:
|
||||||
|
try:
|
||||||
|
support_id = int(identifier)
|
||||||
|
support = db.query(Support).filter(Support.id == support_id).first()
|
||||||
|
if support:
|
||||||
|
return support
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
pass
|
||||||
|
return db.query(Support).filter(Support.support_code == str(identifier)).first()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _serialize_support(db: Session, support: Support) -> dict:
|
||||||
|
project = db.query(models.Project).filter(models.Project.id == support.project_id).first()
|
||||||
|
milestone = db.query(MilestoneModel).filter(MilestoneModel.id == support.milestone_id).first()
|
||||||
|
assignee = None
|
||||||
|
if support.assignee_id:
|
||||||
|
assignee = db.query(models.User).filter(models.User.id == support.assignee_id).first()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"id": support.id,
|
||||||
|
"code": support.support_code,
|
||||||
|
"support_code": support.support_code,
|
||||||
|
"title": support.title,
|
||||||
|
"description": support.description,
|
||||||
|
"status": support.status.value if hasattr(support.status, "value") else support.status,
|
||||||
|
"priority": support.priority.value if hasattr(support.priority, "value") else support.priority,
|
||||||
|
"project_id": support.project_id,
|
||||||
|
"project_code": project.project_code if project else None,
|
||||||
|
"milestone_id": support.milestone_id,
|
||||||
|
"milestone_code": milestone.milestone_code if milestone else None,
|
||||||
|
"reporter_id": support.reporter_id,
|
||||||
|
"assignee_id": support.assignee_id,
|
||||||
|
"taken_by": assignee.username if assignee else None,
|
||||||
|
"created_at": support.created_at,
|
||||||
|
"updated_at": support.updated_at,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/supports/{project_code}/{milestone_id}", tags=["Supports"])
|
@router.get("/supports/{project_code}/{milestone_id}", tags=["Supports"])
|
||||||
def list_supports(project_code: str, milestone_id: int, db: Session = Depends(get_db)):
|
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()
|
project = db.query(models.Project).filter(models.Project.project_code == project_code).first()
|
||||||
@@ -495,15 +535,7 @@ def list_supports(project_code: str, milestone_id: int, db: Session = Depends(ge
|
|||||||
Support.milestone_id == milestone_id
|
Support.milestone_id == milestone_id
|
||||||
).all()
|
).all()
|
||||||
|
|
||||||
return [{
|
return [_serialize_support(db, s) for s in supports]
|
||||||
"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"])
|
@router.post("/supports/{project_code}/{milestone_id}", status_code=status.HTTP_201_CREATED, tags=["Supports"])
|
||||||
@@ -537,7 +569,89 @@ def create_support(project_code: str, milestone_id: int, support_data: dict, db:
|
|||||||
db.add(support)
|
db.add(support)
|
||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(support)
|
db.refresh(support)
|
||||||
return support
|
return _serialize_support(db, support)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/supports/{support_id}", tags=["Supports"])
|
||||||
|
def get_support(support_id: str, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)):
|
||||||
|
support = _find_support_by_id_or_code(db, support_id)
|
||||||
|
if not support:
|
||||||
|
raise HTTPException(status_code=404, detail="Support not found")
|
||||||
|
check_project_role(db, current_user.id, support.project_id, min_role="viewer")
|
||||||
|
return _serialize_support(db, support)
|
||||||
|
|
||||||
|
|
||||||
|
@router.patch("/supports/{support_id}", tags=["Supports"])
|
||||||
|
def update_support(support_id: str, support_data: dict, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)):
|
||||||
|
support = _find_support_by_id_or_code(db, support_id)
|
||||||
|
if not support:
|
||||||
|
raise HTTPException(status_code=404, detail="Support not found")
|
||||||
|
check_project_role(db, current_user.id, support.project_id, min_role="dev")
|
||||||
|
|
||||||
|
allowed_fields = {"title", "description", "status", "priority"}
|
||||||
|
updated = False
|
||||||
|
for field, value in support_data.items():
|
||||||
|
if field not in allowed_fields:
|
||||||
|
continue
|
||||||
|
if field == "status" and value is not None:
|
||||||
|
value = SupportStatus(value)
|
||||||
|
if field == "priority" and value is not None:
|
||||||
|
value = SupportPriority(value)
|
||||||
|
setattr(support, field, value)
|
||||||
|
updated = True
|
||||||
|
|
||||||
|
if not updated:
|
||||||
|
raise HTTPException(status_code=400, detail="No supported fields to update")
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
db.refresh(support)
|
||||||
|
return _serialize_support(db, support)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/supports/{support_id}", status_code=status.HTTP_204_NO_CONTENT, tags=["Supports"])
|
||||||
|
def delete_support(support_id: str, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)):
|
||||||
|
support = _find_support_by_id_or_code(db, support_id)
|
||||||
|
if not support:
|
||||||
|
raise HTTPException(status_code=404, detail="Support not found")
|
||||||
|
check_project_role(db, current_user.id, support.project_id, min_role="dev")
|
||||||
|
db.delete(support)
|
||||||
|
db.commit()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/supports/{support_id}/take", tags=["Supports"])
|
||||||
|
def take_support(support_id: str, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)):
|
||||||
|
support = _find_support_by_id_or_code(db, support_id)
|
||||||
|
if not support:
|
||||||
|
raise HTTPException(status_code=404, detail="Support not found")
|
||||||
|
check_project_role(db, current_user.id, support.project_id, min_role="dev")
|
||||||
|
|
||||||
|
if support.assignee_id and support.assignee_id != current_user.id:
|
||||||
|
assignee = db.query(models.User).filter(models.User.id == support.assignee_id).first()
|
||||||
|
assignee_name = assignee.username if assignee else str(support.assignee_id)
|
||||||
|
raise HTTPException(status_code=409, detail=f"Support is already taken by {assignee_name}")
|
||||||
|
|
||||||
|
support.assignee_id = current_user.id
|
||||||
|
db.commit()
|
||||||
|
db.refresh(support)
|
||||||
|
return _serialize_support(db, support)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/supports/{support_id}/transition", tags=["Supports"])
|
||||||
|
def transition_support(support_id: str, support_data: dict, db: Session = Depends(get_db), current_user: models.User = Depends(get_current_user_or_apikey)):
|
||||||
|
support = _find_support_by_id_or_code(db, support_id)
|
||||||
|
if not support:
|
||||||
|
raise HTTPException(status_code=404, detail="Support not found")
|
||||||
|
check_project_role(db, current_user.id, support.project_id, min_role="dev")
|
||||||
|
|
||||||
|
status_value = support_data.get("status")
|
||||||
|
if not status_value:
|
||||||
|
raise HTTPException(status_code=400, detail="status is required")
|
||||||
|
|
||||||
|
support.status = SupportStatus(status_value)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(support)
|
||||||
|
return _serialize_support(db, support)
|
||||||
|
|
||||||
|
|
||||||
# ============ Meetings ============
|
# ============ Meetings ============
|
||||||
|
|||||||
Reference in New Issue
Block a user