新增风险项撤回接口和审计记录
This commit is contained in:
parent
e965aad724
commit
6559386871
@ -49,6 +49,16 @@ async def update_risk_item(
|
||||
return ApiResponse(data=await RiskItemService(session).update(item_id, payload, current_user))
|
||||
|
||||
|
||||
@router.post("/{item_id}/withdraw", response_model=ApiResponse[None])
|
||||
async def withdraw_risk_item(
|
||||
item_id: int,
|
||||
session: DatabaseSession,
|
||||
current_user: Annotated[UserAccount, Depends(require_permission("risk_item.review", operate=True))],
|
||||
) -> ApiResponse[None]:
|
||||
await RiskItemService(session).withdraw(item_id, current_user)
|
||||
return ApiResponse(data=None, message="风险项已撤回")
|
||||
|
||||
|
||||
@router.post("/{item_id}/review", response_model=ApiResponse[ReviewRecordData])
|
||||
async def review_risk_item(
|
||||
item_id: int,
|
||||
|
||||
@ -68,6 +68,8 @@ class RiskItemService:
|
||||
filters = []
|
||||
if status != "all":
|
||||
filters.append(RiskItem.status == status)
|
||||
else:
|
||||
filters.append(RiskItem.status != "已撤回")
|
||||
if source_type != "all":
|
||||
filters.append(RiskItem.source_type == source_type)
|
||||
statement = select(RiskItem).where(*filters).order_by(RiskItem.created_at.desc()).limit(limit)
|
||||
@ -105,6 +107,26 @@ class RiskItemService:
|
||||
await self.session.flush()
|
||||
return self.to_data(item)
|
||||
|
||||
async def withdraw(self, item_id: int, operator: UserAccount) -> None:
|
||||
item = await self.session.get(RiskItem, item_id)
|
||||
if item is None:
|
||||
raise AppException("风险项不存在", code=404, status_code=404)
|
||||
if item.status not in {"待审核", "待预审"}:
|
||||
raise AppException("只有待处理风险项可以撤回", code=409, status_code=409)
|
||||
previous_status = item.status
|
||||
item.status = "已撤回"
|
||||
self.session.add(
|
||||
OperationAudit(
|
||||
actor_user_id=operator.id,
|
||||
actor_emp_no=operator.emp_no,
|
||||
action="risk_item.withdraw",
|
||||
resource_type="risk_item",
|
||||
resource_id=str(item.id),
|
||||
audit_metadata={"previous_status": previous_status},
|
||||
)
|
||||
)
|
||||
await self.session.flush()
|
||||
|
||||
async def review(self, item_id: int, action: str, note: str, reviewer: UserAccount) -> ReviewRecordData:
|
||||
item = await self.session.get(RiskItem, item_id)
|
||||
if item is None:
|
||||
|
||||
38
tests/test_risk_item_withdraw.py
Normal file
38
tests/test_risk_item_withdraw.py
Normal file
@ -0,0 +1,38 @@
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from app.core.exceptions import AppException
|
||||
from app.models.entities import OperationAudit, RiskItem, UserAccount
|
||||
from app.services.risk_items import RiskItemService
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pending_risk_item_can_be_withdrawn_with_audit() -> None:
|
||||
item = RiskItem(id=12, source_type="表单", status="待审核", photos=[], ocr_payload={})
|
||||
operator = UserAccount(id=3, emp_no="admin-1", name="管理员", role="admin", status="启用")
|
||||
session = MagicMock()
|
||||
session.get = AsyncMock(return_value=item)
|
||||
session.flush = AsyncMock()
|
||||
|
||||
await RiskItemService(session).withdraw(item.id, operator)
|
||||
|
||||
assert item.status == "已撤回"
|
||||
audit = next(call.args[0] for call in session.add.call_args_list if isinstance(call.args[0], OperationAudit))
|
||||
assert audit.action == "risk_item.withdraw"
|
||||
assert audit.audit_metadata == {"previous_status": "待审核"}
|
||||
session.flush.assert_awaited_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_reviewed_risk_item_cannot_be_withdrawn() -> None:
|
||||
item = RiskItem(id=13, source_type="表单", status="已通过", photos=[], ocr_payload={})
|
||||
operator = UserAccount(id=3, emp_no="admin-1", name="管理员", role="admin", status="启用")
|
||||
session = MagicMock()
|
||||
session.get = AsyncMock(return_value=item)
|
||||
|
||||
with pytest.raises(AppException, match="只有待处理风险项可以撤回"):
|
||||
await RiskItemService(session).withdraw(item.id, operator)
|
||||
|
||||
session.add.assert_not_called()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user