补齐源快照、资料预演、正式导入及工资核算的依赖链路。 新增版本化输入、逐段 FIFO、生成锁和结构化当月调整, 并提供默认关闭的周期采集、有限重试及 Windows 托管。 原始客户资料、私有配置及首页改动不纳入本次提交。 BREAKING CHANGE: 升级前需应用新增迁移,并通过 PAYROLL_MAKER_USER_ID 绑定实际工资制作人,否则业务只读。 旧单批次核算默认关闭;历史兼容需显式启用 PAYROLL_ALLOW_LEGACY_CALCULATION。生产启用和真实金额待验收。
75 lines
2.9 KiB
Python
75 lines
2.9 KiB
Python
"""客户评级等级配置接口(需求 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="评级等级已删除")
|