#!/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