"""客户评级等级配置接口(需求 2.2.5)。 评级计算器的等级映射判定表:判定按 sort_order 升序取首个 min_score ≤ 总分 的等级,max_score 仅展示。区间合法(0≤min≤max≤100)与互不重叠由后端校验 —— 前端表单只是展示约束,后端校验是唯一防线。 列表不分页全量返回:等级映射是判定表,数量个位数,分页无意义。 业务数据属业务操作,登录用户即可访问(区别于系统管理模块的 AdminUser); 写操作经 RequestMetaDep 带入请求元信息,由 service 层写入操作日志。 """ from typing import Annotated from fastapi import APIRouter, Depends, Path from app.api.deps import DbSession, PayrollWriter, RequestMetaDep, get_current_user from app.core.response import ApiResponse, ok from app.models import User from app.schemas.rating import RatingGradeCreateIn, RatingGradeOut, RatingGradeUpdateIn from app.services import rating_service CurrentUser = Annotated[User, Depends(get_current_user)] router = APIRouter(prefix="/rating-grades", tags=["客户评级"]) @router.get("", response_model=ApiResponse[list[RatingGradeOut]], summary="评级等级列表") def list_grades( session: DbSession, _: CurrentUser, ) -> ApiResponse[list[RatingGradeOut]]: """全量等级列表,按判定顺序(sort_order 升序)返回,不分页。""" return ok(rating_service.list_grades(session)) @router.post("", response_model=ApiResponse[RatingGradeOut], summary="新增评级等级") def create_grade( session: DbSession, current_user: PayrollWriter, payload: RatingGradeCreateIn, meta: RequestMetaDep, ) -> ApiResponse[RatingGradeOut]: """新增评级等级。区间须 0≤min≤max≤100 且与既有等级不重叠。""" return ok( rating_service.create_grade(session, payload, operator=current_user, meta=meta), message="评级等级已创建", ) @router.put("/{grade_id}", response_model=ApiResponse[RatingGradeOut], summary="编辑评级等级") def update_grade( session: DbSession, current_user: PayrollWriter, grade_id: Annotated[int, Path(ge=1)], payload: RatingGradeUpdateIn, meta: RequestMetaDep, ) -> ApiResponse[RatingGradeOut]: """编辑评级等级(全量替换)。区间须合法且与其他等级不重叠。""" return ok( rating_service.update_grade(session, grade_id, payload, operator=current_user, meta=meta), message="已保存", ) @router.delete("/{grade_id}", response_model=ApiResponse[None], summary="删除评级等级") def delete_grade( session: DbSession, current_user: PayrollWriter, grade_id: Annotated[int, Path(ge=1)], meta: RequestMetaDep, ) -> ApiResponse[None]: """物理删除评级等级(等级表无下游引用,允许清空,理由见 service 说明)。""" rating_service.delete_grade(session, grade_id, operator=current_user, meta=meta) return ok(message="评级等级已删除")