xf 2 жил өмнө
parent
commit
949950cdda

+ 2 - 1
src/Hotline.Application/FlowEngine/IWorkflowApplication.cs

@@ -27,6 +27,7 @@ namespace Hotline.Application.FlowEngine
         /// <summary>
         /// 查询指派办理人的处理方式及实际办理人
         /// </summary>
-        Task<FlowAssignMode> GetFlowAssignModeAsync(StepDefine StepDefine, List<string> Handlers, CancellationToken cancellationToken);
+        Task<FlowAssignMode> GetFlowAssignModeAsync(StepDefine stepDefine, List<IdName> handlers,
+            CancellationToken cancellationToken);
     }
 }

+ 27 - 10
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -69,8 +69,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var nextStepBoxDefine = _workflowDomainService.GetStepBoxDefine(definition, dto.NextStepCode);
         var workflow = await _workflowDomainService.CreateWorkflowAsync(definition, dto.Title, externalId, cancellationToken);
 
-        var flowAssignMode = await GetFlowAssignModeAsync(nextStepBoxDefine,
-            dto.NextHandlers.Select(d => d.Id).ToList(), cancellationToken);
+        var flowAssignMode = await GetFlowAssignModeAsync(nextStepBoxDefine, dto.NextHandlers, cancellationToken);
 
         await _workflowDomainService.StartAsync(workflow, dto, nextStepBoxDefine, flowAssignMode, cancellationToken);
 
@@ -101,8 +100,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         //if (isStartCountersign && nextStepBoxDefine.StepType is EStepType.CountersignEnd)
         //    throw UserFriendlyException.SameMessage("汇总节点不允许发起会签");
 
-        var flowAssignMode = await GetFlowAssignModeAsync(nextStepBoxDefine,
-            dto.NextHandlers.Select(d => d.Id).ToList(), cancellationToken);
+        var flowAssignMode = await GetFlowAssignModeAsync(nextStepBoxDefine, dto.NextHandlers, cancellationToken);
 
         await _workflowDomainService.NextAsync(workflow, dto, nextStepBoxDefine, isOutOfCallCenter, flowAssignMode, cancellationToken);
 
@@ -136,27 +134,46 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// <summary>
     /// 查询指派办理人的处理方式及实际办理人
     /// </summary>
-    public async Task<FlowAssignMode> GetFlowAssignModeAsync(StepDefine stepDefine, List<string> handlers, CancellationToken cancellationToken)
+    public async Task<FlowAssignMode> GetFlowAssignModeAsync(StepDefine stepDefine, List<IdName> handlers, CancellationToken cancellationToken)
     {
+        if (stepDefine.StepType is EStepType.Start or EStepType.End) return default;
         switch (stepDefine.HandlerType)
         {
             case EHandlerType.Role:
                 if (!handlers.Any())
                 {
                     var roles = await _roleRepository.Queryable()
-                        .Includes(d => d.Accounts)
+                        .Includes(d => d.Accounts, x => x.User)
                         .Where(d => stepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.Name))
                         .ToListAsync();
-                    handlers = roles.SelectMany(d => d.Accounts).Select(d => d.Id).Distinct().ToList();
+                    handlers = roles.SelectMany(d => d.Accounts).Distinct().Select(d => new IdName(d.Id, d.User.Name)).ToList();
                 }
 
-                return new FlowAssignMode(EFlowAssignType.User, handlers);
+                return new FlowAssignMode(EFlowAssignType.User, new HandlerObjects
+                {
+                    UserGroups = new List<HandlerUserGroup>
+                    {
+                        new HandlerUserGroup{ HandlerUsers = handlers }
+                    }
+                });
             case EHandlerType.OrgLevel:
             case EHandlerType.OrgType:
             case EHandlerType.AssignOrg:
-                return new FlowAssignMode(EFlowAssignType.Org, handlers);
+                return new FlowAssignMode(EFlowAssignType.Org, new HandlerObjects
+                {
+                    OrgGroups = new List<HandlerOrgGroup>
+                    {
+                        new HandlerOrgGroup{ HandlerOrgs = handlers }
+                    }
+                });
             case EHandlerType.AssignUser:
-                return new FlowAssignMode(EFlowAssignType.User, handlers);
+                return new FlowAssignMode(EFlowAssignType.User, new HandlerObjects
+                {
+                    UserGroups = new List<HandlerUserGroup>
+                    {
+                        new HandlerUserGroup{ HandlerUsers = handlers }
+                    }
+                });
             default:
                 throw new ArgumentOutOfRangeException();
         }

+ 11 - 0
src/Hotline.Share/Dtos/FlowEngine/IdName.cs

@@ -2,6 +2,17 @@
 
 public class IdName
 {
+    public IdName()
+    {
+
+    }
+
+    public IdName(string id, string name)
+    {
+        Id = id;
+        Name = name;
+    }
+
     public string Id { get; set; }
     public string Name { get; set; }
 }

+ 1 - 1
src/Hotline/CallCenter/Tels/TelDomainService.cs

@@ -61,7 +61,7 @@ public class TelDomainService : ITelDomainService, IScopeDependency
         if (telRest == null)
             throw new UserFriendlyException($"无效分机休息编号, telRestId: {telRestId}", "无效分机休息编号");
         telRest.WorkflowId = workflowId;
-        telRest.Assign(assignMode.FlowAssignType, assignMode.Handlers);
+        telRest.Assign(assignMode.FlowAssignType, assignMode.GetHandlers());
         await _telRestRepository.UpdateAsync(telRest, cancellationToken);
     }
 

+ 28 - 4
src/Hotline/FlowEngine/FlowAssignMode.cs

@@ -1,13 +1,15 @@
-using XF.Domain.Entities;
+using Hotline.FlowEngine.Workflows;
+using Hotline.Share.Dtos.FlowEngine;
+using XF.Domain.Entities;
 
 namespace Hotline.FlowEngine;
 
 public class FlowAssignMode
 {
-    public FlowAssignMode(EFlowAssignType flowAssignType, List<string> handlers)
+    public FlowAssignMode(EFlowAssignType flowAssignType, HandlerObjects handlerObjects)
     {
         FlowAssignType = flowAssignType;
-        Handlers = handlers;
+        HandlerObjects = handlerObjects;
     }
 
     /// <summary>
@@ -15,8 +17,30 @@ public class FlowAssignMode
     /// </summary>
     public EFlowAssignType FlowAssignType { get; set; }
 
+    ///// <summary>
+    ///// 办理人/办理部门(UserIds/OrgCodes)
+    ///// </summary>
+    //public List<IdName> Handlers { get; set; }
+
+    /// <summary>
+    /// 办理对象
+    /// </summary>
+    public HandlerObjects HandlerObjects { get; set; }
+
     /// <summary>
     /// 办理人/办理部门(UserIds/OrgCodes)
     /// </summary>
-    public List<string> Handlers { get; set; }
+    /// <returns></returns>
+    public List<string> GetHandlers()
+    {
+        switch (FlowAssignType)
+        {
+            case EFlowAssignType.Org:
+                return HandlerObjects.OrgGroups.SelectMany(d => d.HandlerOrgs.Select(x => x.Id)).ToList();
+            case EFlowAssignType.User:
+                return HandlerObjects.UserGroups.SelectMany(d => d.HandlerUsers.Select(x => x.Id)).ToList();
+            default:
+                throw new ArgumentOutOfRangeException();
+        }
+    }
 }

+ 62 - 9
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -1,7 +1,9 @@
 using Hotline.FlowEngine.Definitions;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Enums.FlowEngine;
 using SqlSugar;
 using XF.Domain.Entities;
+using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 
 namespace Hotline.FlowEngine.Workflows;
@@ -87,6 +89,12 @@ public class Workflow : CreationEntity
     [SugarColumn(ColumnDataType = "json", IsJson = true)]
     public List<string> HandlerOrgs { get; set; } = new();
 
+    /// <summary>
+    /// 当前办理对象
+    /// </summary>
+    [SugarColumn(ColumnDataType = "json", IsJson = true)]
+    public HandlerObjects CurrentHandlers { get; set; } = new();
+
     /// <summary>
     /// 外部业务唯一标识
     /// </summary>
@@ -123,7 +131,7 @@ public class Workflow : CreationEntity
     [SugarColumn(IsIgnore = true)]
     public List<WorkflowTrace> Traces { get; set; } = new();
 
-    #region Mehod
+    #region Method
 
     /// <summary>
     /// 流程结束
@@ -204,31 +212,76 @@ public class Workflow : CreationEntity
     /// <summary>
     /// 更新当前办理人(代办人或部门)
     /// </summary>
-    public void UpdateHandlers(string handlerId, string handlerOrg, EFlowAssignType assignType, IEnumerable<string> handlers)
+    public void UpdateHandlers(string handlerId, string handlerOrg, EFlowAssignType assignType, HandlerObjects handlerObjects)
     {
-        HandlerUsers.Remove(handlerId);
-        HandlerOrgs.Remove(handlerOrg);
+        RemoveCurrentHandleGroup(handlerId, handlerOrg);
+
         switch (assignType)
         {
             case EFlowAssignType.Org:
-                HandlerOrgs.AddRange(handlers);
-                HandlerOrgs = HandlerOrgs.Distinct().ToList();
+                if (handlerObjects?.OrgGroups == null || !handlerObjects.OrgGroups.Any())
+                    throw new UserFriendlyException("未指派办理人");
+                CurrentHandlers.OrgGroups.AddRange(handlerObjects.OrgGroups);
+                CurrentHandlers.OrgGroups = CurrentHandlers.OrgGroups.Distinct().ToList();
                 break;
             case EFlowAssignType.User:
-                HandlerUsers.AddRange(handlers);
-                HandlerUsers = HandlerUsers.Distinct().ToList();
+                if (CurrentHandlers?.UserGroups == null || !CurrentHandlers.UserGroups.Any())
+                    throw new UserFriendlyException("未指派办理部门");
+                CurrentHandlers.UserGroups.AddRange(handlerObjects.UserGroups);
+                CurrentHandlers.UserGroups = CurrentHandlers.UserGroups.Distinct().ToList();
                 break;
             default:
                 throw new ArgumentOutOfRangeException(nameof(assignType), assignType, null);
         }
     }
 
+    private void RemoveCurrentHandleGroup(string handlerId, string handlerOrg)
+    {
+        if ((CurrentHandlers?.UserGroups == null || !CurrentHandlers.UserGroups.Any())
+           && (CurrentHandlers?.OrgGroups == null || !CurrentHandlers.OrgGroups.Any()))
+            return;
+        CurrentHandlers.UserGroups.RemoveAll(d => d.HandlerUsers.Any(x => x.Id == handlerId));
+        CurrentHandlers.OrgGroups.RemoveAll(d => d.HandlerOrgs.Any(x => x.Id == handlerOrg));
+    }
+
     /// <summary>
     /// 当前用户是否可以办理该流程
     /// </summary>
     /// <returns></returns>
     public bool CanHandle(string userId, string orgCode) =>
-        HandlerUsers.Contains(userId) || HandlerOrgs.Contains(orgCode);
+        Status is EWorkflowStatus.Runnable
+        && (HandlerUsers.Contains(userId) || HandlerOrgs.Contains(orgCode));
 
     #endregion
+}
+
+/// <summary>
+/// 办理对象
+/// </summary>
+public class HandlerObjects
+{
+    public List<HandlerUserGroup> UserGroups { get; set; }
+    public List<HandlerOrgGroup> OrgGroups { get; set; }
+}
+
+/// <summary>
+/// 办理用户分组
+/// </summary>
+public class HandlerUserGroup
+{
+    /// <summary>
+    /// 用户id,name
+    /// </summary>
+    public List<IdName> HandlerUsers { get; set; }
+}
+
+/// <summary>
+/// 办理部门分组
+/// </summary>
+public class HandlerOrgGroup
+{
+    /// <summary>
+    /// 部门code,name
+    /// </summary>
+    public List<IdName> HandlerOrgs { get; set; }
 }

+ 2 - 2
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -121,7 +121,7 @@ namespace Hotline.FlowEngine.Workflows
             workflow.SetWorkflowCurrentStepInfo(isStartCountersign, nextStepBox);
 
             workflow.UpdateHandlers(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgCode,
-            flowAssignMode.FlowAssignType, flowAssignMode.Handlers);
+            flowAssignMode.FlowAssignType, flowAssignMode.HandlerObjects);
 
             await _workflowRepository.UpdateAsync(workflow, cancellationToken);
 
@@ -394,7 +394,7 @@ namespace Hotline.FlowEngine.Workflows
             workflow.SetWorkflowCurrentStepInfo(isStartCountersign, nextStepBox);
 
             workflow.UpdateHandlers(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgCode,
-                flowAssignMode.FlowAssignType, flowAssignMode.Handlers);
+                flowAssignMode.FlowAssignType, flowAssignMode.HandlerObjects);
 
             await _workflowRepository.UpdateAsync(workflow, cancellationToken);
 

+ 2 - 2
src/Hotline/KnowledgeBase/KnowledgeDomainService.cs

@@ -107,7 +107,7 @@ namespace Hotline.KnowledgeBase
             if (knowledgeFlow == null)
                 throw new UserFriendlyException($"无效知识编号, knowledgeFlowId: {knowledgeFlowId}", "无效知识编号");
             knowledgeFlow.WorkflowId = workFlowId;
-            knowledgeFlow.Assign(assignMode.FlowAssignType, assignMode.Handlers);
+            knowledgeFlow.Assign(assignMode.FlowAssignType, assignMode.GetHandlers());
             await _knowledgeWorkFlowRepository.UpdateAsync(knowledgeFlow, cancellationToken);
 
             if (knowledgeFlow.WorkflowModuleStatus != EKnowledgeApplyType.Delete)
@@ -117,7 +117,7 @@ namespace Hotline.KnowledgeBase
                     throw new UserFriendlyException($"无效知识编号, knowledgeId: {knowledgeFlow.KnowledgeId}", "无效知识编号");
                 knowledge.WorkflowId = workFlowId;
                 knowledge.Status = EKnowledgeStatus.Auditing;
-                knowledge.Assign(assignMode.FlowAssignType, assignMode.Handlers);
+                knowledge.Assign(assignMode.FlowAssignType, assignMode.GetHandlers());
                 await _knowledgeRepository.UpdateAsync(knowledge, cancellationToken);
             }
         }

+ 2 - 2
src/Hotline/Orders/OrderDomainService.cs

@@ -79,7 +79,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         order.WorkflowId = workflowId;
 
         //更新指派信息
-        order.Assign(assignMode.FlowAssignType, assignMode.Handlers);
+        order.Assign(assignMode.FlowAssignType, assignMode.GetHandlers());
 
         //更新流转信息
         order.ManageFlow(isCountersignStart, false, currentStepTime, currentStepName, expiredTime);
@@ -99,7 +99,7 @@ public class OrderDomainService : IOrderDomainService, IScopeDependency
         CheckOrderIfFiled(order);
 
         //更新指派信息
-        order.Assign(assignMode.FlowAssignType, assignMode.Handlers);
+        order.Assign(assignMode.FlowAssignType, assignMode.GetHandlers());
 
         //更新流转信息
         order.ManageFlow(isCountersignStart, isCountersignEnd, currentStepTime, currentStepName, expiredTime);