155 lines
5.1 KiB
Python
155 lines
5.1 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
办理节点处理器
|
||
处理办理任务的创建和完成逻辑
|
||
"""
|
||
import logging
|
||
from typing import Dict, Any, Optional, TYPE_CHECKING
|
||
|
||
from sqlalchemy import select
|
||
|
||
from online_dev.workflow.engine.handlers.base_handler import BaseNodeHandler
|
||
|
||
if TYPE_CHECKING:
|
||
from online_dev.workflow.engine.base import ExecutionContext
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
class HandleHandler(BaseNodeHandler):
|
||
"""
|
||
办理节点处理器
|
||
|
||
办理节点类似审批节点,但办理完成后自动推进流程
|
||
支持:
|
||
- 任一办理(any)
|
||
- 全部办理(all)
|
||
- 依次办理(sequential)
|
||
"""
|
||
|
||
async def execute(self, context: 'ExecutionContext', node: Dict) -> None:
|
||
"""
|
||
执行办理节点:创建办理任务
|
||
"""
|
||
from online_dev.workflow.engine.assignee_resolver import assignee_resolver
|
||
|
||
node_id = self.get_node_id(node)
|
||
node_name = self.get_node_name(node)
|
||
node_config = self.get_node_config(node)
|
||
|
||
logger.info(f"创建办理任务 - 节点: {node_id}, 名称: {node_name}")
|
||
|
||
# 解析办理人
|
||
assignee_ids = await assignee_resolver.resolve(
|
||
context.db,
|
||
node_config,
|
||
context.instance,
|
||
context.form_data,
|
||
)
|
||
|
||
if not assignee_ids:
|
||
logger.warning(f"节点 {node_id} 没有办理人,自动跳过")
|
||
await self.advance_to_next(context, node)
|
||
return
|
||
|
||
# 更新实例当前节点
|
||
await self.update_instance_node(context, node)
|
||
|
||
# 创建任务
|
||
multi_handle = node_config.get('multiHandle', 'any')
|
||
|
||
if multi_handle == 'sequential':
|
||
# 依次办理:只创建第一个人的任务
|
||
await self.create_task(context, node, assignee_ids[0], 'handle')
|
||
else:
|
||
# 任一办理/全部办理:创建所有人的任务
|
||
for assignee_id in assignee_ids:
|
||
await self.create_task(context, node, assignee_id, 'handle')
|
||
|
||
async def handle_completion(self, context: 'ExecutionContext', task: Any) -> None:
|
||
"""
|
||
处理办理完成后的流程推进
|
||
|
||
Args:
|
||
context: 执行上下文
|
||
task: 已完成的任务
|
||
"""
|
||
from online_dev.workflow.model import WorkflowTask
|
||
from online_dev.workflow.engine.utils import FlowUtils
|
||
|
||
node = FlowUtils.find_node_by_id(context.flow_definition, task.node_id)
|
||
if not node:
|
||
logger.error(f"找不到节点: {task.node_id}")
|
||
return
|
||
|
||
node_config = self.get_node_config(node)
|
||
multi_handle = node_config.get('multiHandle', 'any')
|
||
|
||
# 检查多人办理逻辑
|
||
if multi_handle == 'all':
|
||
# 全部办理:检查是否所有人都已办理
|
||
stmt = select(WorkflowTask).where(
|
||
WorkflowTask.instance_id == str(context.instance.id),
|
||
WorkflowTask.node_id == task.node_id,
|
||
WorkflowTask.status == 'pending',
|
||
)
|
||
result = await context.db.execute(stmt)
|
||
pending_tasks = result.scalars().all()
|
||
|
||
if len(pending_tasks) > 0:
|
||
logger.info(f"全部办理模式,还有 {len(pending_tasks)} 人未办理")
|
||
return
|
||
|
||
elif multi_handle == 'sequential':
|
||
# 依次办理:检查是否还有下一个人
|
||
next_assignee = await self._get_next_sequential_assignee(context, task)
|
||
if next_assignee:
|
||
await self.create_task(context, node, next_assignee, 'handle')
|
||
return
|
||
|
||
# 办理完成,推进到下一节点
|
||
await self.advance_to_next(context, node)
|
||
|
||
async def _get_next_sequential_assignee(
|
||
self,
|
||
context: 'ExecutionContext',
|
||
current_task: Any,
|
||
) -> Optional[str]:
|
||
"""获取依次办理的下一个办理人"""
|
||
from online_dev.workflow.model import WorkflowTask
|
||
from online_dev.workflow.engine.assignee_resolver import assignee_resolver
|
||
from online_dev.workflow.engine.utils import FlowUtils
|
||
|
||
node = FlowUtils.find_node_by_id(context.flow_definition, current_task.node_id)
|
||
if not node:
|
||
return None
|
||
|
||
node_config = self.get_node_config(node)
|
||
|
||
all_assignees = await assignee_resolver.resolve(
|
||
context.db,
|
||
node_config,
|
||
context.instance,
|
||
context.form_data,
|
||
)
|
||
|
||
if not all_assignees:
|
||
return None
|
||
|
||
stmt = select(WorkflowTask.assignee_id).where(
|
||
WorkflowTask.instance_id == str(context.instance.id),
|
||
WorkflowTask.node_id == current_task.node_id,
|
||
WorkflowTask.status == 'handled',
|
||
).order_by(WorkflowTask.sys_create_datetime)
|
||
result = await context.db.execute(stmt)
|
||
handled_ids = [str(uid) for uid in result.scalars().all()]
|
||
|
||
handled_set = set(handled_ids)
|
||
|
||
for assignee_id in all_assignees:
|
||
if assignee_id not in handled_set:
|
||
return assignee_id
|
||
|
||
return None
|