xf 2 жил өмнө
parent
commit
d6f8a62f6e

+ 30 - 9
src/Hotline.Api/Controllers/WorkflowController.cs

@@ -30,6 +30,7 @@ public class WorkflowController : BaseController
     private readonly IUserRepository _userRepository;
     private readonly ISystemOrganizeRepository _organizeRepository;
     private readonly IRoleRepository _roleRepository;
+    private readonly ISystemDomainService _systemDomainService;
     private readonly ISessionContext _sessionContext;
     private readonly IMapper _mapper;
 
@@ -41,6 +42,7 @@ public class WorkflowController : BaseController
         IUserRepository userRepository,
         ISystemOrganizeRepository organizeRepository,
         IRoleRepository roleRepository,
+        ISystemDomainService systemDomainService,
         ISessionContext sessionContext,
         IMapper mapper)
     {
@@ -51,6 +53,7 @@ public class WorkflowController : BaseController
         _userRepository = userRepository;
         _organizeRepository = organizeRepository;
         _roleRepository = roleRepository;
+        _systemDomainService = systemDomainService;
         _sessionContext = sessionContext;
         _mapper = mapper;
     }
@@ -250,16 +253,16 @@ public class WorkflowController : BaseController
             switch (nextStepDefine.HandlerType)
             {
                 case EHandlerType.AssignUser:
-                    var users = await _userRepository.QueryAsync(d => nextStepDefine.HandlerClassifies.Select(d=>d.Id).Contains(d.Id));
+                    var users = await _userRepository.QueryAsync(d => nextStepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.Id));
                     options.NextSteps = users.Select(d => new KeyValuePair<string, string>(d.Id, d.Name)).ToList();
                     break;
                 case EHandlerType.AssignOrg:
-                    var orgs = await _organizeRepository.QueryAsync(d => nextStepDefine.HandlerClassifies.Select(d=>d.Id).Contains(d.OrgCode));
+                    var orgs = await _organizeRepository.QueryAsync(d => nextStepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.OrgCode));
                     options.NextSteps = orgs.Select(d => new KeyValuePair<string, string>(d.OrgCode, d.OrgName)).ToList();
                     break;
                 case EHandlerType.Role:
                     var roles = await _roleRepository.Queryable().Includes(d => d.Accounts, d => d.User)
-                        .Where(d => nextStepDefine.HandlerClassifies.Select(d=>d.Id).Contains(d.Name)).ToListAsync();
+                        .Where(d => nextStepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.Name)).ToListAsync();
                     var users1 = roles.SelectMany(d => d.Accounts).Select(d => d.User);
                     if (nextStepDefine.OnlySelfOrg ?? false)
                         users1 = users1.Where(d => d.OrgCode == _sessionContext.RequiredOrgCode);
@@ -267,14 +270,14 @@ public class WorkflowController : BaseController
                     break;
                 case EHandlerType.OrgLevel:
                     //当前操作人所属部门的下级部门并且属于配置orgLevel的部门
-                    var levels = nextStepDefine.HandlerClassifies.Select(d=>d.Id).Select(d => int.Parse(d));
+                    var levels = nextStepDefine.HandlerClassifies.Select(d => d.Id).Select(d => int.Parse(d));
                     var orgs1 = await _organizeRepository.QueryAsync(d =>
                         d.IsEnable && d.OrgCode.StartsWith(_sessionContext.RequiredOrgCode) &&
                         levels.Contains(d.OrgLevel));
                     options.NextSteps = orgs1.Select(d => new KeyValuePair<string, string>(d.OrgCode, d.OrgName)).ToList();
                     break;
                 case EHandlerType.OrgType:
-                    var types = nextStepDefine.HandlerClassifies.Select(d=>d.Id).Select(d => Enum.Parse<EOrgType>(d));
+                    var types = nextStepDefine.HandlerClassifies.Select(d => d.Id).Select(d => Enum.Parse<EOrgType>(d));
                     var org2 = await _organizeRepository.QueryAsync(d =>
                         d.IsEnable && d.OrgCode.StartsWith(_sessionContext.RequiredOrgCode) &&
                         types.Contains(d.OrgType));
@@ -338,6 +341,25 @@ public class WorkflowController : BaseController
         return _mapper.Map<IReadOnlyList<StepDefineDto>>(workflow.StepBoxes);
     }
 
+    /// <summary>
+    /// 查询业务流程是否已经启用模板
+    /// </summary>
+    /// <param name="moduleCode"></param>
+    /// <returns>T:已有启用模板,F:无启用模板</returns>
+    [HttpGet("has-define")]
+    public async Task<bool> IsModuleDefined(string moduleCode)
+    {
+        var define = await _definitionRepository.GetAsync(d => d.ModuleCode == moduleCode && d.Status == EDefinitionStatus.Enable,
+            HttpContext.RequestAborted);
+        return define != null;
+    }
+
+    /// <summary>
+    /// 查询办理类型参数
+    /// </summary>
+    /// <param name="handlerType"></param>
+    /// <returns></returns>
+    /// <exception cref="ArgumentOutOfRangeException"></exception>
     [HttpGet("handlerclassify")]
     public async Task<List<KeyValuePair<string, string>>> GetHanlderClassifies(EHandlerType handlerType)
     {
@@ -347,11 +369,10 @@ public class WorkflowController : BaseController
                 var roles = await _roleRepository.QueryAsync();
                 return roles.Select(d => new KeyValuePair<string, string>(d.Name, d.DisplayName)).ToList();
             case EHandlerType.OrgLevel:
-                //todo 一级部门、二级部门...
-                return new();
+                var orgs1 = await _systemDomainService.QueryOrgLevelStringOptionsAsync(HttpContext.RequestAborted);
+                return orgs1.ToList();
             case EHandlerType.OrgType:
-                //todo
-                return new();
+                return EnumExts.GetDescriptions<EOrgType>().Select(d => new KeyValuePair<string, string>(d.Key.ToString(), d.Value)).ToList();
             case EHandlerType.AssignOrg:
                 var orgs = await _organizeRepository.GetOrgJson();
                 return orgs.Select(d => new KeyValuePair<string, string>(d.OrgCode, d.OrgName)).ToList();

+ 58 - 33
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -19,6 +19,8 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     private readonly IWorkflowDomainService _workflowDomainService;
     private readonly IWorkflowRepository _workflowRepository;
     private readonly IWorkflowAssignRepository _workflowAssignRepository;
+    private readonly IUserRepository _userRepository;
+    private readonly IAccountRepository _accountRepository;
     private readonly IUserDomainService _userDomainService;
     private readonly IAccountDomainService _accountDomainService;
     private readonly ISessionContext _sessionContext;
@@ -28,16 +30,16 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         IWorkflowDomainService workflowDomainService,
         IWorkflowRepository workflowRepository,
         IWorkflowAssignRepository workflowAssignRepository,
-        IUserDomainService userDomainService,
-        IAccountDomainService accountDomainService,
+        IUserRepository userRepository,
+        IAccountRepository accountRepository,
         ISessionContext sessionContext)
     {
         _definitionDomainService = definitionDomainService;
         _workflowDomainService = workflowDomainService;
         _workflowRepository = workflowRepository;
         _workflowAssignRepository = workflowAssignRepository;
-        _userDomainService = userDomainService;
-        _accountDomainService = accountDomainService;
+        _userRepository = userRepository;
+        _accountRepository = accountRepository;
         _sessionContext = sessionContext;
     }
 
@@ -55,22 +57,56 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         await _workflowDomainService.StartAsync(workflow, dto, nextStepBoxDefine, cancellationToken);
 
         //更新接办部门(详情页面展示)
+        await AddOrUpdateAssignAsync(workflow, dto, nextStepBoxDefine, cancellationToken);
+
+        return workflow.Id;
+    }
+
+    /// <summary>
+    /// 流转至下一节点(节点办理)
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <param name="cancellationToken"></param>
+    /// <returns></returns>
+    public async Task NextAsync(NextWorkflowDto dto, CancellationToken cancellationToken)
+    {
+        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true, cancellationToken: cancellationToken);
+        var nextStepBoxDefine = _workflowDomainService.GetStepBoxDefine(workflow.Definition, dto.NextStepCode);
+        var isOutOfCallCenter =
+            await CheckIfFlowOutOfCallCenterAsync(nextStepBoxDefine, dto.NextMainHandler, cancellationToken);
+        var isStartCountersign = nextStepBoxDefine.IsStartCountersign(dto.Handlers.Count);
+        await _workflowDomainService.NextAsync(workflow, dto, nextStepBoxDefine, isOutOfCallCenter, isStartCountersign, cancellationToken);
+
+        //更新接办部门(详情页面展示)
+        await AddOrUpdateAssignAsync(workflow, dto, nextStepBoxDefine, cancellationToken);
+    }
+
+    #region private
+
+    /// <summary>
+    /// 更新接办部门
+    /// </summary>
+    private async Task AddOrUpdateAssignAsync(Workflow workflow, BasicWorkflowDto dto, StepDefine nextStepBoxDefine, CancellationToken cancellationToken)
+    {
         if (nextStepBoxDefine.StepType is EStepType.Normal)
         {
             await _workflowAssignRepository.RemoveAsync(d =>
-                d.WorkflowId == workflow.Id && d.OrgCode == _sessionContext.RequiredOrgCode, cancellationToken: cancellationToken);
+                    d.WorkflowId == workflow.Id && d.OrgCode == _sessionContext.RequiredOrgCode,
+                cancellationToken: cancellationToken);
 
             var assigns = new List<WorkflowAssign>();
             switch (nextStepBoxDefine.HandlerType)
             {
                 case EHandlerType.Role:
-                    //todo 1.选了handler,handler为userId 2.未选:如果配置为本部门办理,则为当前办理人orgCode, 非本部门办理??
                     if (dto.Handlers.Any())
                     {
                         //选了handler,handler为userId 
-                        var users1 = await _userDomainService.QueryWithOrgsAsync(dto.Handlers.Select(d => d.Id),
-                            cancellationToken);
-                        assigns = users1.Select(d => WorkflowAssign.Create(workflow.Id, d.OrgCode, d.Organization.OrgName)).ToList();
+                        var users1 = await _userRepository.Queryable()
+                            .Includes(d => d.Organization)
+                            .Where(d => dto.Handlers.Select(d => d.Id).Contains(d.Id))
+                            .ToListAsync();
+                        assigns = users1.Select(d => WorkflowAssign.Create(workflow.Id, d.OrgCode, d.Organization.OrgName))
+                            .ToList();
                     }
                     else
                     {
@@ -84,9 +120,15 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                         }
                         else
                         {
-                            
+                            var accounts = await _accountRepository.Queryable()
+                                .Includes(d => d.User, d => d.Organization)
+                                .Where(d => dto.Handlers.Select(d => d.Id).Contains(d.Name))
+                                .ToListAsync();
+                            assigns = accounts.Select(d => d.User.Organization).Select(d =>
+                                WorkflowAssign.Create(workflow.Id, d.OrgCode, d.OrgName)).ToList();
                         }
                     }
+
                     break;
 
                 case EHandlerType.OrgLevel:
@@ -97,39 +139,22 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
 
                 case EHandlerType.AssignUser:
                     //指定人所属部门
-                    var users = await _userDomainService.QueryWithOrgsAsync(dto.Handlers.Select(d => d.Id),
-                        cancellationToken);
+                    var users = await _userRepository.Queryable()
+                        .Includes(d => d.Organization)
+                        .Where(d => dto.Handlers.Select(d => d.Id).Contains(d.Id))
+                        .ToListAsync();
                     assigns = users.Select(d => WorkflowAssign.Create(workflow.Id, d.OrgCode, d.Organization.OrgName))
                         .ToList();
                     break;
                 default:
                     throw new ArgumentOutOfRangeException();
             }
+
             if (assigns.Any())
                 await _workflowAssignRepository.AddRangeAsync(assigns, cancellationToken);
         }
-
-        return workflow.Id;
-    }
-
-    /// <summary>
-    /// 流转至下一节点(节点办理)
-    /// </summary>
-    /// <param name="dto"></param>
-    /// <param name="cancellationToken"></param>
-    /// <returns></returns>
-    public async Task NextAsync(NextWorkflowDto dto, CancellationToken cancellationToken)
-    {
-        var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true, cancellationToken: cancellationToken);
-        var nextStepBoxDefine = _workflowDomainService.GetStepBoxDefine(workflow.Definition, dto.NextStepCode);
-        var isOutOfCallCenter =
-            await CheckIfFlowOutOfCallCenterAsync(nextStepBoxDefine, dto.NextMainHandler, cancellationToken);
-        var isStartCountersign = nextStepBoxDefine.IsStartCountersign(dto.Handlers.Count);
-        await _workflowDomainService.NextAsync(workflow, dto, nextStepBoxDefine, isOutOfCallCenter, isStartCountersign, cancellationToken);
     }
 
-    #region private
-
     private async Task<bool> CheckIfFlowOutOfCallCenterAsync(StepDefine nextStepBoxDefine, string mainHandler, CancellationToken CancellationToken)
     {
         //current is center & next is not center return true
@@ -145,7 +170,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         if (nextStepBoxDefine.HandlerType is EHandlerType.AssignUser or EHandlerType.Role)
         {
             //mainHandler is userId
-            var handler = await _userDomainService.GetUserAsync(mainHandler, cancellationToken);
+            var handler = await _userRepository.GetAsync(mainHandler, cancellationToken);
             if (handler == null)
                 throw new UserFriendlyException($"mainHandler未找到对应User, handler: {mainHandler}");
             if (string.IsNullOrEmpty(handler.OrgCode))

+ 8 - 3
src/Hotline/FlowEngine/Definitions/DefinitionDomainService.cs

@@ -32,6 +32,11 @@ public class DefinitionDomainService : IDefinitionDomainService, IScopeDependenc
     public async Task PublishAsync(string id, CancellationToken cancellationToken)
     {
         var definitionTemp = await _definitionRepository.GetAsync(id, cancellationToken);
+        if (definitionTemp == null)
+            throw UserFriendlyException.SameMessage("无效模板编号");
+        if(definitionTemp.Status != EDefinitionStatus.Temporary)
+            throw UserFriendlyException.SameMessage("非草稿模板不允许发布");
+
         ValidateDefinition(definitionTemp);
 
         var lastVersion = await GetLastVersionAsync(definitionTemp!.Code, cancellationToken);
@@ -93,19 +98,19 @@ public class DefinitionDomainService : IDefinitionDomainService, IScopeDependenc
         var startSteps = definition.Steps.Where(d => d.StepType == EStepType.Start).ToList();
         if (!startSteps.Any())
             throw UserFriendlyException.SameMessage("未配置开始节点");
-        if (startSteps.Count() > 1)
+        if (startSteps.Count > 1)
             throw UserFriendlyException.SameMessage("开始节点只能有一个");
 
         var endSteps = definition.Steps.Where(d => d.StepType == EStepType.End).ToList();
         if (!endSteps.Any())
             throw UserFriendlyException.SameMessage("未配置结束节点");
-        if (endSteps.Count() > 1)
+        if (endSteps.Count > 1)
             throw UserFriendlyException.SameMessage("结束节点只能有一个");
 
         foreach (var step in definition.Steps)
         {
             if (step.StepType != EStepType.End && !step.NextSteps.Any())
-                throw UserFriendlyException.SameMessage("其中有节点未配置下一节点");
+                throw UserFriendlyException.SameMessage($"{step.Code}节点未配置下一节点");
         }
 
         if (definition.Steps.GroupBy(d => d.Code).Count() < definition.Steps.Count)

+ 0 - 15
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -127,15 +127,6 @@ namespace Hotline.FlowEngine.Workflows
             _mediator.Publish(new StartWorkflowNotify(workflow, assignMode.assignType, assignMode.handlers, dto), cancellationToken);
         }
 
-        /// <summary>
-        /// 新增或更新接办部门信息
-        /// </summary>
-        /// <returns></returns>
-        private async Task AddOrUpdateAssignAsync()
-        {
-
-        }
-
         public async Task<Workflow> GetWorkflowAsync(string workflowId,
             bool withDefine = false, bool withSteps = false,
             bool withTraces = false, bool withSupplements = false,
@@ -281,12 +272,6 @@ namespace Hotline.FlowEngine.Workflows
                 workflow.AssignTime = DateTime.Now;
             }
 
-            //更新当前接办部门
-            if (nextStepBoxDefine.StepType is EStepType.Normal)
-            {
-
-            }
-
             //创建下一节点
             var nextStepBox = await CreateStepAsync(workflow, nextStepBoxDefine, dto, currentStepBox, currentStep, cancellationToken);
 

+ 0 - 3
src/Hotline/Identity/Accounts/IAccountDomainService.cs

@@ -19,8 +19,5 @@ namespace Hotline.Identity.Accounts
         bool IsLockedOut(Account account);
         Task LockOutAsync(Account account, DateTime? lockoutEnd = null, CancellationToken cancellationToken = default);
         Task UnRegisterAsync(Account account, CancellationToken cancellationToken);
-
-        //todo
-        //Task<List<Account>>
     }
 }

+ 19 - 0
src/Hotline/Settings/ISystemDomainService.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Settings
+{
+    public interface ISystemDomainService
+    {
+        /// <summary>
+        /// 查询当前已有数据的部门等级参数
+        /// </summary>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
+        Task<IEnumerable<KeyValuePair<int, string>>> QueryOrgLevelOptionsAsync(CancellationToken cancellationToken);
+        Task<IEnumerable<KeyValuePair<string, string>>> QueryOrgLevelStringOptionsAsync(CancellationToken cancellationToken);
+    }
+}

+ 33 - 0
src/Hotline/Settings/SystemDomainService.cs

@@ -0,0 +1,33 @@
+using XF.Domain.Dependency;
+
+namespace Hotline.Settings;
+
+public class SystemDomainService : ISystemDomainService, IScopeDependency
+{
+    private readonly ISystemOrganizeRepository _organizeRepository;
+
+    public SystemDomainService(ISystemOrganizeRepository organizeRepository)
+    {
+        _organizeRepository = organizeRepository;
+    }
+
+    public async Task<IEnumerable<KeyValuePair<int, string>>> QueryOrgLevelOptionsAsync(CancellationToken cancellationToken)
+    {
+        var max = await _organizeRepository.Queryable()
+            .MaxAsync(d => d.OrgLevel);
+
+        var rsp = new List<KeyValuePair<int, string>>();
+        for (int i = 1; i <= max; i++)
+        {
+            rsp.Add(new KeyValuePair<int, string>(i, $"{i}级部门"));
+        }
+
+        return rsp;
+    }
+
+    public async Task<IEnumerable<KeyValuePair<string, string>>> QueryOrgLevelStringOptionsAsync(CancellationToken cancellationToken)
+    {
+        var rsp = await QueryOrgLevelOptionsAsync(cancellationToken);
+        return rsp.Select(d => new KeyValuePair<string, string>(d.Key.ToString(), d.Value));
+    }
+}

+ 0 - 10
src/Hotline/Users/IUserDomainService.cs

@@ -21,15 +21,5 @@ namespace Hotline.Users
         /// <param name="cancellationToken"></param>
         /// <returns></returns>
         Task<WorkDto?> OffDutyAsync(string userId, CancellationToken cancellationToken);
-
-        Task<User?> GetUserAsync(string userId, CancellationToken cancellationToken);
-
-        /// <summary>
-        /// 查询用户包含部门信息
-        /// </summary>
-        /// <param name="userIds"></param>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
-        Task<IReadOnlyList<User>> QueryWithOrgsAsync(IEnumerable<string> userIds, CancellationToken cancellationToken);
     }
 }

+ 2 - 16
src/Hotline/Users/UserDomainService.cs

@@ -67,10 +67,10 @@ namespace Hotline.Users
             //更新分机组
             foreach (var group in tel.Groups)
             {
-                await _deviceManager.ModifyGroupExtAsync(group.No,tel.No,group.Voice,true, cancellationToken);
+                await _deviceManager.ModifyGroupExtAsync(group.No, tel.No, group.Voice, true, cancellationToken);
             }
 
-            
+
         }
 
 
@@ -98,19 +98,5 @@ namespace Hotline.Users
             #endregion
             return _mapper.Map<WorkDto>(work);
         }
-
-        public async Task<User?> GetUserAsync(string userId, CancellationToken cancellationToken)
-            => await _userRepository.GetAsync(userId, cancellationToken);
-
-        /// <summary>
-        /// 查询用户包含部门信息
-        /// </summary>
-        /// <param name="userIds"></param>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
-        public async Task<IReadOnlyList<User>> QueryWithOrgsAsync(IEnumerable<string> userIds, CancellationToken cancellationToken)
-        {
-            throw new NotImplementedException();
-        }
     }
 }