Bläddra i källkod

Merge branch 'master' of http://110.188.24.182:10023/Fengwo/hotline

田爽 1 år sedan
förälder
incheckning
c3dbc50275

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

@@ -2045,7 +2045,7 @@ public class OrderController : BaseController
             .WhereIF(dto.Channels.Any(), d => dto.Channels.Contains(d.SourceChannelCode)) //来源渠道
             .WhereIF(dto.HotspotIds.Any(), d => dto.HotspotIds.Contains(d.HotspotId)) //热点类型
             .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone!)) //转接号码
-            //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode)))
+                                                                                                                  //.WhereIF(dto.OrgCodes.Any(), d => d.Workflow.Assigns.Any(s => dto.OrgCodes.Contains(s.OrgCode)))
             .WhereIF(dto.OrgCodes.Any(), d => dto.OrgCodes.Contains(d.ActualHandleOrgCode)) //接办部门
             .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.AcceptorName.Contains(dto.NameOrNo!) || d.AcceptorStaffNo.Contains(dto.NameOrNo!)) //受理人/坐席
             .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart) //受理时间开始
@@ -2069,8 +2069,8 @@ public class OrderController : BaseController
             .WhereIF(dto.IdentityType != null, d => d.IdentityType == dto.IdentityType) //来电主体
             .WhereIF(!string.IsNullOrEmpty(dto.FromName), d => d.FromName.Contains(dto.FromName)) //来电人姓名
             .WhereIF(dto.AreaCodes.Any(), d => dto.AreaCodes.Contains(d.AreaCode)) //区域
-            .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true,x=>x.IsProvince == true)
-            .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false,x=>x.IsProvince == false)
+            .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == true, x => x.IsProvince == true)
+            .WhereIF(dto.IsProvinceOrder.HasValue && dto.IsProvinceOrder == false, x => x.IsProvince == false)
             .OrderByDescending(d => d.CreationTime)
             .ToPagedListAsync(dto, HttpContext.RequestAborted);
 
@@ -2129,13 +2129,15 @@ public class OrderController : BaseController
             return new();
 
         string? countersignId = null;
+        var canPrevious = false;
         if (!string.IsNullOrEmpty(order.WorkflowId))
         {
-            var (workflow, unCompleteCountersignId) = await _workflowDomainService.GetWorkflowHandlePermissionAsync(
+            var result = await _workflowDomainService.GetWorkflowHandlePermissionAsync(
                 order.WorkflowId, _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId,
                 cancellationToken: HttpContext.RequestAborted);
-            order.Workflow = workflow;
-            countersignId = unCompleteCountersignId;
+            order.Workflow = result.workflow;
+            countersignId = result.countersignId;
+            canPrevious = result.canPrevious;
 
             await _mediator.Publish(new GetOrderDetailNotify(order.Workflow,
                 _sessionContext.RequiredUserId, _sessionContext.UserName,
@@ -2149,6 +2151,7 @@ public class OrderController : BaseController
         dto.IsCanDelay = !order.OrderDelays.Any(x => x.DelayState == EDelayState.Examining);
         var delayModel = order.OrderDelays.Where(x => x.DelayState == EDelayState.Pass).MaxBy(x => x.CreationTime);
         dto.DelayString = delayModel != null ? delayModel?.DelayNum + "个" + delayModel?.DelayUnit.GetDescription() : "";
+        dto.CanPrevious = canPrevious;
 
         if (dto.FileJson != null && dto.FileJson.Any())
         {
@@ -2160,10 +2163,6 @@ public class OrderController : BaseController
         var call = await _trCallRecordRepository.Queryable().Where(x => x.CallAccept == order.CallId).FirstAsync();
         if (call != null) dto.RecordingFileUrl = call.RecordingFileUrl;
 
-        if (order.Workflow != null)
-        {
-            dto.CanPrevious = !order.Workflow.IsInCountersign;
-        }
         var repeatablesMap = await _repeatableEventDetailRepository.Queryable()
             .Includes(x => x.Order)
             .Where(x => x.OrderId == id).Distinct().ToListAsync();
@@ -2571,7 +2570,7 @@ public class OrderController : BaseController
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == true, d => d.CounterSignType.HasValue)
             .WhereIF(dto.IsCounterSign.HasValue && dto.IsCounterSign == false, d => !d.CounterSignType.HasValue)
             .Where(x => x.Source < ESource.MLSQ || x.Source > ESource.WZSC)
-            .Where(x=>x.Status!= EOrderStatus.BackToProvince)
+            .Where(x => x.Status != EOrderStatus.BackToProvince)
             .OrderByDescending(d => d.StartTime)
             .ToPagedListAsync(dto, HttpContext.RequestAborted);
 
@@ -2618,7 +2617,7 @@ public class OrderController : BaseController
     {
         var oneSendBack = bool.Parse(_systemSettingCacheManager.GetSetting(SettingConstants.OneOrgSendBack)?.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);
@@ -2632,19 +2631,19 @@ public class OrderController : BaseController
             if (prevStep == null)
                 throw UserFriendlyException.SameMessage("未查询到前一节点");
 
-            var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == workflow.ExternalId && x.State == ESendBackAuditState.Apply ).AnyAsync();
+            var sendBack = await _orderSendBackAuditRepository.Queryable().Where(x => x.OrderId == workflow.ExternalId && x.State == ESendBackAuditState.Apply).AnyAsync();
             if (sendBack)
-	            throw UserFriendlyException.SameMessage("当前工单已经生成退回记录");
+                throw UserFriendlyException.SameMessage("当前工单已经生成退回记录");
 
             var order = await _orderRepository
-	            .Queryable()
-	            .Includes(d => d.Workflow)
-	            .FirstAsync(d => d.Id == workflow.ExternalId);
+                .Queryable()
+                .Includes(d => d.Workflow)
+                .FirstAsync(d => d.Id == workflow.ExternalId);
             if (order.Workflow.IsInCountersign) throw UserFriendlyException.SameMessage("工单会签中,无法进行退回!");
 
-			var applyOrg = _organizeRepository.Get(currentStep.AcceptorOrgId);
+            var applyOrg = _organizeRepository.Get(currentStep.AcceptorOrgId);
             var sendBackOrg = _organizeRepository.Get(prevStep.AcceptorOrgId);
-            if ((twoSendBack && 2.Equals(applyOrg.Level) && 1.Equals(sendBackOrg.Level) && !sendBackOrg.IsCenter) 
+            if ((twoSendBack && 2.Equals(applyOrg.Level) && 1.Equals(sendBackOrg.Level) && !sendBackOrg.IsCenter)
                 || (oneSendBack && 1.Equals(applyOrg.Level) && sendBackOrg.IsCenter && !applyOrg.IsCenter))
             {
                 var audit = new OrderSendBackAudit
@@ -2727,7 +2726,7 @@ public class OrderController : BaseController
             .WhereIF(dto.AuditState == 1, d => d.State == ESendBackAuditState.Apply)
             .WhereIF(dto.AuditState == 2 && !dto.State.HasValue, d => d.State > ESendBackAuditState.Apply)
             .WhereIF(dto.AuditState == 2 && dto.State.HasValue, d => d.State == dto.State)
-			.Where(x=>x.SendBackOrgId == _sessionContext.OrgId)
+            .Where(x => x.SendBackOrgId == _sessionContext.OrgId)
             .OrderByDescending(x => x.CreationTime)
             .ToPagedListAsync(dto.PageIndex, dto.PageSize, HttpContext.RequestAborted);
 
@@ -2780,7 +2779,7 @@ public class OrderController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpPost("send_back/batch")]
-    public async Task<object> BatchApplyUrge([FromBody]BatchOrderSendBackAddDto dto)
+    public async Task<object> BatchApplyUrge([FromBody] BatchOrderSendBackAddDto dto)
     {
         int count = dto.OrderIds.Count;
         int successCount = 0;
@@ -2805,10 +2804,11 @@ public class OrderController : BaseController
                 errorCount++;
                 continue;
             }
-            var model = new OrderSendBack() { 
-                 Content = dto.Content,
-                 OrderId = item,
-                 Destination = ESendBackDestination.Province
+            var model = new OrderSendBack()
+            {
+                Content = dto.Content,
+                OrderId = item,
+                Destination = ESendBackDestination.Province
             };
             await _orderSendBackRepository.AddAsync(model, HttpContext.RequestAborted);
             if (!string.IsNullOrEmpty(model.Id))
@@ -2891,7 +2891,7 @@ public class OrderController : BaseController
             var sendBackDto = _mapper.Map<OrderSendBackDto>(sendBack);
             var OrderDto = _mapper.Map<OrderDto>(order);
             //await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderFlowPrevious,
-              //      new PublishOrderSendBackDto() { Order = OrderDto, SendBack = sendBackDto, ClientGuid = "" });
+            //      new PublishOrderSendBackDto() { Order = OrderDto, SendBack = sendBackDto, ClientGuid = "" });
             //try
             //{
             //    await _provinceService.GetCaseBackApply(

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

@@ -261,7 +261,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     public async Task PreviousAsync(PreviousWorkflowDto dto, CancellationToken cancellationToken)
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
-            cancellationToken: cancellationToken);
+            withCountersigns: true, cancellationToken: cancellationToken);
         User user = await _userRepository.Queryable().Includes(x => x.Organization)
             .Where(x => x.Id == _sessionContext.RequiredUserId).FirstAsync();
         await _workflowDomainService.PreviousAsync(workflow, dto, user, cancellationToken);
@@ -273,7 +273,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     public async Task OrderPreviousAsync(PreviousWorkflowDto dto, string userId, CancellationToken cancellationToken)
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withSteps: true,
-            cancellationToken: cancellationToken);
+           withCountersigns: true, cancellationToken: cancellationToken);
         User user = await _userRepository.Queryable().Includes(x => x.Organization).Where(x => x.Id == userId).FirstAsync();
         await _workflowDomainService.PreviousAsync(workflow, dto, user, cancellationToken);
     }

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

@@ -35,7 +35,7 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 查询工作流包含当前用户办理权限(是否可办理)
         /// </summary>
-        Task<(Workflow, string?)> GetWorkflowHandlePermissionAsync(string workflowId, string userId, string orgCode,
+        Task<(Workflow workflow, string? countersignId, bool canPrevious)> GetWorkflowHandlePermissionAsync(string workflowId, string userId, string orgId,
             CancellationToken cancellationToken = default);
 
         /// <summary>

+ 79 - 29
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -250,17 +250,29 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 查询工作流包含当前用户结束会签权限(是否可结束)
         /// </summary>
-        public async Task<(Workflow, string?)> GetWorkflowHandlePermissionAsync(
-            string workflowId, string userId, string orgCode, CancellationToken cancellationToken = default)
+        public async Task<(Workflow, string?, bool)> GetWorkflowHandlePermissionAsync(
+            string workflowId, string userId, string orgId, CancellationToken cancellationToken = default)
         {
             var workflow = await GetWorkflowAsync(workflowId, withSteps: true, withCountersigns: true,
                 cancellationToken: cancellationToken);
+
+            var canPrevious = false;
+            if (workflow.CanHandle(userId, orgId))
+            {
+                var currentStep = FindCurrentStepWaitForHandle(workflow, userId, orgId);
+                if(currentStep.Status is not EWorkflowStepStatus.Handled)
+                {
+                    canPrevious = !(currentStep.IsInCountersign() && 
+                                    !currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId));
+                }
+            }
+
             var unCompletedCountersign = workflow.Countersigns.FirstOrDefault(d => !d.IsCompleted() && d.StarterId == userId);
-            if (unCompletedCountersign is null) return (workflow, null);
+            if (unCompletedCountersign is null) return (workflow, null, canPrevious);
 
             var existCountersignEndStep = workflow.Steps.Exists(d =>
                 d.IsCountersignEndStep && d.CountersignStartStepId == unCompletedCountersign.StartStepId);
-            return (workflow, existCountersignEndStep ? null : unCompletedCountersign.Id);
+            return (workflow, existCountersignEndStep ? null : unCompletedCountersign.Id, canPrevious);
         }
 
         /// <summary>
@@ -550,15 +562,18 @@ namespace Hotline.FlowEngine.Workflows
             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;
+            WorkflowStep? prevStep, countersignStartStep = null;
             if (isCurrentTopCountersignEndStep)
             {
-                //todo end countersign
                 //prev is topstart's prev
-                var countersignStartStep =
-                    workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);
+                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
             {
@@ -567,25 +582,48 @@ namespace Hotline.FlowEngine.Workflows
             if (prevStep == null)
                 throw UserFriendlyException.SameMessage("未查询到前一节点");
 
-            if(prevStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
+            if (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("未查询到会签发起节点");
 
+            // add prev current to remove list
             var removeSteps = new List<WorkflowStep> { currentStep, prevStep };
-            //todo remove steps after prevStep
-
 
-            //1. remove steps between cs end to start except startStep 2. prev == start
-            if (prevStep.IsCountersignEndStep)
+            if (shouldCountersignEnd)
             {
-                var countersignStartStep = workflow.Steps.FirstOrDefault(d => d.Id == prevStep.CountersignStartStepId);
-                if (countersignStartStep is null)
-                    throw new UserFriendlyException("未查询到对应会签开始节点");
-                SearchCsSteps(countersignStartStep, prevStep, workflow.Steps, ref removeSteps);
-                removeSteps.Add(prevStep);
+                //add cs steps to remove list
+                SearchCountersignSteps(countersignStartStep!, workflow.Steps, ref removeSteps);
+
+                //end cs
+                var currentCountersign =
+                    workflow.Countersigns.FirstOrDefault(d => d.Id == countersignStartStep.StartCountersignId);
+                if (currentCountersign is null)
+                    throw new UserFriendlyException(
+                        $"未查询到对应会签信息,workflowId:{workflow.Id}, countersignId:{currentStep.CountersignId}",
+                        "无效会签编号");
+
+                //结束step会签信息
+                countersignStartStep.CountersignEnd();
+                await _workflowStepRepository.UpdateAsync(countersignStartStep, cancellationToken);
+                //updateSteps.Add(countersignStartStep);
 
-                prevStep = countersignStartStep;
+                //结束会签
+                currentCountersign.End(currentStep.Id, currentStep.Code, currentStep.BusinessType,
+                    _sessionContext.RequiredUserId, _sessionContext.UserName,
+                    _sessionContext.RequiredOrgId, _sessionContext.OrgName,
+                    _sessionContext.OrgAreaCode, _sessionContext.OrgAreaName);
+                await _workflowCountersignRepository.UpdateAsync(currentCountersign, cancellationToken);
+
+                //update workflow cs status
+                if (workflow.CheckIfCountersignOver())
+                    workflow.EndCountersign();
             }
 
             //update trace
@@ -600,16 +638,9 @@ namespace Hotline.FlowEngine.Workflows
             if (workflow.Status is EWorkflowStatus.Completed)
                 workflow.SetStatusRunnable();
 
-            //更新当前办理节点信息
-            //workflow.UpdateWorkflowCurrentStepInfo(false,
-            //    operater.Id, operater.Name,
-            //    operater.OrgId, operater.Organization.Name,
-            //    operater.Organization.AreaCode, operater.Organization.AreaName,
-            //    nextStep: newPrevStep);
-            //workflow.UpdateActualStepWhenAssign(newPrevStep, prevStep.Handlers.First(), prevStep.HandlerType);
+            //更新实际办理节点信息
             workflow.UpdateActualStepWhenAssign(newPrevStep, prevStep.HandlerOrgName, prevStep.HandlerOrgId);
-
-
+            
             //更新流程可办理对象
             workflow.UpdatePreviousHandlers(operater.Id, operater.OrgId, prevStep);
 
@@ -622,7 +653,26 @@ namespace Hotline.FlowEngine.Workflows
         }
 
         /// <summary>
-        /// 查找当前节点至结束节点之前的所有节点(不含头尾)
+        /// 查找当前会签内所有节点(含start,end)
+        /// </summary>
+        private void SearchCountersignSteps(WorkflowStep startStep, List<WorkflowStep> steps, ref List<WorkflowStep> csSteps)
+        {
+            if (startStep.IsStartCountersign)
+            {
+                var countersignSteps = steps.Where(d => d.CountersignId == startStep.StartCountersignId).ToList();
+                if (countersignSteps.Any())
+                {
+                    foreach (var countersignStep in countersignSteps)
+                    {
+                        SearchCountersignSteps(countersignStep, steps, ref csSteps);
+                    }
+                }
+            }
+            csSteps.Add(startStep);
+        }
+
+        /// <summary>
+        /// 查找当前节点至结束节点间的所有节点(不含头尾)
         /// </summary>
         private void SearchCsSteps(WorkflowStep step, WorkflowStep csEndStep,
             List<WorkflowStep> steps, ref List<WorkflowStep> removeSteps)