Browse Source

fixed: 工单退回跨会签异常

Xfedge 1 year ago
parent
commit
d26027953f

+ 73 - 53
src/Hotline.Api/Controllers/OrderController.cs

@@ -2745,64 +2745,84 @@ public class OrderController : BaseController
     /// 工单退回退回(返回前一节点)
     /// 工单退回退回(返回前一节点)
     /// </summary>
     /// </summary>
     [HttpPost("order_previous")]
     [HttpPost("order_previous")]
-    public async Task Previous([FromBody] PreviousWorkflowDto dto)
+    public async Task Previous([FromBody] OrderPreviousDto dto)
     {
     {
         var oneSendBack = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.OneOrgSendBack)?.SettingValue[0]);
         var oneSendBack = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.OneOrgSendBack)?.SettingValue[0]);
         var twoSendBack = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.TwoOrgSendBack)?.SettingValue[0]);
         var twoSendBack = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.TwoOrgSendBack)?.SettingValue[0]);
         if (oneSendBack || twoSendBack)
         if (oneSendBack || twoSendBack)
         {
         {
-            var workflow =
-                await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, cancellationToken: HttpContext.RequestAborted);
-            var currentStep = _workflowDomainService.GetUnHandleStep(workflow.Steps, _sessionContext.RequiredOrgId,
-                _sessionContext.RequiredUserId);
-
-            if (workflow.FlowType is EFlowType.Review && currentStep.StepType is EStepType.Start && currentStep.IsOrigin)
-                throw UserFriendlyException.SameMessage("当前流程已退回到开始节点");
-
-            var prevStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.PrevStepId);
-            if (prevStep == null)
-                throw UserFriendlyException.SameMessage("未查询到前一节点");
-
-            var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == workflow.ExternalId && x.State == ESendBackAuditState.Apply).AnyAsync();
-            if (sendBack)
-                throw UserFriendlyException.SameMessage("当前工单已经生成退回记录");
-
-            var order = await _orderRepository
-                .Queryable()
-                .Includes(d => d.Workflow)
-                .FirstAsync(d => d.Id == workflow.ExternalId);
-            if (order.Workflow.IsInCountersign) throw UserFriendlyException.SameMessage("工单会签中,无法进行退回!");
-
-            //var applyOrg = _organizeRepository.Get(currentStep.AcceptorOrgId.CalcOrgLevel());
-            //var sendBackOrg = _organizeRepository.Get(prevStep.AcceptorOrgId.CalcOrgLevel());
-            if ((twoSendBack && 2.Equals(currentStep.AcceptorOrgId.CalcOrgLevel()) && 1.Equals(prevStep.AcceptorOrgId.CalcOrgLevel()) && !prevStep.AcceptorOrgId.IsCenter())
-                || (oneSendBack && 1.Equals(currentStep.AcceptorOrgId.CalcOrgLevel()) && prevStep.AcceptorOrgId.IsCenter() && !currentStep.AcceptorOrgId.IsCenter()))
-            {
-                var audit = new OrderSendBackAudit
-                {
-                    OrderId = workflow.ExternalId,
-                    State = ESendBackAuditState.Apply,
-                    Content = dto.Opinion,
-                    SendBackData = dto,
-                    ApplyOrgId = currentStep.AcceptorOrgId,
-                    ApplyOrgName = currentStep!.AcceptorOrgName,
-                    SendBackOrgId = prevStep.AcceptorOrgId,
-                    SendBackOrgName = prevStep!.AcceptorOrgName,
-                    WorkflowOrgId = _sessionContext.RequiredOrgId,
-                    WorkflowUserId = _sessionContext.RequiredUserId
-                };
-                await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted);
-            }
-            //中心内部流转  不走审批流程  3级部门不走审批 
-            else if (prevStep.AcceptorOrgId.IsCenter() && currentStep.AcceptorOrgId.IsCenter())
-            {
-                await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
-                //发送短信TODO
-            }
-            //不进入前两个判断都是默认退
-            else{
-	            await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
-			}
+   //          var workflow =
+   //              await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true, cancellationToken: HttpContext.RequestAborted);
+   //          var currentStep = _workflowDomainService.GetUnHandleStep(workflow.Steps, _sessionContext.RequiredOrgId,
+   //              _sessionContext.RequiredUserId);
+   //
+   //          if (workflow.FlowType is EFlowType.Review && currentStep.StepType is EStepType.Start && currentStep.IsOrigin)
+   //              throw UserFriendlyException.SameMessage("当前流程已退回到开始节点");
+   //
+   //          var prevStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.PrevStepId);
+   //          if (prevStep == null)
+   //              throw UserFriendlyException.SameMessage("未查询到前一节点");
+   //
+   //          var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == workflow.ExternalId && x.State == ESendBackAuditState.Apply).AnyAsync();
+   //          if (sendBack)
+   //              throw UserFriendlyException.SameMessage("当前工单已经生成退回记录");
+   //
+   //          var order = await _orderRepository
+   //              .Queryable()
+   //              .Includes(d => d.Workflow)
+   //              .FirstAsync(d => d.Id == workflow.ExternalId);
+   //          if (order.Workflow.IsInCountersign) throw UserFriendlyException.SameMessage("工单会签中,无法进行退回!");
+   //
+   //          //var applyOrg = _organizeRepository.Get(currentStep.AcceptorOrgId.CalcOrgLevel());
+   //          //var sendBackOrg = _organizeRepository.Get(prevStep.AcceptorOrgId.CalcOrgLevel());
+   //          if ((twoSendBack && 2.Equals(currentStep.AcceptorOrgId.CalcOrgLevel()) && 1.Equals(prevStep.AcceptorOrgId.CalcOrgLevel()) && !prevStep.AcceptorOrgId.IsCenter())
+   //              || (oneSendBack && 1.Equals(currentStep.AcceptorOrgId.CalcOrgLevel()) && prevStep.AcceptorOrgId.IsCenter() && !currentStep.AcceptorOrgId.IsCenter()))
+   //          {
+   //              var audit = new OrderSendBackAudit
+   //              {
+   //                  OrderId = workflow.ExternalId,
+   //                  State = ESendBackAuditState.Apply,
+   //                  Content = dto.Opinion,
+   //                  SendBackData = dto,
+   //                  ApplyOrgId = currentStep.AcceptorOrgId,
+   //                  ApplyOrgName = currentStep!.AcceptorOrgName,
+   //                  SendBackOrgId = prevStep.AcceptorOrgId,
+   //                  SendBackOrgName = prevStep!.AcceptorOrgName,
+   //                  WorkflowOrgId = _sessionContext.RequiredOrgId,
+   //                  WorkflowUserId = _sessionContext.RequiredUserId
+   //              };
+   //              await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted);
+   //          }
+   //          //中心内部流转  不走审批流程  3级部门不走审批 
+   //          else if (prevStep.AcceptorOrgId.IsCenter() && currentStep.AcceptorOrgId.IsCenter())
+   //          {
+   //              await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
+   //              //发送短信TODO
+   //          }
+   //          //不进入前两个判断都是默认退
+   //          else{
+	  //           await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
+			// }
+
+          var (currentStep, prevStep,isOrgToCenter, isSecondToFirstOrgLevel) = await _workflowApplication.GetPreviousInformationAsync(
+                dto.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, HttpContext.RequestAborted);
+          if ((oneSendBack && isOrgToCenter) || (twoSendBack && isSecondToFirstOrgLevel))
+          {
+              var audit = new OrderSendBackAudit
+              {
+                  OrderId = dto.OrderId,
+                  State = ESendBackAuditState.Apply,
+                  Content = dto.Opinion,
+                  SendBackData = dto,
+                  ApplyOrgId = currentStep.AcceptorOrgId,
+                  ApplyOrgName = currentStep!.AcceptorOrgName,
+                  SendBackOrgId = prevStep.HandlerOrgId,//prevStep.AcceptorOrgId,
+                  SendBackOrgName = prevStep.HandlerOrgName,//prevStep!.AcceptorOrgName,
+                  WorkflowOrgId = _sessionContext.RequiredOrgId,
+                  WorkflowUserId = _sessionContext.RequiredUserId
+              };
+              await _orderSendBackAuditRepository.AddAsync(audit, HttpContext.RequestAborted);
+          }
         }
         }
         else
         else
         {
         {

+ 7 - 7
src/Hotline.Api/StartupExtensions.cs

@@ -95,22 +95,22 @@ internal static class StartupExtensions
         var callCenterConfiguration = configuration.GetSection("CallCenterConfiguration").Get<CallCenterConfiguration>();
         var callCenterConfiguration = configuration.GetSection("CallCenterConfiguration").Get<CallCenterConfiguration>();
         //迅时IPPBX
         //迅时IPPBX
         services.AddNewRock(callCenterConfiguration.DeviceConfigs.Address);
         services.AddNewRock(callCenterConfiguration.DeviceConfigs.Address);
-
+  
         ////wex
         ////wex
         //services.AddWex(callCenterConfiguration.Wex.Address);
         //services.AddWex(callCenterConfiguration.Wex.Address);
-
+  
         //tr
         //tr
         var trConfig = configuration.GetRequiredSection("Tr").Get<TrConfiguration>();
         var trConfig = configuration.GetRequiredSection("Tr").Get<TrConfiguration>();
         services.AddTrSdk(trConfig.Address, trConfig.Username, trConfig.Password);
         services.AddTrSdk(trConfig.Address, trConfig.Username, trConfig.Password);
-
+  
 		//jths 
 		//jths 
 		services.AddAiJths(configuration.GetSection("AiQuality").Get<AiQualityConfig>().Url);
 		services.AddAiJths(configuration.GetSection("AiQuality").Get<AiQualityConfig>().Url);
-
+  
         //宜宾企业服务
         //宜宾企业服务
         services.Configure<EnterpriseConfig>(d => configuration.GetSection("Enterprise").Bind(d));
         services.Configure<EnterpriseConfig>(d => configuration.GetSection("Enterprise").Bind(d));
         var enterpriseConfig = configuration.GetSection("Enterprise").Get<EnterpriseConfig>();
         var enterpriseConfig = configuration.GetSection("Enterprise").Get<EnterpriseConfig>();
         services.AddYbEnterpriseSdk(enterpriseConfig?.AddressUrl);
         services.AddYbEnterpriseSdk(enterpriseConfig?.AddressUrl);
-
+  
         var aiVisitConfig = configuration.GetSection("AiVisit").Get<AiVisitConfig>();
         var aiVisitConfig = configuration.GetSection("AiVisit").Get<AiVisitConfig>();
         services.AddAiVisitService(aiVisitConfig.Url, aiVisitConfig.Appkey, aiVisitConfig.ServiceVersion, aiVisitConfig.SceneUid, aiVisitConfig.RuleUid,aiVisitConfig.VisitFromNameKey,aiVisitConfig.VisitFromGenderKey,aiVisitConfig.VisitCreationTimeKey,aiVisitConfig.VisitOrderTitleKey);
         services.AddAiVisitService(aiVisitConfig.Url, aiVisitConfig.Appkey, aiVisitConfig.ServiceVersion, aiVisitConfig.SceneUid, aiVisitConfig.RuleUid,aiVisitConfig.VisitFromNameKey,aiVisitConfig.VisitFromGenderKey,aiVisitConfig.VisitCreationTimeKey,aiVisitConfig.VisitOrderTitleKey);
 
 
@@ -125,8 +125,8 @@ internal static class StartupExtensions
         })
         })
             .AddValidatorsFromAssembly(typeof(AppContractsStartupExtensions).Assembly);
             .AddValidatorsFromAssembly(typeof(AppContractsStartupExtensions).Assembly);
 
 
-        //mq
-        services.AddMq(configuration);
+        // //mq
+        // services.AddMq(configuration);
 
 
         services.AddSingleton<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
         services.AddSingleton<IAuthorizationPolicyProvider, AuthorizationPolicyProvider>();
         services.AddSingleton<IAuthorizationHandler, PermissionHandler>();
         services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

+ 9 - 3
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -14,8 +14,6 @@ namespace Hotline.Application.FlowEngine
 {
 {
     public interface IWorkflowApplication
     public interface IWorkflowApplication
     {
     {
-
-
         /// <summary>
         /// <summary>
         /// 开始流程
         /// 开始流程
         /// </summary>
         /// </summary>
@@ -25,7 +23,8 @@ namespace Hotline.Application.FlowEngine
         /// <summary>
         /// <summary>
         /// 流转至下一节点(节点办理)
         /// 流转至下一节点(节点办理)
         /// </summary>
         /// </summary>
-        Task<Workflow> NextAsync(NextWorkflowDto dto, DateTime? expiredTime = null, CancellationToken cancellationToken = default);
+        Task<Workflow> NextAsync(NextWorkflowDto dto, DateTime? expiredTime = null,
+            CancellationToken cancellationToken = default);
 
 
         /// <summary>
         /// <summary>
         /// 退回(返回前一节点)
         /// 退回(返回前一节点)
@@ -108,5 +107,12 @@ namespace Hotline.Application.FlowEngine
         /// <param name="cancellationToken"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
         /// <returns></returns>
         Task<WorkflowModule> GetWorkflowModuleAsync(string code, CancellationToken cancellationToken);
         Task<WorkflowModule> GetWorkflowModuleAsync(string code, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 检查退回节点信息
+        /// </summary>
+        Task<(WorkflowStep currentStep, WorkflowStep prevStep, bool isOrgToCenter, bool isSecondToFirstOrgLevel)>
+            GetPreviousInformationAsync(string workflowId, string operatorId, string operatorOrgId,
+                CancellationToken cancellationToken);
     }
     }
 }
 }

+ 50 - 19
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -115,7 +115,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
 
         //下一节点是否为动态节点
         //下一节点是否为动态节点
         var isNextDynamic = startStepDefine.InstanceMode is EInstanceMode.Dynamic &&
         var isNextDynamic = startStepDefine.InstanceMode is EInstanceMode.Dynamic &&
-                                      !_workflowDomainService.DynamicShouldTerminal(startStepDefine, _sessionContext.OrgLevel);
+                            !_workflowDomainService.DynamicShouldTerminal(startStepDefine, _sessionContext.OrgLevel);
         var firstStepDefine = isNextDynamic
         var firstStepDefine = isNextDynamic
             ? startStepDefine
             ? startStepDefine
             : definition.FindStepDefine(dto.NextStepCode);
             : definition.FindStepDefine(dto.NextStepCode);
@@ -161,7 +161,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         //    _sessionContext.OrgIsCenter, firstStepDefine.Code);
         //    _sessionContext.OrgIsCenter, firstStepDefine.Code);
 
 
         if (dto.Files.Any())
         if (dto.Files.Any())
-            startStep.FileJson = await _fileRepository.AddFileAsync(dto.Files, workflow.ExternalId, startStep.Id, cancellationToken);
+            startStep.FileJson =
+                await _fileRepository.AddFileAsync(dto.Files, workflow.ExternalId, startStep.Id, cancellationToken);
 
 
         await _workflowStepRepository.AddAsync(startStep, cancellationToken);
         await _workflowStepRepository.AddAsync(startStep, cancellationToken);
         workflow.Steps.Add(startStep);
         workflow.Steps.Add(startStep);
@@ -191,9 +192,11 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// <summary>
     /// <summary>
     /// 流转至下一节点(节点办理)
     /// 流转至下一节点(节点办理)
     /// </summary>
     /// </summary>
-    public async Task<Workflow> NextAsync(NextWorkflowDto dto, DateTime? expiredTime = null, CancellationToken cancellationToken = default)
+    public async Task<Workflow> NextAsync(NextWorkflowDto dto, DateTime? expiredTime = null,
+        CancellationToken cancellationToken = default)
     {
     {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true, withCountersigns: true,
+        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
+            withCountersigns: true,
             cancellationToken: cancellationToken);
             cancellationToken: cancellationToken);
         //await NextAsync(workflow, dto, dto.ExpiredTime, dto.IsStartCountersign, cancellationToken);
         //await NextAsync(workflow, dto, dto.ExpiredTime, dto.IsStartCountersign, cancellationToken);
 
 
@@ -202,7 +205,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         //    (dto.StepExpiredTime <= DateTime.Now || dto.StepExpiredTime > workflow.ExpiredTime))
         //    (dto.StepExpiredTime <= DateTime.Now || dto.StepExpiredTime > workflow.ExpiredTime))
         //    throw UserFriendlyException.SameMessage("节点期满时间无效");
         //    throw UserFriendlyException.SameMessage("节点期满时间无效");
 
 
-        var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
+        var currentStep =
+            _workflowDomainService.FindCurrentStepWaitForHandle(workflow, _sessionContext.RequiredUserId,
+                _sessionContext.RequiredOrgId);
         if (currentStep.Status is EWorkflowStepStatus.Handled)
         if (currentStep.Status is EWorkflowStepStatus.Handled)
             throw new UserFriendlyException("该状态不支持继续办理");
             throw new UserFriendlyException("该状态不支持继续办理");
 
 
@@ -272,7 +277,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     public async Task PreviousAsync(PreviousWorkflowDto dto, string userId, CancellationToken cancellationToken)
     public async Task PreviousAsync(PreviousWorkflowDto dto, string userId, CancellationToken cancellationToken)
     {
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
-           withCountersigns: true, cancellationToken: cancellationToken);
+            withCountersigns: true, cancellationToken: cancellationToken);
         var user = await _userRepository.Queryable()
         var user = await _userRepository.Queryable()
             .Includes(x => x.Organization)
             .Includes(x => x.Organization)
             .FirstAsync(x => x.Id == userId, cancellationToken);
             .FirstAsync(x => x.Id == userId, cancellationToken);
@@ -285,7 +290,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     public async Task RecallAsync(RecallDto dto, DateTime? expiredTime, CancellationToken cancellationToken)
     public async Task RecallAsync(RecallDto dto, DateTime? expiredTime, CancellationToken cancellationToken)
     {
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
-                cancellationToken: cancellationToken);
+            cancellationToken: cancellationToken);
 
 
         //await _orderDomainService.ReadyToRecallAsync(workflow.ExternalId, cancellationToken);
         //await _orderDomainService.ReadyToRecallAsync(workflow.ExternalId, cancellationToken);
 
 
@@ -293,8 +298,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         if (targetStepDefine.StepType is EStepType.End)
         if (targetStepDefine.StepType is EStepType.End)
             throw UserFriendlyException.SameMessage("结束节点不支持撤回");
             throw UserFriendlyException.SameMessage("结束节点不支持撤回");
         //var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
         //var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
-        var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign, dto.NextHandlers,
-                cancellationToken);
+        var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign,
+            dto.NextHandlers,
+            cancellationToken);
 
 
         await _workflowDomainService.RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, expiredTime, cancellationToken);
         await _workflowDomainService.RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, expiredTime, cancellationToken);
     }
     }
@@ -324,7 +330,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         CancellationToken cancellationToken = default)
         CancellationToken cancellationToken = default)
     {
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withDefine: true, withSteps: true,
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withDefine: true, withSteps: true,
-                cancellationToken: cancellationToken);
+            cancellationToken: cancellationToken);
         var endStepDefine = workflow.WorkflowDefinition.FindEndStepDefine();
         var endStepDefine = workflow.WorkflowDefinition.FindEndStepDefine();
         if (endStepDefine is null)
         if (endStepDefine is null)
             throw new UserFriendlyException("未正确配置结束节点");
             throw new UserFriendlyException("未正确配置结束节点");
@@ -333,10 +339,10 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             throw new UserFriendlyException("未找到实际办理节点");
             throw new UserFriendlyException("未找到实际办理节点");
 
 
         await _workflowDomainService.EndAsync(workflow, new BasicWorkflowDto
         await _workflowDomainService.EndAsync(workflow, new BasicWorkflowDto
-        {
-            Opinion = opinion,
-            Files = files
-        }, endStepDefine, currentStep,
+            {
+                Opinion = opinion,
+                Files = files
+            }, endStepDefine, currentStep,
             reviewResult, cancellationToken);
             reviewResult, cancellationToken);
     }
     }
 
 
@@ -527,7 +533,9 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     {
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withDefine: true, withSteps: true,
         var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withDefine: true, withSteps: true,
             cancellationToken: cancellationToken);
             cancellationToken: cancellationToken);
-        var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId);
+        var currentStep =
+            _workflowDomainService.FindCurrentStepWaitForHandle(workflow, _sessionContext.RequiredUserId,
+                _sessionContext.RequiredOrgId);
         if (currentStep.StepType is EStepType.End)
         if (currentStep.StepType is EStepType.End)
             throw new UserFriendlyException("结束节点无需办理");
             throw new UserFriendlyException("结束节点无需办理");
 
 
@@ -543,7 +551,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
 
         var currentStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, currentStep.Code);
         var currentStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, currentStep.Code);
 
 
-        if (currentStep.InstanceMode is EInstanceMode.Dynamic && !_workflowDomainService.DynamicShouldTerminal(currentStepDefine, _sessionContext.OrgLevel))
+        if (currentStep.InstanceMode is EInstanceMode.Dynamic &&
+            !_workflowDomainService.DynamicShouldTerminal(currentStepDefine, _sessionContext.OrgLevel))
         {
         {
             //动态生成下一步
             //动态生成下一步
             var nextStepOption = await GetDynamicStepAsync(currentStep.InstancePolicy.Value, currentStep.StepType,
             var nextStepOption = await GetDynamicStepAsync(currentStep.InstancePolicy.Value, currentStep.StepType,
@@ -571,7 +580,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
 
                     //按会签策略
                     //按会签策略
                     var nextStepOption =
                     var nextStepOption =
-                        await GetDynamicStepAsync(currentStep.CountersignPolicy.Value, currentStep.StepType, currentStep.BusinessType,
+                        await GetDynamicStepAsync(currentStep.CountersignPolicy.Value, currentStep.StepType,
+                            currentStep.BusinessType,
                             cancellationToken);
                             cancellationToken);
 
 
                     dto.Steps = new List<NextStepOption> { nextStepOption, countersignEndOption };
                     dto.Steps = new List<NextStepOption> { nextStepOption, countersignEndOption };
@@ -777,6 +787,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             {
             {
                 nextStepOption = await GetConfigStepAsync(workflow.FlowType, stepDefine, cancellationToken);
                 nextStepOption = await GetConfigStepAsync(workflow.FlowType, stepDefine, cancellationToken);
             }
             }
+
             nextStepOption.InputRealHandler = currentStep.StepType == EStepType.Normal &&
             nextStepOption.InputRealHandler = currentStep.StepType == EStepType.Normal &&
                                               stepDefine.StepType is EStepType.Summary or EStepType.End;
                                               stepDefine.StepType is EStepType.Summary or EStepType.End;
             stepOptions.Add(nextStepOption);
             stepOptions.Add(nextStepOption);
@@ -1044,7 +1055,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             FlowDirection = null,
             FlowDirection = null,
             StepType = stepType,
             StepType = stepType,
             BusinessType = businessType,
             BusinessType = businessType,
-            HandlerType = EHandlerType.OrgLevel,//目前所有动态策略均属于部门等级
+            HandlerType = EHandlerType.OrgLevel, //目前所有动态策略均属于部门等级
             Items = items
             Items = items
         };
         };
     }
     }
@@ -1127,7 +1138,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// 查询下一节点办理对象类型(user or org)及实际办理对象
     /// 查询下一节点办理对象类型(user or org)及实际办理对象
     /// </summary>
     /// </summary>
     public async Task<FlowAssignInfo> GetNextStepFlowAssignInfoAsync(Workflow workflow, WorkflowStep currentStep,
     public async Task<FlowAssignInfo> GetNextStepFlowAssignInfoAsync(Workflow workflow, WorkflowStep currentStep,
-      BasicWorkflowDto dto, StepDefine nextStepDefine, bool isNextDynamic, CancellationToken cancellationToken)
+        BasicWorkflowDto dto, StepDefine nextStepDefine, bool isNextDynamic, CancellationToken cancellationToken)
     {
     {
         if (nextStepDefine.StepType is EStepType.End) return new();
         if (nextStepDefine.StepType is EStepType.End) return new();
 
 
@@ -1243,5 +1254,25 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         return wfModule;
         return wfModule;
     }
     }
 
 
+    /// <summary>
+    /// 检查退回节点信息
+    /// </summary>
+    public async Task<(WorkflowStep currentStep, WorkflowStep prevStep, bool isOrgToCenter, bool isSecondToFirstOrgLevel)>
+        GetPreviousInformationAsync(string workflowId, string operatorId, string operatorOrgId,
+            CancellationToken cancellationToken)
+    {
+        var workflow = await _workflowDomainService.GetWorkflowAsync(workflowId, withSteps: true,
+            withCountersigns: true, cancellationToken: cancellationToken);
+        var (currentStep, prevStep, _) = _workflowDomainService.GetPreviousStep(workflow, operatorId, operatorOrgId);
+        var isOrgToCenter = currentStep.BusinessType is EBusinessType.Department &&
+                            prevStep.BusinessType is EBusinessType.Center or EBusinessType.Send;
+        var isSecondToFirstOrgLevel = currentStep.HandlerType is EHandlerType.OrgLevel &&
+                                      currentStep.Handlers.First().Key.CheckIfOrgLevelIs(2) &&
+                                      prevStep.HandlerType is EHandlerType.OrgLevel &&
+                                      prevStep.Handlers.First().Key.CheckIfOrgLevelIs(1) &&
+                                      !prevStep.Handlers.First().Key.IsCenter();
+        return (currentStep, prevStep, isOrgToCenter, isSecondToFirstOrgLevel);
+    }
+
     #endregion
     #endregion
 }
 }

+ 8 - 0
src/Hotline.Share/Dtos/Order/OrderPreviousDto.cs

@@ -0,0 +1,8 @@
+using Hotline.Share.Dtos.FlowEngine;
+
+namespace Hotline.Share.Dtos.Order;
+
+public class OrderPreviousDto : PreviousWorkflowDto
+{
+    public string OrderId { get; set; }
+}

+ 6 - 0
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -195,5 +195,11 @@ namespace Hotline.FlowEngine.Workflows
         /// 获取会签类型
         /// 获取会签类型
         /// </summary>
         /// </summary>
         ECounterSignType GetCounterSignType(EBusinessType businessType);
         ECounterSignType GetCounterSignType(EBusinessType businessType);
+
+        /// <summary>
+        /// 查询退回节点信息
+        /// </summary>
+        (WorkflowStep currentStep, WorkflowStep prevStep, WorkflowStep? countersignStartStep) GetPreviousStep(
+            Workflow workflow, string operaterId, string operaterOrgId);
     }
     }
 }
 }

+ 83 - 66
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -7,9 +7,7 @@ using Hotline.Settings;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.FlowEngine.Definition;
 using Hotline.Share.Dtos.FlowEngine.Definition;
-using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.FlowEngine;
-using Hotline.Share.Enums.Settings;
 using Hotline.Users;
 using Hotline.Users;
 using MapsterMapper;
 using MapsterMapper;
 using MediatR;
 using MediatR;
@@ -287,7 +285,8 @@ namespace Hotline.FlowEngine.Workflows
                 }
                 }
             }
             }
 
 
-            var unCompletedCountersign = workflow.Countersigns.FirstOrDefault(d => !d.IsCompleted() && d.StarterId == userId);
+            var unCompletedCountersign = workflow.Countersigns
+                .FirstOrDefault(d => !d.IsCompleted() && d.StarterId == userId);
             if (unCompletedCountersign is null) return (workflow, null, canPrevious);
             if (unCompletedCountersign is null) return (workflow, null, canPrevious);
 
 
             //var existCountersignEndStep = workflow.Steps.Exists(d =>
             //var existCountersignEndStep = workflow.Steps.Exists(d =>
@@ -491,13 +490,13 @@ namespace Hotline.FlowEngine.Workflows
 
 
             //创建下一/N个节点(会签汇总节点:会签未全部办理时不创建,最后一个会签办理节点创建会签汇总节点)
             //创建下一/N个节点(会签汇总节点:会签未全部办理时不创建,最后一个会签办理节点创建会签汇总节点)
             var nextSteps = await CreateNextStepsAsync(workflow, currentStep, dto, nextStepDefine, isNextDynamic,
             var nextSteps = await CreateNextStepsAsync(workflow, currentStep, dto, nextStepDefine, isNextDynamic,
-                    flowAssignInfo, expiredTime, cancellationToken);
+                flowAssignInfo, expiredTime, cancellationToken);
 
 
             //赋值当前节点的下级办理节点
             //赋值当前节点的下级办理节点
             if (dto.IsStartCountersign
             if (dto.IsStartCountersign
                 //|| (currentStep.IsInCountersign() &&
                 //|| (currentStep.IsInCountersign() &&
                 //    !currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
                 //    !currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
-                )
+               )
             {
             {
                 currentStep.CreateCountersignSteps(nextSteps);
                 currentStep.CreateCountersignSteps(nextSteps);
                 await _workflowStepRepository.UpdateAsync(currentStep, cancellationToken);
                 await _workflowStepRepository.UpdateAsync(currentStep, cancellationToken);
@@ -551,63 +550,25 @@ namespace Hotline.FlowEngine.Workflows
         /// 退回(返回前一节点)
         /// 退回(返回前一节点)
         /// </summary>
         /// </summary>
         /// <returns></returns>
         /// <returns></returns>
-        public async Task PreviousAsync(Workflow workflow, PreviousWorkflowDto dto, User operater, CancellationToken cancellationToken)
+        public async Task PreviousAsync(Workflow workflow, PreviousWorkflowDto dto, User operater,
+            CancellationToken cancellationToken)
         {
         {
             ValidatePermission(workflow, operater.OrgId, operater.Id);
             ValidatePermission(workflow, operater.OrgId, operater.Id);
-            //CheckWhetherRunnable(workflow.Status);
-            //if (workflow.IsInCountersign)
-            //    throw UserFriendlyException.SameMessage("会签流程不支持退回");
 
 
-            var currentStep = GetUnHandleStep(workflow.Steps, operater.OrgId, operater.Id);
-            var isCurrentTopCountersignEndStep = workflow.IsInCountersign && currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId);
-            if (currentStep.IsInCountersign() && !isCurrentTopCountersignEndStep)
-                throw UserFriendlyException.SameMessage("会签节点不支持退回");
+            var (currentStep, prevStep, countersignStartStep) = GetPreviousStep(workflow, operater.Id, operater.OrgId);
 
 
             //保存附件
             //保存附件
             if (dto.Files.Any())
             if (dto.Files.Any())
-                currentStep.FileJson = await _fileRepository.AddFileAsync(dto.Files, workflow.ExternalId, currentStep.Id, cancellationToken);
-
-            if (workflow.FlowType is EFlowType.Review && currentStep.StepType is EStepType.Start && currentStep.IsOrigin)
-                throw UserFriendlyException.SameMessage("当前流程已退回到开始节点");
-
-            //当退回操作遇到会签时,删除所有会签节点直达topCsStep
-            var shouldCountersignEnd = false;
-            //find prevStep, update handler
-            WorkflowStep? prevStep, countersignStartStep = null;
-            if (isCurrentTopCountersignEndStep)
-            {
-                //prev is topstart's prev
-                countersignStartStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);
-                if (countersignStartStep is null)
-                    throw new UserFriendlyException("未查询到对应会签开始节点");
-                prevStep = workflow.Steps.FirstOrDefault(d => d.Id == countersignStartStep.PrevStepId);
-                shouldCountersignEnd = true;
-            }
-            else
-            {
-                prevStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.PrevStepId);
-            }
-            if (prevStep == null)
-                throw UserFriendlyException.SameMessage("未查询到前一节点");
-
-            if (workflow.IsInCountersign && prevStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
-            {
-                countersignStartStep = workflow.Steps.FirstOrDefault(d => d.Id == prevStep.CountersignStartStepId);
-                if (countersignStartStep is null)
-                    throw new UserFriendlyException("未查询到对应会签开始节点");
-                prevStep = workflow.Steps.FirstOrDefault(d => d.Id == prevStep.CountersignStartStepId);
-                shouldCountersignEnd = true;
-            }
-            if (prevStep == null)
-                throw UserFriendlyException.SameMessage("未查询到会签发起节点");
+                currentStep.FileJson = await _fileRepository.AddFileAsync(
+                    dto.Files, workflow.ExternalId, currentStep.Id, cancellationToken);
 
 
             // add prev current to remove list
             // add prev current to remove list
             var removeSteps = new List<WorkflowStep> { currentStep, prevStep };
             var removeSteps = new List<WorkflowStep> { currentStep, prevStep };
 
 
-            if (shouldCountersignEnd)
+            if (countersignStartStep is not null)
             {
             {
                 //add cs steps to remove list
                 //add cs steps to remove list
-                SearchCountersignSteps(countersignStartStep!, workflow.Steps, ref removeSteps);
+                SearchCountersignSteps(countersignStartStep, workflow.Steps, ref removeSteps);
 
 
                 //end cs
                 //end cs
                 var currentCountersign =
                 var currentCountersign =
@@ -638,7 +599,8 @@ namespace Hotline.FlowEngine.Workflows
             var trace = await PreviousTraceAsync(workflow.Id, dto, currentStep, cancellationToken);
             var trace = await PreviousTraceAsync(workflow.Id, dto, currentStep, cancellationToken);
 
 
             //复制上一个节点为待接办
             //复制上一个节点为待接办
-            var newPrevStep = await DuplicateStepWithTraceAsync(workflow, prevStep, EWorkflowTraceStatus.Previous, cancellationToken);
+            var newPrevStep =
+                await DuplicateStepWithTraceAsync(workflow, prevStep, EWorkflowTraceStatus.Previous, cancellationToken);
 
 
             //remove workflow.steps
             //remove workflow.steps
             await _workflowStepRepository.RemoveRangeAsync(removeSteps, cancellationToken);
             await _workflowStepRepository.RemoveRangeAsync(removeSteps, cancellationToken);
@@ -660,6 +622,50 @@ namespace Hotline.FlowEngine.Workflows
             await _mediator.Publish(new PreviousNotify(workflow, newPrevStep, dto, isOrgToCenter), cancellationToken);
             await _mediator.Publish(new PreviousNotify(workflow, newPrevStep, dto, isOrgToCenter), cancellationToken);
         }
         }
 
 
+        /// <summary>
+        /// 查询退回节点信息
+        /// </summary>
+        public (WorkflowStep currentStep, WorkflowStep prevStep, WorkflowStep? countersignStartStep) GetPreviousStep(
+            Workflow workflow, string operaterId, string operaterOrgId)
+        {
+            var currentStep = GetUnHandleStep(workflow.Steps, operaterOrgId, operaterId);
+            var isCurrentTopCountersignEndStep = workflow.IsInCountersign &&
+                                                 currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId);
+            if (currentStep.IsInCountersign() && !isCurrentTopCountersignEndStep)
+                throw UserFriendlyException.SameMessage("会签节点不支持退回");
+
+            if (workflow.FlowType is EFlowType.Review && currentStep.StepType is EStepType.Start && currentStep.IsOrigin)
+                throw UserFriendlyException.SameMessage("当前流程已退回到开始节点");
+
+            //当退回操作遇到会签时,删除所有会签节点直达topCsStep
+            //find prevStep, update handler
+            WorkflowStep? prevStep, countersignStartStep = null;
+            if (isCurrentTopCountersignEndStep)
+            {
+                //prev is topstart's prev
+                countersignStartStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);
+                if (countersignStartStep is null)
+                    throw new UserFriendlyException("未查询到对应会签开始节点");
+                prevStep = workflow.Steps.FirstOrDefault(d => d.Id == countersignStartStep.PrevStepId);
+            }
+            else
+            {
+                prevStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.PrevStepId);
+            }
+            if (prevStep == null)
+                throw UserFriendlyException.SameMessage("未查询到前一节点");
+
+            if (prevStep.IsCountersignEndStep)
+            {
+                countersignStartStep = workflow.Steps.FirstOrDefault(d => d.Id == prevStep.CountersignStartStepId);
+                prevStep = countersignStartStep ?? throw new UserFriendlyException("未查询到对应会签开始节点");
+                if (prevStep == null)
+                    throw UserFriendlyException.SameMessage("未查询到前一节点");
+            }
+
+            return (currentStep, prevStep, countersignStartStep);
+        }
+
         /// <summary>
         /// <summary>
         /// 查找当前会签内所有节点(含start,end)
         /// 查找当前会签内所有节点(含start,end)
         /// </summary>
         /// </summary>
@@ -676,6 +682,7 @@ namespace Hotline.FlowEngine.Workflows
                     }
                     }
                 }
                 }
             }
             }
+
             csSteps.Add(startStep);
             csSteps.Add(startStep);
         }
         }
 
 
@@ -722,7 +729,8 @@ namespace Hotline.FlowEngine.Workflows
             if (workflow.Status is EWorkflowStatus.Completed)
             if (workflow.Status is EWorkflowStatus.Completed)
                 workflow.SetStatusRunnable();
                 workflow.SetStatusRunnable();
 
 
-            var newStartStep = await DuplicateStepWithTraceAsync(workflow, startStep, EWorkflowTraceStatus.Recall, cancellationToken);
+            var newStartStep =
+                await DuplicateStepWithTraceAsync(workflow, startStep, EWorkflowTraceStatus.Recall, cancellationToken);
 
 
             //更新当前办理节点信息
             //更新当前办理节点信息
             //workflow.UpdateWorkflowCurrentStepInfo(false,
             //workflow.UpdateWorkflowCurrentStepInfo(false,
@@ -868,10 +876,10 @@ namespace Hotline.FlowEngine.Workflows
             await _workflowStepRepository.UpdateAsync(currentStep, cancellationToken);
             await _workflowStepRepository.UpdateAsync(currentStep, cancellationToken);
 
 
             workflow.UpdateActualStepWhenHandle(currentStep,
             workflow.UpdateActualStepWhenHandle(currentStep,
-                    _sessionContext.RequiredUserId, _sessionContext.UserName,
-                    _sessionContext.RequiredOrgId, _sessionContext.OrgName,
-                    _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
-                    _sessionContext.OrgLevel);
+                _sessionContext.RequiredUserId, _sessionContext.UserName,
+                _sessionContext.RequiredOrgId, _sessionContext.OrgName,
+                _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
+                _sessionContext.OrgLevel);
 
 
             var endStepDefine = workflow.WorkflowDefinition.FindEndStepDefine();
             var endStepDefine = workflow.WorkflowDefinition.FindEndStepDefine();
             var endTrace = await EndAsync(workflow, dto, endStepDefine, currentStep, EReviewResult.Failed,
             var endTrace = await EndAsync(workflow, dto, endStepDefine, currentStep, EReviewResult.Failed,
@@ -1135,7 +1143,8 @@ namespace Hotline.FlowEngine.Workflows
                         if (csStartStep is null)
                         if (csStartStep is null)
                             throw new UserFriendlyException("未查询到会签节点");
                             throw new UserFriendlyException("未查询到会签节点");
 
 
-                        nextSteps = await CreateCsEndStepsByPrevStepAsync(workflow, csStartStep, dto, expiredTime, cancellationToken);
+                        nextSteps = await CreateCsEndStepsByPrevStepAsync(workflow, csStartStep, dto, expiredTime,
+                            cancellationToken);
                     }
                     }
                 }
                 }
                 else
                 else
@@ -1143,7 +1152,8 @@ namespace Hotline.FlowEngine.Workflows
                     if (dto.BackToCountersignEnd)
                     if (dto.BackToCountersignEnd)
                     {
                     {
                         //todo check if cs all complete, create next
                         //todo check if cs all complete, create next
-                        nextSteps = await CreateCsEndStepsByPrevStepAsync(workflow, currentStep, dto, expiredTime, cancellationToken);
+                        nextSteps = await CreateCsEndStepsByPrevStepAsync(workflow, currentStep, dto, expiredTime,
+                            cancellationToken);
                     }
                     }
                     else
                     else
                     {
                     {
@@ -1385,7 +1395,8 @@ namespace Hotline.FlowEngine.Workflows
         /// 开始会签(创建会签数据,更新currentStep会签数据)
         /// 开始会签(创建会签数据,更新currentStep会签数据)
         /// </summary>
         /// </summary>
         private async Task StartCountersignAsync(Workflow workflow, WorkflowStep startStep, BasicWorkflowDto dto,
         private async Task StartCountersignAsync(Workflow workflow, WorkflowStep startStep, BasicWorkflowDto dto,
-            EFlowAssignType? flowAssignType, ECounterSignType? counterSignType, DateTime? expiredTime, CancellationToken cancellationToken)
+            EFlowAssignType? flowAssignType, ECounterSignType? counterSignType, DateTime? expiredTime,
+            CancellationToken cancellationToken)
         {
         {
             var countersign = await CreateCountersignAsync(
             var countersign = await CreateCountersignAsync(
                 workflow, startStep, dto.NextHandlers, flowAssignType,
                 workflow, startStep, dto.NextHandlers, flowAssignType,
@@ -1671,7 +1682,8 @@ namespace Hotline.FlowEngine.Workflows
                 workflow.SetStatusRunnable();
                 workflow.SetStatusRunnable();
 
 
             var targetStepNew = targetIsStartStep
             var targetStepNew = targetIsStartStep
-                ? await CreateStartStepAsync(workflow, targetStepDefine, dto, dto.NextHandlers, traceStatus, expiredTime, cancellationToken)
+                ? await CreateStartStepAsync(workflow, targetStepDefine, dto, dto.NextHandlers, traceStatus, expiredTime,
+                    cancellationToken)
                 : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto,
                 : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto,
                     flowAssignInfo.FlowAssignType, dto.NextHandlers,
                     flowAssignInfo.FlowAssignType, dto.NextHandlers,
                     null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceStatus,
                     null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceStatus,
@@ -1857,7 +1869,8 @@ namespace Hotline.FlowEngine.Workflows
         /// <param name="orgId">当前办理人orgId</param>
         /// <param name="orgId">当前办理人orgId</param>
         /// <param name="cancellationToken"></param>
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
         /// <returns></returns>
-        public async Task<bool> CheckCurrentIsStartStepAsync(string workflowId, string userId, string orgId, CancellationToken cancellationToken)
+        public async Task<bool> CheckCurrentIsStartStepAsync(string workflowId, string userId, string orgId,
+            CancellationToken cancellationToken)
         {
         {
             var workflow = await GetWorkflowAsync(workflowId, withSteps: true, cancellationToken: cancellationToken);
             var workflow = await GetWorkflowAsync(workflowId, withSteps: true, cancellationToken: cancellationToken);
             var currentStep = GetStep(workflow.Steps, orgId, userId, d => d != EWorkflowStepStatus.Handled);
             var currentStep = GetStep(workflow.Steps, orgId, userId, d => d != EWorkflowStepStatus.Handled);
@@ -1920,7 +1933,8 @@ namespace Hotline.FlowEngine.Workflows
                 throw new UserFriendlyException("该会签已汇总");
                 throw new UserFriendlyException("该会签已汇总");
 
 
             var updateCountersigns = new List<WorkflowCountersign>();
             var updateCountersigns = new List<WorkflowCountersign>();
-            EndCountersignWithCascade(countersign, workflow.Countersigns, startCountersignStep.BusinessType, ref updateCountersigns);
+            EndCountersignWithCascade(countersign, workflow.Countersigns, startCountersignStep.BusinessType,
+                ref updateCountersigns);
 
 
             if (updateCountersigns.Any())
             if (updateCountersigns.Any())
             {
             {
@@ -1937,11 +1951,13 @@ namespace Hotline.FlowEngine.Workflows
 
 
                 //cp会签发起节点变为待办节点
                 //cp会签发起节点变为待办节点
                 //1. create terminal trace 2. 撤回至startStep
                 //1. create terminal trace 2. 撤回至startStep
-                var newStep = await DuplicateStepWithTraceAsync(workflow, startCountersignStep, EWorkflowTraceStatus.Normal, cancellationToken);
+                var newStep = await DuplicateStepWithTraceAsync(workflow, startCountersignStep, EWorkflowTraceStatus.Normal,
+                    cancellationToken);
 
 
                 //当topcsStep结束cs时,实际办理节点应该更新为newStep
                 //当topcsStep结束cs时,实际办理节点应该更新为newStep
                 if (startCountersignStep.Id == workflow.TopCountersignStepId)
                 if (startCountersignStep.Id == workflow.TopCountersignStepId)
-                    workflow.UpdateActualStepWhenAssign(newStep, startCountersignStep.HandlerOrgName, startCountersignStep.HandlerOrgId);
+                    workflow.UpdateActualStepWhenAssign(newStep, startCountersignStep.HandlerOrgName,
+                        startCountersignStep.HandlerOrgId);
 
 
                 //csEndStep又开启了cs,在结束会签时,如果该节点是topcs的end节点, workflow.topcsStep应该更新为前一cs开启stepId
                 //csEndStep又开启了cs,在结束会签时,如果该节点是topcs的end节点, workflow.topcsStep应该更新为前一cs开启stepId
                 if (startCountersignStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
                 if (startCountersignStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
@@ -1961,7 +1977,6 @@ namespace Hotline.FlowEngine.Workflows
                 workflow.UpdateHandlers(removeHandlers, newStep.FlowAssignType.Value, handlerObjs);
                 workflow.UpdateHandlers(removeHandlers, newStep.FlowAssignType.Value, handlerObjs);
 
 
                 await _workflowRepository.UpdateAsync(workflow, cancellationToken);
                 await _workflowRepository.UpdateAsync(workflow, cancellationToken);
-
             }
             }
 
 
             return workflow;
             return workflow;
@@ -1981,6 +1996,7 @@ namespace Hotline.FlowEngine.Workflows
                     }
                     }
                 }
                 }
             }
             }
+
             EndStepByTerminalCs(step, traces, ref updateSteps, ref updateTraces);
             EndStepByTerminalCs(step, traces, ref updateSteps, ref updateTraces);
         }
         }
 
 
@@ -2002,6 +2018,7 @@ namespace Hotline.FlowEngine.Workflows
                     _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
                     _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName,
                     _sessionContext.OrgIsCenter, opinion);
                     _sessionContext.OrgIsCenter, opinion);
             }
             }
+
             updateSteps.Add(step);
             updateSteps.Add(step);
 
 
             if (isHandled) return;
             if (isHandled) return;
@@ -2081,7 +2098,7 @@ namespace Hotline.FlowEngine.Workflows
             DateTime? expiredTime,
             DateTime? expiredTime,
             string stepName,
             string stepName,
             bool isOrigin,
             bool isOrigin,
-            EHandlerType? handlerType = null//动态节点依据动态策略判断
+            EHandlerType? handlerType = null //动态节点依据动态策略判断
         )
         )
         {
         {
             if (!handlers.Any())
             if (!handlers.Any())