xf 1 year ago
parent
commit
585d3fdfcc

+ 2 - 2
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -439,8 +439,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         {
             if (currentStep.IsCountersignEndStep)
             {
-                //当前待办节点为会签汇总节点时:检查是否为顶级会签发起节点(csstate==none),t:按配置往下走,f:继续往上汇总,不需要重复往下指派
-                if (currentStep.CountersignStartStepId != workflow.TopCountersignStepId)
+                //当前待办节点为会签汇总节点时:检查是否为顶级会签汇总节点,t:按配置往下走,f:继续往上汇总,不需要重复往下指派
+                if (!currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
                 {
                     //查找当前节点对应会签开始节点的上级作为下一个cs汇总节点的汇总对象
                     var startCountersignStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);

+ 54 - 409
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -238,8 +238,6 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 受理(接办)
         /// </summary>
-
-        //new
         public async Task AcceptAsync(Workflow workflow,
             string userId, string? userName,
             string orgId, string? orgName,
@@ -255,33 +253,6 @@ namespace Hotline.FlowEngine.Workflows
 
             if (currentStep.Handlers.All(d => d.Key != orgId && d.Key != userId)) return;
 
-            //if (currentStep.HandlerType is EHandlerType.AssignedOrg or EHandlerType.OrgLevel or EHandlerType.OrgType
-            //   || (currentStep.InstanceMode is EInstanceMode.Dynamic && !currentStep.DynamicShouldTerminal())//动态并且非结束节点
-            //       || (currentStep.IsInCountersign() && !currentStep.IsCountersignEndStep)//会签并且非会签节点
-            //       )
-            //{
-            //    //orgId
-            //    if (currentStep.Handlers.All(d => d.Key != orgId)) return;
-            //}
-            //else
-            //{
-            //    //userId
-            //    if (currentStep.Handlers.All(d => d.Key != userId)) return;
-            //}
-
-            //if (currentStep.HandlerType is EHandlerType.AssignedUser or EHandlerType.Role
-            //&& !currentStep.IsInCountersign()
-            //&& currentStep.InstanceMode is EInstanceMode.Config
-            //)
-            //{
-            //    //userId
-            //    if (currentStep.Handlers.All(d => d.Key != userId)) return;
-            //}
-            //else
-            //{
-            //    //orgId
-            //    if (currentStep.Handlers.All(d => d.Key != orgId)) return;
-            //}
             if (currentStep.StepType is EStepType.End)
                 throw new UserFriendlyException("当前流程已流转到最终步骤");
 
@@ -318,6 +289,7 @@ namespace Hotline.FlowEngine.Workflows
         public async Task NextAsync(Workflow workflow, WorkflowStep currentStep, NextWorkflowDto dto, StepDefine nextStepDefine,
             FlowAssignInfo flowAssignInfo, DateTime expiredTime, CancellationToken cancellationToken)
         {
+            //todo 1.汇总节点的创建不能简单看上级节点发起的是否全办完
             ValidatePermission(workflow);
             CheckWhetherRunnable(workflow.Status);
 
@@ -367,13 +339,23 @@ namespace Hotline.FlowEngine.Workflows
             //操作为回到会签汇总时,更新开始会签节点的会签办理状态
             if (currentStep.IsInCountersign() && dto.BackToCountersignEnd)
             {
-                var countersignStartStep = workflow.Steps.FirstOrDefault(d => d.StartCountersignId == currentStep.CountersignId);
+                var targetStep = currentStep;
+                if (currentStep.IsCountersignEndStep)
+                {
+                    var csStartStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);
+                    if (csStartStep is null)
+                        throw new UserFriendlyException("未查询到会签开始节点");
+                    targetStep = csStartStep;
+                }
+
+                var countersignStartStep = workflow.Steps.FirstOrDefault(d => d.Id == targetStep.PrevStepId);
                 if (countersignStartStep is null)
-                    throw new UserFriendlyException("未查询到会签开始节点");
-                if (!countersignStartStep.IsStartCountersign)
-                    throw new UserFriendlyException("查询到会签开始节点状态异常");
+                    throw new UserFriendlyException("未查询到目标节点的前一节点");
 
-                countersignStartStep.CountersignSteps.First(d => d.StepId == currentStep.Id).Completed = true;
+                var csStep = countersignStartStep.CountersignSteps.FirstOrDefault(d => d.StepId == targetStep.Id);
+                if (csStep is null)
+                    throw new UserFriendlyException("未查询到当前待办节点");
+                csStep.Completed = true;
                 updateSteps.Add(countersignStartStep);
             }
 
@@ -468,19 +450,18 @@ namespace Hotline.FlowEngine.Workflows
                 {
                     //todo check if current is topend f: csStartStep.prev
                     //todo t: check if dto.StartCs t: csconfig f: config
-                    if (currentStep.CountersignStartStepId == workflow.TopCountersignStepId)
+                    if (currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
                     {
                         if (dto.IsStartCountersign)
                         {
                             //todo 依据会签策略创建会签下一级节点
-                            nextSteps = await CreateStepsAsync(workflow, nextStepDefine, currentStep, dto, dto.NextHandlers,
-                                EWorkflowStepStatus.WaitForAccept, currentStep.GetNextStepCountersignPosition(),
-                                expiredTime, false, cancellationToken);
+                            nextSteps = await CreateCountersignStepsAsync(workflow, nextStepDefine, currentStep, dto,
+                                expiredTime, cancellationToken);
                         }
                         else
                         {
                             //todo 创建普通节点(根据配置)
-                            nextSteps = await CreateStepsByDefineAsync(workflow, nextStepDefine, currentStep, dto, expiredTime, cancellationToken);
+                            nextSteps = await CreateConfigStepsAsync(workflow, nextStepDefine, currentStep, dto, expiredTime, cancellationToken);
                         }
                     }
                     else
@@ -504,48 +485,56 @@ namespace Hotline.FlowEngine.Workflows
                     else
                     {
                         //todo 依据会签策略创建会签下一级节点
-                        nextSteps = await CreateStepsAsync(workflow, nextStepDefine, currentStep, dto, dto.NextHandlers,
-                            EWorkflowStepStatus.WaitForAccept, currentStep.GetNextStepCountersignPosition(),
-                            expiredTime, false, cancellationToken);
+                        nextSteps = await CreateCountersignStepsAsync(workflow, nextStepDefine, currentStep, dto,
+                            expiredTime, cancellationToken);
                     }
                 }
             }
-            else if (dto.IsStartCountersign)
+            else if (dto.IsStartCountersign)//top
             {
                 //todo 依据会签策略创建会签下一级节点
-                nextSteps = await CreateStepsAsync(workflow, nextStepDefine, currentStep, dto, dto.NextHandlers,
-                    EWorkflowStepStatus.WaitForAccept, currentStep.GetNextStepCountersignPosition(),
-                        expiredTime, false, cancellationToken);
+                nextSteps = await CreateCountersignStepsAsync(workflow, nextStepDefine, currentStep, dto,
+                    expiredTime, cancellationToken);
             }
             else if (currentStep.InstanceMode is EInstanceMode.Dynamic && !currentStep.DynamicShouldTerminal())
             {
                 //todo 创建动态下一级节点
                 nextSteps = await CreateStepsAsync(workflow, nextStepDefine, currentStep, dto, dto.NextHandlers,
-                    EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None,
+                    null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None,
                     expiredTime, false, cancellationToken);
             }
             else
             {
                 //todo 创建普通节点(根据配置)
-                nextSteps = await CreateStepsByDefineAsync(workflow, nextStepDefine, currentStep, dto, expiredTime, cancellationToken);
+                nextSteps = await CreateConfigStepsAsync(workflow, nextStepDefine, currentStep, dto, expiredTime, cancellationToken);
             }
 
             return nextSteps;
         }
 
+        private Task<List<WorkflowStep>> CreateCountersignStepsAsync(
+            Workflow workflow,
+            StepDefine stepDefine,
+            WorkflowStep prevStep,
+            BasicWorkflowDto dto,
+            DateTime expiredTime,
+            CancellationToken cancellationToken
+        )
+        {
+            var countersignId = prevStep.IsStartCountersign ? prevStep.StartCountersignId : prevStep.CountersignId;
+
+            return CreateStepsAsync(workflow, stepDefine, prevStep, dto, dto.NextHandlers, countersignId,
+                  EWorkflowStepStatus.WaitForAccept, prevStep.GetNextStepCountersignPosition(),
+                  expiredTime, false, cancellationToken);
+        }
+
         /// <summary>
         /// 根据传入节点的上一节点创建会签汇总节点(汇总传入节点的前一节点)
         /// </summary>
-        /// <param name="workflow"></param>
-        /// <param name="currentStep"></param>
-        /// <param name="dto"></param>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
-        /// <exception cref="UserFriendlyException"></exception>
-        private async Task<List<WorkflowStep>> CreateCsEndStepsByPrevStepAsync(Workflow workflow, WorkflowStep currentStep, BasicWorkflowDto dto,
-            CancellationToken cancellationToken)
+        private async Task<List<WorkflowStep>> CreateCsEndStepsByPrevStepAsync(Workflow workflow, WorkflowStep step,
+            BasicWorkflowDto dto, CancellationToken cancellationToken)
         {
-            var prevStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.PrevStepId);
+            var prevStep = workflow.Steps.FirstOrDefault(d => d.Id == step.PrevStepId);
             if (prevStep is null)
                 throw new UserFriendlyException("未查询到当前节点上级节点");
             var nextSteps = new List<WorkflowStep>();
@@ -683,7 +672,7 @@ namespace Hotline.FlowEngine.Workflows
                 if (lastStep is null || lastStep.StepType is EStepType.End)
                     throw new UserFriendlyException($"流程流转数据异常,未结束流程出现endStep, flowId: {workflow.Id}", "流程流转数据异常");
 
-                var targetSteps = await CreateStepsByDefineAsync(workflow, targetStepDefine, lastStep, dto, workflow.ExpiredTime, cancellationToken);
+                var targetSteps = await CreateConfigStepsAsync(workflow, targetStepDefine, lastStep, dto, workflow.ExpiredTime, cancellationToken);
                 targetStep = targetSteps.First();
 
                 workflow.EndCountersign();
@@ -931,39 +920,6 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 办理节点
         /// </summary>
-        //private async Task HandleStepAsync(Workflow workflow, BasicWorkflowDto dto, WorkflowStep currentStepBox, WorkflowStep currentStep,
-        //    ECounterSignType counterSignType, CancellationToken cancellationToken)
-        //{
-        //    if (currentStep.Status is EWorkflowStepStatus.Handled or EWorkflowStepStatus.Created)
-        //        throw UserFriendlyException.SameMessage("当前节点状态无法办理");
-
-        //    if (currentStep.Status is EWorkflowStepStatus.WaitForAccept)
-        //        await AcceptAsync(workflow,
-        //            _sessionContext.RequiredUserId,
-        //            _sessionContext.UserName,
-        //            _sessionContext.RequiredOrgId,
-        //            _sessionContext.OrgName,
-        //            cancellationToken);
-        //    if (currentStep.StepType is EStepType.End)
-        //        throw new UserFriendlyException("当前流程已流转到最终步骤");
-
-        //    //创建会签数据
-        //    if (dto.IsStartCountersign)
-        //        await StartCountersignAsync(workflow, dto, currentStepBox, currentStep, counterSignType, cancellationToken);
-
-        //    _mapper.Map(dto, currentStep);
-
-        //    //step办理状态
-        //    currentStep.Handled(
-        //        _sessionContext.RequiredUserId, _sessionContext.UserName,
-        //        _sessionContext.RequiredOrgId, _sessionContext.OrgName,
-        //        _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
-        //        dto.NextStepCode);
-
-        //    //stepBox办理状态
-        //    currentStepBox.CheckStepBoxStatusAndUpdate();
-        //}
-        //new
         private async Task HandleStepAsync(WorkflowStep step, Workflow workflow, BasicWorkflowDto dto,
              ECounterSignType? counterSignType, CancellationToken cancellationToken)
         {
@@ -1273,7 +1229,7 @@ namespace Hotline.FlowEngine.Workflows
             //var targetStepBoxNew = await CreateStepAsync(workflow, targetStepDefine, dto, EWorkflowStepStatus.WaitForAccept,
             //     targetPrevStepBox, targetPrevStep, traceStatus, workflow.ExpiredTime, cancellationToken);
 
-            var targetStepsNew = await CreateStepsByDefineAsync(workflow, targetStepDefine, targetPrevStep, dto, workflow.ExpiredTime, cancellationToken);
+            var targetStepsNew = await CreateConfigStepsAsync(workflow, targetStepDefine, targetPrevStep, dto, workflow.ExpiredTime, cancellationToken);
 
             //更新当前办理节点信息
             workflow.UpdateWorkflowCurrentStepInfo(dto.IsStartCountersign, nextStep: targetStepsNew.First());
@@ -1311,60 +1267,6 @@ namespace Hotline.FlowEngine.Workflows
                 throw UserFriendlyException.SameMessage("无办理权限");
         }
 
-        //private async Task<(WorkflowStep startStepBox, WorkflowStep startStep, WorkflowStep firstStepBox)> CreateStartAndFirstStepAsync(
-        //    Workflow workflow, BasicWorkflowDto dto, CancellationToken cancellationToken)
-        //{
-        //    if (workflow.Steps.Any())
-        //        throw UserFriendlyException.SameMessage("无法重复创建开始节点");
-
-        //    var startStepDefinition = workflow.WorkflowDefinition.Steps.FirstOrDefault(d => d.StepType == EStepType.Start);
-        //    if (startStepDefinition == null)
-        //        throw new UserFriendlyException($"模板未配置开始节点, defineCode: {workflow.WorkflowDefinition.Code}", "模板未配置开始节点");
-
-        //    var startStepBox = CreateStepBox(workflow.Id, startStepDefinition, string.Empty);
-        //    await _workflowStepRepository.AddAsync(startStepBox, cancellationToken);
-
-
-        //    //start节点的办理人分类默认为用户,即为当前发起流程的操作员
-        //    var handler = new Kv { Key = _sessionContext.RequiredUserId, Value = _sessionContext.UserName };
-
-        //    //开始节点的下一个节点(工单业务:话务员节点)
-        //    var firstStepCode = workflow.WorkflowDefinition.FindStartStepDefine().NextSteps.First().Code;
-        //    var startStep = await CreateStartSubStepAsync(handler, firstStepCode, startStepBox, dto, cancellationToken);
-
-        //    //开始节点trace
-        //    await CreateTraceAsync(workflow, startStep, cancellationToken: cancellationToken);
-
-        //    //创建firstStep
-        //    var firsStepDefine = workflow.WorkflowDefinition.FindStepDefine(firstStepCode);
-        //    var firstStepBox = await CreateStepAsync(workflow, firsStepDefine, dto, EWorkflowStepStatus.WaitForHandle,
-        //        startStepBox, startStep, EWorkflowTraceStatus.Normal, workflow.ExpiredTime, cancellationToken);
-
-        //    return (startStepBox, startStep, firstStepBox);
-        //}
-
-        //private async Task<(WorkflowStep stepBox, WorkflowStep step)> CreateEndStepAsync(
-        //    Workflow workflow,
-        //    StepDefine endStepDefine,
-        //    WorkflowStep prevStepBox,
-        //    WorkflowStep prevStep,
-        //    CancellationToken cancellationToken)
-        //{
-        //    if (workflow.Steps.Any(d => d.StepType == EStepType.End))
-        //        throw UserFriendlyException.SameMessage("无法重复创建结束节点");
-
-        //    var stepBox = CreateStepBox(workflow.Id, endStepDefine, prevStepBox.Id);
-        //    await _workflowStepRepository.AddAsync(stepBox, cancellationToken);
-
-        //    var handler = new Kv { Key = _sessionContext.RequiredUserId, Value = _sessionContext.UserName };
-        //    var step = await CreateEndSubStepAsync(handler, stepBox, prevStep, cancellationToken);
-
-        //    //end trace
-        //    await CreateTraceAsync(workflow, step, cancellationToken: cancellationToken);
-
-        //    return (stepBox, step);
-        //}
-
         private async Task<WorkflowStep> CreateEndStepAsync(
             Workflow workflow,
             StepDefine endStepDefine,
@@ -1394,52 +1296,7 @@ namespace Hotline.FlowEngine.Workflows
             return step;
         }
 
-        /// <summary>
-        /// 创建节点(不含开始、结束节点)
-        /// </summary>
-        //private async Task<WorkflowStep> CreateStepAsync(
-        //Workflow workflow,
-        //StepDefine stepBoxDefine,
-        //BasicWorkflowDto dto,
-        //EWorkflowStepStatus status,
-        //WorkflowStep prevStepBox,
-        //WorkflowStep prevStep,
-        //EWorkflowTraceStatus traceStatus,
-        //DateTime expiredTime,
-        //CancellationToken cancellationToken)
-        //{
-        //    if (stepBoxDefine.StepType is EStepType.Start or EStepType.End)
-        //        throw new UserFriendlyException("该方法不支持创建开始或结束节点");
-        //    var stepBox = workflow.Steps.FirstOrDefault(d => d.Code == stepBoxDefine.Code);
-        //    if (stepBox == null)
-        //    {
-        //        stepBox = CreateStepBox(workflow.Id, stepBoxDefine, prevStepBox.Id);
-        //        await _workflowStepRepository.AddAsync(stepBox, cancellationToken);
-        //        workflow.Steps.Add(stepBox);
-        //    }
-        //    else if (stepBox.Status != EWorkflowStepStatus.Created)
-        //    {
-        //        stepBox.Status = EWorkflowStepStatus.Created;
-        //        await _workflowStepRepository.UpdateAsync(stepBox, cancellationToken);
-        //    }
-
-        //    //下一节点为汇总节点时,同一会签只需要创建一次汇总节点
-        //    if (stepBoxDefine.StepType is EStepType.Summary && prevStep.CountersignPosition == ECountersignPosition.Inner)
-        //    {
-        //        var step = stepBox.Steps.FirstOrDefault(d =>
-        //            d.IsInCountersign && d.CountersignId == prevStep.CountersignId);
-        //        if (step != null)
-        //            return stepBox;
-        //    }
-
-        //    await CreateSubStepsAsync(workflow, stepBoxDefine, dto, stepBox, status, prevStep, traceStatus, expiredTime, cancellationToken);
-
-
-        //    return stepBox;
-        //}
-
-        //new
-        public async Task<List<WorkflowStep>> CreateStepsByDefineAsync(
+        public async Task<List<WorkflowStep>> CreateConfigStepsAsync(
             Workflow workflow,
             StepDefine stepDefine,
             WorkflowStep prevStep,
@@ -1459,21 +1316,18 @@ namespace Hotline.FlowEngine.Workflows
                 handlers = dto.NextHandlers;
             }
 
-            //var countersignId = prevStep.HasStartedCountersign() ? prevStep.StartCountersignId : prevStep.CountersignId;
-
-            return await CreateStepsAsync(workflow, stepDefine, prevStep, dto, handlers,
+            return await CreateStepsAsync(workflow, stepDefine, prevStep, dto, handlers, null,
                 EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None,
                 expiredTime, true, cancellationToken);
         }
 
-        //new
         private async Task<List<WorkflowStep>> CreateStepsAsync(
             Workflow workflow,
             StepDefine stepDefine,
             WorkflowStep prevStep,
             BasicWorkflowDto dto,
             List<Kv> handlers,
-            //string? countersignId,
+            string? countersignId,
             EWorkflowStepStatus stepStatus,
             ECountersignPosition csPosition,
             DateTime expiredTime,
@@ -1481,7 +1335,9 @@ namespace Hotline.FlowEngine.Workflows
             CancellationToken cancellationToken
             )
         {
-            var countersignId = prevStep.IsStartCountersign ? prevStep.StartCountersignId : prevStep.CountersignId;
+            //var countersignId = prevStep.IsStartCountersign
+            //    ? prevStep.StartCountersignId
+            //    : prevStep.IsInCountersign() ? prevStep.Id : null;
 
             List<WorkflowStep> steps = new();
             if (dto.IsStartCountersign)
@@ -1515,114 +1371,9 @@ namespace Hotline.FlowEngine.Workflows
             return steps;
         }
 
-        //private async Task<WorkflowStep> CreateStartSubStepAsync(
-        //    Kv handler,
-        //    string nextStepCode,
-        //    WorkflowStep stepBox,
-        //    BasicWorkflowDto dto,
-        //    CancellationToken cancellationToken)
-        //{
-        //    //开始节点既不发起会签,也不处于会签中
-        //    var subStep = CreateSubStep(stepBox, new List<Kv> { handler }, nextStepCode, null,
-        //        null, null, EWorkflowStepStatus.Handled, ECountersignPosition.None, DateTime.Today,
-        //        _mapper.Map<StepExtension>(dto.Extension));
-        //    subStep.Accept(_sessionContext.RequiredUserId, _sessionContext.UserName,
-        //        _sessionContext.RequiredOrgId, _sessionContext.OrgName);
-
-        //    //step办理状态
-        //    subStep.Handle(_sessionContext.RequiredUserId, _sessionContext.UserName,
-        //        _sessionContext.RequiredOrgId, _sessionContext.OrgName,
-        //        _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
-        //        nextStepCode);
-
-        //    subStep.Opinion = "流程开启";
-        //    stepBox.Steps.Add(subStep);
-        //    await _workflowStepRepository.AddAsync(subStep, cancellationToken);
-        //    return subStep;
-        //}
-
-        //private async Task<WorkflowStep> CreateEndSubStepAsync(
-        //    Kv handler,
-        //    WorkflowStep currentStepBox,
-        //    WorkflowStep prevStep,
-        //    CancellationToken cancellationToken)
-        //{
-        //    var subStep = CreateSubStep(currentStepBox, new List<Kv> { handler }, null, null, prevStep.Id,
-        //        null, EWorkflowStepStatus.Handled, ECountersignPosition.None, DateTime.Today, new());
-        //    subStep.Accept(_sessionContext.RequiredUserId, _sessionContext.UserName, _sessionContext.RequiredOrgId,
-        //        _sessionContext.OrgName);
-        //    subStep.Handle(_sessionContext.RequiredUserId, _sessionContext.UserName,
-        //        _sessionContext.RequiredOrgId, _sessionContext.OrgName,
-        //        _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
-        //        string.Empty);
-
-        //    currentStepBox.Steps.Add(subStep);
-        //    await _workflowStepRepository.AddAsync(subStep, cancellationToken);
-        //    return subStep;
-        //}
-
-        //private async Task CreateSubStepsAsync(
-        //    Workflow workflow,
-        //    StepDefine stepBoxDefine,
-        //    BasicWorkflowDto dto,
-        //    WorkflowStep stepBox,
-        //    EWorkflowStepStatus stepStatus,
-        //    WorkflowStep prevStep,
-        //    EWorkflowTraceStatus traceStatus,
-        //    DateTime expiredTime,
-        //    CancellationToken cancellationToken = default)
-        //{
-        //    var countersignStatus = stepBoxDefine.StepType is EStepType.Summary
-        //        ? prevStep.IsInCountersign()
-        //            ? ECountersignPosition.Inner
-        //            : ECountersignPosition.None
-        //        : prevStep.GetNextStepCountersignPosition();
-
-        //    var countersignId = dto.IsStartCountersign ? prevStep.StartCountersignId : prevStep.CountersignId;
-
-        //    List<WorkflowStep> subSteps;
-        //    var stepExtension = _mapper.Map<StepExtension>(dto.Extension);
-        //    if (stepBoxDefine.HandlerType is EHandlerType.AssignedUser or EHandlerType.AssignedOrg)
-        //    {
-        //        subSteps = CreateSubSteps(dto.IsStartCountersign, stepBox, stepBox.HandlerClassifies, dto.NextStepCode, dto.NextMainHandler,
-        //            prevStep?.Id, countersignId, stepStatus, countersignStatus, expiredTime, stepExtension);
-        //    }
-        //    else
-        //    {
-        //        if (stepBoxDefine.HandlerType != EHandlerType.Role && !dto.NextHandlers.Any())
-        //            throw new UserFriendlyException("未指定节点处理者");
-        //        subSteps = CreateSubSteps(dto.IsStartCountersign, stepBox, dto.NextHandlers, dto.NextStepCode, dto.NextMainHandler,
-        //            prevStep?.Id, countersignId, stepStatus, countersignStatus, expiredTime, stepExtension);
-        //    }
-        //    stepBox.Steps.AddRange(subSteps);
-        //    await _workflowStepRepository.AddRangeAsync(subSteps, cancellationToken);
-
-        //    //create traces
-        //    foreach (var step in subSteps)
-        //    {
-        //        await CreateTraceAsync(workflow, step, traceStatus, cancellationToken);
-        //    }
-        //}
-
-
         /// <summary>
         /// 查询未完成节点
         /// </summary>
-        /// <param name="stepBoxes"></param>
-        /// <param name="orgCode"></param>
-        /// <param name="userId"></param>
-        /// <returns></returns>
-        //private (WorkflowStep, WorkflowStep) GetUnCompleteStep(List<WorkflowStep> stepBoxes, string orgCode, string userId)
-        //{
-        //    var (stepBox, step) = GetStep(stepBoxes, orgCode, userId, d => d != EWorkflowStepStatus.Handled);
-        //    if (step == null)
-        //        throw new UserFriendlyException(
-        //            $"未找到对应节点, workflowId: {stepBoxes.FirstOrDefault()?.WorkflowId} orgCode:{orgCode}, userId: {userId}",
-        //            "未找到对应节点");
-        //    return (stepBox, step);
-        //}
-
-        //new
         private WorkflowStep GetUnHandleStep(List<WorkflowStep> steps, string orgCode, string userId)
         {
             var step = GetStep(steps, orgCode, userId, d => d != EWorkflowStepStatus.Handled);
@@ -1633,116 +1384,10 @@ namespace Hotline.FlowEngine.Workflows
             return step;
         }
 
-        //private (WorkflowStep, WorkflowStep) GetUnCompleteStepOrDefault(List<WorkflowStep> stepBoxes, string orgCode, string userId) =>
-        //    GetStep(stepBoxes, orgCode, userId, d => d != EWorkflowStepStatus.Handled);
-
-        //private (WorkflowStep, WorkflowStep) GetStep(List<WorkflowStep> stepBoxes, string orgCode, string userId, Func<EWorkflowStepStatus, bool> predicate)
-        //{
-        //    if (!stepBoxes.Any()) throw new UserFriendlyException("该流程中暂无节点");
-        //    foreach (var stepBox in stepBoxes)
-        //    {
-        //        foreach (var step in stepBox.Steps)
-        //        {
-        //            if (predicate(step.Status) && (step.Handlers.Any(d => d.Id == orgCode) || step.Handlers.Any(d => d.Id == userId)))
-        //                return (stepBox, step);
-        //        }
-        //    }
-
-        //    return new();
-        //}
-
-        //new
         private WorkflowStep? GetStep(List<WorkflowStep> steps, string orgCode, string userId, Func<EWorkflowStepStatus, bool> predicate) =>
             steps.FirstOrDefault(d =>
                 predicate(d.Status) && d.Handlers.Any(x => x.Key == orgCode || x.Key == userId));
 
-        //private WorkflowStep CreateStepBox(string workflowId, StepDefine stepDefine, string prevStepBoxId)
-        //{
-        //    var stepBox = _mapper.Map<WorkflowStep>(stepDefine);
-        //    stepBox.WorkflowId = workflowId;
-        //    stepBox.PrevStepId = prevStepBoxId;
-        //    stepBox.NextStepCode = string.Empty;
-        //    stepBox.Opinion = string.Empty;
-        //    stepBox.CountersignStartStepCode = stepDefine.CountersignStartStepCode;
-        //    stepBox.CountersignEndStepCode = stepDefine.CountersignEndStepCode;
-        //    return stepBox;
-        //}
-
-        //private List<WorkflowStep> CreateSubSteps(
-        //    bool isPrevStartCountersign,
-        //    WorkflowStep stepBox,
-        //    List<Kv> handlers,
-        //    string nextStepCode,
-        //    string? nextMainHandler,
-        //    string? prevStepId,
-        //    string? countersignId,
-        //    EWorkflowStepStatus stepStatus,
-        //    ECountersignPosition countersignPosition,
-        //    DateTime expiredTime,
-        //    StepExtension extension)
-        //{
-        //    if (countersignPosition is ECountersignPosition.None && !string.IsNullOrEmpty(countersignId))
-        //        throw UserFriendlyException.SameMessage("非法参数");
-        //    if (countersignPosition is not ECountersignPosition.None && string.IsNullOrEmpty(countersignId))
-        //        throw UserFriendlyException.SameMessage("非法参数");
-
-        //    //依据是否发起会签创建step,发起会签表示一个handler创建一个step,未发起会签默认作为或签处理,只创建一个step
-        //    var steps = new List<WorkflowStep>();
-        //    if (isPrevStartCountersign)
-        //    {
-        //        foreach (var handler in handlers)
-        //        {
-        //            var step = CreateSubStep(stepBox, new List<Kv> { handler }, nextStepCode, nextMainHandler,
-        //                prevStepId, countersignId, stepStatus, countersignPosition, expiredTime, extension);
-
-        //            steps.Add(step);
-        //        }
-        //    }
-        //    else
-        //    {
-        //        var step = CreateSubStep(stepBox, handlers, nextStepCode, nextMainHandler,
-        //            prevStepId, countersignId, stepStatus, countersignPosition, expiredTime, extension);
-
-        //        steps.Add(step);
-        //    }
-
-        //    return steps;
-        //}
-
-        //private WorkflowStep CreateSubStep(
-        //    WorkflowStep stepBox,
-        //    List<Kv> handlers,
-        //    string nextStepCode,
-        //    string? nextMainHandler,
-        //    string? prevStepId,
-        //    string? prevStepCode,
-        //    string? countersignId,
-        //    EWorkflowStepStatus stepStatus,
-        //    ECountersignPosition countersignPosition,
-        //    DateTime expiredTime)
-        //{
-        //    if (!handlers.Any())
-        //        throw new UserFriendlyException("非法参数");
-        //    var step = _mapper.Map<WorkflowStep>(stepBox);
-        //    var handlerIds = handlers.Select(d => d.Key).ToList();
-        //    var isMain = handlers.Count == 1 || (handlers.Count > 1 || handlerIds.First() == nextMainHandler);
-
-        //    step.ParentId = stepBox.Id;
-        //    step.Handlers = handlers;
-        //    step.NextStepCode = step.StepType is EStepType.End ? string.Empty : nextStepCode;
-        //    step.IsMain = isMain;
-        //    step.PrevStepId = prevStepId;
-        //    step.PrevStepCode = prevStepCode;
-        //    step.CountersignId = countersignId;
-        //    step.Status = stepStatus;
-        //    step.CountersignPosition = countersignPosition;
-        //    step.StepExpiredTime = expiredTime;
-        //    step.TimeLimit = GetTimeLimit("");//todo 过期时间
-
-        //    return step;
-        //}
-
-        //new
         private WorkflowStep CreateStep(
             StepDefine stepDefine,
             WorkflowStep prevStep,

+ 11 - 1
src/Hotline/FlowEngine/Workflows/WorkflowStep.cs

@@ -228,7 +228,7 @@ public class WorkflowStep : StepBasicEntity
     {
         //if (!HasStartedCountersign())
         //    throw new UserFriendlyException("该节点未发起会签");
-        //outer的情况也属于特殊会签
+        //outer属于特殊会签
         return CountersignSteps.All(d => d.Completed);
     }
 
@@ -238,6 +238,16 @@ public class WorkflowStep : StepBasicEntity
     /// <returns></returns>
     public bool DynamicShouldTerminal() => TerminalDynamicMark == PrevChosenStepCode;
 
+    /// <summary>
+    /// 是否是顶级会签汇总节点
+    /// </summary>
+    public bool IsTopCountersignEndStep(string? topCountersignStepId)
+    {
+        if (string.IsNullOrEmpty(topCountersignStepId))
+            throw new UserFriendlyException($"无效顶级会签节点编号,流程可能未处于会签中, wfId: {WorkflowId}");
+        return IsCountersignEndStep && CountersignStartStepId == topCountersignStepId;
+    }
+
     #endregion
 }
 

+ 3 - 0
src/XF.Domain.Repository/Entity.cs

@@ -2,6 +2,7 @@
 using XF.Domain.Entities;
 using XF.Domain.Events;
 using XF.Domain.Extensions;
+using XF.Utility.SequentialId;
 
 namespace XF.Domain.Repository;
 
@@ -288,4 +289,6 @@ public abstract class PositionWorkflowEntity : PositionEntity, IWorkflow
                 throw new ArgumentOutOfRangeException(nameof(type), type, null);
         }
     }
+
+    public void InitId() => Id = SequentialStringGenerator.Create();
 }