from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.orm import Session from dao import employment_dao from database import get_db from schema.common import ApiResponse from schema.employment_schema import ( ClassEmploymentStats, EmploymentOut, EmploymentUpdate, EmploymentUpsert, SalaryMarketComparison, ) app = APIRouter(prefix="/employment", tags=["就业管理"]) # ==================== 基础 CRUD ==================== @app.get("/list", response_model=ApiResponse[list[EmploymentOut]], summary="获取就业记录列表") def list_employment( student_id: str | None = Query(None, description="学生ID"), company_name: str | None = Query(None, description="公司名称(模糊)"), salary_min: float | None = Query(None, description="最低月薪"), salary_max: float | None = Query(None, description="最高月薪"), db: Session = Depends(get_db), ): return ApiResponse(data=employment_dao.list_employment(db, { "student_id": student_id, "company_name": company_name, "salary_min": salary_min, "salary_max": salary_max, })) @app.get("/student/{student_id}", response_model=ApiResponse[list[EmploymentOut]], summary="获取指定学生全部就业记录") def list_student_employment(student_id: str, db: Session = Depends(get_db)): data = employment_dao.list_by_student(db, student_id) if not data: raise HTTPException(status_code=404, detail="该学生暂无就业记录") return ApiResponse(data=data) @app.get("/class/{class_id}", response_model=ApiResponse[list[EmploymentOut]], summary="获取班级全部就业记录") def list_class_employment(class_id: str, db: Session = Depends(get_db)): return ApiResponse(data=employment_dao.list_by_class(db, class_id)) @app.post("/students/{student_id}", response_model=ApiResponse[EmploymentOut], summary="新增学生就业信息") def create_employment(student_id: str, payload: EmploymentUpsert, db: Session = Depends(get_db)): data_dict = payload.model_dump(exclude_unset=True, exclude_none=True) return ApiResponse(data=employment_dao.create_by_student(db, student_id, data_dict)) @app.put("/{emp_id}", response_model=ApiResponse[EmploymentOut], summary="修改就业信息") def update_employment(emp_id: str, payload: EmploymentUpdate, db: Session = Depends(get_db)): updates = payload.model_dump(exclude_unset=True, exclude_none=True) data = employment_dao.update_by_emp_id(db, emp_id, updates) if not data: raise HTTPException(status_code=404, detail="就业记录不存在") return ApiResponse(data=data) @app.delete("/{emp_id}", response_model=ApiResponse, summary="删除就业信息") def delete_employment(emp_id: str, db: Session = Depends(get_db)): if not employment_dao.delete_by_emp_id(db, emp_id): raise HTTPException(status_code=404, detail="就业记录不存在") return ApiResponse() # ==================== 新增功能点 ==================== @app.get("/stats/class/{class_id}", response_model=ApiResponse[ClassEmploymentStats], summary="班级就业统计仪表盘") def get_class_stats(class_id: str, db: Session = Depends(get_db)): return ApiResponse(data=employment_dao.get_class_employment_stats(db, class_id)) @app.get("/warnings", response_model=ApiResponse[list[dict]], summary="就业跟进预警") def get_warnings( days: int = Query(30, description="简历开放后多少天未签约算超时"), class_id: str | None = Query(None, description="按班级筛选"), db: Session = Depends(get_db), ): return ApiResponse(data=employment_dao.get_employment_warnings(db, days, class_id)) @app.get("/salary-market/{student_id}", response_model=ApiResponse[SalaryMarketComparison], summary="薪资行情对标") def salary_market_compare(student_id: str, db: Session = Depends(get_db)): data = employment_dao.compare_salary_with_market(db, student_id) if not data: raise HTTPException(status_code=404, detail="该学生无有效就业记录") return ApiResponse(data=data)