xfe 1 year ago
parent
commit
1dad17f1ed

+ 141 - 77
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -18,6 +18,7 @@ using Hotline.Share.Enums.Identity;
 using Hotline.Share.Enums.Order;
 using Hotline.Users;
 using MapsterMapper;
+using System.Threading;
 using XF.Domain.Authentications;
 using XF.Domain.Dependency;
 using XF.Domain.Entities;
@@ -420,7 +421,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             //var nextStepOption = CreateDynamicStep(startStep.InstancePolicy);
             //dto.Steps = new List<NextStepOption> { nextStepOption };
             //return dto;
-            var nextStepOption = await CreateDynamicStepAsync(startStep.InstancePolicy.Value, cancellationToken);
+            var nextStepOption = await GetDynamicStepAsync(startStep.InstancePolicy.Value, cancellationToken);
             return new NextStepsDto
             {
                 Steps = new List<NextStepOption> { nextStepOption }
@@ -436,7 +437,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         //        .ToList();
         return new NextStepsDto
         {
-            Steps = await CreateConfigStepsAsync(startStep.StepType, firstStepDefines, cancellationToken)
+            Steps = await GetConfigStepsAsync(startStep.StepType, startStep.BusinessType, firstStepDefines, cancellationToken)
         };
         //dto.Steps = steps;
         //return dto;
@@ -463,7 +464,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         if (currentStep.InstanceMode is EInstanceMode.Dynamic && !DynamicShouldTerminal(currentStep))
         {
             //动态生成下一步
-            var nextStepOption = await CreateDynamicStepAsync(currentStep.InstancePolicy.Value, cancellationToken);
+            var nextStepOption = await GetDynamicStepAsync(currentStep.InstancePolicy.Value, cancellationToken);
             dto.Steps = new List<NextStepOption> { nextStepOption };
             return dto;
         }
@@ -482,7 +483,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                         throw new UserFriendlyException(
                             $"未查询到会签开始节点,workflowId: {workflow.Id}, startStepId: {currentStep.CountersignStartStepId}",
                             "未查询到会签开始节点,数据异常");
-                    var countersignEndOption = CreateCsEndStepByPrev(workflow.Steps, startCountersignStep);
+                    var countersignEndOption = GetCsEndStepByPrev(workflow.Steps, startCountersignStep);
 
                     dto.Steps = new List<NextStepOption> { countersignEndOption };
                     return dto;
@@ -491,10 +492,10 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             else
             {
                 //汇总节点
-                var countersignEndOption = CreateCsEndStepByPrev(workflow.Steps, currentStep);
+                var countersignEndOption = GetCsEndStepByPrev(workflow.Steps, currentStep);
                 //按会签策略
                 var nextStepOption =
-                    await CreateDynamicStepAsync(currentStep.CountersignPolicy.Value, cancellationToken);
+                    await GetDynamicStepAsync(currentStep.CountersignPolicy.Value, currentStep.IsOrigin, currentStep.BusinessType, cancellationToken);
                 dto.Steps = new List<NextStepOption> { nextStepOption, countersignEndOption };
                 return dto;
             }
@@ -504,7 +505,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         if (!nextDefines.Any())
             throw new UserFriendlyException("未正确配置下一节点");
 
-        dto.Steps = await CreateConfigStepsAsync(currentStep.StepType, nextDefines, cancellationToken);
+        dto.Steps = await GetConfigStepsAsync(currentStep.StepType, currentStep.BusinessType, nextDefines, cancellationToken);
 
         if (currentStep.IsInCountersign() && currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
         {
@@ -535,10 +536,36 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var stepDefines = workflow.WorkflowDefinition.FindStepDefines(stepCodes);
         return new NextStepsDto
         {
-            Steps = await CreateConfigStepsAsync(null, stepDefines, cancellationToken)
+            Steps = await GetRecallConfigStepsAsync(stepDefines, cancellationToken)
         };
     }
 
+    private async Task<IReadOnlyList<NextStepOption>> GetRecallConfigStepsAsync(List<StepDefine> stepDefines, CancellationToken cancellationToken)
+    {
+        var stepOptions = new List<NextStepOption>();
+        foreach (var stepDefine in stepDefines)
+        {
+            var nextStepOption = await GetConfigStepAsync(stepDefine, cancellationToken);
+            if (stepDefine.StepType is EStepType.End)
+            {
+                stepOptions.Add(nextStepOption);
+                continue;
+            }
+
+            nextStepOption.InputRealHandler = false;
+            //todo thk 派单->坐席, 会签中怎么界定当前节点?
+            nextStepOption.FlowDirection =
+                stepDefine.BusinessType is EBusinessType.Center or EBusinessType.Send
+                    ? EFlowDirection.OrgToCenter
+                    : stepDefine.BusinessType is EBusinessType.Department
+                        ? EFlowDirection.CenterToOrg
+                        : null;
+            stepOptions.Add(nextStepOption);
+        }
+
+        return stepOptions;
+    }
+
     /// <summary>
     /// 查询跳转可选节点
     /// </summary>
@@ -548,7 +575,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             await _workflowDomainService.GetWorkflowAsync(workflowId, true, cancellationToken: cancellationToken);
         return new NextStepsDto
         {
-            Steps = await CreateConfigStepsAsync(null, workflow.WorkflowDefinition.Steps, cancellationToken)
+            //Steps = await GetConfigStepsAsync(null, workflow.WorkflowDefinition.Steps, cancellationToken)
         };
     }
 
@@ -563,7 +590,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var stepDefines = workflow.WorkflowDefinition.FindStepDefines(steps.Select(d => d.Code));
         return new NextStepsDto
         {
-            Steps = await CreateConfigStepsAsync(null, stepDefines, cancellationToken)
+            //Steps = await GetConfigStepsAsync(null, stepDefines, cancellationToken)
         };
     }
 
@@ -580,84 +607,121 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         await _workflowDomainService.RejectAsync(workflow, basicDto, cancellationToken);
     }
 
-    private async Task<List<NextStepOption>> CreateConfigStepsAsync(EStepType? currentStepType,
-        List<StepDefine> stepDefines, CancellationToken cancellationToken)
+    private async Task<List<NextStepOption>> GetConfigStepsAsync(EStepType? currentStepType,
+        EBusinessType? currentBusinessType, List<StepDefine> stepDefines, CancellationToken cancellationToken)
     {
         var stepOptions = new List<NextStepOption>();
         foreach (var stepDefine in stepDefines)
         {
-            var handlers = new List<Kv>();
+            var nextStepOption = await GetConfigStepAsync(stepDefine, cancellationToken);
             if (stepDefine.StepType is EStepType.End)
             {
-                stepOptions.Add(new NextStepOption
-                {
-                    Key = stepDefine.Code,
-                    Value = stepDefine.Name,
-                    Items = handlers
-                });
+                stepOptions.Add(nextStepOption);
                 continue;
             }
 
-            var levelOneOrgCode = _sessionContext.RequiredOrgId.GetHigherOrgCode();
-            switch (stepDefine.HandlerType)
-            {
-                case EHandlerType.AssignedUser:
-                case EHandlerType.AssignedOrg:
-                    handlers = stepDefine.HandlerTypeItems;
-                    break;
-                case EHandlerType.Role:
-                    //当前操作人所属部门的下级部门并且属于配置包含角色
-                    var roles = await _roleRepository.Queryable()
-                        .Includes(
-                            d => d.Accounts.Where(
-                                x => !x.IsDeleted && x.Status == EAccountStatus.Normal).ToList(),
-                            x => x.User)
-                        .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
-                        .ToListAsync(cancellationToken);
-                    var users1 = roles.SelectMany(d => d.Accounts).Select(d => d.User);
-
-                    //解决当前为一级部门选择中心汇总
-                    if (stepDefine.StepType != EStepType.Summary || stepDefine.BusinessType != EBusinessType.Center)
-                        users1 = users1.Where(d => d.OrgId.StartsWith(levelOneOrgCode));
-
-                    handlers = users1.Select(d => new Kv(d.Id, d.Name)).ToList();
-                    break;
-                case EHandlerType.OrgLevel:
-                    //当前操作人所属部门的垂直部门并且属于配置orgLevel的部门
-                    var levels = stepDefine.HandlerTypeItems.Select(d => d.Key).Select(d => int.Parse(d));
-                    var orgs1 = await _organizeRepository.Queryable()
-                        .Where(d => d.IsEnable && levels.Contains(d.Level))
-                        .WhereIF(!levelOneOrgCode.IsCenter(), d => d.Id.StartsWith(levelOneOrgCode))
-                        .ToListAsync(cancellationToken);
-
-                    handlers = orgs1.Select(d => new Kv(d.Id, d.Name)).ToList();
-                    break;
-                case EHandlerType.OrgType:
-                    var types = stepDefine.HandlerTypeItems.Select(d => d.Key)
-                        .Select(d => Enum.Parse<EOrgType>(d));
-                    var orgs2 = await _organizeRepository.Queryable()
-                        .Where(d => d.IsEnable && types.Contains(d.OrgType))
-                        .WhereIF(!levelOneOrgCode.IsCenter(), d => d.Id.StartsWith(levelOneOrgCode))
-                        .ToListAsync(cancellationToken);
+            nextStepOption.InputRealHandler = currentStepType.HasValue &&
+                (currentStepType != EStepType.Summary && stepDefine.StepType == EStepType.Summary);
+            nextStepOption.FlowDirection = currentBusinessType.HasValue
+                ? CheckFlowDirection(currentBusinessType.Value, stepDefine.BusinessType)
+                : null;
+            stepOptions.Add(nextStepOption);
+        }
 
-                    handlers = orgs2.Select(d => new Kv(d.Id, d.Name)).ToList();
-                    break;
-                default:
-                    throw new ArgumentOutOfRangeException();
-            }
+        return stepOptions;
+    }
 
-            stepOptions.Add(new NextStepOption
+    public async Task<NextStepOption> GetConfigStepAsync(StepDefine stepDefine, CancellationToken cancellationToken)
+    {
+        var handlers = new List<Kv>();
+        if (stepDefine.StepType is EStepType.End)
+        {
+            return new NextStepOption
             {
                 Key = stepDefine.Code,
                 Value = stepDefine.Name,
-                InputRealHandler = currentStepType.HasValue &&
-                                   (currentStepType != EStepType.Summary && stepDefine.StepType == EStepType.Summary),
-                BusinessType = stepDefine.BusinessType,
                 Items = handlers
-            });
+            };
         }
 
-        return stepOptions;
+        var levelOneOrgCode = _sessionContext.RequiredOrgId.GetHigherOrgCode();
+        switch (stepDefine.HandlerType)
+        {
+            case EHandlerType.AssignedUser:
+            case EHandlerType.AssignedOrg:
+                handlers = stepDefine.HandlerTypeItems;
+                break;
+            case EHandlerType.Role:
+                //当前操作人所属部门的下级部门并且属于配置包含角色
+                var roles = await _roleRepository.Queryable()
+                    .Includes(
+                        d => d.Accounts.Where(
+                            x => !x.IsDeleted && x.Status == EAccountStatus.Normal).ToList(),
+                        x => x.User)
+                    .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
+                    .ToListAsync(cancellationToken);
+                var users1 = roles.SelectMany(d => d.Accounts).Select(d => d.User);
+
+                //解决当前为一级部门选择中心汇总
+                if (stepDefine.StepType != EStepType.Summary || stepDefine.BusinessType != EBusinessType.Center)
+                    users1 = users1.Where(d => d.OrgId.StartsWith(levelOneOrgCode));
+
+                handlers = users1.Select(d => new Kv(d.Id, d.Name)).ToList();
+                break;
+            case EHandlerType.OrgLevel:
+                //当前操作人所属部门的垂直部门并且属于配置orgLevel的部门
+                var levels = stepDefine.HandlerTypeItems.Select(d => d.Key).Select(d => int.Parse(d));
+                var orgs1 = await _organizeRepository.Queryable()
+                    .Where(d => d.IsEnable && levels.Contains(d.Level))
+                    .WhereIF(!levelOneOrgCode.IsCenter(), d => d.Id.StartsWith(levelOneOrgCode))
+                    .ToListAsync(cancellationToken);
+
+                handlers = orgs1.Select(d => new Kv(d.Id, d.Name)).ToList();
+                break;
+            case EHandlerType.OrgType:
+                var types = stepDefine.HandlerTypeItems.Select(d => d.Key)
+                    .Select(d => Enum.Parse<EOrgType>(d));
+                var orgs2 = await _organizeRepository.Queryable()
+                    .Where(d => d.IsEnable && types.Contains(d.OrgType))
+                    .WhereIF(!levelOneOrgCode.IsCenter(), d => d.Id.StartsWith(levelOneOrgCode))
+                    .ToListAsync(cancellationToken);
+
+                handlers = orgs2.Select(d => new Kv(d.Id, d.Name)).ToList();
+                break;
+            default:
+                throw new ArgumentOutOfRangeException();
+        }
+
+        return new NextStepOption
+        {
+            Key = stepDefine.Code,
+            Value = stepDefine.Name,
+            Items = handlers
+        };
+    }
+
+    private EFlowDirection? CheckFlowDirection(EBusinessType sourceStepBusinessType, EBusinessType directionStepBusinessType)
+    {
+        switch (sourceStepBusinessType)
+        {
+            case EBusinessType.Center:
+            case EBusinessType.Send:
+                return directionStepBusinessType is EBusinessType.Department
+                    ? EFlowDirection.CenterToOrg
+                    : directionStepBusinessType is EBusinessType.File
+                        ? EFlowDirection.CenterToFile
+                        : EFlowDirection.CenterToCenter;
+            case EBusinessType.Department:
+                return directionStepBusinessType is EBusinessType.Center or EBusinessType.Send
+                    ? EFlowDirection.OrgToCenter
+                    : directionStepBusinessType is EBusinessType.Department
+                    ? EFlowDirection.OrgToOrg
+                    : null;
+            case EBusinessType.File:
+                return null;
+            default:
+                throw new ArgumentOutOfRangeException(nameof(sourceStepBusinessType), sourceStepBusinessType, null);
+        }
     }
 
     private bool DynamicShouldTerminal(WorkflowStep step)
@@ -828,7 +892,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     }
 
 
-    private NextStepOption CreateCsEndStepByPrev(List<WorkflowStep> steps, WorkflowStep step)
+    private NextStepOption GetCsEndStepByPrev(List<WorkflowStep> steps, WorkflowStep step)
     {
         var prevStep = steps.FirstOrDefault(d => d.Id == step.PrevStepId);
         if (prevStep is null)
@@ -884,12 +948,12 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         };
     }
 
-    private async Task<NextStepOption> CreateDynamicStepAsync(EDynamicPolicy policy,
-        CancellationToken cancellationToken)
+    private async Task<NextStepOption> GetDynamicStepAsync(EDynamicPolicy policy, bool isOrigin,
+        EBusinessType currentBusinessType, CancellationToken cancellationToken)
     {
         int orgLevel;
         List<Kv> items;
-        EBusinessType businessType;
+        EFlowDirection flowDirection;
         var levelOneOrgCode = _sessionContext.RequiredOrgId.GetHigherOrgCode();
         switch (policy)
         {
@@ -903,7 +967,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                         .Where(d => d.IsCenter)
                         .Select(d => new Kv { Key = d.Id, Value = d.Name })
                         .ToListAsync(cancellationToken);
-                    businessType = EBusinessType.Center;
+                    flowDirection = 
                 }
                 else
                 {
@@ -969,7 +1033,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         };
     }
 
-    //private async Task<IReadOnlyList<NextStepOption>> CreateConfigStepsAsync(List<StepDefine> stepDefines,
+    //private async Task<IReadOnlyList<NextStepOption>> GetConfigStepsAsync(List<StepDefine> stepDefines,
     //    CancellationToken cancellationToken)
     //{
     //    foreach (var stepDefine in stepDefines)

+ 1 - 0
src/Hotline.Application/Handlers/FlowEngine/NextStepHandler.cs

@@ -13,6 +13,7 @@ using Hotline.Settings.TimeLimits;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.Settings;
+using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.Order;
 using Hotline.Share.Enums.Settings;
 using Hotline.Share.Mq;

+ 4 - 1
src/Hotline.Share/Dtos/FlowEngine/NextStepsDto.cs

@@ -30,7 +30,10 @@ public class NextStepOption : Kv
     /// </summary>
     public bool InputRealHandler { get; set; }
 
-    public EBusinessType BusinessType { get; set; }
+    /// <summary>
+    /// 流转方向
+    /// </summary>
+    public EFlowDirection? FlowDirection { get; set; }
 
     public IReadOnlyList<Kv> Items { get; set; }
 }

+ 14 - 0
src/Hotline.Share/Enums/FlowEngine/EFlowDirection.cs

@@ -0,0 +1,14 @@
+namespace Hotline.Share.Enums.FlowEngine;
+
+public enum EFlowDirection
+{
+    CenterToOrg = 0,
+
+    OrgToCenter = 1,
+
+    CenterToCenter = 2,
+
+    OrgToOrg = 3,
+
+    CenterToFile = 4,
+}

+ 0 - 18
src/Hotline/FlowEngine/EFlowDirection.cs

@@ -1,18 +0,0 @@
-namespace Hotline.FlowEngine;
-
-public enum EFlowDirection
-{
-    /// <summary>
-    /// 中心流转至部门
-    /// </summary>
-    CenterToOrg = 0,
-
-    /// <summary>
-    /// 部门流转至中心
-    /// </summary>
-    OrgToCenter = 1,
-
-    CenterToCenter = 2,
-
-    OrgToOrg = 3,
-}

+ 1 - 0
src/Hotline/FlowEngine/Notifications/WorkflowNotify.cs

@@ -1,6 +1,7 @@
 using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Share.Dtos.FlowEngine;
+using Hotline.Share.Enums.FlowEngine;
 using MediatR;
 
 namespace Hotline.FlowEngine.Notifications;