"""Projects router.""" from typing import List from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.core.config import get_db from app.models import models from app.schemas import schemas router = APIRouter(prefix="/projects", tags=["Projects"]) @router.post("", response_model=schemas.ProjectResponse, status_code=status.HTTP_201_CREATED) def create_project(project: schemas.ProjectCreate, db: Session = Depends(get_db)): db_project = models.Project(**project.model_dump()) db.add(db_project) db.commit() db.refresh(db_project) return db_project @router.get("", response_model=List[schemas.ProjectResponse]) def list_projects(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): return db.query(models.Project).offset(skip).limit(limit).all() @router.get("/{project_id}", response_model=schemas.ProjectResponse) def get_project(project_id: int, db: Session = Depends(get_db)): project = db.query(models.Project).filter(models.Project.id == project_id).first() if not project: raise HTTPException(status_code=404, detail="Project not found") return project @router.patch("/{project_id}", response_model=schemas.ProjectResponse) def update_project(project_id: int, project_update: schemas.ProjectUpdate, db: Session = Depends(get_db)): project = db.query(models.Project).filter(models.Project.id == project_id).first() if not project: raise HTTPException(status_code=404, detail="Project not found") for field, value in project_update.model_dump(exclude_unset=True).items(): setattr(project, field, value) db.commit() db.refresh(project) return project @router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_project(project_id: int, db: Session = Depends(get_db)): project = db.query(models.Project).filter(models.Project.id == project_id).first() if not project: raise HTTPException(status_code=404, detail="Project not found") db.delete(project) db.commit() return None # ---- Members ---- @router.post("/{project_id}/members", response_model=schemas.ProjectMemberResponse, status_code=status.HTTP_201_CREATED) def add_project_member(project_id: int, member: schemas.ProjectMemberCreate, db: Session = Depends(get_db)): project = db.query(models.Project).filter(models.Project.id == project_id).first() if not project: raise HTTPException(status_code=404, detail="Project not found") user = db.query(models.User).filter(models.User.id == member.user_id).first() if not user: raise HTTPException(status_code=404, detail="User not found") existing = db.query(models.ProjectMember).filter( models.ProjectMember.project_id == project_id, models.ProjectMember.user_id == member.user_id ).first() if existing: raise HTTPException(status_code=400, detail="User already a member") db_member = models.ProjectMember(project_id=project_id, user_id=member.user_id, role=member.role) db.add(db_member) db.commit() db.refresh(db_member) return db_member @router.get("/{project_id}/members", response_model=List[schemas.ProjectMemberResponse]) def list_project_members(project_id: int, db: Session = Depends(get_db)): return db.query(models.ProjectMember).filter(models.ProjectMember.project_id == project_id).all() @router.delete("/{project_id}/members/{user_id}", status_code=status.HTTP_204_NO_CONTENT) def remove_project_member(project_id: int, user_id: int, db: Session = Depends(get_db)): member = db.query(models.ProjectMember).filter( models.ProjectMember.project_id == project_id, models.ProjectMember.user_id == user_id ).first() if not member: raise HTTPException(status_code=404, detail="Member not found") db.delete(member) db.commit() return None # ---- Worklog summary ---- from app.models.worklog import WorkLog from sqlalchemy import func as sqlfunc @router.get("/{project_id}/worklogs/summary") def project_worklog_summary(project_id: int, db: Session = Depends(get_db)): results = db.query( models.User.id, models.User.username, sqlfunc.sum(WorkLog.hours).label("total_hours"), sqlfunc.count(WorkLog.id).label("log_count") ).join(WorkLog, WorkLog.user_id == models.User.id)\ .join(models.Issue, WorkLog.issue_id == models.Issue.id)\ .filter(models.Issue.project_id == project_id)\ .group_by(models.User.id, models.User.username).all() total = sum(r.total_hours for r in results) by_user = [{"user_id": r.id, "username": r.username, "hours": round(r.total_hours, 2), "logs": r.log_count} for r in results] return {"project_id": project_id, "total_hours": round(total, 2), "by_user": by_user}