Files
Mutual_Fund/service/work_order.py
T

143 lines
5.1 KiB
Python
Raw Normal View History

"""业务工单链:认领 → 提交审核 → 复核(软校验职责分离,流转写审计)。
状态机:待处理 ─认领─► 处理中 ─提交审核─► 待审核 ─复核─► 已完成 / 已驳回(终态)。
流转均用条件更新防并发跳步,每次流转写 audit_log。
"""
from __future__ import annotations
from datetime import datetime
from sqlalchemy.ext.asyncio import AsyncSession
from model.audit_log import AuditLog
from model.biz_work_order import BizWorkOrder
from model.sys_user import SysUser
from repositories.biz_work_order import BizWorkOrderRepo
from schemas.work_order import WorkOrderResp
from utils.exceptions import NotFoundError, ParamError
def _audit(db: AsyncSession, user: SysUser, module: str, action: str, target, detail: str) -> None:
db.add(
AuditLog(
user_id=user.id,
username=user.real_name or user.username,
module=module,
action=action,
target=str(target),
detail=detail,
status="成功",
)
)
def _resp(wo: BizWorkOrder) -> WorkOrderResp:
return WorkOrderResp(
id=wo.id,
work_order_no=wo.work_order_no,
order_type=wo.order_type,
sub_type=wo.sub_type,
customer_id=wo.customer_id,
submitter_id=wo.submitter_id,
handler_id=wo.handler_id,
current_node=wo.current_node,
priority=wo.priority,
status=wo.status,
biz_content=wo.biz_content,
create_time=wo.create_time,
update_time=wo.update_time,
)
async def list_work_orders(db: AsyncSession, status: str | None = None) -> list[WorkOrderResp]:
orders = await BizWorkOrderRepo(db).list_with_filter(status=status)
return [_resp(o) for o in orders]
async def get_work_order(db: AsyncSession, work_order_id: int) -> WorkOrderResp:
wo = await BizWorkOrderRepo(db).get(work_order_id)
if wo is None:
raise NotFoundError("工单不存在")
return _resp(wo)
async def claim(db: AsyncSession, user: SysUser, work_order_id: int) -> dict:
"""认领:待处理 → 处理中,handler_id 记为当前专员。"""
wo_repo = BizWorkOrderRepo(db)
wo = await wo_repo.get(work_order_id)
if wo is None:
raise NotFoundError("工单不存在")
try:
if not await wo_repo.conditional_transition(
work_order_id,
from_status="待处理",
to_status="处理中",
handler_id=user.id,
update_time=datetime.now(),
):
raise ParamError("工单已被认领或状态已变更")
_audit(db, user, "work_order", "claim", work_order_id, f"认领工单 {wo.work_order_no}:待处理 → 处理中")
await db.commit()
return {"work_order_id": work_order_id, "status": "处理中", "work_order_no": wo.work_order_no}
except Exception:
await db.rollback()
raise
async def submit_review(db: AsyncSession, user: SysUser, work_order_id: int) -> dict:
"""提交审核:处理中 → 待审核。"""
wo_repo = BizWorkOrderRepo(db)
wo = await wo_repo.get(work_order_id)
if wo is None:
raise NotFoundError("工单不存在")
try:
if not await wo_repo.conditional_transition(
work_order_id,
from_status="处理中",
to_status="待审核",
current_node="复核",
update_time=datetime.now(),
):
raise ParamError("工单状态已变更,无法提交审核")
_audit(db, user, "work_order", "submit_review", work_order_id, f"提交审核工单 {wo.work_order_no}:处理中 → 待审核")
await db.commit()
return {"work_order_id": work_order_id, "status": "待审核", "work_order_no": wo.work_order_no}
except Exception:
await db.rollback()
raise
async def review(
db: AsyncSession, user: SysUser, work_order_id: int, approve: bool, comment: str | None = None
) -> dict:
"""复核:待审核 → 已完成 / 已驳回(终态)。复核人与处理人为同一人时软校验仅提示。"""
wo_repo = BizWorkOrderRepo(db)
wo = await wo_repo.get(work_order_id)
if wo is None:
raise NotFoundError("工单不存在")
to_status = "已完成" if approve else "已驳回"
warning = "复核人与处理人为同一人" if wo.handler_id == user.id else None
try:
if not await wo_repo.conditional_transition(
work_order_id,
from_status="待审核",
to_status=to_status,
current_node="完成",
update_time=datetime.now(),
):
raise ParamError("工单状态已变更,无法复核")
detail = f"复核工单 {wo.work_order_no}:待审核 → {to_status}"
if comment:
detail += f"({comment})"
_audit(db, user, "work_order", "review", work_order_id, detail)
await db.commit()
return {
"work_order_id": work_order_id,
"status": to_status,
"work_order_no": wo.work_order_no,
"warning": warning,
}
except Exception:
await db.rollback()
raise