Эх сурвалжийг харах

Merge branch 'master' of http://git.12345lm.cn/Fengwo/hotline

Dun.Jason 1 жил өмнө
parent
commit
31332e329d

+ 22 - 49
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -113,8 +113,10 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         //如果发起会签需检查是否支持发起会签
         var startStepDefine = definition.FindStartStepDefine();
 
-        var firstStepDefine = startStepDefine.InstanceMode is EInstanceMode.Dynamic &&
-                              !DynamicShouldTerminal(startStepDefine, _sessionContext.OrgLevel)
+        //下一节点是否为动态节点
+        var isNextDynamic = startStepDefine.InstanceMode is EInstanceMode.Dynamic &&
+                                      !_workflowDomainService.DynamicShouldTerminal(startStepDefine, _sessionContext.OrgLevel);
+        var firstStepDefine = isNextDynamic
             ? startStepDefine
             : definition.FindStepDefine(dto.NextStepCode);
         if (firstStepDefine is null)
@@ -161,10 +163,10 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         workflow.Traces.Add(startTrace);
 
         var flowAssignInfo =
-            await GetNextStepFlowAssignInfoAsync(workflow, startStepDefine, startStep, firstStepDefine, dto, cancellationToken);
+            await GetNextStepFlowAssignInfoAsync(workflow, startStep, dto, firstStepDefine, isNextDynamic, cancellationToken);
 
-        await _workflowDomainService.StartAsync(workflow, startStep, dto, firstStepDefine, flowAssignInfo,
-            cancellationToken);
+        await _workflowDomainService.StartAsync(workflow, startStep, dto, firstStepDefine, isNextDynamic,
+            flowAssignInfo, cancellationToken);
 
         return workflow.Id;
     }
@@ -189,8 +191,12 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
         var currentStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, currentStep.Code);
 
+        //下一节点是否为动态节点
+        var isNextDynamic = currentStepDefine.InstanceMode is EInstanceMode.Dynamic &&
+                            !_workflowDomainService.DynamicShouldTerminal(currentStepDefine, _sessionContext.OrgLevel);
+
         StepDefine nextStepDefine;
-        if ((currentStep.InstanceMode is EInstanceMode.Dynamic && !DynamicShouldTerminal(currentStep))
+        if (isNextDynamic
             || (currentStep.IsInCountersign() && !currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
             || dto.IsStartCountersign)
         {
@@ -222,11 +228,10 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         }
 
         var flowAssignInfo =
-            await GetNextStepFlowAssignInfoAsync(workflow, currentStepDefine, currentStep, nextStepDefine, dto,
-                cancellationToken);
+            await GetNextStepFlowAssignInfoAsync(workflow, currentStep, dto, nextStepDefine, isNextDynamic, cancellationToken);
 
-        await _workflowDomainService.NextAsync(workflow, currentStep, dto, nextStepDefine, flowAssignInfo,
-            cancellationToken);
+        await _workflowDomainService.NextAsync(workflow, currentStep, dto, nextStepDefine, isNextDynamic,
+            flowAssignInfo, cancellationToken);
     }
 
     /// <summary>
@@ -480,7 +485,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         //};
 
         if (startStepDefine.InstanceMode is EInstanceMode.Dynamic &&
-            !DynamicShouldTerminal(startStepDefine, _sessionContext.OrgLevel))
+            !_workflowDomainService.DynamicShouldTerminal(startStepDefine, _sessionContext.OrgLevel))
         {
             //var nextStepOption = CreateDynamicStep(startStep.InstancePolicy);
             //dto.Steps = new List<NextStepOption> { nextStepOption };
@@ -531,7 +536,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             IsMainHandlerShow = workflow.WorkflowDefinition.IsMainHandlerShow,
         };
 
-        if (currentStep.InstanceMode is EInstanceMode.Dynamic && !DynamicShouldTerminal(currentStep))
+        var currentStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, currentStep.Code);
+
+        if (currentStep.InstanceMode is EInstanceMode.Dynamic && !_workflowDomainService.DynamicShouldTerminal(currentStepDefine, _sessionContext.OrgLevel))
         {
             //动态生成下一步
             var nextStepOption = await GetDynamicStepAsync(currentStep.InstancePolicy.Value, currentStep.StepType,
@@ -846,38 +853,6 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         }
     }
 
-    private bool DynamicShouldTerminal(WorkflowStep step)
-    {
-        if (step.InstanceMode is not EInstanceMode.Dynamic)
-            throw new UserFriendlyException("非动态节点");
-        switch (step.InstancePolicy)
-        {
-            case EDynamicPolicy.OrgUpCenterTop:
-            case EDynamicPolicy.OrgUp:
-            case EDynamicPolicy.OrgDownCenterTop:
-            case EDynamicPolicy.OrgDown:
-                return step.DynamicShouldTerminal();
-            default:
-                throw new ArgumentOutOfRangeException();
-        }
-    }
-
-    private bool DynamicShouldTerminal(StepDefine currentStepDefine, int currentOrgLevel)
-    {
-        if (currentStepDefine.InstanceMode is not EInstanceMode.Dynamic)
-            throw new UserFriendlyException("非动态节点");
-        switch (currentStepDefine.InstancePolicy)
-        {
-            case EDynamicPolicy.OrgUpCenterTop:
-            case EDynamicPolicy.OrgUp:
-            case EDynamicPolicy.OrgDownCenterTop:
-            case EDynamicPolicy.OrgDown:
-                return currentStepDefine.TerminalDynamicMark == currentOrgLevel.ToString();
-            default:
-                throw new ArgumentOutOfRangeException();
-        }
-    }
-
     private NextStepOption GetCsEndStepByPrev(List<WorkflowStep> steps, WorkflowStep step)
     {
         var prevStep = steps.FirstOrDefault(d => d.Id == step.PrevStepId);
@@ -1089,9 +1064,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// <summary>
     /// 查询下一节点办理对象类型(user or org)及实际办理对象
     /// </summary>
-    public async Task<FlowAssignInfo> GetNextStepFlowAssignInfoAsync(Workflow workflow, StepDefine currentStepDefine,
-        WorkflowStep currentStep,
-        StepDefine nextStepDefine, BasicWorkflowDto dto, CancellationToken cancellationToken)
+    public async Task<FlowAssignInfo> GetNextStepFlowAssignInfoAsync(Workflow workflow, WorkflowStep currentStep,
+      BasicWorkflowDto dto, StepDefine nextStepDefine, bool isNextDynamic, CancellationToken cancellationToken)
     {
         if (nextStepDefine.StepType is EStepType.End) return new();
 
@@ -1140,8 +1114,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             }
         }
 
-        if (currentStep.InstanceMode is EInstanceMode.Dynamic &&
-            !DynamicShouldTerminal(currentStepDefine, _sessionContext.OrgLevel))
+        if (isNextDynamic)
             return FlowAssignInfo.Create(EFlowAssignType.Org, handlers, isStartCountersign);
 
         return await GetNextStepFlowAssignInfoByDefineAsync(nextStepDefine, isStartCountersign, handlers,

+ 19 - 14
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -23,7 +23,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 进行流程的开始节点
         /// </summary>
         Task StartAsync(Workflow workflow, WorkflowStep startStep, BasicWorkflowDto dto, StepDefine firstStepDefine,
-            FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken);
+            bool isNextDynamic, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken);
 
         /// <summary>
         /// 查询工作流
@@ -48,12 +48,12 @@ namespace Hotline.FlowEngine.Workflows
         /// 办理(流转至下一节点)
         /// </summary>
         Task NextAsync(Workflow workflow, WorkflowStep currentStep, NextWorkflowDto dto, StepDefine nextStepDefine,
-            FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken);
+            bool isNextDynamic, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken);
 
-		/// <summary>
-		/// 退回(返回前一节点)
-		/// </summary>
-		/// <returns></returns>
+        /// <summary>
+        /// 退回(返回前一节点)
+        /// </summary>
+        /// <returns></returns>
         Task PreviousAsync(Workflow workflow, PreviousWorkflowDto dto, User operater, CancellationToken cancellationToken);
 
         /// <summary>
@@ -141,14 +141,14 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         Task EndCountersignAsync(string workflowId, CancellationToken cancellationToken);
 
-		/// <summary>
-		/// 查询未完成节点
-		/// </summary>
-		/// <param name="steps"></param>
-		/// <param name="orgCode"></param>
-		/// <param name="userId"></param>
-		/// <returns></returns>
-		WorkflowStep GetUnHandleStep(List<WorkflowStep> steps, string orgCode, string userId);
+        /// <summary>
+        /// 查询未完成节点
+        /// </summary>
+        /// <param name="steps"></param>
+        /// <param name="orgCode"></param>
+        /// <param name="userId"></param>
+        /// <returns></returns>
+        WorkflowStep GetUnHandleStep(List<WorkflowStep> steps, string orgCode, string userId);
 
         /// <summary>
         /// 检查当前办理节点是否为开始节点
@@ -159,5 +159,10 @@ namespace Hotline.FlowEngine.Workflows
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
         Task<bool> CheckCurrentIsStartStepAsync(string workflowId, string userId, string orgId, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 检查动态节点是否该终止
+        /// </summary>
+        bool DynamicShouldTerminal(StepDefine currentStepDefine, int currentOrgLevel);
     }
 }

+ 89 - 30
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -100,13 +100,12 @@ namespace Hotline.FlowEngine.Workflows
         /// 流程开始
         /// </summary>
         public async Task StartAsync(Workflow workflow, WorkflowStep startStep, BasicWorkflowDto dto,
-            StepDefine firstStepDefine, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
+            StepDefine firstStepDefine, bool isNextDynamic, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
         {
             //1. 创建first节点 (和trace)2.办理开始节点 
 
             //firststeps
-            var firstSteps = await CreateNextStepsAsync(workflow, firstStepDefine, startStep, dto, flowAssignInfo,
-                cancellationToken);
+            var firstSteps = await CreateNextStepsAsync(workflow, startStep, dto, firstStepDefine, isNextDynamic, flowAssignInfo, cancellationToken);
             if (firstSteps.Any())
                 workflow.Steps.AddRange(firstSteps);
 
@@ -273,7 +272,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 办理(流转至下一节点)
         /// </summary>
         public async Task NextAsync(Workflow workflow, WorkflowStep currentStep, NextWorkflowDto dto,
-            StepDefine nextStepDefine, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
+            StepDefine nextStepDefine, bool isNextDynamic, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
         {
             ValidatePermission(workflow, _sessionContext.RequiredOrgId, _sessionContext.RequiredUserId);
             CheckWhetherRunnable(workflow.Status);
@@ -404,8 +403,8 @@ namespace Hotline.FlowEngine.Workflows
             ////    workflow.CenterToOrg(CalculateExpiredTime(workflow.WorkflowDefinition.Code));//todo 过期时间
 
             //创建下一/N个节点(会签汇总节点:会签未全部办理时不创建,最后一个会签办理节点创建会签汇总节点)
-            var nextSteps = await CreateNextStepsAsync(workflow, nextStepDefine, currentStep, dto, flowAssignInfo,
-                cancellationToken);
+            var nextSteps = await CreateNextStepsAsync(workflow, currentStep, dto, nextStepDefine, isNextDynamic,
+                flowAssignInfo, cancellationToken);
 
             //赋值当前节点的下级办理节点
             if (dto.IsStartCountersign
@@ -900,9 +899,8 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 创建下1/N个节点
         /// </summary>
-        private async Task<List<WorkflowStep>> CreateNextStepsAsync(Workflow workflow, StepDefine nextStepDefine,
-            WorkflowStep currentStep, BasicWorkflowDto dto, FlowAssignInfo flowAssignInfo,
-            CancellationToken cancellationToken)
+        private async Task<List<WorkflowStep>> CreateNextStepsAsync(Workflow workflow, WorkflowStep currentStep, BasicWorkflowDto dto,
+            StepDefine nextStepDefine, bool isNextDynamic, FlowAssignInfo flowAssignInfo, CancellationToken cancellationToken)
         {
             List<WorkflowStep> nextSteps = new();
             if (currentStep.IsInCountersign())
@@ -915,13 +913,13 @@ namespace Hotline.FlowEngine.Workflows
                     {
                         if (dto.IsStartCountersign)
                         {
-                            //todo 依据会签策略创建会签下一级节点
+                            //依据会签策略创建会签下一级节点
                             nextSteps = await CreateCountersignStepsAsync(workflow, nextStepDefine, currentStep, dto,
                                 flowAssignInfo.FlowAssignType, cancellationToken);
                         }
                         else
                         {
-                            //todo 创建普通节点(根据配置)
+                            //创建普通节点(根据配置)
                             nextSteps = await CreateConfigStepsAsync(workflow, nextStepDefine, currentStep, dto,
                                 flowAssignInfo, EWorkflowTraceStatus.Normal, cancellationToken);
                         }
@@ -948,7 +946,7 @@ namespace Hotline.FlowEngine.Workflows
                     }
                     else
                     {
-                        //todo 依据会签策略创建会签下一级节点
+                        //依据会签策略创建会签下一级节点
                         nextSteps = await CreateCountersignStepsAsync(workflow, nextStepDefine, currentStep, dto,
                             flowAssignInfo.FlowAssignType, cancellationToken);
                     }
@@ -956,20 +954,19 @@ namespace Hotline.FlowEngine.Workflows
             }
             else if (dto.IsStartCountersign) //top
             {
-                //todo 依据会签策略创建会签下一级节点
+                //依据会签策略创建会签下一级节点
                 nextSteps = await CreateCountersignStepsAsync(workflow, nextStepDefine, currentStep, dto,
                     flowAssignInfo.FlowAssignType, cancellationToken);
             }
-            else if (currentStep.InstanceMode is EInstanceMode.Dynamic && !currentStep.DynamicShouldTerminal())
+            else if (isNextDynamic)
             {
-                //todo 创建动态下一级节点
-                nextSteps = await CreateStepsAsync(workflow, nextStepDefine, currentStep, dto,
-                    flowAssignInfo.FlowAssignType, dto.NextHandlers, null, EWorkflowStepStatus.WaitForAccept,
-                    ECountersignPosition.None, false, EWorkflowTraceStatus.Normal, cancellationToken);
+                //创建动态下一级节点
+                nextSteps = await CreateDynamicStepsAsync(workflow, nextStepDefine, currentStep, dto, flowAssignInfo,
+                    cancellationToken);
             }
             else
             {
-                //todo 创建普通节点(根据配置)
+                //创建普通节点(根据配置)
                 nextSteps = await CreateConfigStepsAsync(workflow, nextStepDefine, currentStep, dto, flowAssignInfo,
                     EWorkflowTraceStatus.Normal, cancellationToken);
             }
@@ -977,6 +974,29 @@ namespace Hotline.FlowEngine.Workflows
             return nextSteps;
         }
 
+        private async Task<List<WorkflowStep>> CreateDynamicStepsAsync(
+            Workflow workflow,
+            StepDefine nextStepDefine,
+            WorkflowStep prevStep,
+            BasicWorkflowDto dto,
+            FlowAssignInfo flowAssignInfo,
+            CancellationToken cancellationToken)
+        {
+            var handlerType = nextStepDefine.InstancePolicy switch
+            {
+                EDynamicPolicy.OrgUpCenterTop => EHandlerType.OrgLevel,
+                EDynamicPolicy.OrgUp => EHandlerType.OrgLevel,
+                EDynamicPolicy.OrgDownCenterTop => EHandlerType.OrgLevel,
+                EDynamicPolicy.OrgDown => EHandlerType.OrgLevel,
+                null => throw new ArgumentOutOfRangeException(),
+                _ => throw new ArgumentOutOfRangeException()
+            };
+
+            return await CreateStepsAsync(workflow, nextStepDefine, prevStep, dto,
+                flowAssignInfo.FlowAssignType, dto.NextHandlers, null, EWorkflowStepStatus.WaitForAccept,
+                ECountersignPosition.None, false, EWorkflowTraceStatus.Normal, handlerType, cancellationToken);
+        }
+
         private Task<List<WorkflowStep>> CreateCountersignStepsAsync(
             Workflow workflow,
             StepDefine stepDefine,
@@ -989,10 +1009,20 @@ namespace Hotline.FlowEngine.Workflows
         {
             var countersignId = prevStep.IsStartCountersign ? prevStep.StartCountersignId : prevStep.CountersignId;
 
+            var handlerType = stepDefine.CountersignPolicy switch
+            {
+                EDynamicPolicy.OrgUpCenterTop => EHandlerType.OrgLevel,
+                EDynamicPolicy.OrgUp => EHandlerType.OrgLevel,
+                EDynamicPolicy.OrgDownCenterTop => EHandlerType.OrgLevel,
+                EDynamicPolicy.OrgDown => EHandlerType.OrgLevel,
+                null => throw new ArgumentOutOfRangeException(),
+                _ => throw new ArgumentOutOfRangeException()
+            };
+
             return CreateStepsAsync(workflow, stepDefine, prevStep, dto, flowAssignType, dto.NextHandlers,
                 countersignId,
                 EWorkflowStepStatus.WaitForAccept, prevStep.GetNextStepCountersignPosition(),
-                false, EWorkflowTraceStatus.Normal, cancellationToken);
+                false, EWorkflowTraceStatus.Normal, handlerType, cancellationToken);
         }
 
         /// <summary>
@@ -1441,7 +1471,7 @@ namespace Hotline.FlowEngine.Workflows
                 : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto,
                     flowAssignInfo.FlowAssignType, dto.NextHandlers,
                     null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceStatus,
-                    cancellationToken)).First();
+                    null, cancellationToken)).First();
 
 
             //更新当前办理节点信息
@@ -1538,7 +1568,7 @@ namespace Hotline.FlowEngine.Workflows
 
             return await CreateStepsAsync(workflow, stepDefine, prevStep, dto, flowAssignInfo.FlowAssignType, handlers,
                 null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceStatus,
-                cancellationToken);
+                null, cancellationToken);
         }
 
         private async Task<List<WorkflowStep>> CreateStepsAsync(
@@ -1554,7 +1584,8 @@ namespace Hotline.FlowEngine.Workflows
             //DateTime expiredTime,
             bool isOrigin,
             EWorkflowTraceStatus traceStatus,
-            CancellationToken cancellationToken
+            EHandlerType? handlerType = null,
+            CancellationToken cancellationToken = default
         )
         {
             //var countersignId = prevStep.IsStartCountersign
@@ -1568,7 +1599,7 @@ namespace Hotline.FlowEngine.Workflows
                 {
                     var step = CreateStep(stepDefine, prevStep, workflow.Id, flowAssignType, new List<Kv> { handler },
                         dto.NextStepCode, dto.NextMainHandler, countersignId,
-                        stepStatus, csPosition, workflow.ExpiredTime, dto.NextStepName, isOrigin);
+                        stepStatus, csPosition, workflow.ExpiredTime, dto.NextStepName, isOrigin, handlerType);
 
                     steps.Add(step);
                 }
@@ -1577,7 +1608,7 @@ namespace Hotline.FlowEngine.Workflows
             {
                 var step = CreateStep(stepDefine, prevStep, workflow.Id, flowAssignType, handlers,
                     dto.NextStepCode, dto.NextMainHandler, countersignId,
-                    stepStatus, csPosition, workflow.ExpiredTime, dto.NextStepName, isOrigin);
+                    stepStatus, csPosition, workflow.ExpiredTime, dto.NextStepName, isOrigin, handlerType);
 
                 steps.Add(step);
             }
@@ -1617,10 +1648,34 @@ namespace Hotline.FlowEngine.Workflows
         public async Task<bool> CheckCurrentIsStartStepAsync(string workflowId, string userId, string orgId, CancellationToken cancellationToken)
         {
             var workflow = await GetWorkflowAsync(workflowId, withSteps: true, cancellationToken: cancellationToken);
-            //var currentStep = FindCurrentStepWaitForHandle(workflow, userId, orgId);
-            //if (currentStep.StepType is EStepType.End)
-            //    throw new UserFriendlyException("结束节点无需办理");
-            return workflow.Steps.Count == 1;
+            var currentStep = FindCurrentStepWaitForHandle(workflow, userId, orgId);
+            return workflow.Steps.Count == 1 && currentStep.StepType is EStepType.Start && currentStep.IsOrigin;
+        }
+
+        /// <summary>
+        /// 检查动态节点是否该终止
+        /// </summary>
+        public bool DynamicShouldTerminal(StepDefine currentStepDefine, int currentOrgLevel)
+        {
+            if (currentStepDefine.InstanceMode is not EInstanceMode.Dynamic)
+                throw new UserFriendlyException("非动态节点");
+            switch (currentStepDefine.InstancePolicy)
+            {
+                case EDynamicPolicy.OrgUpCenterTop:
+                case EDynamicPolicy.OrgUp:
+                    if (!int.TryParse(currentStepDefine.TerminalDynamicMark, out var tMark))
+                        throw new UserFriendlyException(
+                            $"TerminalDynamicMark parse to int failed, tMark: {currentStepDefine.TerminalDynamicMark}");
+                    return currentOrgLevel <= tMark;
+                case EDynamicPolicy.OrgDownCenterTop:
+                case EDynamicPolicy.OrgDown:
+                    if (!int.TryParse(currentStepDefine.TerminalDynamicMark, out var tMark1))
+                        throw new UserFriendlyException(
+                            $"TerminalDynamicMark parse to int failed, tMark: {currentStepDefine.TerminalDynamicMark}");
+                    return currentOrgLevel >= tMark1;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
         }
 
         private WorkflowStep? GetStep(List<WorkflowStep> steps, string orgCode, string userId,
@@ -1641,7 +1696,8 @@ namespace Hotline.FlowEngine.Workflows
             ECountersignPosition countersignPosition,
             DateTime expiredTime,
             string stepName,
-            bool isOrigin
+            bool isOrigin,
+            EHandlerType? handlerType = null//动态节点依据动态策略判断
         )
         {
             if (!handlers.Any())
@@ -1665,6 +1721,9 @@ namespace Hotline.FlowEngine.Workflows
             step.IsOrigin = isOrigin;
             step.Name = stepName;
 
+            if (handlerType.HasValue)
+                step.HandlerType = handlerType.Value;
+
             return step;
         }