- agent_dispatcher、alert_service、report_generator、 oss_storage、work_order_service 全部使用 beijing_now() - 全局无遗留 UTC 时间调用 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
145 lines
4.2 KiB
Python
145 lines
4.2 KiB
Python
"""
|
|
工单服务
|
|
|
|
提供工单的创建、查询、更新功能。
|
|
由交互Agent的工单Handler调用。
|
|
"""
|
|
|
|
import uuid
|
|
from typing import Optional, Dict, List, Tuple
|
|
|
|
from app.models import WorkOrder, WorkOrderStatus, WorkOrderPriority, get_session
|
|
from app.utils.logger import logger
|
|
from app.utils.timezone import beijing_now
|
|
|
|
|
|
def generate_order_no() -> str:
|
|
"""生成工单编号: WO + YYYYMMDDHHmmss + 6位uuid"""
|
|
ts = beijing_now().strftime("%Y%m%d%H%M%S")
|
|
return f"WO{ts}{uuid.uuid4().hex[:6].upper()}"
|
|
|
|
|
|
class WorkOrderService:
|
|
"""工单服务"""
|
|
|
|
def create_work_order(
|
|
self,
|
|
title: str,
|
|
description: str = "",
|
|
priority: str = "medium",
|
|
assignee_uid: str = "",
|
|
assignee_name: str = "",
|
|
alarm_id: str = "",
|
|
) -> Optional[WorkOrder]:
|
|
"""创建工单"""
|
|
db = get_session()
|
|
try:
|
|
valid_priorities = [e.value for e in WorkOrderPriority]
|
|
order = WorkOrder(
|
|
order_no=generate_order_no(),
|
|
title=title,
|
|
description=description,
|
|
priority=WorkOrderPriority(priority) if priority in valid_priorities else WorkOrderPriority.MEDIUM,
|
|
assignee_id=assignee_uid,
|
|
assignee_name=assignee_name,
|
|
status=WorkOrderStatus.CREATED,
|
|
)
|
|
if alarm_id:
|
|
order.alert_no = alarm_id
|
|
|
|
db.add(order)
|
|
db.commit()
|
|
db.refresh(order)
|
|
logger.info(f"工单已创建: {order.order_no}, title={title}")
|
|
return order
|
|
except Exception as e:
|
|
db.rollback()
|
|
logger.error(f"创建工单失败: {e}")
|
|
return None
|
|
finally:
|
|
db.close()
|
|
|
|
def get_work_order(self, order_no: str) -> Optional[WorkOrder]:
|
|
"""查询工单"""
|
|
db = get_session()
|
|
try:
|
|
return db.query(WorkOrder).filter(WorkOrder.order_no == order_no).first()
|
|
finally:
|
|
db.close()
|
|
|
|
def get_work_orders(
|
|
self,
|
|
status: Optional[str] = None,
|
|
assignee_id: Optional[str] = None,
|
|
page: int = 1,
|
|
page_size: int = 20,
|
|
) -> Tuple[List[WorkOrder], int]:
|
|
"""分页查询工单"""
|
|
db = get_session()
|
|
try:
|
|
query = db.query(WorkOrder)
|
|
if status:
|
|
query = query.filter(WorkOrder.status == status)
|
|
if assignee_id:
|
|
query = query.filter(WorkOrder.assignee_id == assignee_id)
|
|
|
|
total = query.count()
|
|
orders = (
|
|
query.order_by(WorkOrder.created_at.desc())
|
|
.offset((page - 1) * page_size)
|
|
.limit(page_size)
|
|
.all()
|
|
)
|
|
return orders, total
|
|
finally:
|
|
db.close()
|
|
|
|
def update_status(
|
|
self,
|
|
order_no: str,
|
|
status: str,
|
|
result: str = "",
|
|
) -> Optional[WorkOrder]:
|
|
"""更新工单状态"""
|
|
db = get_session()
|
|
try:
|
|
order = db.query(WorkOrder).filter(WorkOrder.order_no == order_no).first()
|
|
if not order:
|
|
return None
|
|
|
|
valid_statuses = [e.value for e in WorkOrderStatus]
|
|
if status in valid_statuses:
|
|
order.status = WorkOrderStatus(status)
|
|
|
|
if result:
|
|
order.result = result
|
|
|
|
now = beijing_now()
|
|
if status == "processing" and not order.started_at:
|
|
order.started_at = now
|
|
elif status == "completed":
|
|
order.completed_at = now
|
|
|
|
order.updated_at = now
|
|
db.commit()
|
|
db.refresh(order)
|
|
logger.info(f"工单状态更新: {order_no} -> {status}")
|
|
return order
|
|
except Exception as e:
|
|
db.rollback()
|
|
logger.error(f"更新工单失败: {e}")
|
|
return None
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
# 全局单例
|
|
_work_order_service: Optional[WorkOrderService] = None
|
|
|
|
|
|
def get_work_order_service() -> WorkOrderService:
|
|
global _work_order_service
|
|
if _work_order_service is None:
|
|
_work_order_service = WorkOrderService()
|
|
return _work_order_service
|