from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.api.deps import require_roles from app.db.session import get_db from app.models import AdminUser, ProjectCourse from app.schemas.project import ProjectCourseCreate, ProjectCourseOut, ProjectCourseUpdate from app.services.logs import diff_values, log_action router = APIRouter() @router.get("", response_model=list[ProjectCourseOut]) def list_projects( db: Session = Depends(get_db), _: AdminUser = Depends(require_roles("system_admin", "certificate_admin", "readonly")), ) -> list[ProjectCourse]: return db.query(ProjectCourse).order_by(ProjectCourse.code.asc()).all() @router.post("", response_model=ProjectCourseOut, status_code=status.HTTP_201_CREATED) def create_project( payload: ProjectCourseCreate, db: Session = Depends(get_db), admin: AdminUser = Depends(require_roles("system_admin", "certificate_admin")), ) -> ProjectCourse: if db.query(ProjectCourse).filter(ProjectCourse.code == payload.code).first(): raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="项目代码已存在") project = ProjectCourse( code=payload.code, name=payload.name, default_certificate_name=payload.name, default_course_name=payload.default_course_name, default_stage_name=payload.default_stage_name, default_issuer_name=payload.default_issuer_name, ) db.add(project) log_action(db, admin, "create_project", "project_course", detail={"code": payload.code, "name": payload.name, "status": project.status}) db.commit() db.refresh(project) return project @router.put("/{project_id}", response_model=ProjectCourseOut) def update_project( project_id: int, payload: ProjectCourseUpdate, db: Session = Depends(get_db), admin: AdminUser = Depends(require_roles("system_admin", "certificate_admin")), ) -> ProjectCourse: project = db.get(ProjectCourse, project_id) if not project: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="项目不存在") before = { "name": project.name, "default_course_name": project.default_course_name, "default_stage_name": project.default_stage_name, "default_issuer_name": project.default_issuer_name, "status": project.status, } if payload.name is not None: project.name = payload.name project.default_certificate_name = payload.name if payload.default_course_name is not None: project.default_course_name = payload.default_course_name if payload.default_stage_name is not None: project.default_stage_name = payload.default_stage_name if payload.default_issuer_name is not None: project.default_issuer_name = payload.default_issuer_name if payload.status is not None: project.status = payload.status after = { "name": project.name, "default_course_name": project.default_course_name, "default_stage_name": project.default_stage_name, "default_issuer_name": project.default_issuer_name, "status": project.status, } log_action(db, admin, "update_project", "project_course", project.id, {"code": project.code, "name": project.name, "changes": diff_values(before, after, list(after.keys()))}) db.commit() db.refresh(project) return project