|
@@ -1004,18 +1004,161 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
prevStep.FlowAssignType = prevStep.StepType == EStepType.Start ? EFlowAssignType.Org : prevStep.FlowAssignType;
|
|
|
}
|
|
|
|
|
|
+ dto.ReverseFlowStepAssignInfo ??= new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser);
|
|
|
+ var prevStepDefine = workflow.WorkflowDefinition.FindStepDefine(prevStep.Code);
|
|
|
+ var stepAssignInfo = GetStepAssignInfo(dto.ReverseFlowStepAssignInfo, prevStep, prevStepDefine);
|
|
|
|
|
|
//复制上一个节点为待接办
|
|
|
// 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 newPrevStep = DuplicateStep(prevStep, EWorkflowTraceType.Previous, stepAssignInfo, dto.ExpiredTime);
|
|
|
+ ////退给派单组节点,需按照平均分配原则派给一个派单员 禅道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);
|
|
|
+ //}
|
|
|
+
|
|
|
+ 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
|
|
|
{
|
|
|
- var handle = dto.Handler;
|
|
|
- newPrevStep.Assign(handle.UserId, handle.Username, handle.OrgId, handle.OrgName, handle.RoleId, handle.RoleName);
|
|
|
+ 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,
|
|
|
+ CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ //ValidatePermission(workflow, operater.OrgId, operater.Id);
|
|
|
+ if (string.IsNullOrEmpty(operatorInfo.UserId)
|
|
|
+ && string.IsNullOrEmpty(operatorInfo.OrgId)
|
|
|
+ && !operatorInfo.Roles.Any())
|
|
|
+ throw new UserFriendlyException("无效当前操作人信息");
|
|
|
+
|
|
|
+ var (currentStep, prevStep, countersignStartStep) =
|
|
|
+ GetPreviousStep(workflow, operatorInfo.UserId, operatorInfo.OrgId, operatorInfo.Roles);
|
|
|
+
|
|
|
+ //保存附件
|
|
|
+ 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,
|
|
|
+ operatorInfo.UserId, operatorInfo.UserName,
|
|
|
+ operatorInfo.OrgId, operatorInfo.OrgName,
|
|
|
+ operatorInfo.OrgAreaCode, operatorInfo.OrgAreaName);
|
|
|
+
|
|
|
+ await _workflowCountersignRepository.UpdateAsync(currentCountersign, cancellationToken);
|
|
|
+
|
|
|
+ //update workflow cs status
|
|
|
+ if (workflow.CheckIfCountersignOver())
|
|
|
+ workflow.EndCountersign();
|
|
|
}
|
|
|
|
|
|
+ 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(operatorInfo.UserId, operatorInfo.UserName,
|
|
|
+ operatorInfo.OrgId, operatorInfo.OrgName,
|
|
|
+ operatorInfo.OrgAreaCode, operatorInfo.OrgAreaName,
|
|
|
+ operatorInfo.OrgIsCenter, EHandleMode.Previous, dto.Opinion);
|
|
|
+
|
|
|
+ //如果有传入期满时间 新节点为传入的期满时间
|
|
|
+ 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;
|
|
|
+ //}
|
|
|
+
|
|
|
+ dto.ReverseFlowStepAssignInfo ??= new ReverseFlowStepAssignInfo(EReverseFlowStepCreationPolicy.OriginStepUser);
|
|
|
+ var prevStepDefine = workflow.WorkflowDefinition.FindStepDefine(prevStep.Code);
|
|
|
+ var stepAssignInfo = GetStepAssignInfo(dto.ReverseFlowStepAssignInfo, prevStep, prevStepDefine);
|
|
|
+
|
|
|
+ //复制上一个节点为待接办
|
|
|
+ var newPrevStep = DuplicateStep(prevStep, EWorkflowTraceType.Previous, stepAssignInfo, dto.ExpiredTime);
|
|
|
+ ////退给派单组节点,需按照平均分配原则派给一个派单员 禅道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);
|
|
|
+ //}
|
|
|
+
|
|
|
+ //dto.ReverseFlowStepAssignInfo ??= new ReverseFlowStepAssignInfo
|
|
|
+ //{
|
|
|
+ // ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.OriginStepUser
|
|
|
+ //};
|
|
|
+ //var prevStepDefine = workflow.WorkflowDefinition.FindStepDefine(prevStep.Code);
|
|
|
+ //ReverseFlowAssignStepHandler(dto.ReverseFlowStepAssignInfo, newPrevStep, prevStep, prevStepDefine);
|
|
|
+
|
|
|
await _workflowStepRepository.AddAsync(newPrevStep, cancellationToken);
|
|
|
await CreateTraceAsync(workflow, newPrevStep, EWorkflowTraceType.Previous, cancellationToken);
|
|
|
|
|
@@ -1141,64 +1284,6 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
.ToListAsync(cancellationToken);
|
|
|
}
|
|
|
|
|
|
- ///// <summary>
|
|
|
- ///// 批量改变办理对象
|
|
|
- ///// </summary>
|
|
|
- //public async Task<ICollection<string>> ChangeHandlerRangeAsync(string sendPoolId,
|
|
|
- // IReadOnlyList<(string userId, string username, string orgId, string orgName, IReadOnlyList<string> stepIds)> handlers,
|
|
|
- // CancellationToken cancellationToken)
|
|
|
- //{
|
|
|
- // var stepsIds = handlers.SelectMany(d => d.stepIds).ToList();
|
|
|
- // var steps = await _workflowStepRepository.Queryable()
|
|
|
- // .Includes(d => d.Workflow)
|
|
|
- // .Includes(d => d.WorkflowTrace)
|
|
|
- // //.Includes(d => d.StepHandlers)
|
|
|
- // .Where(d => stepsIds.Contains(d.Id))
|
|
|
- // .ToListAsync(cancellationToken);
|
|
|
- // foreach (var handler in handlers)
|
|
|
- // {
|
|
|
- // var thisHandlers = new List<Kv> { new(handler.userId, handler.username) };
|
|
|
- // var thisHandlerGroup = new HandlerGroupItem
|
|
|
- // {
|
|
|
- // GroupId = Guid.NewGuid().ToString(),
|
|
|
- // Key = handler.userId,
|
|
|
- // Value = handler.username,
|
|
|
- // };
|
|
|
- // var thisSteps = steps.Where(d => handler.stepIds.Contains(d.Id)).ToList();
|
|
|
- // foreach (var thisStep in thisSteps)
|
|
|
- // {
|
|
|
- // //var stepHandler = WorkflowStepHandler.Create(thisStep.Workflow.Id, thisStep.Workflow.ExternalId,
|
|
|
- // // thisStep.FlowAssignType ?? EFlowAssignType.User, handler.userId, handler.username, handler.orgId, handler.orgName);
|
|
|
- // //thisStep.StepHandlers.Clear();
|
|
|
- // //thisStep.StepHandlers.Add(stepHandler);
|
|
|
-
|
|
|
- // thisStep.Handlers = thisHandlers;
|
|
|
-
|
|
|
- // //update trace
|
|
|
- // thisStep.WorkflowTrace.Handlers = thisStep.Handlers;
|
|
|
-
|
|
|
- // // update workflow
|
|
|
- // thisStep.Workflow.FlowedUserIds.Remove(sendPoolId);
|
|
|
- // thisStep.Workflow.FlowedUserIds.Add(handler.userId);
|
|
|
- // thisStep.Workflow.UpdateHandlers(sendPoolId, null, EFlowAssignType.User,
|
|
|
- // new List<HandlerGroupItem> { thisHandlerGroup }, true);
|
|
|
-
|
|
|
- // var handlerUser = thisStep.Workflow.HandlerUsers.FirstOrDefault(d => d.Key == sendPoolId);
|
|
|
- // if (handlerUser == null) continue;
|
|
|
- // handlerUser.Key = handler.userId;
|
|
|
- // handlerUser.Value = handler.username;
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // await _workflowStepRepository.UpdateNav(steps)
|
|
|
- // .Include(d => d.WorkflowTrace)
|
|
|
- // .Include(d => d.Workflow)
|
|
|
- // //.Include(d => d.StepHandlers)
|
|
|
- // .ExecuteCommandAsync();
|
|
|
-
|
|
|
- // return steps.Select(d => d.WorkflowId).ToList();
|
|
|
- //}
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// 批量修改工单办理对象
|
|
|
/// </summary>
|
|
@@ -1300,8 +1385,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
/// 查询该部门最后办理节点
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
- public async Task<WorkflowStep> FindLastHandleStepAsync(string workflowId, string orgId,
|
|
|
- CancellationToken cancellation)
|
|
|
+ public async Task<WorkflowStep> FindLastHandleStepAsync(string workflowId, string orgId, CancellationToken cancellation)
|
|
|
{
|
|
|
return await _workflowStepRepository.Queryable()
|
|
|
.Where(d => d.WorkflowId == workflowId
|
|
@@ -1606,42 +1690,220 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
/// <summary>
|
|
|
/// 撤回(返回到之前任意节点)
|
|
|
/// </summary>
|
|
|
- public async Task RecallAsync(Workflow workflow, RecallDto dto, StepDefine targetStepDefine,
|
|
|
- FlowAssignInfo flowAssignInfo, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled,
|
|
|
+ public async Task<bool> RecallAsync(RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
|
|
|
+ EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode,
|
|
|
+ CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ var workflow = await GetWorkflowAsync(dto.WorkflowId, withDefine: true, withSteps: true,
|
|
|
+ withTraces: true, withCountersigns: true, cancellationToken: cancellationToken);
|
|
|
+
|
|
|
+ var targetStepDefine = GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
|
|
|
+ if (targetStepDefine.StepType is EStepType.End)
|
|
|
+ throw UserFriendlyException.SameMessage("结束节点不支持撤回");
|
|
|
+
|
|
|
+ var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
|
|
|
+ if (targetStep is null)
|
|
|
+ throw UserFriendlyException.SameMessage("该流程尚未流转至该节点");
|
|
|
+
|
|
|
+ return await RecallAsync(workflow, dto, reverseFlowStepAssignInfo, targetStepDefine, targetStep, traceType,
|
|
|
+ expiredTime, isOrderFiled, handleMode, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 撤回(返回到之前任意节点)
|
|
|
+ /// </summary>
|
|
|
+ public Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
|
|
|
+ StepDefine targetStepDefine, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled,
|
|
|
EHandleMode handleMode, CancellationToken cancellationToken)
|
|
|
{
|
|
|
var targetStep = workflow.Steps.FirstOrDefault(d => d.Code == dto.NextStepCode && d.IsOrigin);
|
|
|
if (targetStep is null)
|
|
|
throw UserFriendlyException.SameMessage("该流程尚未流转至该节点");
|
|
|
|
|
|
- //update uncompleted traces
|
|
|
- //await RecallTraceAsync(workflow.Traces, dto.Opinion, _sessionContext, cancellationToken);
|
|
|
+ //var isOrgToCenter = await RecallAsync(workflow, dto, reverseFlowStepAssignInfo, targetStepDefine, targetStep,
|
|
|
+ // traceType, expiredTime, isOrderFiled, handleMode, cancellationToken);
|
|
|
+
|
|
|
+ //await _workflowRepository.UpdateAsync(workflow, cancellationToken);
|
|
|
|
|
|
- var isOrgToCenter = await RecallAsync(workflow, dto, flowAssignInfo, targetStepDefine, targetStep,
|
|
|
+ //await _publisher.PublishAsync(new RecallNotify(workflow, targetStep, dto, isOrgToCenter),
|
|
|
+ // PublishStrategy.ParallelWhenAll, cancellationToken);
|
|
|
+
|
|
|
+ //return isOrgToCenter;
|
|
|
+
|
|
|
+ return RecallAsync(workflow, dto, reverseFlowStepAssignInfo, targetStepDefine, targetStep,
|
|
|
traceType, expiredTime, isOrderFiled, handleMode, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
|
|
|
+ WorkflowStep targetStep, EWorkflowTraceType traceType, DateTime? expiredTime, bool isOrderFiled,
|
|
|
+ EHandleMode handleMode, CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ var targetStepDefine = GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
|
|
|
+ if (targetStepDefine.StepType is EStepType.End)
|
|
|
+ throw UserFriendlyException.SameMessage("结束节点不支持撤回");
|
|
|
+
|
|
|
+ return RecallAsync(workflow, dto, reverseFlowStepAssignInfo,
|
|
|
+ targetStepDefine, targetStep, traceType,
|
|
|
+ expiredTime, isOrderFiled, handleMode, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ public async Task<bool> RecallAsync(Workflow workflow, RecallDto dto, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
|
|
|
+ StepDefine targetStepDefine, WorkflowStep targetStep, EWorkflowTraceType traceType,
|
|
|
+ DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode, CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ var targetIsStartStep = targetStepDefine.StepType is EStepType.Start;
|
|
|
+ var updateTraces = new List<WorkflowTrace>();
|
|
|
+
|
|
|
+ //update uncomplete traces
|
|
|
+ var uncompleteTraces = workflow.Traces.Where(d => d.Status != EWorkflowStepStatus.Handled).ToList();
|
|
|
+ if (uncompleteTraces.Any())
|
|
|
+ {
|
|
|
+ foreach (var trace in uncompleteTraces)
|
|
|
+ {
|
|
|
+ trace.Handle(
|
|
|
+ _sessionContextProvider.SessionContext.RequiredUserId, _sessionContextProvider.SessionContext.UserName,
|
|
|
+ _sessionContextProvider.SessionContext.RequiredOrgId, _sessionContextProvider.SessionContext.OrgName,
|
|
|
+ _sessionContextProvider.SessionContext.OrgAreaCode, _sessionContextProvider.SessionContext.OrgAreaName,
|
|
|
+ _sessionContextProvider.SessionContext.OrgIsCenter, handleMode, dto.Opinion);
|
|
|
+ }
|
|
|
+
|
|
|
+ //await _workflowTraceRepository.UpdateRangeAsync(uncompleteTraces, cancellationToken);
|
|
|
+ updateTraces.AddRange(uncompleteTraces);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var endTrace = workflow.Traces.Where(d => d.StepType == EStepType.End).MaxBy(d => d.CreationTime);
|
|
|
+ if (endTrace is not null)
|
|
|
+ {
|
|
|
+ endTrace.Opinion += ("\r\n" + dto.Opinion);
|
|
|
+ updateTraces.Add(endTrace);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //get targetStep's previous
|
|
|
+ WorkflowStep? targetPrevStep = null;
|
|
|
+ if (!targetIsStartStep)
|
|
|
+ {
|
|
|
+ targetPrevStep = workflow.Steps.FirstOrDefault(d => d.Id == targetStep.PrevStepId);
|
|
|
+ if (targetPrevStep == null)
|
|
|
+ throw new UserFriendlyException($"{nameof(RecallAsync)}, 未找到目标节点的前一节点, flowId: {workflow.Id}");
|
|
|
+ }
|
|
|
+
|
|
|
+ //查询所有目标节点之后的节点,然后删掉(包括目标节点)
|
|
|
+ var removeSteps = GetStepsBehindTargetStep(workflow.Steps, targetStep);
|
|
|
+ if (removeSteps.Any())
|
|
|
+ {
|
|
|
+ await _workflowStepRepository.RemoveRangeAsync(removeSteps, cancellationToken);
|
|
|
+ workflow.Steps.RemoveAll(d => removeSteps.Contains(d));
|
|
|
+
|
|
|
+ //更新快照对应节点状态
|
|
|
+ var stepIds = removeSteps.Select(d => d.Id).ToList();
|
|
|
+ var traces = workflow.Traces.Where(d => stepIds.Contains(d.StepId)).ToList();
|
|
|
+ //await UpdateTracesStateAsync(updateTraces, EWorkflowTraceState.StepRemoveByRecall, cancellationToken);
|
|
|
+ foreach (var trace in traces)
|
|
|
+ {
|
|
|
+ trace.TraceState = isOrderFiled
|
|
|
+ ? EWorkflowTraceState.StepRemoveByRecallWhenFiled
|
|
|
+ : EWorkflowTraceState.StepRemoveByRecall;
|
|
|
+ }
|
|
|
+
|
|
|
+ updateTraces.AddRange(traces);
|
|
|
+ }
|
|
|
+
|
|
|
+ await _workflowTraceRepository.UpdateRangeAsync(updateTraces, cancellationToken);
|
|
|
+
|
|
|
+ //结束会签
|
|
|
+ var unCompleteCountersigns = workflow.Countersigns.Where(d => !d.IsCompleted()).ToList();
|
|
|
+ if (unCompleteCountersigns.Any())
|
|
|
+ {
|
|
|
+ foreach (var unCompleteCountersign in unCompleteCountersigns)
|
|
|
+ {
|
|
|
+ unCompleteCountersign.End(null, null, EBusinessType.File,
|
|
|
+ _sessionContextProvider.SessionContext.RequiredUserId, _sessionContextProvider.SessionContext.UserName,
|
|
|
+ _sessionContextProvider.SessionContext.RequiredOrgId, _sessionContextProvider.SessionContext.OrgName,
|
|
|
+ _sessionContextProvider.SessionContext.OrgAreaCode, _sessionContextProvider.SessionContext.OrgAreaName);
|
|
|
+ }
|
|
|
+
|
|
|
+ await _workflowCountersignRepository.UpdateRangeAsync(unCompleteCountersigns, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ workflow.EndCountersign();
|
|
|
+ workflow.ResetOption();
|
|
|
+ if (workflow.Status is EWorkflowStatus.Completed)
|
|
|
+ workflow.SetStatusRunnable();
|
|
|
+
|
|
|
+ var assigner = new UserInfo(
|
|
|
+ _sessionContextProvider.SessionContext.UserId,
|
|
|
+ _sessionContextProvider.SessionContext.UserName,
|
|
|
+ _sessionContextProvider.SessionContext.OrgId,
|
|
|
+ _sessionContextProvider.SessionContext.OrgName,
|
|
|
+ _sessionContextProvider.SessionContext.OrgIsCenter
|
|
|
+ );
|
|
|
+
|
|
|
+ //var targetStepNew = targetIsStartStep
|
|
|
+ // ? await CreateStartStepAsync(workflow, targetStepDefine, dto, assigner,
|
|
|
+ // dto.NextHandlers.First(), traceType, expiredTime, flowAssignInfo.FlowAssignType, cancellationToken)
|
|
|
+ // : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto, assigner,
|
|
|
+ // flowAssignInfo.FlowAssignType, dto.NextHandlers,
|
|
|
+ // null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceType,
|
|
|
+ // null, expiredTime, cancellationToken: cancellationToken)).First();
|
|
|
+
|
|
|
+ var stepAssignInfo = GetStepAssignInfo(reverseFlowStepAssignInfo, targetStep, targetStepDefine);
|
|
|
+ var targetStepNew = targetIsStartStep
|
|
|
+ ? await CreateStartStepAsync(workflow, targetStepDefine, dto, assigner,
|
|
|
+ stepAssignInfo, traceType, expiredTime, stepAssignInfo.FlowAssignType, cancellationToken)
|
|
|
+ : (await CreateStepsAsync(workflow, targetStepDefine, targetPrevStep, dto, assigner,
|
|
|
+ stepAssignInfo.FlowAssignType, [stepAssignInfo],
|
|
|
+ null, EWorkflowStepStatus.WaitForAccept, ECountersignPosition.None, true, traceType,
|
|
|
+ null, expiredTime, cancellationToken: cancellationToken)).First();
|
|
|
+
|
|
|
+ //更新实际办理节点信息
|
|
|
+ workflow.UpdateActualStepWhenAssign(targetStepNew, new FlowStepHandler
|
|
|
+ {
|
|
|
+ UserId = targetStep.HandlerId,
|
|
|
+ Username = targetStep.HandlerName,
|
|
|
+ OrgId = targetStep.HandlerOrgId,
|
|
|
+ OrgName = targetStep.HandlerOrgName
|
|
|
+ });
|
|
|
+
|
|
|
+ workflow.UpdateCurrentStepWhenAssign(targetStepNew, new FlowStepHandler
|
|
|
+ {
|
|
|
+ UserId = targetStep.HandlerId,
|
|
|
+ Username = targetStep.HandlerName,
|
|
|
+ OrgId = targetStep.HandlerOrgId,
|
|
|
+ OrgName = targetStep.HandlerOrgName
|
|
|
+ });
|
|
|
+
|
|
|
+ //取消维护workflow得冗余字段(FlowedOrgIds, HandlerOrgs)
|
|
|
+ //workflow.Assign(flowAssignInfo.FlowAssignType, flowAssignInfo.GetHandlerIds());
|
|
|
+ //workflow.ResetHandlers(flowAssignInfo.FlowAssignType, flowAssignInfo.HandlerObjects);
|
|
|
|
|
|
await _workflowRepository.UpdateAsync(workflow, cancellationToken);
|
|
|
|
|
|
+ //calc workflow expired time
|
|
|
+ var isOrgToCenter = CheckIfFlowFromOrgToCenter(workflow, targetStep);
|
|
|
+
|
|
|
await _publisher.PublishAsync(new RecallNotify(workflow, targetStep, dto, isOrgToCenter),
|
|
|
PublishStrategy.ParallelWhenAll, cancellationToken);
|
|
|
+
|
|
|
+ return isOrgToCenter;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 撤回至开始节点
|
|
|
/// </summary>
|
|
|
- public async Task RecallToStartStepAsync(string workflowId, string opinion, bool isOrderFiled, DateTime? expiredTime,
|
|
|
- EHandleMode handleMode, CancellationToken cancellationToken)
|
|
|
+ public async Task RecallToStartStepAsync(Workflow workflow, string opinion, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
|
|
|
+ DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode, CancellationToken cancellationToken)
|
|
|
{
|
|
|
//todo 1.当前待办节点删掉 2.当前待办trace更新(status, opinion) 3.复制startStep为待办 4.更新workflow(status, csStatus, handlers) 5.publish event
|
|
|
- var workflow = await GetWorkflowAsync(workflowId, withDefine: true, withSteps: true, withTraces: true, withCountersigns: true,
|
|
|
- cancellationToken: cancellationToken);
|
|
|
- var startStep = workflow.Steps.First(d => d.StepType == EStepType.Start);
|
|
|
+ var startStep = workflow.Steps.Where(d => d.StepType == EStepType.Start && d.IsOrigin)
|
|
|
+ .MaxBy(d => d.CreationTime);
|
|
|
if (startStep is null)
|
|
|
- throw new UserFriendlyException($"数据异常, workflowId: {workflowId}", "该流程无开始节点");
|
|
|
+ throw new UserFriendlyException($"数据异常, workflowId: {workflow.Id}", "该流程无开始节点");
|
|
|
|
|
|
//await RecallToTargetStepAsync(workflow, startStep, opinion, current, cancellationToken);
|
|
|
|
|
|
- var targetStepDefine = workflow.WorkflowDefinition.Steps.FirstOrDefault(d => d.StepType == EStepType.Start);
|
|
|
+ var startStepDefine = workflow.WorkflowDefinition.Steps.FirstOrDefault(d => d.StepType == EStepType.Start);
|
|
|
var dto = new RecallDto
|
|
|
{
|
|
|
Opinion = opinion,
|
|
@@ -1649,7 +1911,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
NextStepName = startStep.Name,
|
|
|
BusinessType = startStep.BusinessType,
|
|
|
StepType = startStep.StepType,
|
|
|
- HandlerType = targetStepDefine.HandlerType,
|
|
|
+ HandlerType = startStepDefine.HandlerType,
|
|
|
NextHandlers = new List<FlowStepHandler>
|
|
|
{
|
|
|
new FlowStepHandler
|
|
@@ -1665,28 +1927,30 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
- var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
|
|
|
- dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
|
|
|
- //flowAssignInfo.FlowAssignType = EFlowAssignType.Role;
|
|
|
- await RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
- handleMode, cancellationToken);
|
|
|
+ //var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
|
|
|
+ // dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
|
|
|
+ ////flowAssignInfo.FlowAssignType = EFlowAssignType.Role;
|
|
|
+ //await RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
+ // handleMode, cancellationToken);
|
|
|
+ await RecallAsync(workflow, dto, reverseFlowStepAssignInfo, startStepDefine, startStep,
|
|
|
+ EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
+ handleMode, cancellationToken);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 撤回至派单节点
|
|
|
/// </summary>
|
|
|
- public async Task RecallToSendStepAsync(string workflowId, string opinion, bool isOrderFiled, DateTime? expiredTime,
|
|
|
- EHandleMode handleMode, CancellationToken cancellationToken)
|
|
|
+ public async Task RecallToSendStepAsync(Workflow workflow, string opinion, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
|
|
|
+ DateTime? expiredTime, bool isOrderFiled, EHandleMode handleMode, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- var workflow = await GetWorkflowAsync(workflowId, withDefine: true, withSteps: true, withTraces: true, withCountersigns: true,
|
|
|
- cancellationToken: cancellationToken);
|
|
|
- var sendStep = workflow.Steps.FirstOrDefault(d => d.BusinessType == EBusinessType.Send);
|
|
|
+ var sendStep = workflow.Steps.Where(d => d.BusinessType == EBusinessType.Send && d.IsOrigin)
|
|
|
+ .MaxBy(d => d.CreationTime);
|
|
|
if (sendStep is null)
|
|
|
- throw new UserFriendlyException($"未找到派单节点, workflowId: {workflowId}", "该流程无派单节点");
|
|
|
+ throw new UserFriendlyException($"未找到派单节点, workflowId: {workflow.Id}", "该流程无派单节点");
|
|
|
|
|
|
//await RecallToTargetStepAsync(workflow, sendStep, opinion, current, cancellationToken);
|
|
|
|
|
|
- var targetStepDefine = workflow.WorkflowDefinition.Steps.FirstOrDefault(d => d.BusinessType == EBusinessType.Send);
|
|
|
+ var sendStepDefine = workflow.WorkflowDefinition.Steps.FirstOrDefault(d => d.BusinessType == EBusinessType.Send);
|
|
|
var dto = new RecallDto
|
|
|
{
|
|
|
Opinion = opinion,
|
|
@@ -1694,7 +1958,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
NextStepName = sendStep.Name,
|
|
|
BusinessType = sendStep.BusinessType,
|
|
|
StepType = sendStep.StepType,
|
|
|
- HandlerType = targetStepDefine.HandlerType,
|
|
|
+ HandlerType = sendStepDefine.HandlerType,
|
|
|
NextHandlers = new List<FlowStepHandler>
|
|
|
{
|
|
|
new FlowStepHandler
|
|
@@ -1710,10 +1974,14 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
- var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
|
|
|
- dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
|
|
|
- //flowAssignInfo.FlowAssignType = EFlowAssignType.Role;
|
|
|
- await RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
+ //var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
|
|
|
+ // dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
|
|
|
+ ////flowAssignInfo.FlowAssignType = EFlowAssignType.Role;
|
|
|
+ //await RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
+ // handleMode, cancellationToken);
|
|
|
+
|
|
|
+ await RecallAsync(workflow, dto, reverseFlowStepAssignInfo, sendStepDefine, sendStep,
|
|
|
+ EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
handleMode, cancellationToken);
|
|
|
}
|
|
|
|
|
@@ -1721,87 +1989,93 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
/// 特提至中心(优先派单组其次坐席)
|
|
|
/// </summary>
|
|
|
/// <returns>true 派单组 false 话务部</returns>
|
|
|
- public async Task<(bool, Workflow workflow)> RecallToCenterFirstToSendAsync(string workflowId, string opinion, bool isOrderFiled,
|
|
|
- DateTime? expiredTime, List<FlowStepHandler>? handlers, EHandleMode handleMode, CancellationToken cancellationToken)
|
|
|
+ public async Task<(bool, Workflow workflow)> RecallToCenterFirstToSendAsync(string workflowId, string opinion, ReverseFlowStepAssignInfo reverseFlowStepAssignInfo,
|
|
|
+ bool isOrderFiled, DateTime? expiredTime, EHandleMode handleMode, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- bool isPaiDan = true;
|
|
|
+ var isPaiDan = false;
|
|
|
var workflow = await GetWorkflowAsync(workflowId, withDefine: true, withSteps: true, withTraces: true, withCountersigns: true,
|
|
|
cancellationToken: cancellationToken);
|
|
|
- var sendStep = workflow.Steps.FirstOrDefault(d => d.BusinessType == EBusinessType.Send);
|
|
|
- if (sendStep is not null)
|
|
|
+ var hasSendStep = workflow.Steps.Any(d => d.BusinessType == EBusinessType.Send);
|
|
|
+ if (hasSendStep)
|
|
|
{
|
|
|
- var targetStepDefine = workflow.WorkflowDefinition.Steps.FirstOrDefault(d => d.BusinessType == EBusinessType.Send);
|
|
|
- var dto = new RecallDto
|
|
|
- {
|
|
|
- Opinion = opinion,
|
|
|
- NextStepCode = sendStep.Code,
|
|
|
- NextStepName = sendStep.Name,
|
|
|
- BusinessType = sendStep.BusinessType,
|
|
|
- StepType = sendStep.StepType,
|
|
|
- HandlerType = targetStepDefine.HandlerType,
|
|
|
- NextHandlers = new List<FlowStepHandler>
|
|
|
- {
|
|
|
- new FlowStepHandler
|
|
|
- {
|
|
|
- Key = sendStep.RoleId,
|
|
|
- Value = sendStep.RoleName,
|
|
|
- RoleId = sendStep.RoleId,
|
|
|
- RoleName = sendStep.RoleName,
|
|
|
- UserId = sendStep.HandlerId,
|
|
|
- Username = sendStep.HandlerName,
|
|
|
- OrgId = sendStep.HandlerOrgId,
|
|
|
- OrgName = sendStep.HandlerOrgName,
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- if (_appOptions.Value.IsZiGong && handlers != null && handlers.Any())
|
|
|
- {
|
|
|
- dto.NextHandlers = handlers;
|
|
|
- }
|
|
|
-
|
|
|
- var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
|
|
|
- dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
|
|
|
- await RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
- handleMode, cancellationToken);
|
|
|
+ //var targetStepDefine = workflow.WorkflowDefinition.Steps.FirstOrDefault(d => d.BusinessType == EBusinessType.Send);
|
|
|
+ //var dto = new RecallDto
|
|
|
+ //{
|
|
|
+ // Opinion = opinion,
|
|
|
+ // NextStepCode = sendStep.Code,
|
|
|
+ // NextStepName = sendStep.Name,
|
|
|
+ // BusinessType = sendStep.BusinessType,
|
|
|
+ // StepType = sendStep.StepType,
|
|
|
+ // HandlerType = targetStepDefine.HandlerType,
|
|
|
+ // NextHandlers = new List<FlowStepHandler>
|
|
|
+ // {
|
|
|
+ // new FlowStepHandler
|
|
|
+ // {
|
|
|
+ // Key = sendStep.RoleId,
|
|
|
+ // Value = sendStep.RoleName,
|
|
|
+ // RoleId = sendStep.RoleId,
|
|
|
+ // RoleName = sendStep.RoleName,
|
|
|
+ // UserId = sendStep.HandlerId,
|
|
|
+ // Username = sendStep.HandlerName,
|
|
|
+ // OrgId = sendStep.HandlerOrgId,
|
|
|
+ // OrgName = sendStep.HandlerOrgName,
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ //};
|
|
|
+ //if (_appOptions.Value.IsZiGong && handlers != null && handlers.Any())
|
|
|
+ //{
|
|
|
+ // dto.NextHandlers = handlers;
|
|
|
+ //}
|
|
|
+
|
|
|
+ //var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
|
|
|
+ // dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
|
|
|
+ //await RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
+ // handleMode, cancellationToken);
|
|
|
+
|
|
|
+ await RecallToSendStepAsync(workflow, opinion, reverseFlowStepAssignInfo, expiredTime, isOrderFiled,
|
|
|
+ handleMode, cancellationToken);
|
|
|
+ isPaiDan = true;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- var startStep = workflow.Steps.First(d => d.StepType == EStepType.Start);
|
|
|
- if (startStep is null)
|
|
|
- throw new UserFriendlyException($"数据异常, workflowId: {workflowId}", "该流程无开始节点");
|
|
|
-
|
|
|
- //await RecallToTargetStepAsync(workflow, startStep, opinion, current, cancellationToken);
|
|
|
-
|
|
|
- var targetStepDefine = workflow.WorkflowDefinition.Steps.FirstOrDefault(d => d.StepType == EStepType.Start);
|
|
|
- var dto = new RecallDto
|
|
|
- {
|
|
|
- Opinion = opinion,
|
|
|
- NextStepCode = startStep.Code,
|
|
|
- NextStepName = startStep.Name,
|
|
|
- BusinessType = startStep.BusinessType,
|
|
|
- StepType = startStep.StepType,
|
|
|
- HandlerType = targetStepDefine.HandlerType,
|
|
|
- NextHandlers = new List<FlowStepHandler>
|
|
|
- {
|
|
|
- new FlowStepHandler
|
|
|
- {
|
|
|
- Key = startStep.RoleId,
|
|
|
- Value = startStep.RoleName,
|
|
|
- RoleId = startStep.RoleId,
|
|
|
- RoleName = startStep.RoleName,
|
|
|
- UserId = startStep.HandlerId,
|
|
|
- Username = startStep.HandlerName,
|
|
|
- OrgId = startStep.HandlerOrgId,
|
|
|
- OrgName = startStep.HandlerOrgName,
|
|
|
- }
|
|
|
- }
|
|
|
- };
|
|
|
- var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
|
|
|
- dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
|
|
|
- //flowAssignInfo.FlowAssignType = EFlowAssignType.Role;
|
|
|
- await RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
- handleMode, cancellationToken);
|
|
|
- isPaiDan = false;
|
|
|
+ //var startStep = workflow.Steps.First(d => d.StepType == EStepType.Start);
|
|
|
+ //if (startStep is null)
|
|
|
+ // throw new UserFriendlyException($"数据异常, workflowId: {workflowId}", "该流程无开始节点");
|
|
|
+
|
|
|
+ ////await RecallToTargetStepAsync(workflow, startStep, opinion, current, cancellationToken);
|
|
|
+
|
|
|
+ //var targetStepDefine = workflow.WorkflowDefinition.Steps.FirstOrDefault(d => d.StepType == EStepType.Start);
|
|
|
+ //var dto = new RecallDto
|
|
|
+ //{
|
|
|
+ // Opinion = opinion,
|
|
|
+ // NextStepCode = startStep.Code,
|
|
|
+ // NextStepName = startStep.Name,
|
|
|
+ // BusinessType = startStep.BusinessType,
|
|
|
+ // StepType = startStep.StepType,
|
|
|
+ // HandlerType = targetStepDefine.HandlerType,
|
|
|
+ // NextHandlers = new List<FlowStepHandler>
|
|
|
+ // {
|
|
|
+ // new FlowStepHandler
|
|
|
+ // {
|
|
|
+ // Key = startStep.RoleId,
|
|
|
+ // Value = startStep.RoleName,
|
|
|
+ // RoleId = startStep.RoleId,
|
|
|
+ // RoleName = startStep.RoleName,
|
|
|
+ // UserId = startStep.HandlerId,
|
|
|
+ // Username = startStep.HandlerName,
|
|
|
+ // OrgId = startStep.HandlerOrgId,
|
|
|
+ // OrgName = startStep.HandlerOrgName,
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ //};
|
|
|
+ //var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.HandlerType, dto.IsStartCountersign,
|
|
|
+ // dto.NextHandlers.Select(d => new Kv(d.Key, d.Value)).ToList(), cancellationToken);
|
|
|
+ ////flowAssignInfo.FlowAssignType = EFlowAssignType.Role;
|
|
|
+ //await RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, EWorkflowTraceType.Recall, expiredTime, isOrderFiled,
|
|
|
+ // handleMode, cancellationToken);
|
|
|
+ await RecallToStartStepAsync(workflow, opinion, reverseFlowStepAssignInfo, expiredTime, isOrderFiled,
|
|
|
+ handleMode, cancellationToken);
|
|
|
+ //isPaiDan = false;
|
|
|
}
|
|
|
|
|
|
return (new(isPaiDan, workflow));
|
|
@@ -2177,6 +2451,92 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
|
|
|
#region private method
|
|
|
|
|
|
+ private StepAssignInfo GetStepAssignInfo(ReverseFlowStepAssignInfo assignInfo,
|
|
|
+ WorkflowStep? targetStep = null, StepDefine? targetStepDefine = null)
|
|
|
+ {
|
|
|
+ switch (assignInfo.ReverseFlowStepCreationPolicy)
|
|
|
+ {
|
|
|
+ case EReverseFlowStepCreationPolicy.OriginStep:
|
|
|
+ if (targetStep is null)
|
|
|
+ throw new UserFriendlyException("参数异常:原节点信息为空");
|
|
|
+ return GetStepAssignInfo(targetStep);
|
|
|
+ case EReverseFlowStepCreationPolicy.OriginStepUser:
|
|
|
+ if (string.IsNullOrEmpty(targetStep?.HandlerId))
|
|
|
+ throw new UserFriendlyException("参数异常:原节点办理人为空");
|
|
|
+ return GetStepAssignInfo(targetStep, EFlowAssignType.User);
|
|
|
+ case EReverseFlowStepCreationPolicy.OriginStepOrg:
|
|
|
+ if (string.IsNullOrEmpty(targetStep?.HandlerOrgId))
|
|
|
+ throw new UserFriendlyException("参数异常:原节点办理部门为空");
|
|
|
+ return GetStepAssignInfo(targetStep, EFlowAssignType.Org);
|
|
|
+ case EReverseFlowStepCreationPolicy.OriginStepRole:
|
|
|
+ if (string.IsNullOrEmpty(targetStep?.RoleId))
|
|
|
+ throw new UserFriendlyException("参数异常:原节点办理角色为空");
|
|
|
+ return GetStepAssignInfo(targetStep, EFlowAssignType.Role);
|
|
|
+ case EReverseFlowStepCreationPolicy.OriginStepOrgAndRole:
|
|
|
+ if (string.IsNullOrEmpty(targetStep?.RoleId) || string.IsNullOrEmpty(targetStep?.HandlerOrgId))
|
|
|
+ throw new UserFriendlyException("参数异常:原节点办理角色或部门为空");
|
|
|
+ return GetStepAssignInfo(targetStep, EFlowAssignType.OrgAndRole);
|
|
|
+ case EReverseFlowStepCreationPolicy.AssignHandler:
|
|
|
+ if (assignInfo?.StepAssignInfo is null)
|
|
|
+ throw new UserFriendlyException("参数异常:节点指定办理对象信息为空");
|
|
|
+ return assignInfo.StepAssignInfo;
|
|
|
+ case EReverseFlowStepCreationPolicy.OriginDefinition:
|
|
|
+ if (targetStepDefine is null)
|
|
|
+ throw new UserFriendlyException("参数异常:节点配置信息为空");
|
|
|
+ return GetStepAssignInfo(targetStepDefine);
|
|
|
+ default:
|
|
|
+ throw new ArgumentOutOfRangeException();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private StepAssignInfo GetStepAssignInfo(StepDefine stepDefine)
|
|
|
+ {
|
|
|
+ var handler = stepDefine.HandlerTypeItems.FirstOrDefault();
|
|
|
+ if (handler is null)
|
|
|
+ throw new UserFriendlyException($"未正确配置节点办理对象, stepcode: {stepDefine.Code}", "未正确配置节点办理对象");
|
|
|
+ var rsp = new StepAssignInfo();
|
|
|
+ switch (stepDefine.HandlerType)
|
|
|
+ {
|
|
|
+ case EHandlerType.Role:
|
|
|
+ rsp.FlowAssignType = EFlowAssignType.Role;
|
|
|
+ rsp.RoleId = handler.Key;
|
|
|
+ rsp.RoleName = handler.Value;
|
|
|
+ break;
|
|
|
+ case EHandlerType.AssignedUser:
|
|
|
+ rsp.FlowAssignType = EFlowAssignType.User;
|
|
|
+ rsp.UserId = handler.Key;
|
|
|
+ rsp.Username = handler.Value;
|
|
|
+ break;
|
|
|
+ case EHandlerType.AssignedOrg:
|
|
|
+ rsp.FlowAssignType = EFlowAssignType.Org;
|
|
|
+ rsp.OrgId = handler.Key;
|
|
|
+ rsp.OrgName = handler.Value;
|
|
|
+ break;
|
|
|
+ case EHandlerType.OrgType:
|
|
|
+ throw new ArgumentOutOfRangeException("部门类型不支持按配置指派");
|
|
|
+ case EHandlerType.OrgLevel:
|
|
|
+ throw new ArgumentOutOfRangeException("部门等级不支持按配置指派");
|
|
|
+ default:
|
|
|
+ throw new ArgumentOutOfRangeException();
|
|
|
+ }
|
|
|
+
|
|
|
+ return rsp;
|
|
|
+ }
|
|
|
+
|
|
|
+ private StepAssignInfo GetStepAssignInfo(WorkflowStep targetStep, EFlowAssignType? flowAssignType = null)
|
|
|
+ {
|
|
|
+ return new StepAssignInfo
|
|
|
+ {
|
|
|
+ FlowAssignType = (flowAssignType ?? targetStep.FlowAssignType) ?? EFlowAssignType.User,
|
|
|
+ UserId = targetStep.HandlerId,
|
|
|
+ Username = targetStep.HandlerName,
|
|
|
+ OrgId = targetStep.HandlerOrgId,
|
|
|
+ OrgName = targetStep.HandlerOrgName,
|
|
|
+ RoleId = targetStep.RoleId,
|
|
|
+ RoleName = targetStep.RoleName,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
private Workflow CreateWorkflow(WorkflowModule wfModule, string title, string? externalId = null)
|
|
|
{
|
|
|
var definition = wfModule.Definition;
|
|
@@ -2687,7 +3047,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
var isToCenter = targetStep.IsCenter();
|
|
|
if (!isToCenter) return false;
|
|
|
|
|
|
- var isFromOrg = workflow.Steps.Any(d => d.BusinessType is EBusinessType.Department);
|
|
|
+ var isFromOrg = workflow.Steps.Any(d => d.BusinessType is EBusinessType.Department or EBusinessType.DepartmentLeader);
|
|
|
return isFromOrg && isToCenter;
|
|
|
}
|
|
|
|
|
@@ -2695,22 +3055,18 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
/// 复制一个节点为待接办
|
|
|
/// </summary>
|
|
|
private async Task<WorkflowStep> DuplicateStepWithTraceAsync(Workflow workflow, WorkflowStep step,
|
|
|
- EWorkflowTraceType traceType, DateTime expiredTime, CancellationToken cancellationToken)
|
|
|
+ EWorkflowTraceType traceType, StepAssignInfo? stepAssignInfo, DateTime expiredTime, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- var newStep = DuplicateStep(step, traceType, expiredTime);
|
|
|
+ var newStep = DuplicateStep(step, traceType, stepAssignInfo, expiredTime);
|
|
|
|
|
|
await _workflowStepRepository.AddAsync(newStep, cancellationToken);
|
|
|
- //await _workflowStepRepository.AddNav(newStep)
|
|
|
- // .Include(d => d.StepHandlers)
|
|
|
- // .ExecuteCommandAsync();
|
|
|
-
|
|
|
|
|
|
await CreateTraceAsync(workflow, newStep, traceType, cancellationToken);
|
|
|
|
|
|
return newStep;
|
|
|
}
|
|
|
|
|
|
- private WorkflowStep DuplicateStep(WorkflowStep step, EWorkflowTraceType traceType, DateTime? expiredTime)
|
|
|
+ private WorkflowStep DuplicateStep(WorkflowStep step, EWorkflowTraceType traceType, StepAssignInfo? stepAssignInfo, DateTime? expiredTime)
|
|
|
{
|
|
|
var newStep = _mapper.Map<WorkflowStep>(step);
|
|
|
newStep.Reset();
|
|
@@ -2726,20 +3082,23 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
newStep.StepExpiredTime = expiredTime;
|
|
|
newStep.InitId();
|
|
|
|
|
|
- //退回场景:指派给原办理人,其余场景:按照原节点原始指派方式复制 //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;
|
|
|
+ if (stepAssignInfo is not null)
|
|
|
+ newStep.Assign(stepAssignInfo);
|
|
|
|
|
|
- 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;
|
|
|
+
|
|
|
+ // newStep.Assign(step.HandlerId, step.HandlerName, step.HandlerOrgId, step.HandlerOrgName, step.RoleId, step.RoleName);
|
|
|
+ //}
|
|
|
|
|
|
return newStep;
|
|
|
}
|
|
@@ -3478,7 +3837,11 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
var stepToDuplicate = startCountersignStep.IsCountersignEndStep
|
|
|
? GetCsLoopStartStep(workflow.Steps, startCountersignStep)
|
|
|
: startCountersignStep;
|
|
|
- var newStep = await DuplicateStepWithTraceAsync(workflow, stepToDuplicate, EWorkflowTraceType.Normal, expireTime, cancellationToken);
|
|
|
+ var stepAssignInfo = GetStepAssignInfo(new ReverseFlowStepAssignInfo
|
|
|
+ {
|
|
|
+ ReverseFlowStepCreationPolicy = EReverseFlowStepCreationPolicy.OriginStep
|
|
|
+ }, stepToDuplicate);
|
|
|
+ var newStep = await DuplicateStepWithTraceAsync(workflow, stepToDuplicate, EWorkflowTraceType.Normal, stepAssignInfo, expireTime, cancellationToken);
|
|
|
|
|
|
//当topcsStep结束cs时,实际办理节点应该更新为newStep
|
|
|
if (startCountersignStep.Id == workflow.TopCountersignStepId)
|
|
@@ -3687,7 +4050,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
return step;
|
|
|
}
|
|
|
|
|
|
- private async Task<FlowAssignInfo> GetNextStepFlowAssignInfoByDefineAsync(StepDefine nextStepDefine,
|
|
|
+ public async Task<FlowAssignInfo> GetNextStepFlowAssignInfoByDefineAsync(StepDefine nextStepDefine,
|
|
|
EHandlerType handlerType, bool isStartCountersign, List<Kv> handlers, CancellationToken cancellationToken)
|
|
|
{
|
|
|
switch (handlerType)
|