xfe 2 місяців тому
батько
коміт
3144e3541b

Різницю між файлами не показано, бо вона завелика
+ 231 - 183
src/Hotline.Api/Controllers/OrderController.cs


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

@@ -353,7 +353,7 @@ public class WorkflowController : BaseController
     [HttpPost("previous")]
     public async Task Previous([FromBody] PreviousWorkflowDto dto)
     {
-        await _workflowApplication.PreviousAsync(dto, HttpContext.RequestAborted);
+        await _workflowApplication.PreviousAsync(dto, cancellationToken: HttpContext.RequestAborted);
     }
 
     /// <summary>

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

@@ -47,14 +47,14 @@ namespace Hotline.Application.FlowEngine
         /// 退回(返回前一节点)
         /// </summary>
         Task<EFlowDirection> PreviousAsync(PreviousWorkflowDto dto,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 工单退回(返回前一节点)
         /// </summary>
         Task<EFlowDirection> PreviousAsync(PreviousWorkflowDto dto, string applicantId, string applicantOrgId, string[] applicantRoleIds,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
 
         ///// <summary>

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

@@ -346,7 +346,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// 退回(返回前一节点)
     /// </summary>
     public async Task<EFlowDirection> PreviousAsync(PreviousWorkflowDto dto,
-        Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+        Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
         CancellationToken cancellationToken = default)
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
@@ -364,7 +364,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
     /// 工单退回(返回前一节点)
     /// </summary>
     public async Task<EFlowDirection> PreviousAsync(PreviousWorkflowDto dto, string applicantId, string applicantOrgId, string[] applicantRoleIds,
-        Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+        Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
         CancellationToken cancellationToken = default)
     {
         var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,

+ 9 - 6
src/Hotline.Application/Orders/IOrderApplication.cs

@@ -1,4 +1,5 @@
 using System.Data;
+using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Workflows;
 using Hotline.Orders;
 using Hotline.Settings;
@@ -324,14 +325,11 @@ namespace Hotline.Application.Orders
         /// <param name="dto"></param>
         /// <returns></returns>
         ISugarQueryable<OrderVisitDetail> MayScreenList(MayScreenListDto dto);
-
-
+        
         ISugarQueryable<Order> QueryWaitedForSeat(QueryOrderWaitedDto dto);
-
-
+        
         ISugarQueryable<Order> QueryWaited(QueryOrderWaitedDto dto);
-
-
+        
         /// <summary>
         /// 受理类型前10
         /// </summary>
@@ -409,5 +407,10 @@ namespace Hotline.Application.Orders
         /// </summary>
         /// <returns></returns>
         Task HandleFromWanggeyuanToMaskAsync(string orderId, CancellationToken cancellation);
+        
+        /// <summary>
+        /// 查询退回操作目标节点的指派对象
+        /// </summary>
+        StepAssignInfo GetOrderPreviousAssignInfo(Workflow workflow, StepDefine prevStepDefine, WorkflowStep prevStep);
     }
 }

+ 63 - 0
src/Hotline.Application/Orders/OrderApplication.cs

@@ -45,6 +45,7 @@ using PanGu;
 using SqlSugar;
 using System.Data;
 using System.Dynamic;
+using Hotline.FlowEngine.Definitions;
 using Hotline.FlowEngine.Notifications;
 using Hotline.Share.Dtos.FlowEngine.Workflow;
 using XF.Domain.Authentications;
@@ -3549,6 +3550,68 @@ public class OrderApplication : IOrderApplication, IScopeDependency
             cancellationToken: cancellationToken);
     }
 
+    /// <summary>
+    /// 查询退回操作目标节点的指派对象
+    /// </summary>
+    public StepAssignInfo GetOrderPreviousAssignInfo(Workflow workflow, StepDefine prevStepDefine, WorkflowStep prevStep)
+    {
+        //自贡需求:
+        // 1. 工单退回、特提、重办到话务部节点时,所有坐席都可以查看和办理
+        // 2. 退回到派单组时需执行平均分配逻辑
+        //宜宾需求:
+        // 1、退回至话务部:所有坐席都可以查看和办理(除某些场景下本来就需指定办理对象,如:发布时退回……)
+        // 2、退回至派单组:默认退给之前的派单员(除某些场景下本来就需指定办理对象,如:发布时退回……)
+        // 3、话务员特提至话务部:根据特提申请时候选择来,指定的办理对象才能查看和办理
+        // 4、派单员特提至派单组:根据特提申请时候选择来,指定的办理对象才能查看和办理
+        // 5、班长特提至派单组,办理对象必选(已实现)
+        // 6、班长特提至话务部,办理对象非必选,没选择则所有坐席都可以查看和办理
+        //泸州需求:
+        /* 1、特提(仅针对特提到热线中心节点)
+           1.1、工单特提回话务部,办理对象需调整所有坐席都可以查看和办理
+           1.2、工单特提到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
+           2、退回功能(仅针对退回到热线中心节点)
+           2.1、退回到话务部节点,只有之前受理人才能办理;
+           2.2、退回到派单组或者班长审批等其它热线中心节点,只有之前办理人才能办理
+         */
+        var rsp = new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser);
+
+        switch (targetStepBusinessType)
+        {
+            case EBusinessType.Seat:
+                if (_appOptions.Value.IsZiGong || _appOptions.Value.IsYiBin)
+                {
+                    rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.OriginDefinition;
+                }
+                break;
+            case EBusinessType.Send:
+                if (_appOptions.Value.IsZiGong)
+                {
+                    if (handler is null)
+                        throw new UserFriendlyException("参数异常,退回派单组需要通过平均派单指定办理人");
+
+                    rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.AssignHandler;
+                    rsp.StepAssignInfo = handler;
+                }
+                break;
+            case EBusinessType.Department:
+                rsp.ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.OriginStepOrg;
+                break;
+            case EBusinessType.DepartmentLeader:
+                break;
+            case EBusinessType.CenterMonitor:
+                break;
+            case EBusinessType.CenterLeader:
+                break;
+            case EBusinessType.Unknown:
+                break;
+            case EBusinessType.File:
+            default:
+                throw new ArgumentOutOfRangeException(nameof(targetStepBusinessType), targetStepBusinessType, null);
+        }
+
+        return rsp;
+    }
+
     #region private
 
     /// <summary>

+ 1 - 1
src/Hotline.Application/Subscribers/DatasharingSubscriber.cs

@@ -520,7 +520,7 @@ namespace Hotline.Application.Subscribers
                 PreviousWorkflowDto previous = new PreviousWorkflowDto();
                 previous.Opinion = dto.ProvinceScreenResult.AuditOpinion;
                 previous.WorkflowId = orderScreen.WorkflowId;
-                await _workflowApplication.PreviousAsync(previous, cancellationToken);
+                await _workflowApplication.PreviousAsync(previous, cancellationToken: cancellationToken);
             }
 
             if (int.Parse(dto.ProvinceScreenResult.AuditResult) > 0)

+ 9 - 8
src/Hotline.Share/Dtos/FlowEngine/Workflow/PreviousWorkflowDto.cs

@@ -12,16 +12,17 @@ public class PreviousWorkflowDto : EndWorkflowIdDto
     /// </summary>
     public DateTime? ExpiredTime { get; set; }
 
-    ///// <summary>
-    ///// 指定办理对象
-    ///// </summary>
-    //public FlowStepHandler? Handler { get; set; }
-
     /// <summary>
-    /// 逆向流程,节点指派方式
-    /// 退回、特提
+    /// 指定办理对象
     /// </summary>
-    public ReverseFlowStepAssignInfo ReverseFlowStepAssignInfo { get; set; }
+    public FlowStepHandler? Handler { get; set; }
+    // public StepAssignInfo? Handler { get; set; }
+
+    // /// <summary>
+    // /// 逆向流程,节点指派方式
+    // /// 退回、特提
+    // /// </summary>
+    // public ReverseFlowStepAssignInfo ReverseFlowStepAssignInfo { get; set; }
 }
 
 /// <summary>

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

@@ -31,8 +31,8 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// new 
         /// </summary>
-        Task<(Workflow, WorkflowStep)> StartAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null, 
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+        Task<(Workflow, WorkflowStep)> StartAsync(StartWorkflowDto dto, string externalId, DateTime? expiredTime = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
 
         /// <summary>
@@ -40,7 +40,7 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         Task<List<WorkflowStep>> NextAsync(ISessionContext current, NextWorkflowDto dto,
             DateTime? expiredTime = null, bool isAutoFillSummaryOpinion = false,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
 
         /// <summary>
@@ -83,32 +83,32 @@ namespace Hotline.FlowEngine.Workflows
         /// 退回(new)
         /// </summary>
         Task<EFlowDirection> PreviousAsync(Workflow workflow, PreviousWorkflowDto dto, OperatorInfo operatorInfo,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
 
         /// <summary>
         /// 撤回(返回到之前任意节点)
         /// </summary>
-        Task<bool> RecallAsync(RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
+        Task<bool> RecallAsync(RecallDto dto,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
 
-        Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo, StepDefine targetStepDefine,
+        Task<bool> RecallAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
 
-        Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
+        Task<bool> RecallAsync(Workflow workflow, RecallDto dto,
             StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceType traceType,
             DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,  
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
 
-        Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
+        Task<bool> RecallAsync(Workflow workflow, RecallDto dto,
             WorkflowStep targetStep, EWorkflowTraceType traceType,
-            DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode, 
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,  
+            DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default);
 
         /// <summary>
@@ -193,7 +193,7 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         WorkflowStep CreateStartStep(Workflow workflow, StepDefine startStepDefine, BasicWorkflowDto dto, UserInfo assigner,
             FlowStepHandler handler, DateTime? expiredTime, EFlowAssignType? flowAssignType = EFlowAssignType.User,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null);
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null);
 
         /// <summary>
         /// 查询未完成节点

+ 276 - 77
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -166,7 +166,7 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         public async Task<(Workflow, WorkflowStep)> StartAsync(StartWorkflowDto dto,
             string externalId, DateTime? expiredTime = null,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             //     var validator = new StartWorkflowDtoValidator();
@@ -282,7 +282,7 @@ namespace Hotline.FlowEngine.Workflows
         /// </summary>
         public async Task<List<WorkflowStep>> NextAsync(ISessionContext current, NextWorkflowDto dto,
             DateTime? expiredTime = null, bool isAutoFillSummaryOpinion = false,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             var workflow = await GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
@@ -694,11 +694,163 @@ namespace Hotline.FlowEngine.Workflows
             return workflow.ActualHandleStepAcceptTime;
         }
 
+        /// <summary>
+        /// 退回(返回前一节点)
+        /// </summary>
+        /// <returns></returns>
+        public async Task<EFlowDirection> PreviousAsync(Workflow workflow, PreviousWorkflowDto dto,
+            string applicantId, string applicantName,
+            string applicantOrgId, string applicantOrgName,
+            string applicantOrgAreaCode, string applicantOrgAreaName,
+            bool applicantIsCenter, string[] applicantRoleIds,
+            CancellationToken cancellationToken)
+        {
+            //ValidatePermission(workflow, operater.OrgId, operater.Id);
+
+            var (currentStep, prevStep, countersignStartStep) =
+                GetPreviousStep(workflow, applicantId, applicantOrgId, applicantRoleIds);
+
+            //保存附件
+            if (dto.Files.Any())
+                currentStep.FileJson = await _fileRepository.AddFileAsync(
+                    dto.Files, workflow.ExternalId, currentStep.Id, cancellationToken);
+
+            // add prev current to remove list
+            var removeSteps = new List<WorkflowStep> { currentStep, prevStep };
+
+            if (countersignStartStep is not null)
+            {
+                //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);
+
+                //结束会签
+                //currentCountersign.End(currentStep.Id, currentStep.Code, currentStep.BusinessType,
+                //    current.RequiredUserId, current.UserName,
+                //    current.RequiredOrgId, current.OrgName,
+                //    current.OrgAreaCode, current.OrgAreaName);
+                currentCountersign.End(currentStep.Id, currentStep.Code, currentStep.BusinessType,
+                    applicantId, applicantName,
+                    applicantOrgId, applicantOrgName,
+                    applicantOrgAreaCode, applicantOrgAreaName);
+
+                await _workflowCountersignRepository.UpdateAsync(currentCountersign, cancellationToken);
+
+                //update workflow cs status
+                if (workflow.CheckIfCountersignOver())
+                    workflow.EndCountersign();
+            }
+
+            //update trace
+            //var trace = await PreviousTraceAsync(workflow.Id, dto, currentStep,
+            //    applicantId, applicantName,
+            //    applicantOrgId, applicantOrgName,
+            //    applicantOrgAreaCode, applicantOrgAreaName,
+            //    applicantIsCenter, cancellationToken);
+            var trace = workflow.Traces.First(t => t.StepId == currentStep.Id);
+            // _mapper.Map(dto, trace);
+            trace.FileJson = currentStep.FileJson;
+            trace.IsSms = dto.AcceptSms;
+            trace.Opinion = dto.Opinion;
+
+            //HandleTrace(trace, dto.Opinion, current);
+
+            trace.Handle(applicantId, applicantName,
+                applicantOrgId, applicantOrgName,
+                applicantOrgAreaCode, applicantOrgAreaName,
+                applicantIsCenter, EHandleMode.Previous, dto.Opinion);
+
+            //await _workflowTraceRepository.UpdateAsync(trace, cancellationToken);
+
+            //如果有传入期满时间 新节点为传入的期满时间
+            if (dto.ExpiredTime.HasValue)
+                prevStep.StepExpiredTime = dto.ExpiredTime;
+
+            if (workflow.FlowType == EFlowType.Handle)
+            {
+                prevStep.FlowAssignType = prevStep.BusinessType is EBusinessType.Seat ? EFlowAssignType.Role :
+                    prevStep.BusinessType is EBusinessType.Send ? EFlowAssignType.User : EFlowAssignType.Org;
+            }
+
+            //甄别退回到最开始节点到部门
+            if (workflow.FlowType == EFlowType.Review && workflow.ModuleCode == WorkflowModuleConsts.OrderScreen)
+            {
+                prevStep.FlowAssignType = prevStep.StepType == EStepType.Start ? EFlowAssignType.Org : prevStep.FlowAssignType;
+            }
+
+
+            //复制上一个节点为待接办
+            // var newPrevStep =
+            //     await DuplicateStepWithTraceAsync(workflow, prevStep, EWorkflowTraceType.Previous, cancellationToken);
+            var newPrevStep = DuplicateStep(prevStep, EWorkflowTraceType.Previous, dto.ExpiredTime);
+            //退给派单组节点,需按照平均分配原则派给一个派单员 禅道299 TODO
+            if (dto.Handler != null) //todo 改为按策略判断
+            {
+                var handle = dto.Handler;
+                newPrevStep.Assign(handle.UserId, handle.Username, handle.OrgId, handle.OrgName, handle.RoleId, handle.RoleName);
+            }
+
+            await _workflowStepRepository.AddAsync(newPrevStep, cancellationToken);
+            await CreateTraceAsync(workflow, newPrevStep, EWorkflowTraceType.Previous, cancellationToken);
+
+            //remove workflow.steps
+            await _workflowStepRepository.RemoveRangeAsync(removeSteps, cancellationToken);
+
+            var stepIds = removeSteps.Select(d => d.Id).ToList();
+            var updateTraces = workflow.Traces.Where(d => stepIds.Contains(d.StepId)).ToList();
+            await UpdateTracesStateAsync(updateTraces, EWorkflowTraceState.StepRemoveByPrevious, cancellationToken);
+
+            if (workflow.Status is EWorkflowStatus.Completed)
+                workflow.SetStatusRunnable();
+
+            //更新实际办理节点信息
+            workflow.UpdateActualStepWhenAssign(newPrevStep, new FlowStepHandler
+            {
+                UserId = newPrevStep.HandlerId,
+                Username = newPrevStep.HandlerName,
+                OrgId = newPrevStep.HandlerOrgId,
+                OrgName = newPrevStep.HandlerOrgName,
+            });
+
+            workflow.UpdateCurrentStepWhenAssign(newPrevStep, new FlowStepHandler
+            {
+                UserId = newPrevStep.HandlerId,
+                Username = newPrevStep.HandlerName,
+                OrgId = newPrevStep.HandlerOrgId,
+                OrgName = newPrevStep.HandlerOrgName,
+            });
+
+            // //更新流程可办理对象
+            // workflow.UpdatePreviousHandlers(applicantId, applicantOrgId, prevStep);
+
+            //orgToCenter会触发重新计算期满时间,1.无需审核按当前时间进行计算 2.需审核按审核通过时间计算
+            var isOrgToCenter = prevStep.BusinessType is EBusinessType.Send && prevStep.IsOrigin;
+
+            await _workflowRepository.UpdateAsync(workflow, cancellationToken);
+
+            await _publisher.PublishAsync(new PreviousNotify(workflow, newPrevStep, dto, isOrgToCenter),
+                PublishStrategy.ParallelWhenAll, cancellationToken);
+
+            return GetFlowDirection(currentStep.BusinessType, prevStep.BusinessType);
+        }
+
         /// <summary>
         /// 退回(new)
         /// </summary>
         public async Task<EFlowDirection> PreviousAsync(Workflow workflow, PreviousWorkflowDto dto, OperatorInfo operatorInfo,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             //ValidatePermission(workflow, operater.OrgId, operater.Id);
@@ -765,25 +917,31 @@ namespace Hotline.FlowEngine.Workflows
             if (dto.ExpiredTime.HasValue)
                 prevStep.StepExpiredTime = dto.ExpiredTime;
 
-            //if (workflow.FlowType == EFlowType.Handle) //该逻辑需放在退回操作前依据业务判断
-            //{
-            //    prevStep.FlowAssignType = prevStep.BusinessType is EBusinessType.Seat ? EFlowAssignType.Role :
-            //        prevStep.BusinessType is EBusinessType.Send ? EFlowAssignType.User : EFlowAssignType.Org;
-            //}
+            if (workflow.FlowType == EFlowType.Handle) //该逻辑需放在退回操作前依据业务判断
+            {
+                prevStep.FlowAssignType = prevStep.BusinessType is EBusinessType.Seat ? EFlowAssignType.Role :
+                    prevStep.BusinessType is EBusinessType.Send ? EFlowAssignType.User : EFlowAssignType.Org;
+            }
+
+            //甄别退回到最开始节点到部门
+            if (workflow.FlowType == EFlowType.Review && workflow.ModuleCode == WorkflowModuleConsts.OrderScreen)
+            {
+                prevStep.FlowAssignType = prevStep.StepType == EStepType.Start ? EFlowAssignType.Org : prevStep.FlowAssignType;
+            }
 
-            dto.ReverseFlowStepAssignInfo ??= new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser);
-            var prevStepDefine = workflow.WorkflowDefinition.FindStepDefine(prevStep.Code);
-            //todo
-            var stepAssignInfo = GetStepAssignInfo(dto.ReverseFlowStepAssignInfo, prevStep, prevStepDefine);
+            // dto.ReverseFlowStepAssignInfo ??= new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser);
+            // //todo
+            // var stepAssignInfo = GetStepAssignInfo(dto.ReverseFlowStepAssignInfo, prevStep, prevStepDefine);
 
+            var prevStepDefine = workflow.WorkflowDefinition.FindStepDefine(prevStep.Code);
             //复制上一个节点为待接办
             var newPrevStep = DuplicateStep(workflow, prevStepDefine, prevStep, EWorkflowTraceType.Previous, dto.ExpiredTime, stepConfig);
-            ////退给派单组节点,需按照平均分配原则派给一个派单员 禅道299 TODO
-            //if (dto.ReverseFlowStepAssignInfo != null) //todo 改为按策略判断
-            //{
-            //    var handle = dto.ReverseFlowStepAssignInfo.StepAssignInfo;
-            //    newPrevStep.Assign(handle.UserId, handle.Username, handle.OrgId, handle.OrgName, handle.RoleId, handle.RoleName);
-            //}
+            //退给派单组节点,需按照平均分配原则派给一个派单员 禅道299 TODO
+            if (dto.Handler != null) //todo 改为按策略判断
+            {
+                var handle = dto.Handler;
+                newPrevStep.Assign(handle.UserId, handle.Username, handle.OrgId, handle.OrgName, handle.RoleId, handle.RoleName);
+            }
 
             await _workflowStepRepository.AddAsync(newPrevStep, cancellationToken);
             await CreateTraceAsync(workflow, newPrevStep, EWorkflowTraceType.Previous, cancellationToken);
@@ -1337,9 +1495,9 @@ namespace Hotline.FlowEngine.Workflows
         /// <summary>
         /// 撤回(返回到之前任意节点)
         /// </summary>
-        public async Task<bool> RecallAsync(RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
+        public async Task<bool> RecallAsync(RecallDto dto,
             EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             var workflow = await GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
@@ -1353,44 +1511,44 @@ namespace Hotline.FlowEngine.Workflows
             if (targetStep is null)
                 throw UserFriendlyException.SameMessage("该流程尚未流转至该节点");
 
-            return await RecallAsync(workflow, dto, reverseFlowStepAssignInfo, targetStepDefine, targetStep, traceType,
+            return await RecallAsync(workflow, dto, targetStepDefine, targetStep, traceType,
                 expiredTime, isOrderFiled, handleMode, stepConfig, cancellationToken);
         }
 
         /// <summary>
         /// 撤回(返回到之前任意节点)
         /// </summary>
-        public Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
+        public Task<bool> RecallAsync(Workflow workflow, RecallDto dto,
             StepDefine targetStepDefine, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
             if (targetStep is null)
                 throw UserFriendlyException.SameMessage("该流程尚未流转至该节点");
 
-            return RecallAsync(workflow, dto, reverseFlowStepAssignInfo, targetStepDefine, targetStep,
+            return RecallAsync(workflow, dto, targetStepDefine, targetStep,
                 traceType, expiredTime, isOrderFiled, handleMode, stepConfig, cancellationToken);
         }
 
-        public Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
+        public Task<bool> RecallAsync(Workflow workflow, RecallDto dto,
             WorkflowStep targetStep, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             var targetStepDefine = GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
             if (targetStepDefine.StepType is EStepType.End)
                 throw UserFriendlyException.SameMessage("结束节点不支持撤回");
 
-            return RecallAsync(workflow, dto, reverseFlowStepAssignInfo,
+            return RecallAsync(workflow, dto,
                 targetStepDefine, targetStep, traceType,
                 expiredTime, isOrderFiled, handleMode, stepConfig, cancellationToken);
         }
 
-        public async Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
+        public async Task<bool> RecallAsync(Workflow workflow, RecallDto dto,
             StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceType traceType,
             DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             var targetIsStartStep = targetStepDefine.StepType is EStepType.Start;
@@ -1490,7 +1648,7 @@ namespace Hotline.FlowEngine.Workflows
             //        null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceType,
             //        null, expiredTime, cancellationToken: cancellationToken)).First();
 
-            var stepAssignInfo = GetStepAssignInfo(reverseFlowStepAssignInfo, targetStep, targetStepDefine);
+            //var stepAssignInfo = GetStepAssignInfo(reverseFlowStepAssignInfo, targetStep, targetStepDefine);
             var targetStepNew = targetIsStartStep
                 ? await CreateStartStepAsync(workflow, targetStepDefine, dto, assigner,
                     stepAssignInfo, traceType, expiredTime, stepConfig, cancellationToken)
@@ -1867,7 +2025,7 @@ namespace Hotline.FlowEngine.Workflows
             Workflow workflow, StepDefine startStepDefine,
             BasicWorkflowDto dto, UserInfo assigner, FlowStepHandler handler, DateTime? expiredTime,
             EFlowAssignType? flowAssignType = EFlowAssignType.User,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null)
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null)
         {
             //startstep
             var nextSteps = _mapper.Map<List<StepSimple>>(startStepDefine.NextSteps);
@@ -1903,13 +2061,14 @@ namespace Hotline.FlowEngine.Workflows
 
             startStep.InitId();
 
-            if (stepConfig != null)
-            {
-                var stepAssignInfo = stepConfig(workflow, startStepDefine, null);
-                var validator = new StepAssignInfoValidator();
-                validator.ValidateAndThrow(stepAssignInfo);
-                startStep.Assign(stepAssignInfo);
-            }
+            // if (stepConfig != null)
+            // {
+            //     var stepAssignInfo = stepConfig(workflow, startStepDefine, null);
+            //     var validator = new StepAssignInfoValidator();
+            //     validator.ValidateAndThrow(stepAssignInfo);
+            //     startStep.Assign(stepAssignInfo);
+            // }
+            stepConfig?.Invoke(workflow, startStepDefine, null, startStep);
 
             return startStep;
         }
@@ -2273,7 +2432,7 @@ namespace Hotline.FlowEngine.Workflows
         private async Task<WorkflowStep> CreateStartStepAsync(Workflow workflow, StepDefine startStepDefine,
             BasicWorkflowDto dto, UserInfo assigner, StepAssignInfo stepAssignInfo,
             EWorkflowTraceType traceType, DateTime? expiredTime,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             var startStep = CreateStartStep(workflow, startStepDefine, dto, assigner, stepAssignInfo, expiredTime,
@@ -2289,7 +2448,7 @@ namespace Hotline.FlowEngine.Workflows
         private async Task<List<WorkflowStep>> CreateNextStepsAsync(Workflow workflow, WorkflowStep currentStep,
             BasicWorkflowDto dto, StepDefine nextStepDefine, UserInfo assigner, bool isNextDynamic,
             DateTime? expiredTime, bool isStartCountersign, bool isAutoFillSummaryOpinion = false,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             List<WorkflowStep> nextSteps = new();
@@ -2392,7 +2551,7 @@ namespace Hotline.FlowEngine.Workflows
             BasicWorkflowDto dto,
             UserInfo assigner,
             DateTime? expiredTime,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             var handlerType = nextStepDefine.InstancePolicy switch
@@ -2424,7 +2583,7 @@ namespace Hotline.FlowEngine.Workflows
             BasicWorkflowDto dto,
             UserInfo assigner,
             DateTime? expiredTime,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default
         )
         {
@@ -2725,9 +2884,7 @@ namespace Hotline.FlowEngine.Workflows
             return newStep;
         }
 
-        private WorkflowStep DuplicateStep(Workflow workflow, StepDefine stepDefine, WorkflowStep step,
-            EWorkflowTraceType traceType, DateTime? expiredTime,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null)
+        private WorkflowStep DuplicateStep(WorkflowStep step, EWorkflowTraceType traceType, DateTime? expiredTime)
         {
             var newStep = _mapper.Map<WorkflowStep>(step);
             newStep.Reset();
@@ -2742,32 +2899,74 @@ namespace Hotline.FlowEngine.Workflows
             newStep.IsStartedCountersignEnd = step.IsStartedCountersignEnd;
             newStep.StepExpiredTime = expiredTime;
             newStep.InitId();
-            
+
             newStep.Assign(step);
 
-            if (stepConfig != null)
+            //退回场景:指派给原办理人,其余场景:按照原节点原始指派方式复制 //todo 重构为参数传入办理对象
+            if (traceType is EWorkflowTraceType.Previous)
             {
-                //workflow, targetStepDefine, targetStep 
-                var stepAssignInfo = stepConfig(workflow, stepDefine, step);
-                var validator = new StepAssignInfoValidator();
-                validator.ValidateAndThrow(stepAssignInfo);
-                step.Assign(stepAssignInfo);
+                newStep.FlowAssignType = step.FlowAssignType;
+                //    //newStep.FlowAssignType = EFlowAssignType.User;
+                //    // 是否中心  临时紧急修改 后续在流程模版定义是否原办理人退回类型 来实现流程 禅道200
+                //    //newStep.FlowAssignType = step.BusinessType is EBusinessType.Seat or EBusinessType.Send
+                //    //    ? step.BusinessType is EBusinessType.Send ? EFlowAssignType.User : EFlowAssignType.Role
+                //    //    : EFlowAssignType.Org;
+                //    //if (newStep is { FlowAssignType: EFlowAssignType.Role, BusinessType: EBusinessType.Send })
+                //    //    newStep.FlowAssignType = EFlowAssignType.User;
+
+                newStep.Assign(step.HandlerId, step.HandlerName, step.HandlerOrgId, step.HandlerOrgName, step.RoleId, step.RoleName);
             }
 
-            ////退回场景:指派给原办理人,其余场景:按照原节点原始指派方式复制 //todo 重构为参数传入办理对象
-            //if (traceType is EWorkflowTraceType.Previous)
-            //{
-            //    newStep.FlowAssignType = step.FlowAssignType;
-            //    //newStep.FlowAssignType = EFlowAssignType.User;
-            //    // 是否中心  临时紧急修改 后续在流程模版定义是否原办理人退回类型 来实现流程 禅道200
-            //    //newStep.FlowAssignType = step.BusinessType is EBusinessType.Seat or EBusinessType.Send
-            //    //    ? step.BusinessType is EBusinessType.Send ? EFlowAssignType.User : EFlowAssignType.Role
-            //    //    : EFlowAssignType.Org;
-            //    //if (newStep is { FlowAssignType: EFlowAssignType.Role, BusinessType: EBusinessType.Send })
-            //    //    newStep.FlowAssignType = EFlowAssignType.User;
+            return newStep;
+        }
+
+        //new
+        private WorkflowStep DuplicateStep(
+            Workflow workflow, StepDefine stepDefine, WorkflowStep step,
+            EWorkflowTraceType traceType, DateTime? expiredTime,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null)
+        {
+            var newStep = _mapper.Map<WorkflowStep>(step);
+            newStep.Reset();
+            newStep.Status = EWorkflowStepStatus.WaitForAccept;
+            newStep.PrevStepId = step.PrevStepId;
+            newStep.IsMain = step.IsMain;
+            newStep.IsOrigin = step.IsOrigin;
+            //newStep.ParentId = step.ParentId;
+            newStep.Handlers = step.Handlers;
+            newStep.StartCountersignId = step.StartCountersignId;
+            newStep.CountersignId = step.CountersignId;
+            newStep.IsStartedCountersignEnd = step.IsStartedCountersignEnd;
+            newStep.StepExpiredTime = expiredTime;
+            newStep.InitId();
+
+            newStep.Assign(step);
+
+            stepConfig?.Invoke(workflow, stepDefine, step, newStep);
 
-            //    newStep.Assign(step.HandlerId, step.HandlerName, step.HandlerOrgId, step.HandlerOrgName, step.RoleId, step.RoleName);
-            //}
+            // if (stepConfig != null)
+            // {
+            //     //workflow, targetStepDefine, targetStep 
+            //     var stepAssignInfo = stepConfig(workflow, stepDefine, step);
+            //     var validator = new StepAssignInfoValidator();
+            //     validator.ValidateAndThrow(stepAssignInfo);
+            //     step.Assign(stepAssignInfo);
+            // }
+
+            // //退回场景:指派给原办理人,其余场景:按照原节点原始指派方式复制 //todo 重构为参数传入办理对象
+            // if (traceType is EWorkflowTraceType.Previous)
+            // {
+            //     newStep.FlowAssignType = step.FlowAssignType;
+            //     //    //newStep.FlowAssignType = EFlowAssignType.User;
+            //     //    // 是否中心  临时紧急修改 后续在流程模版定义是否原办理人退回类型 来实现流程 禅道200
+            //     //    //newStep.FlowAssignType = step.BusinessType is EBusinessType.Seat or EBusinessType.Send
+            //     //    //    ? step.BusinessType is EBusinessType.Send ? EFlowAssignType.User : EFlowAssignType.Role
+            //     //    //    : EFlowAssignType.Org;
+            //     //    //if (newStep is { FlowAssignType: EFlowAssignType.Role, BusinessType: EBusinessType.Send })
+            //     //    //    newStep.FlowAssignType = EFlowAssignType.User;
+            //
+            //     newStep.Assign(step.HandlerId, step.HandlerName, step.HandlerOrgId, step.HandlerOrgName, step.RoleId, step.RoleName);
+            // }
 
             return newStep;
         }
@@ -3182,7 +3381,7 @@ namespace Hotline.FlowEngine.Workflows
             EWorkflowTraceType traceType,
             DateTime? expiredTime,
             bool isAutoFillSummaryOpinion = false,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default)
         {
             // List<FlowStepHandler> handlers;
@@ -3227,7 +3426,7 @@ namespace Hotline.FlowEngine.Workflows
             EHandlerType? handlerType = null,
             DateTime? expiredTime = null,
             string? opinion = null,
-            Func<Workflow, StepDefine, WorkflowStep, StepAssignInfo>? stepConfig = null,
+            Action<Workflow, StepDefine, WorkflowStep, WorkflowStep>? stepConfig = null,
             CancellationToken cancellationToken = default
         )
         {
@@ -3240,14 +3439,14 @@ namespace Hotline.FlowEngine.Workflows
                     dto.NextStepName, isOrigin, isMain, handlerType, dto.BusinessType, dto.FlowDirection, opinion);
 
                 //workflow,nextStepDefine,currentStep,
-                //stepConfig?.Invoke(workflow, stepDefine, prevStep, step);
-                if (stepConfig != null)
-                {
-                    var stepAssignInfo = stepConfig(workflow, stepDefine, prevStep);
-                    var validator = new StepAssignInfoValidator();
-                    await validator.ValidateAndThrowAsync(stepAssignInfo, cancellationToken);
-                    step.Assign(stepAssignInfo);
-                }
+                stepConfig?.Invoke(workflow, stepDefine, prevStep, step);
+                // if (stepConfig != null)
+                // {
+                //     var stepAssignInfo = stepConfig(workflow, stepDefine, prevStep);
+                //     var validator = new StepAssignInfoValidator();
+                //     await validator.ValidateAndThrowAsync(stepAssignInfo, cancellationToken);
+                //     step.Assign(stepAssignInfo);
+                // }
 
                 steps.Add(step);
             }
@@ -3517,13 +3716,13 @@ namespace Hotline.FlowEngine.Workflows
                 var stepToDuplicate = startCountersignStep.IsCountersignEndStep
                     ? GetCsLoopStartStep(workflow.Steps, startCountersignStep)
                     : startCountersignStep;
-                
+
                 // var stepAssignInfo = GetStepAssignInfo(new ReverseFlowStepAssignInfo
                 // {
                 //     ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.OriginStep
                 // }, stepToDuplicate);
                 //
-                var stepDefine =  workflow.WorkflowDefinition.FindStepDefine(stepToDuplicate.Code);
+                var stepDefine = workflow.WorkflowDefinition.FindStepDefine(stepToDuplicate.Code);
                 var newStep = await DuplicateStepWithTraceAsync(workflow, stepDefine, stepToDuplicate, EWorkflowTraceType.Normal, expireTime,
                     cancellationToken);
 

+ 0 - 1
src/Hotline/Orders/IOrderDomainService.cs

@@ -120,7 +120,6 @@ namespace Hotline.Orders
         /// 查询退回操作目标节点的指派方式
         /// </summary>
         ReverseFlowStepAssignInfo GetOrderPreviousAssignInfo(EBusinessType targetStepBusinessType, StepAssignInfo? handler);
-        ReverseFlowStepAssignInfo GetOrderPreviousAssignInfo(EBusinessType targetStepBusinessType, StepAssignInfo? handler);
 
         /// <summary>
         /// 查询特提操作目标节点的指派方式

Деякі файли не було показано, через те що забагато файлів було змінено