""" SCRM 系统对接 API 路由 提供给 SCRM 系统调用的数据查询接口 认证方式:Bearer Token (SCRM_API_KEY) """ import logging from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from app.core.deps import get_db, verify_scrm_api_key from app.services.scrm_service import SCRMService from app.schemas.scrm import ( EmployeePositionResponse, EmployeePositionData, PositionCoursesResponse, PositionCoursesData, KnowledgePointSearchRequest, KnowledgePointSearchResponse, KnowledgePointSearchData, KnowledgePointDetailResponse, KnowledgePointDetailData, SCRMErrorResponse, ) logger = logging.getLogger(__name__) router = APIRouter(prefix="/scrm", tags=["scrm"]) # ==================== 1. 获取员工岗位 ==================== @router.get( "/employees/{userid}/position", response_model=EmployeePositionResponse, summary="获取员工岗位(通过userid)", description="根据企微 userid 查询员工在考陪练系统中的岗位信息", responses={ 200: {"model": EmployeePositionResponse, "description": "成功"}, 401: {"model": SCRMErrorResponse, "description": "认证失败"}, 404: {"model": SCRMErrorResponse, "description": "员工不存在"}, } ) async def get_employee_position_by_userid( userid: str, _: bool = Depends(verify_scrm_api_key), db: AsyncSession = Depends(get_db) ): """ 获取员工岗位(通过企微userid) - **userid**: 企微员工 userid """ service = SCRMService(db) result = await service.get_employee_position(userid=userid) if result is None: raise HTTPException( status_code=404, detail={ "code": 404, "message": "员工不存在", "data": None } ) # 检查是否有多个匹配结果 if result.get("multiple_matches"): return { "code": 0, "message": f"找到 {result['count']} 个匹配的员工,请确认", "data": result } return EmployeePositionResponse( code=0, message="success", data=EmployeePositionData(**result) ) @router.get( "/employees/search/by-name", summary="获取员工岗位(通过姓名搜索)", description="根据员工姓名查询员工在考陪练系统中的岗位信息,支持精确匹配和模糊匹配", responses={ 200: {"description": "成功"}, 401: {"model": SCRMErrorResponse, "description": "认证失败"}, 404: {"model": SCRMErrorResponse, "description": "员工不存在"}, } ) async def get_employee_position_by_name( name: str = Query(..., description="员工姓名,支持精确匹配和模糊匹配"), _: bool = Depends(verify_scrm_api_key), db: AsyncSession = Depends(get_db) ): """ 获取员工岗位(通过姓名搜索) - **name**: 员工姓名(必填),优先精确匹配,无结果时模糊匹配 注意:如果有多个同名员工,会返回员工列表供确认 """ service = SCRMService(db) result = await service.get_employee_position(name=name) if result is None: raise HTTPException( status_code=404, detail={ "code": 404, "message": f"未找到姓名包含 '{name}' 的员工", "data": None } ) # 检查是否有多个匹配结果 if result.get("multiple_matches"): return { "code": 0, "message": f"找到 {result['count']} 个匹配的员工,请确认后使用 employee_id 精确查询", "data": result } return EmployeePositionResponse( code=0, message="success", data=EmployeePositionData(**result) ) @router.get( "/employees/by-id/{employee_id}/position", response_model=EmployeePositionResponse, summary="获取员工岗位(通过员工ID)", description="根据员工ID精确查询员工岗位信息,用于多个同名员工时的精确查询", responses={ 200: {"model": EmployeePositionResponse, "description": "成功"}, 401: {"model": SCRMErrorResponse, "description": "认证失败"}, 404: {"model": SCRMErrorResponse, "description": "员工不存在"}, } ) async def get_employee_position_by_id( employee_id: int, _: bool = Depends(verify_scrm_api_key), db: AsyncSession = Depends(get_db) ): """ 获取员工岗位(通过员工ID精确查询) - **employee_id**: 员工ID(考陪练系统用户ID) 适用场景:通过姓名搜索返回多个匹配结果后,使用此接口精确查询 """ service = SCRMService(db) result = await service.get_employee_position_by_id(employee_id) if result is None: raise HTTPException( status_code=404, detail={ "code": 404, "message": "员工不存在", "data": None } ) return EmployeePositionResponse( code=0, message="success", data=EmployeePositionData(**result) ) # ==================== 2. 获取岗位课程列表 ==================== @router.get( "/positions/{position_id}/courses", response_model=PositionCoursesResponse, summary="获取岗位课程列表", description="获取指定岗位的必修/选修课程列表", responses={ 200: {"model": PositionCoursesResponse, "description": "成功"}, 401: {"model": SCRMErrorResponse, "description": "认证失败"}, 404: {"model": SCRMErrorResponse, "description": "岗位不存在"}, } ) async def get_position_courses( position_id: int, course_type: Optional[str] = Query( default="all", description="课程类型:required/optional/all", regex="^(required|optional|all)$" ), _: bool = Depends(verify_scrm_api_key), db: AsyncSession = Depends(get_db) ): """ 获取岗位课程列表 - **position_id**: 岗位ID - **course_type**: 课程类型筛选(required/optional/all,默认 all) """ service = SCRMService(db) result = await service.get_position_courses(position_id, course_type) if result is None: raise HTTPException( status_code=404, detail={ "code": 40002, "message": "position_id 不存在", "data": None } ) return PositionCoursesResponse( code=0, message="success", data=PositionCoursesData(**result) ) # ==================== 3. 搜索知识点 ==================== @router.post( "/knowledge-points/search", response_model=KnowledgePointSearchResponse, summary="搜索知识点", description="根据关键词和岗位搜索匹配的知识点", responses={ 200: {"model": KnowledgePointSearchResponse, "description": "成功"}, 401: {"model": SCRMErrorResponse, "description": "认证失败"}, 400: {"model": SCRMErrorResponse, "description": "请求参数错误"}, } ) async def search_knowledge_points( request: KnowledgePointSearchRequest, _: bool = Depends(verify_scrm_api_key), db: AsyncSession = Depends(get_db) ): """ 搜索知识点 - **keywords**: 搜索关键词列表(必填) - **position_id**: 岗位ID(用于优先排序,可选) - **course_ids**: 限定课程范围(可选) - **knowledge_type**: 知识点类型筛选(可选) - **limit**: 返回数量,默认10,最大100 """ service = SCRMService(db) result = await service.search_knowledge_points( keywords=request.keywords, position_id=request.position_id, course_ids=request.course_ids, knowledge_type=request.knowledge_type, limit=request.limit ) return KnowledgePointSearchResponse( code=0, message="success", data=KnowledgePointSearchData(**result) ) # ==================== 4. 获取知识点详情 ==================== @router.get( "/knowledge-points/{knowledge_point_id}", response_model=KnowledgePointDetailResponse, summary="获取知识点详情", description="获取知识点的完整信息", responses={ 200: {"model": KnowledgePointDetailResponse, "description": "成功"}, 401: {"model": SCRMErrorResponse, "description": "认证失败"}, 404: {"model": SCRMErrorResponse, "description": "知识点不存在"}, } ) async def get_knowledge_point_detail( knowledge_point_id: int, _: bool = Depends(verify_scrm_api_key), db: AsyncSession = Depends(get_db) ): """ 获取知识点详情 - **knowledge_point_id**: 知识点ID """ service = SCRMService(db) result = await service.get_knowledge_point_detail(knowledge_point_id) if result is None: raise HTTPException( status_code=404, detail={ "code": 40003, "message": "knowledge_point_id 不存在", "data": None } ) return KnowledgePointDetailResponse( code=0, message="success", data=KnowledgePointDetailData(**result) )