Files

155 lines
5.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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