Parcourir la source

Merge branch 'master' of http://git.fwt.com/Hotline/hotline

TANG JIANG il y a 2 ans
Parent
commit
23586f09f2

+ 1 - 1
src/Hotline.Api/Controllers/OrderController.cs

@@ -133,7 +133,7 @@ public class OrderController : BaseController
             order.Workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId, withSteps: true, withSupplements: true, withAssigns: true, cancellationToken: HttpContext.RequestAborted);
 
             _mediator.Publish(new GetOrderDetailNotify(order.Workflow, _sessionContext.RequiredUserId,
-                _sessionContext.UserName, _sessionContext.RequiredOrgCode, _sessionContext.OrgName));
+                 _sessionContext.UserName, _sessionContext.RequiredOrgCode, _sessionContext.OrgName));
         }
 
         var dto = _mapper.Map<OrderDto>(order);

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

@@ -98,14 +98,14 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
         var isOutOfCallCenter = nextStepBoxDefine.StepType is not EStepType.End
                                 && await CheckIfFlowOutOfCallCenterAsync(nextStepBoxDefine, dto.NextMainHandler, cancellationToken);
 
-        var isStartCountersign = nextStepBoxDefine.IsStartCountersign(dto.NextHandlers.Count);
-        if (isStartCountersign && nextStepBoxDefine.StepType is EStepType.CountersignEnd)
-            throw UserFriendlyException.SameMessage("汇总节点不允许发起会签");
+        //var isStartCountersign = nextStepBoxDefine.IsStartCountersign(dto.NextHandlers.Count);
+        //if (isStartCountersign && nextStepBoxDefine.StepType is EStepType.CountersignEnd)
+        //    throw UserFriendlyException.SameMessage("汇总节点不允许发起会签");
 
         var flowAssignMode = await GetFlowAssignModeAsync(nextStepBoxDefine,
             dto.NextHandlers.Select(d => d.Id).ToList(), cancellationToken);
 
-        await _workflowDomainService.NextAsync(workflow, dto, nextStepBoxDefine, isOutOfCallCenter, isStartCountersign, flowAssignMode, cancellationToken);
+        await _workflowDomainService.NextAsync(workflow, dto, nextStepBoxDefine, isOutOfCallCenter, flowAssignMode, cancellationToken);
 
         //更新接办部门(详情页面展示)
         await AddOrUpdateAssignAsync(workflow, dto, nextStepBoxDefine, cancellationToken);
@@ -145,7 +145,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
                         .Includes(d => d.Accounts)
                         .Where(d => stepDefine.HandlerClassifies.Select(d => d.Id).Contains(d.Name))
                         .ToListAsync();
-                    handlers = roles.SelectMany(d => d.Accounts).Select(d => d.Id).ToList();
+                    handlers = roles.SelectMany(d => d.Accounts).Select(d => d.Id).Distinct().ToList();
                 }
 
                 return new FlowAssignMode(EFlowAssignType.User, handlers);

+ 1 - 1
src/Hotline.CacheManager/RolePermissionsCacheManager.cs

@@ -12,7 +12,7 @@ namespace Hotline.CacheManager
 {
     public class RolePermissionsCacheManager : IRolePermissionsCacheManager, IScopeDependency
     {
-        private const string RolePermissionCacheKey = "RolePermissionCache_";
+        private const string RolePermissionCacheKey = "RolePermissionCache:";
         private readonly ITypedCache<IReadOnlyList<string>> _cache;
         private readonly ISystemAuthorityRepository _systemAuthorityRepository;
 

+ 1 - 1
src/Hotline.Repository.SqlSugar/Extensions/SqlSugarStartupExtensions.cs

@@ -172,7 +172,7 @@ namespace Hotline.Repository.SqlSugar.Extensions
             /***写AOP等方法***/
             db.Aop.OnLogExecuting = (sql, pars) =>
             {
-                //Log.Information(sql);
+                Log.Information(sql);
             };
             db.Aop.OnError = (exp) =>//SQL报错
             {

+ 1 - 1
src/Hotline/FlowEngine/Definitions/StepDefine.cs

@@ -16,7 +16,7 @@ public class StepDefine : StepBasic
     /// </summary>
     /// <param name="handlerCount">下一节点办理人数量</param>
     /// <returns></returns>
-    public bool IsStartCountersign(int handlerCount)
+    public bool IsStartCountersign11(int handlerCount)
     {
         if (StepType is EStepType.End) return false;
 

+ 1 - 1
src/Hotline/FlowEngine/Workflows/IWorkflowDomainService.cs

@@ -28,7 +28,7 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 办理(流转至下一节点)
         /// </summary>
-        Task NextAsync(Workflow workflow, BasicWorkflowDto dto, StepDefine nextStepBoxDefine, bool isOutOfCallCenter, bool isStartCountersign, FlowAssignMode flowAssignMode, CancellationToken cancellationToken);
+        Task NextAsync(Workflow workflow, BasicWorkflowDto dto, StepDefine nextStepBoxDefine, bool isOutOfCallCenter, FlowAssignMode flowAssignMode, CancellationToken cancellationToken);
 
         /// <summary>
         /// 退回(返回前一节点)

+ 2 - 0
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -211,9 +211,11 @@ public class Workflow : CreationEntity
         {
             case EFlowAssignType.Org:
                 HandlerOrgs.AddRange(handlers);
+                HandlerOrgs = HandlerOrgs.Distinct().ToList();
                 break;
             case EFlowAssignType.User:
                 HandlerUsers.AddRange(handlers);
+                HandlerUsers = HandlerUsers.Distinct().ToList();
                 break;
             default:
                 throw new ArgumentOutOfRangeException(nameof(assignType), assignType, null);

+ 61 - 37
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -89,17 +89,17 @@ namespace Hotline.FlowEngine.Workflows
         {
             //var nextStepBoxDefine = GetStepBoxDefine(workflow.Definition, dto.NextStepCode);
 
-            var isStartCountersign = nextStepBoxDefine.IsStartCountersign(dto.NextHandlers.Count);
-            //检查是否支持会签
-            if (isStartCountersign && nextStepBoxDefine.CountersignMode == ECountersignMode.UnSupport)
-                throw new UserFriendlyException($"当前节点不支持会签, defineCode: {workflow.Definition.Code}", "当前节点不支持会签");
-
             //1. 如果不是按角色指派,handlers必填 2. 如果按角色指派,handlers可以不选
             if (nextStepBoxDefine.HandlerType is not EHandlerType.Role && !dto.NextHandlers.Any())
                 throw UserFriendlyException.SameMessage("未指派办理人");
 
             //开始节点
-            var (startStepBox, startStep) = await CreateStartStepAsync(workflow, dto, isStartCountersign, cancellationToken);
+            var (startStepBox, startStep) = await CreateStartStepAsync(workflow, dto, cancellationToken);
+
+            var isStartCountersign = startStep.ShouldStartCountersign(dto.NextHandlers.Count);
+            //检查是否支持会签
+            if (isStartCountersign && startStep.CountersignMode == ECountersignMode.UnSupport)
+                throw new UserFriendlyException($"当前节点不支持发起会签, stepId: {startStep.Id}", "当前节点不支持发起会签");
 
             if (isStartCountersign)
             {
@@ -228,7 +228,7 @@ namespace Hotline.FlowEngine.Workflows
         /// 办理(流转至下一节点)
         /// </summary>
         public async Task NextAsync(Workflow workflow, BasicWorkflowDto dto, StepDefine nextStepBoxDefine,
-            bool isOutOfCallCenter, bool isStartCountersign, FlowAssignMode flowAssignMode, CancellationToken cancellationToken)
+            bool isOutOfCallCenter, FlowAssignMode flowAssignMode, CancellationToken cancellationToken)
         {
             ValidatePermission(workflow);
             CheckWhetherRunnable(workflow.Status);
@@ -238,6 +238,12 @@ namespace Hotline.FlowEngine.Workflows
             var (currentStepBox, currentStep) = GetUnCompleteStep(workflow.StepBoxes, _sessionContext.RequiredOrgCode, _sessionContext.RequiredUserId);
             if (currentStep.Status is EWorkflowStepStatus.Completed or EWorkflowStepStatus.Created)
                 throw UserFriendlyException.SameMessage("当前节点状态无法办理");
+
+            var isStartCountersign = currentStep.ShouldStartCountersign(dto.NextHandlers.Count);
+            //检查是否支持会签
+            if (isStartCountersign && currentStep.CountersignMode == ECountersignMode.UnSupport)
+                throw new UserFriendlyException($"当前节点不支持发起会签, stepId: {currentStep.Id}", "当前节点不支持发起会签");
+
             if (currentStep.Status is EWorkflowStepStatus.Assigned)
                 await AcceptAsync(workflow,
                     _sessionContext.RequiredUserId,
@@ -248,15 +254,15 @@ namespace Hotline.FlowEngine.Workflows
             if (currentStep.StepType is EStepType.End)
                 throw new UserFriendlyException("当前流程已流转到最终步骤");
 
-            //检查是否支持会签办理
-            if (isStartCountersign && nextStepBoxDefine.CountersignMode == ECountersignMode.UnSupport)
-                throw UserFriendlyException.SameMessage($"下一节点不支持会签办理, code: {currentStep.Code}");
-            WorkflowCountersign? countersign = null;
+            ////检查是否支持会签办理
+            //if (isStartCountersign && nextStepBoxDefine.CountersignMode == ECountersignMode.UnSupport)
+            //    throw UserFriendlyException.SameMessage($"下一节点不支持会签办理, code: {currentStep.Code}");
+            //WorkflowCountersign? countersign = null;
             if (isStartCountersign)
             {
                 //创建会签数据
-                countersign = await CreateCountersignAsync(workflow.Id, currentStep.Id, currentStep.Code,
-                    dto.NextHandlers.Count, currentStep.CountersignId, cancellationToken);
+                var countersign = await CreateCountersignAsync(workflow.Id, currentStep.Id, currentStep.Code,
+                     dto.NextHandlers.Count, currentStep.CountersignId, cancellationToken);
                 currentStep.StartCountersign(countersign.Id);
             }
 
@@ -282,7 +288,7 @@ namespace Hotline.FlowEngine.Workflows
                     throw new UserFriendlyException(
                     $"未查询到会签开始stepBox, workflowId: {workflow.Id}, stepCode: {currentStep.CountersignStartCode}", "未查询到会签开始节点");
                 var countersignStartStep =
-                    countersignStartStepBox.Steps.FirstOrDefault(d => d.HasStartCountersign && d.StartCountersignId == currentStep.CountersignId);
+                    countersignStartStepBox.Steps.FirstOrDefault(d => d.HasStartedCountersign && d.StartCountersignId == currentStep.CountersignId);
                 if (countersignStartStep != null)//如果==null,说明未发起会签是继承的外层会签
                 {
                     //结束step会签信息
@@ -364,7 +370,7 @@ namespace Hotline.FlowEngine.Workflows
                     //(当前办理节点所处同一会签内的所有step全都办理完成并且如果开启了会签的step,必须会签结束)
                     var unComplete = steps.Any(d =>
                         d.Status != EWorkflowStepStatus.Completed ||
-                        (d.HasStartCountersign && !d.IsStartedCountersignComplete.Value));
+                        (d.HasStartedCountersign && !d.IsStartedCountersignComplete.Value));
                     nextStepCanHandle = !unComplete;
                 }
             }
@@ -426,11 +432,21 @@ namespace Hotline.FlowEngine.Workflows
         {
             ValidatePermission(workflow);
             CheckWhetherRunnable(workflow.Status);
+
+            var (currentStepBox, currentStep) = GetUnCompleteStep(workflow.StepBoxes, _sessionContext.RequiredOrgCode, _sessionContext.RequiredUserId);
+            if (currentStepBox.StepType is EStepType.Start)
+                throw UserFriendlyException.SameMessage("当前流程已退回到开始节点");
+
+            var isStartCountersign = currentStep.ShouldStartCountersign(dto.NextHandlers.Count);
+            //检查是否支持会签
+            if (isStartCountersign && currentStep.CountersignMode == ECountersignMode.UnSupport)
+                throw new UserFriendlyException($"当前节点不支持发起会签, stepId: {currentStep.Id}", "当前节点不支持发起会签");
+
             var targetStepBox = workflow.StepBoxes.FirstOrDefault(d => d.Code == dto.TargetStepCode);
             if (targetStepBox is null)
                 throw UserFriendlyException.SameMessage("该流程尚未流转至该节点");
 
-            await RecallAsync(workflow, dto, targetStepBox, cancellationToken);
+            await RecallAsync(workflow, dto, targetStepBox, isStartCountersign, cancellationToken);
 
             //todo publish
         }
@@ -441,8 +457,6 @@ namespace Hotline.FlowEngine.Workflows
         public async Task JumpAsync(Workflow workflow, RecallDto dto, CancellationToken cancellationToken)
         {
             CheckWhetherRunnable(workflow.Status);
-            //update uncompleted traces
-            await JumpTraceAsync(workflow.Id, dto, cancellationToken);
 
             var (currentStepBox, currentStep) = GetUnCompleteStep(workflow.StepBoxes, _sessionContext.RequiredOrgCode, _sessionContext.RequiredUserId);
             if (currentStepBox.StepType is EStepType.Start)
@@ -450,12 +464,17 @@ namespace Hotline.FlowEngine.Workflows
             if (currentStepBox.StepType is EStepType.End)
                 throw UserFriendlyException.SameMessage("当前流程已流转到结束节点");
 
+            var isStartCountersign = currentStep.ShouldStartCountersign(dto.NextHandlers.Count);
+            //检查是否支持会签
+            if (isStartCountersign && currentStep.CountersignMode == ECountersignMode.UnSupport)
+                throw new UserFriendlyException($"当前节点不支持发起会签, stepId: {currentStep.Id}", "当前节点不支持发起会签");
+
             var targetStepBox = workflow.StepBoxes.FirstOrDefault(d => d.Code == dto.TargetStepCode);
             if (targetStepBox == null)
             {
                 //向后跳转
                 var nextStepBoxDefine = GetStepBoxDefine(workflow.Definition, dto.NextStepCode);
-                var isStartCountersign = nextStepBoxDefine.IsStartCountersign(dto.NextHandlers.Count);
+                //var isStartCountersign = nextStepBoxDefine.IsStartCountersign(dto.NextHandlers.Count);
                 var nextStepBox = await CreateStepAsync(isStartCountersign, workflow, nextStepBoxDefine, dto, EWorkflowStepStatus.Assigned, currentStepBox, currentStep, cancellationToken);
 
                 await ResetWorkflowCurrentStepInfo(workflow, dto, nextStepBox, cancellationToken);
@@ -488,9 +507,12 @@ namespace Hotline.FlowEngine.Workflows
             else
             {
                 //返回之前节点
-                await RecallAsync(workflow, dto, targetStepBox, cancellationToken);
+                await RecallAsync(workflow, dto, targetStepBox, isStartCountersign, cancellationToken);
             }
 
+            //update uncompleted traces
+            await JumpTraceAsync(workflow.Id, dto, cancellationToken);
+
             //todo publish
         }
 
@@ -682,7 +704,7 @@ namespace Hotline.FlowEngine.Workflows
             return parentTrace;
         }
 
-        private async Task RecallAsync(Workflow workflow, RecallDto dto, WorkflowStep targetStepBox, CancellationToken cancellationToken)
+        private async Task RecallAsync(Workflow workflow, RecallDto dto, WorkflowStep targetStepBox, bool isStartCountersign, CancellationToken cancellationToken)
         {
             //update uncompleted traces
             await RecallTraceAsync(workflow.Id, dto, cancellationToken);
@@ -701,7 +723,7 @@ namespace Hotline.FlowEngine.Workflows
 
             //recreate targetStep
             var nextStepBoxDefine = GetStepBoxDefine(workflow.Definition, dto.NextStepCode);
-            var isStartCountersign = nextStepBoxDefine.IsStartCountersign(dto.NextHandlers.Count);
+            //var isStartCountersign = nextStepBoxDefine.IsStartCountersign(dto.NextHandlers.Count);
             await CreateStepAsync(isStartCountersign, workflow, nextStepBoxDefine, dto, EWorkflowStepStatus.Assigned, targetStepBox, targetStepBox.Steps.First(), cancellationToken);
 
             //flow manage
@@ -743,7 +765,7 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 创建开始节点(保存开始流程的办理意见,对应definition的start节点)
         /// </summary>
-        private async Task<(WorkflowStep stepBox, WorkflowStep step)> CreateStartStepAsync(Workflow workflow, BasicWorkflowDto dto, bool isStartCountersign, CancellationToken cancellationToken)
+        private async Task<(WorkflowStep stepBox, WorkflowStep step)> CreateStartStepAsync(Workflow workflow, BasicWorkflowDto dto, CancellationToken cancellationToken)
         {
             if (workflow.StepBoxes.Any())
                 throw UserFriendlyException.SameMessage("无法反复开始流程");
@@ -844,19 +866,19 @@ namespace Hotline.FlowEngine.Workflows
             await _workflowStepRepository.AddRangeAsync(subSteps, cancellationToken);
         }
 
-        private (WorkflowStep stepBox, WorkflowStep step) GetStep(List<WorkflowStep> stepBoxes, string stepId)
-        {
-            foreach (var stepBox in stepBoxes)
-            {
-                foreach (var step in stepBox.Steps)
-                {
-                    if (step.Id == stepId)
-                        return (stepBox, step);
-                }
-            }
-
-            throw new UserFriendlyException("未找到对应节点");
-        }
+        //private (WorkflowStep stepBox, WorkflowStep step) GetStep(List<WorkflowStep> stepBoxes, string stepId)
+        //{
+        //    foreach (var stepBox in stepBoxes)
+        //    {
+        //        foreach (var step in stepBox.Steps)
+        //        {
+        //            if (step.Id == stepId)
+        //                return (stepBox, step);
+        //        }
+        //    }
+
+        //    throw new UserFriendlyException("未找到对应节点");
+        //}
 
         /// <summary>
         /// 查询未完成节点
@@ -869,7 +891,9 @@ namespace Hotline.FlowEngine.Workflows
         {
             var (stepBox, step) = GetStep(stepBoxes, orgCode, userId, d => d != EWorkflowStepStatus.Completed);
             if (step == null)
-                throw new UserFriendlyException("未找到对应节点");
+                throw new UserFriendlyException(
+                    $"未找到对应节点, workflowId: {stepBoxes.FirstOrDefault()?.WorkflowId} orgCode:{orgCode}, userId: {userId}",
+                    "未找到对应节点");
             return (stepBox, step);
         }
 

+ 16 - 2
src/Hotline/FlowEngine/Workflows/WorkflowStep.cs

@@ -85,7 +85,7 @@ public class WorkflowStep : StepBasicEntity
     /// 是否发起过会签
     /// </summary>
     [SugarColumn(IsIgnore = true)]
-    public bool HasStartCountersign => !string.IsNullOrEmpty(StartCountersignId);
+    public bool HasStartedCountersign => !string.IsNullOrEmpty(StartCountersignId);
 
     #endregion
 
@@ -162,13 +162,27 @@ public class WorkflowStep : StepBasicEntity
     /// <returns></returns>
     public EStepCountersignStatus GetNextStepCountersignStatus()
     {
-        if (HasStartCountersign)
+        if (HasStartedCountersign)
         {
             return EStepCountersignStatus.InCountersign;
         }
         return IsInCountersign ? EStepCountersignStatus.OuterCountersign : EStepCountersignStatus.None;
     }
 
+    /// <summary>
+    /// 检查该节点是否应该发起会签(办理时确认是否应该作为发起会签节点处理)
+    /// </summary>
+    /// <returns></returns>
+    public bool ShouldStartCountersign(int handlerCount)
+    {
+        if (StepType is EStepType.End) return false;
+
+        //需求:按角色指派默认不发起会签
+        if (HandlerType is EHandlerType.Role) return false;
+
+        return handlerCount > 1;
+    }
+
     #endregion
 
 }