feat: 新增员工行为画像算法与费用风险标签体系
后端新增员工行为画像算法模块,支持标签规则引擎和评分计算, 完善员工模型、银行信息、序列化和导入逻辑,优化报销审批流 和工作流常量,增强 Hermes 同步和知识同步能力,前端新增费 用画像详情弹窗、雷达图和风险卡片组件,完善登录页和工作台 样式,优化文档中心和归档中心交互,补充单元测试。
This commit is contained in:
39
server/src/app/api/v1/endpoints/employee_profiles.py
Normal file
39
server/src/app/api/v1/endpoints/employee_profiles.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import CurrentUserContext, get_current_user, get_db
|
||||
from app.schemas.employee_profile import EmployeeProfileLatestRead
|
||||
from app.services.employee_behavior_profile_service import EmployeeBehaviorProfileService
|
||||
|
||||
router = APIRouter(prefix="/employee-profiles")
|
||||
DbSession = Annotated[Session, Depends(get_db)]
|
||||
CurrentUser = Annotated[CurrentUserContext, Depends(get_current_user)]
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{employee_id}/latest",
|
||||
response_model=EmployeeProfileLatestRead,
|
||||
summary="读取员工最新业务行为画像",
|
||||
description="返回员工在指定场景下的最新画像快照,审批场景默认只展示费用支出和流程质量画像。",
|
||||
)
|
||||
def get_employee_latest_profile(
|
||||
employee_id: str,
|
||||
db: DbSession,
|
||||
current_user: CurrentUser,
|
||||
scene: Annotated[str, Query(max_length=50)] = "approval",
|
||||
claim_id: Annotated[str | None, Query(max_length=80)] = None,
|
||||
window_days: Annotated[int, Query(ge=1, le=365)] = 90,
|
||||
expense_type_scope: Annotated[str, Query(max_length=50)] = "overall",
|
||||
) -> EmployeeProfileLatestRead:
|
||||
del current_user
|
||||
return EmployeeBehaviorProfileService(db).get_latest_profile(
|
||||
employee_id=employee_id,
|
||||
scene=scene,
|
||||
claim_id=claim_id,
|
||||
window_days=window_days,
|
||||
expense_type_scope=expense_type_scope,
|
||||
)
|
||||
@@ -601,6 +601,38 @@ def approve_expense_claim(
|
||||
return claim
|
||||
|
||||
|
||||
@router.post(
|
||||
"/claims/{claim_id}/pay",
|
||||
response_model=ExpenseClaimRead,
|
||||
summary="确认报销单已付款",
|
||||
description="财务人员或高级财务人员确认待付款报销单已完成付款。",
|
||||
responses={
|
||||
status.HTTP_404_NOT_FOUND: {
|
||||
"model": ErrorResponse,
|
||||
"description": "单据不存在。",
|
||||
},
|
||||
status.HTTP_400_BAD_REQUEST: {
|
||||
"model": ErrorResponse,
|
||||
"description": "当前用户或单据状态不允许确认付款。",
|
||||
},
|
||||
},
|
||||
)
|
||||
def pay_expense_claim(
|
||||
claim_id: str,
|
||||
db: DbSession,
|
||||
current_user: CurrentUser,
|
||||
) -> ExpenseClaimRead:
|
||||
service = ExpenseClaimService(db)
|
||||
try:
|
||||
claim = service.mark_claim_paid(claim_id, current_user)
|
||||
except ValueError as error:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(error)) from error
|
||||
|
||||
if claim is None:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Claim not found")
|
||||
return claim
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/claims/{claim_id}",
|
||||
response_model=ExpenseClaimActionResponse,
|
||||
|
||||
Reference in New Issue
Block a user