|
@@ -23,6 +23,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
private readonly IWorkflowTraceRepository _workflowTraceRepository;
|
|
|
private readonly IWorkflowSupplementRepository _workflowSupplementRepository;
|
|
|
private readonly IWorkflowAssignRepository _workflowAssignRepository;
|
|
|
+ private readonly IWorkflowCountersignRepository _workflowCountersignRepository;
|
|
|
private readonly ISessionContext _sessionContext;
|
|
|
private readonly IMapper _mapper;
|
|
|
private readonly IMediator _mediator;
|
|
@@ -34,6 +35,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
IWorkflowTraceRepository workflowTraceRepository,
|
|
|
IWorkflowSupplementRepository workflowSupplementRepository,
|
|
|
IWorkflowAssignRepository workflowAssignRepository,
|
|
|
+ IWorkflowCountersignRepository workflowCountersignRepository,
|
|
|
ISessionContext sessionContext,
|
|
|
IMapper mapper,
|
|
|
IMediator mediator,
|
|
@@ -44,6 +46,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
_workflowTraceRepository = workflowTraceRepository;
|
|
|
_workflowSupplementRepository = workflowSupplementRepository;
|
|
|
_workflowAssignRepository = workflowAssignRepository;
|
|
|
+ _workflowCountersignRepository = workflowCountersignRepository;
|
|
|
|
|
|
_sessionContext = sessionContext;
|
|
|
_mapper = mapper;
|
|
@@ -95,8 +98,19 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
if (nextStepBoxDefine.HandlerType is not EHandlerType.Role && !dto.NextHandlers.Any())
|
|
|
throw UserFriendlyException.SameMessage("未指派办理人");
|
|
|
|
|
|
- //第二节点的previousId is string.Empty
|
|
|
- var nextStepBox = await CreateStepAsync(workflow, nextStepBoxDefine, dto, cancellationToken: cancellationToken);
|
|
|
+ var (startStepBox, startStep) = await CreateStartStepAsync(workflow, dto, cancellationToken);
|
|
|
+
|
|
|
+ if (isStartCountersign)
|
|
|
+ {
|
|
|
+ //创建会签数据
|
|
|
+ var countersign = await CreateCountersignAsync(workflow.Id, startStep.Id, startStep.Code, dto.NextHandlers.Count, startStep.CountersignId, cancellationToken);
|
|
|
+ startStep.StartCountersignId = countersign.Id;
|
|
|
+ await _workflowStepRepository.UpdateAsync(startStep, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
+ //第二节点(创建即为 已指派/待接办 状态)
|
|
|
+ var nextStepBox = await CreateStepAsync(workflow, nextStepBoxDefine, dto, EWorkflowStepStatus.Assigned,
|
|
|
+ startStepBox, startStep, cancellationToken);
|
|
|
|
|
|
//更新当前节点名称、时间、会签节点code 等字段
|
|
|
workflow.SetWorkflowCurrentStepInfo(isStartCountersign, nextStepBox);
|
|
@@ -113,7 +127,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
public async Task<Workflow> GetWorkflowAsync(string workflowId,
|
|
|
bool withDefine = false, bool withSteps = false,
|
|
|
bool withTraces = false, bool withSupplements = false,
|
|
|
- bool withAssigns = false,
|
|
|
+ bool withAssigns = false, bool withCountersigns = false,
|
|
|
CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
var query = _workflowRepository.Queryable().Where(d => d.Id == workflowId);
|
|
@@ -123,6 +137,8 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
query = query.Includes(d => d.Supplements, d => d.Creator);
|
|
|
if (withAssigns)
|
|
|
query = query.Includes(d => d.Assigns);
|
|
|
+ if (withCountersigns)
|
|
|
+ query = query.Includes(d => d.Countersigns);
|
|
|
|
|
|
var workflow = await query.FirstAsync();
|
|
|
if (workflow is null)
|
|
@@ -215,6 +231,8 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
#region 办理当前节点
|
|
|
|
|
|
var (currentStepBox, currentStep) = GetUnCompleteStep(workflow.StepBoxes, _sessionContext.RequiredOrgCode, _sessionContext.RequiredUserId);
|
|
|
+ if (currentStep.Status is EWorkflowStepStatus.Completed or EWorkflowStepStatus.Created)
|
|
|
+ throw UserFriendlyException.SameMessage("当前节点状态无法办理");
|
|
|
if (currentStep.Status is EWorkflowStepStatus.Assigned)
|
|
|
await AcceptAsync(workflow,
|
|
|
_sessionContext.RequiredUserId,
|
|
@@ -228,8 +246,15 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
//检查是否支持会签办理
|
|
|
if (isStartCountersign && nextStepBoxDefine.CountersignMode == ECountersignMode.UnSupport)
|
|
|
throw UserFriendlyException.SameMessage($"下一节点不支持会签办理, code: {currentStep.Code}");
|
|
|
+ WorkflowCountersign? countersign = null;
|
|
|
if (isStartCountersign)
|
|
|
- currentStep.StartCountersign();
|
|
|
+ {
|
|
|
+ //创建会签数据
|
|
|
+ countersign = await CreateCountersignAsync(workflow.Id, currentStep.Id, currentStep.Code,
|
|
|
+ dto.NextHandlers.Count, currentStep.CountersignId, cancellationToken);
|
|
|
+ currentStep.StartCountersign(countersign.Id);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
_mapper.Map(dto, currentStep);
|
|
|
|
|
@@ -246,11 +271,26 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
//结束当前会签流程
|
|
|
if (currentStep.StepType is EStepType.CountersignEnd && currentStep.IsInCountersign)
|
|
|
{
|
|
|
- var countersignStartStep = FindCountersignStartStep(workflow, currentStep.CountersignStartCode, currentStep.PrevCountersignId);
|
|
|
- if (countersignStartStep.HasStartCountersign)
|
|
|
+ var countersignStartStepBox =
|
|
|
+ workflow.StepBoxes.FirstOrDefault(d => d.Code == currentStep.CountersignStartCode);
|
|
|
+ if (countersignStartStepBox is null)
|
|
|
+ throw new UserFriendlyException(
|
|
|
+ $"未查询到会签开始stepBox, workflowId: {workflow.Id}, stepCode: {currentStep.CountersignStartCode}", "未查询到会签开始节点");
|
|
|
+ var countersignStartStep =
|
|
|
+ countersignStartStepBox.Steps.FirstOrDefault(d => d.HasStartCountersign && d.StartCountersignId == currentStep.CountersignId);
|
|
|
+ if (countersignStartStep != null)//如果==null,说明未发起会签是继承的外层会签
|
|
|
{
|
|
|
+ //结束step会签信息
|
|
|
countersignStartStep.CountersignComplete();
|
|
|
updateSteps.Add(countersignStartStep);
|
|
|
+
|
|
|
+ //结束会签
|
|
|
+ var currentCountersign = workflow.Countersigns.FirstOrDefault(d => d.Id == currentStep.CountersignId);
|
|
|
+ if (currentCountersign is null)
|
|
|
+ throw new UserFriendlyException(
|
|
|
+ $"未查询到对应会签信息,workflowId:{workflow.Id}, countersignId:{currentStep.CountersignId}", "无效会签编号");
|
|
|
+ currentCountersign.Complete(currentStep.Id, currentStep.Code);
|
|
|
+ await _workflowCountersignRepository.UpdateAsync(currentCountersign, cancellationToken);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -262,7 +302,7 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
|
|
|
//检查会签是否结束,并更新当前会签节点字段
|
|
|
var isCountersignOver = false;
|
|
|
- if (workflow.IsInCountersign())
|
|
|
+ if (currentStep.StepType is EStepType.CountersignEnd && workflow.IsInCountersign())
|
|
|
{
|
|
|
isCountersignOver = workflow.CheckIfCountersignOver();
|
|
|
if (isCountersignOver)
|
|
@@ -301,49 +341,37 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
await _mediator.Publish(new OrderRecallFinalManageNotify(workflow), cancellationToken);
|
|
|
}
|
|
|
|
|
|
- //创建下一节点
|
|
|
- var nextStepBox = await CreateStepAsync(workflow, nextStepBoxDefine, dto, currentStepBox, currentStep, cancellationToken);
|
|
|
+ //创建下一节点(会签汇总节点不重复创建)
|
|
|
+ var nextStepBox = await CreateStepAsync(workflow, nextStepBoxDefine, dto, EWorkflowStepStatus.Created,
|
|
|
+ currentStepBox, currentStep, cancellationToken);
|
|
|
|
|
|
//下一节点为汇总节点时,检查下一节点是否可办理
|
|
|
+ var nextStepCanHandle = true;
|
|
|
if (nextStepBox.StepType is EStepType.CountersignEnd)
|
|
|
{
|
|
|
if (currentStep.IsInCountersign)
|
|
|
{
|
|
|
- var stepCode = currentStep.StepType is EStepType.CountersignEnd
|
|
|
- ? currentStep.CountersignStartCode
|
|
|
- : currentStep.Code;
|
|
|
-
|
|
|
- var countersignId = string.IsNullOrEmpty(currentStep.TopCountersignId)
|
|
|
- ? currentStep.PrevCountersignId
|
|
|
- : currentStep.TopCountersignId;
|
|
|
-
|
|
|
- var stepBox = workflow.StepBoxes.First(d => d.Code == stepCode);
|
|
|
- var countersignSteps =
|
|
|
- stepBox.Steps.Where(d => d.PrevCountersignId == countersignId);
|
|
|
-
|
|
|
- //check all complete or cs complete
|
|
|
- var canHandle = true;
|
|
|
- foreach (var countersignStep in countersignSteps)
|
|
|
- {
|
|
|
- if (countersignStep.Status != EWorkflowStepStatus.Completed) break;
|
|
|
- if (countersignStep.HasStartCountersign && !countersignStep.IsCountersignComplete.GetValueOrDefault()) break;
|
|
|
- }
|
|
|
-
|
|
|
- if (canHandle)
|
|
|
- {
|
|
|
- await UpdateNextCountersignEndAssignedAsync(nextStepBox, currentStep, cancellationToken);
|
|
|
- _mediator.Publish(new CountersignEndAssigned(workflow), cancellationToken);
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- await UpdateNextCountersignEndAssignedAsync(nextStepBox, currentStep, cancellationToken);
|
|
|
- _mediator.Publish(new CountersignEndAssigned(workflow), cancellationToken);
|
|
|
+ //同一会签Id,非汇总节点
|
|
|
+ var steps = await _workflowStepRepository.QueryAsync(d =>
|
|
|
+ d.WorkflowId == workflow.Id
|
|
|
+ && d.CountersignId == currentStep.CountersignId
|
|
|
+ && d.StepType != EStepType.End);
|
|
|
+ //(当前办理节点所处同一会签内的所有step全都办理完成并且如果开启了会签的step,必须会签结束)
|
|
|
+ var unComplete = steps.Any(d =>
|
|
|
+ d.Status != EWorkflowStepStatus.Completed ||
|
|
|
+ (d.HasStartCountersign && !d.IsStartedCountersignComplete.Value));
|
|
|
+ nextStepCanHandle = !unComplete;
|
|
|
}
|
|
|
}
|
|
|
+ if (nextStepCanHandle)
|
|
|
+ {
|
|
|
+ //将下一节点处理为已指派/可接办
|
|
|
+ await SetNextCountersignEndAssignedAsync(nextStepBox, currentStep, cancellationToken);
|
|
|
+ _mediator.Publish(new CountersignEndAssigned(workflow), cancellationToken);
|
|
|
+ }
|
|
|
|
|
|
- //更新当前节点名称、时间、会签节点code 等字段
|
|
|
+
|
|
|
+ //更新workflow当前节点名称、时间、会签节点code 等字段
|
|
|
workflow.SetWorkflowCurrentStepInfo(isStartCountersign, nextStepBox);
|
|
|
|
|
|
workflow.UpdateHandlers(_sessionContext.RequiredUserId, _sessionContext.RequiredOrgCode,
|
|
@@ -411,11 +439,18 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
//update uncompleted traces
|
|
|
await JumpTraceAsync(workflow.Id, dto, cancellationToken);
|
|
|
|
|
|
+ var (currentStepBox, currentStep) = GetUnCompleteStep(workflow.StepBoxes, _sessionContext.RequiredOrgCode, _sessionContext.RequiredUserId);
|
|
|
+ if (currentStepBox.StepType is EStepType.Start)
|
|
|
+ throw UserFriendlyException.SameMessage("当前流程已退回到开始节点");
|
|
|
+ if (currentStepBox.StepType is EStepType.End)
|
|
|
+ throw UserFriendlyException.SameMessage("当前流程已流转到结束节点");
|
|
|
+
|
|
|
var targetStepBox = workflow.StepBoxes.FirstOrDefault(d => d.Code == dto.TargetStepCode);
|
|
|
if (targetStepBox == null)
|
|
|
{
|
|
|
+ //向后跳转
|
|
|
var nextStepBoxDefine = GetStepBoxDefine(workflow.Definition, dto.NextStepCode);
|
|
|
- var nextStepBox = await CreateStepAsync(workflow, nextStepBoxDefine, dto, cancellationToken: cancellationToken);
|
|
|
+ var nextStepBox = await CreateStepAsync(workflow, nextStepBoxDefine, dto, EWorkflowStepStatus.Assigned, currentStepBox, currentStep, cancellationToken);
|
|
|
|
|
|
await ResetWorkflowCurrentStepInfo(workflow, dto, nextStepBox, cancellationToken);
|
|
|
|
|
@@ -453,15 +488,6 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
//todo publish
|
|
|
}
|
|
|
|
|
|
- private async Task ResetWorkflowCurrentStepInfo(Workflow workflow, RecallDto dto, WorkflowStep stepBox, CancellationToken cancellationToken)
|
|
|
- {
|
|
|
- //更新当前节点名称、时间、会签节点code
|
|
|
- workflow.CloseCountersignStatus();
|
|
|
- var isCountersign = dto.NextHandlers.Count > 1;
|
|
|
- workflow.SetWorkflowCurrentStepInfo(isCountersign, stepBox);
|
|
|
- await _workflowRepository.UpdateAsync(workflow, cancellationToken);
|
|
|
- }
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// 补充
|
|
|
/// </summary>
|
|
@@ -516,6 +542,21 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
|
|
|
#region private
|
|
|
|
|
|
+ private async Task<WorkflowCountersign> CreateCountersignAsync(string workflowId, string startStepId, string startStepCode, int count, string? parentId = null, CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
+ var countersign = new WorkflowCountersign
|
|
|
+ {
|
|
|
+ WorkflowId = workflowId,
|
|
|
+ StartStepId = startStepId,
|
|
|
+ StartStepCode = startStepCode,
|
|
|
+ Members = count,
|
|
|
+ ParentId = parentId,
|
|
|
+ };
|
|
|
+ await _workflowCountersignRepository.AddAsync(countersign, cancellationToken);
|
|
|
+ return countersign;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 更新下级汇总节点可办理状态
|
|
|
/// </summary>
|
|
@@ -523,13 +564,22 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
/// <param name="currentStep"></param>
|
|
|
/// <param name="cancellationToken"></param>
|
|
|
/// <returns></returns>
|
|
|
- private async Task UpdateNextCountersignEndAssignedAsync(WorkflowStep nextStepBox, WorkflowStep currentStep, CancellationToken cancellationToken)
|
|
|
+ private async Task SetNextCountersignEndAssignedAsync(WorkflowStep nextStepBox, WorkflowStep currentStep, CancellationToken cancellationToken)
|
|
|
{
|
|
|
- var countersignId = string.IsNullOrEmpty(currentStep.TopCountersignId)
|
|
|
- ? currentStep.PrevCountersignId
|
|
|
- : currentStep.TopCountersignId;
|
|
|
+ WorkflowStep? nextStep;
|
|
|
+ if (currentStep.StepCountersignStatus is EStepCountersignStatus.InCountersign)
|
|
|
+ {
|
|
|
+ nextStep = nextStepBox.Steps.FirstOrDefault(d => d.CountersignId == currentStep.CountersignId);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ nextStep = nextStepBox.Steps.FirstOrDefault(d => d.ParentId == currentStep.Id);
|
|
|
+ }
|
|
|
|
|
|
- var nextStep = nextStepBox.Steps.First(d => d.PrevCountersignId == countersignId);
|
|
|
+ if (nextStep == null)
|
|
|
+ throw new UserFriendlyException(
|
|
|
+ $"未查询到下一节点, workflowId:{currentStep.WorkflowId}, currentStepId: {currentStep.Id}");
|
|
|
+
|
|
|
nextStep.SetAssigned();
|
|
|
|
|
|
await _workflowStepRepository.UpdateAsync(nextStep, cancellationToken);
|
|
@@ -611,13 +661,13 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
trace.ExpiredTime = workflow.ExpiredTime;
|
|
|
trace.TimeLimit = workflow.TimeLimit;
|
|
|
|
|
|
- if (!string.IsNullOrEmpty(currentStep.PreviousId) && currentStepBox.Steps.Count > 1)
|
|
|
+ //处于会签中的节点,其对应的trace.parentId赋值上级trace.Id
|
|
|
+ if(currentStep.StepCountersignStatus is EStepCountersignStatus.InCountersign)
|
|
|
{
|
|
|
- //有会签
|
|
|
var parentTrace = await GetWorkflowTraceAsync(workflow.Id, currentStep.PreviousId, cancellationToken);
|
|
|
trace.ParentId = parentTrace.Id;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
await _workflowTraceRepository.AddAsync(trace, cancellationToken);
|
|
|
}
|
|
|
|
|
@@ -649,20 +699,32 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
|
|
|
//recreate targetStep
|
|
|
var nextStepBoxDefine = GetStepBoxDefine(workflow.Definition, dto.NextStepCode);
|
|
|
- await CreateStepAsync(workflow, nextStepBoxDefine, dto, targetStepBox, targetStepBox.Steps.First(), cancellationToken);
|
|
|
+ await CreateStepAsync(workflow, nextStepBoxDefine, dto, EWorkflowStepStatus.Assigned, targetStepBox, targetStepBox.Steps.First(), cancellationToken);
|
|
|
|
|
|
//flow manage
|
|
|
if (workflow.IsInCountersign())
|
|
|
{
|
|
|
var currentCountersignStepBox =
|
|
|
- workflow.StepBoxes.First(d => d.Code == workflow.CurrentCountersignStepCode);
|
|
|
+ workflow.StepBoxes.First(d => d.Code == workflow.TopCountersignStepCode);
|
|
|
//目标节点在初始会签节点之前或正好
|
|
|
- if (targetStepBox.Code == workflow.CurrentCountersignStepCode || targetStepBox.CreationTime < currentCountersignStepBox.CreationTime)
|
|
|
+ if (targetStepBox.Code == workflow.TopCountersignStepCode || targetStepBox.CreationTime < currentCountersignStepBox.CreationTime)
|
|
|
await ResetWorkflowCurrentStepInfo(workflow, dto, targetStepBox, cancellationToken);
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 重置currentStep信息
|
|
|
+ /// </summary>
|
|
|
+ private async Task ResetWorkflowCurrentStepInfo(Workflow workflow, RecallDto dto, WorkflowStep stepBox, CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ //更新当前节点名称、时间、会签节点code
|
|
|
+ workflow.CloseCountersignStatus();
|
|
|
+ var isCountersign = dto.NextHandlers.Count > 1;
|
|
|
+ workflow.SetWorkflowCurrentStepInfo(isCountersign, stepBox);
|
|
|
+ await _workflowRepository.UpdateAsync(workflow, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
private static void CheckWhetherRunnable(EWorkflowStatus status)
|
|
|
{
|
|
|
if (status is not EWorkflowStatus.Runnable)
|
|
@@ -675,89 +737,103 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
throw new UserFriendlyException("无办理权限");
|
|
|
}
|
|
|
|
|
|
- private async Task<WorkflowStep> CreateStepAsync(Workflow workflow, StepDefine stepBoxDefine, BasicWorkflowDto dto,
|
|
|
+ /// <summary>
|
|
|
+ /// 创建开始节点(保存开始流程的办理意见,对应definition的start节点)
|
|
|
+ /// </summary>
|
|
|
+ private async Task<(WorkflowStep stepBox, WorkflowStep step)> CreateStartStepAsync(Workflow workflow, BasicWorkflowDto dto, CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ if (workflow.StepBoxes.Any())
|
|
|
+ throw UserFriendlyException.SameMessage("无法反复开始流程");
|
|
|
+
|
|
|
+ var startStepDefinition = workflow.Definition.Steps.FirstOrDefault(d => d.StepType == EStepType.Start);
|
|
|
+ if (startStepDefinition == null)
|
|
|
+ throw new UserFriendlyException($"模板未配置开始节点, defineCode: {workflow.Definition.Code}", "模板未配置开始节点");
|
|
|
+
|
|
|
+ var stepBox = CreateStepBox(workflow.Id, startStepDefinition, dto, string.Empty);
|
|
|
+ await _workflowStepRepository.AddAsync(stepBox, cancellationToken);
|
|
|
+
|
|
|
+ //start节点的办理人分类默认为用户,即为当前发起流程的操作员
|
|
|
+ var handler = new IdName { Id = _sessionContext.RequiredUserId, Name = _sessionContext.UserName };
|
|
|
+ await CreateStartSubStepAsync(handler, dto, stepBox, null, cancellationToken);
|
|
|
+ return (stepBox, stepBox.Steps.First());
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 创建节点(不含开始、结束节点)
|
|
|
+ /// </summary>
|
|
|
+ private async Task<WorkflowStep> CreateStepAsync(Workflow workflow, StepDefine stepBoxDefine, BasicWorkflowDto dto, EWorkflowStepStatus status,
|
|
|
WorkflowStep? prevStepBox = null, WorkflowStep? prevStep = null, CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
if (stepBoxDefine.StepType is EStepType.Start or EStepType.End)
|
|
|
- throw new UserFriendlyException("开始和结束节点无法创建子节点");
|
|
|
+ throw new UserFriendlyException("该方法不支持创建开始或结束节点");
|
|
|
var stepBox = workflow.StepBoxes.FirstOrDefault(d => d.Code == stepBoxDefine.Code);
|
|
|
if (stepBox == null)
|
|
|
{
|
|
|
stepBox = CreateStepBox(workflow.Id, stepBoxDefine, dto, prevStepBox?.Id ?? string.Empty);
|
|
|
await _workflowStepRepository.AddAsync(stepBox, cancellationToken);
|
|
|
}
|
|
|
-
|
|
|
- if (stepBoxDefine.StepType is EStepType.CountersignEnd && workflow.IsInCountersign())
|
|
|
+ else if (stepBox.Status != EWorkflowStepStatus.Created)
|
|
|
{
|
|
|
- if (prevStep is null)
|
|
|
- throw new UserFriendlyException($"汇总节点的上级节点不能为空节点,workflowId: {workflow.Id}", "创建汇总节点异常");
|
|
|
-
|
|
|
- var countersignId = string.IsNullOrEmpty(prevStep.TopCountersignId)
|
|
|
- ? prevStep.PrevCountersignId
|
|
|
- : prevStep.TopCountersignId;
|
|
|
-
|
|
|
- var step = stepBox.Steps.FirstOrDefault(d => d.PrevCountersignId == countersignId);
|
|
|
- if (step != null) return stepBox;
|
|
|
-
|
|
|
- var countersignStartStep = FindCountersignStartStep(workflow, stepBoxDefine.CountersignStartCode, countersignId);
|
|
|
- string? topCountersignId = countersignStartStep.StepType is EStepType.CountersignEnd
|
|
|
- ? countersignStartStep.TopCountersignId
|
|
|
- : countersignStartStep.IsInCountersign
|
|
|
- ? countersignStartStep.PrevCountersignId
|
|
|
- : null;
|
|
|
-
|
|
|
- await CreateSubStepsAsync(stepBoxDefine, dto, stepBox, prevStep.Id, EWorkflowStepStatus.Created,
|
|
|
- countersignId, topCountersignId, cancellationToken);
|
|
|
+ stepBox.Status = EWorkflowStepStatus.Created;
|
|
|
+ await _workflowStepRepository.UpdateAsync(stepBox, cancellationToken);
|
|
|
}
|
|
|
- else
|
|
|
- {
|
|
|
- if (prevStep is null)
|
|
|
- {
|
|
|
-
|
|
|
- //开始流程或向后跳转场景
|
|
|
- await CreateSubStepsAsync(stepBoxDefine, dto, stepBox, string.Empty, EWorkflowStepStatus.Assigned,
|
|
|
- null, null, cancellationToken);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- var prevCountersignId = prevStep.HasStartCountersign
|
|
|
- ? prevStep.StartCountersignId
|
|
|
- : prevStep.PrevCountersignId;
|
|
|
|
|
|
- await CreateSubStepsAsync(stepBoxDefine, dto, stepBox, prevStep.Id, EWorkflowStepStatus.Assigned,
|
|
|
- prevCountersignId, null, cancellationToken);
|
|
|
- }
|
|
|
+ //下一节点为汇总节点时,同一会签只需要创建一次汇总节点
|
|
|
+ if (stepBoxDefine.StepType is EStepType.CountersignEnd && prevStep.StepCountersignStatus == EStepCountersignStatus.InCountersign)
|
|
|
+ {
|
|
|
+ var step = stepBox.Steps.FirstOrDefault(d =>
|
|
|
+ d.IsInCountersign && d.CountersignId == prevStep.CountersignId);
|
|
|
+ if (step != null)
|
|
|
+ return stepBox;
|
|
|
}
|
|
|
|
|
|
+ await CreateSubStepsAsync(stepBoxDefine, dto, stepBox, status, prevStep, cancellationToken);
|
|
|
+
|
|
|
return stepBox;
|
|
|
}
|
|
|
|
|
|
+ private async Task CreateStartSubStepAsync(
|
|
|
+ IdName handler,
|
|
|
+ BasicWorkflowDto dto,
|
|
|
+ WorkflowStep stepBox,
|
|
|
+ string? startCountersignId = null,
|
|
|
+ CancellationToken cancellationToken = default)
|
|
|
+ {
|
|
|
+ var nextCountersignStatus = string.IsNullOrEmpty(startCountersignId)
|
|
|
+ ? EStepCountersignStatus.InCountersign
|
|
|
+ : EStepCountersignStatus.None;
|
|
|
+ var subStep = CreateSubStep(stepBox, handler, dto.NextMainHandler, null, startCountersignId, null,
|
|
|
+ EWorkflowStepStatus.Completed, nextCountersignStatus);
|
|
|
+ _mapper.Map(dto, subStep);
|
|
|
+ stepBox.Steps.Add(subStep);
|
|
|
+ await _workflowStepRepository.AddAsync(subStep, cancellationToken);
|
|
|
+ }
|
|
|
+
|
|
|
private async Task CreateSubStepsAsync(
|
|
|
StepDefine stepBoxDefine,
|
|
|
BasicWorkflowDto dto,
|
|
|
WorkflowStep stepBox,
|
|
|
- string prevStepId,
|
|
|
EWorkflowStepStatus stepStatus,
|
|
|
- string? prevCountersignId = null,
|
|
|
- string? topCountersignId = null,
|
|
|
+ WorkflowStep? prevStep = null,
|
|
|
CancellationToken cancellationToken = default)
|
|
|
{
|
|
|
+ //开始节点无会签
|
|
|
+ var countersignStatus = prevStep?.GetNextStepCountersignStatus() ?? EStepCountersignStatus.None;
|
|
|
+ List<WorkflowStep> subSteps;
|
|
|
if (stepBoxDefine.HandlerType is EHandlerType.AssignUser or EHandlerType.AssignOrg)
|
|
|
{
|
|
|
- var subSteps = CreateSubSteps(stepBox, stepBox.HandlerClassifies, dto.NextMainHandler,
|
|
|
- prevStepId, prevCountersignId, topCountersignId, stepStatus);
|
|
|
- stepBox.Steps.AddRange(subSteps);
|
|
|
- await _workflowStepRepository.AddRangeAsync(subSteps, cancellationToken);
|
|
|
+ subSteps = CreateSubSteps(stepBox, stepBox.HandlerClassifies, dto.NextMainHandler,
|
|
|
+ prevStep?.Id, prevStep?.StartCountersignId, stepStatus, countersignStatus);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
if (stepBoxDefine.HandlerType != EHandlerType.Role && !dto.NextHandlers.Any())
|
|
|
throw new UserFriendlyException("未指定节点处理者");
|
|
|
- var subSteps = CreateSubSteps(stepBox, dto.NextHandlers, dto.NextMainHandler,
|
|
|
- prevStepId, prevCountersignId, topCountersignId, stepStatus);
|
|
|
- stepBox.Steps.AddRange(subSteps);
|
|
|
- await _workflowStepRepository.AddRangeAsync(subSteps, cancellationToken);
|
|
|
+ subSteps = CreateSubSteps(stepBox, dto.NextHandlers, dto.NextMainHandler,
|
|
|
+ prevStep?.Id, prevStep?.StartCountersignId, stepStatus, countersignStatus);
|
|
|
}
|
|
|
+ stepBox.Steps.AddRange(subSteps);
|
|
|
+ await _workflowStepRepository.AddRangeAsync(subSteps, cancellationToken);
|
|
|
}
|
|
|
|
|
|
private (WorkflowStep stepBox, WorkflowStep step) GetStep(List<WorkflowStep> stepBoxes, string stepId)
|
|
@@ -807,10 +883,9 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
return new();
|
|
|
}
|
|
|
|
|
|
- private WorkflowStep CreateStepBox(string workflowId, StepDefine stepBasic, BasicWorkflowDto dto, string prevStepBoxId)
|
|
|
+ private WorkflowStep CreateStepBox(string workflowId, StepDefine stepDefine, BasicWorkflowDto dto, string prevStepBoxId)
|
|
|
{
|
|
|
- var stepBox = _mapper.Map<WorkflowStep>(stepBasic);
|
|
|
- _mapper.Map(dto, stepBox);
|
|
|
+ var stepBox = _mapper.Map<WorkflowStep>(stepDefine);
|
|
|
stepBox.WorkflowId = workflowId;
|
|
|
stepBox.PreviousId = prevStepBoxId;
|
|
|
return stepBox;
|
|
@@ -818,30 +893,61 @@ namespace Hotline.FlowEngine.Workflows
|
|
|
|
|
|
private List<WorkflowStep> CreateSubSteps(
|
|
|
WorkflowStep stepBox,
|
|
|
- List<IdName> nextHandlers,
|
|
|
+ List<IdName> handlers,
|
|
|
string nextMainHandler,
|
|
|
- string prevStepId,
|
|
|
- string? prevCountersignId,
|
|
|
- string? topCountersignId,
|
|
|
- EWorkflowStepStatus stepStatus)
|
|
|
+ string? prevStepId,
|
|
|
+ string? countersignId,
|
|
|
+ EWorkflowStepStatus stepStatus,
|
|
|
+ EStepCountersignStatus countersignStatus)
|
|
|
{
|
|
|
+ if (countersignStatus is EStepCountersignStatus.None && !string.IsNullOrEmpty(countersignId))
|
|
|
+ throw UserFriendlyException.SameMessage("非法参数");
|
|
|
+ if (countersignStatus is not EStepCountersignStatus.None && string.IsNullOrEmpty(countersignId))
|
|
|
+ throw UserFriendlyException.SameMessage("非法参数");
|
|
|
+
|
|
|
var steps = new List<WorkflowStep>();
|
|
|
- foreach (var nextHandler in nextHandlers)
|
|
|
- {
|
|
|
- var step = _mapper.Map<WorkflowStep>(stepBox);
|
|
|
- step.ParentId = stepBox.Id;
|
|
|
- step.HandlerId = nextHandler.Id;
|
|
|
- step.IsMain = nextHandler.Id == nextMainHandler;
|
|
|
- step.PreviousId = prevStepId;
|
|
|
- step.PrevCountersignId = prevCountersignId;
|
|
|
- step.TopCountersignId = topCountersignId;
|
|
|
- step.Status = stepStatus;
|
|
|
+ foreach (var handler in handlers)
|
|
|
+ {
|
|
|
+ //var step = _mapper.Map<WorkflowStep>(stepBox);
|
|
|
+ //step.ParentId = stepBox.Id;
|
|
|
+ //step.HandlerId = handler.Id;
|
|
|
+ //step.IsMain = handler.Id == nextMainHandler;
|
|
|
+ //step.PreviousId = prevStepId;
|
|
|
+ //step.StartCountersignId = startCountersignId;
|
|
|
+ //step.CountersignId = countersignId;
|
|
|
+ //step.Status = stepStatus;
|
|
|
+
|
|
|
+ var step = CreateSubStep(stepBox, handler, nextMainHandler,
|
|
|
+ prevStepId, null, countersignId, stepStatus, countersignStatus);
|
|
|
steps.Add(step);
|
|
|
}
|
|
|
|
|
|
return steps;
|
|
|
}
|
|
|
|
|
|
+ private WorkflowStep CreateSubStep(
|
|
|
+ WorkflowStep stepBox,
|
|
|
+ IdName handler,
|
|
|
+ string nextMainHandler,
|
|
|
+ string? prevStepId,
|
|
|
+ string? startCountersignId,
|
|
|
+ string? countersignId,
|
|
|
+ EWorkflowStepStatus stepStatus,
|
|
|
+ EStepCountersignStatus countersignStatus)
|
|
|
+ {
|
|
|
+ var step = _mapper.Map<WorkflowStep>(stepBox);
|
|
|
+ step.ParentId = stepBox.Id;
|
|
|
+ step.HandlerId = handler.Id;
|
|
|
+ step.IsMain = handler.Id == nextMainHandler;
|
|
|
+ step.PreviousId = prevStepId;
|
|
|
+ step.StartCountersignId = startCountersignId;
|
|
|
+ step.CountersignId = countersignId;
|
|
|
+ step.Status = stepStatus;
|
|
|
+ step.StepCountersignStatus = countersignStatus;
|
|
|
+
|
|
|
+ return step;
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// 依据配置生成过期时间
|
|
|
/// </summary>
|