- calc_service.calc_receipt:锁回款行→settlement_status=0 校验→发货批次/ 归属前置→resolve_snapshot(回款日)→按 calc_template 分派(与 _preview_rate 同构,‰÷1000 防线)→items 行级折算(行类别阈值,混合按行汇总)→ barter/起付/R→台账 v1→CAS 置已核算,单 audit 事务 - 策略点集中:_personal_rate(#12 经理个人户单笔落 0 待答复)、_row_profit (#20 不含税原样);核算粒度 #25 一期口径=业务级一次性计提(重复回款 repeated=True 仅登记进度) - 台账仓储:生效行查询/业务级判定/版本号;schemas LedgerOut/Query - api /api/v1/calc/*:台账分页/详情/核算触发(写限 admin+marketing_ops) - 测试 8 例:金标准双类别复算到分(DB 锚定 4000.00/39.11/39.11)、 一次性计提、已核算 400、未指定批次、成本缺失行保守 -3000、负绩效照算、 准入、列表筛选;行级明细折算两位固化 - conftest 清理顺序修正:V7 台账/月结清理移到回款/人员删除之前 (RESTRICT 外键不挡序) Co-Authored-By: Claude Code <noreply@anthropic.com>
58 lines
2.1 KiB
Python
58 lines
2.1 KiB
Python
"""绩效核算接口(M3 ④):台账查询与单笔核算触发。
|
||
|
||
核算动作 = 把回款固化为台账行(每笔回款仅一次;重算走独立入口并授权)。
|
||
准入:读=登录即可;写(核算/重算/批量)=管理员与营销后勤
|
||
(权限清单待澄清 #6,答复后细化)。
|
||
"""
|
||
|
||
from typing import Annotated
|
||
|
||
from fastapi import APIRouter, Depends, Path, Query
|
||
|
||
from app.api.deps import DbSession, RequestMetaDep, require_roles
|
||
from app.core.constants import ROLE_ADMIN, ROLE_MARKETING_OPS
|
||
from app.core.response import ApiResponse, PageResult, ok
|
||
from app.models import User
|
||
from app.schemas.calc import CalcReceiptOut, LedgerOut, LedgerQuery
|
||
from app.services import calc_service
|
||
|
||
router = APIRouter(prefix="/calc", tags=["绩效工资 · 绩效核算"])
|
||
|
||
_CalcWriter = Annotated[User, Depends(require_roles(ROLE_ADMIN, ROLE_MARKETING_OPS))]
|
||
|
||
|
||
@router.get("/ledger", response_model=ApiResponse[PageResult[LedgerOut]], summary="绩效台账")
|
||
def list_ledger(
|
||
session: DbSession,
|
||
query: Annotated[LedgerQuery, Query()],
|
||
) -> ApiResponse[PageResult[LedgerOut]]:
|
||
"""分页查询绩效核算台账(默认仅生效行,可筛选历史版本)。"""
|
||
return ok(calc_service.list_ledger_page(session, query))
|
||
|
||
|
||
@router.get("/ledger/{ledger_id}", response_model=ApiResponse[LedgerOut], summary="台账详情")
|
||
def get_ledger(
|
||
session: DbSession,
|
||
ledger_id: Annotated[int, Path(ge=1)],
|
||
) -> ApiResponse[LedgerOut]:
|
||
"""台账行详情(含计算快照)。"""
|
||
return ok(calc_service.get_ledger(session, ledger_id))
|
||
|
||
|
||
@router.post(
|
||
"/receipts/{receipt_id}/calc",
|
||
response_model=ApiResponse[CalcReceiptOut],
|
||
summary="核算回款",
|
||
)
|
||
def calc_receipt(
|
||
receipt_id: Annotated[int, Path(ge=1)],
|
||
session: DbSession,
|
||
current_user: _CalcWriter,
|
||
meta: RequestMetaDep,
|
||
) -> ApiResponse[CalcReceiptOut]:
|
||
"""把回款固化为台账行(每笔回款仅一次;业务级一次性计提,重复回款仅登记进度)。"""
|
||
return ok(
|
||
calc_service.calc_receipt(session, receipt_id, operator=current_user, meta=meta),
|
||
message="核算完成",
|
||
)
|