12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208 |
- using Hotline.Application.Contracts.Validators.FlowEngine;
- using Hotline.Caching.Interfaces;
- using Hotline.FlowEngine;
- using Hotline.FlowEngine.Definitions;
- using Hotline.FlowEngine.WorkflowModules;
- using Hotline.FlowEngine.Workflows;
- using Hotline.Identity.Accounts;
- using Hotline.Identity.Roles;
- using Hotline.Orders;
- using Hotline.Settings;
- using Hotline.Settings.TimeLimits;
- using Hotline.Share.Dtos;
- using Hotline.Share.Dtos.FlowEngine;
- using Hotline.Share.Dtos.FlowEngine.Definition;
- using Hotline.Share.Dtos.Settings;
- using Hotline.Share.Enums.FlowEngine;
- using Hotline.Share.Enums.Identity;
- using Hotline.Share.Enums.Order;
- using Hotline.Users;
- using MapsterMapper;
- using System.Threading;
- using XF.Domain.Authentications;
- using XF.Domain.Dependency;
- using XF.Domain.Entities;
- using XF.Domain.Exceptions;
- using XF.Domain.Extensions;
- using XF.Domain.Repository;
- using XF.Utility.EnumExtensions;
- namespace Hotline.Application.FlowEngine;
- public class WorkflowApplication : IWorkflowApplication, IScopeDependency
- {
- private readonly IDefinitionDomainService _definitionDomainService;
- private readonly IWorkflowDomainService _workflowDomainService;
- private readonly IOrderDomainService _orderDomainService;
- private readonly IWorkflowRepository _workflowRepository;
- private IRepository<WorkflowDefinition> _definitionRepository;
- private IRepository<WorkflowStep> _workflowStepRepository;
- private IRepository<WorkflowTrace> _workflowTraceRepository;
- private readonly IRepository<User> _userRepository;
- private readonly IAccountRepository _accountRepository;
- private readonly ISystemOrganizeRepository _organizeRepository;
- private readonly IRepository<Role> _roleRepository;
- private readonly IWfModuleCacheManager _wfModuleCacheManager;
- private readonly ISystemDomainService _systemDomainService;
- private readonly ITimeLimitDomainService _timeLimitDomainService;
- private readonly IUserDomainService _userDomainService;
- private readonly IAccountDomainService _accountDomainService;
- private readonly ISessionContext _sessionContext;
- private readonly IMapper _mapper;
- public WorkflowApplication(
- IDefinitionDomainService definitionDomainService,
- IWorkflowDomainService workflowDomainService,
- IOrderDomainService orderDomainService,
- IWorkflowRepository workflowRepository,
- IRepository<WorkflowDefinition> definitionRepository,
- IRepository<WorkflowStep> workflowStepRepository,
- IRepository<WorkflowTrace> workflowTraceRepository,
- IRepository<User> userRepository,
- IAccountRepository accountRepository,
- ISystemOrganizeRepository organizeRepository,
- IRepository<Role> roleRepository,
- IWfModuleCacheManager wfModuleCacheManager,
- ISystemDomainService systemDomainService,
- ITimeLimitDomainService timeLimitDomainService,
- ISessionContext sessionContext,
- IMapper mapper
- )
- {
- _definitionDomainService = definitionDomainService;
- _workflowDomainService = workflowDomainService;
- _orderDomainService = orderDomainService;
- _workflowRepository = workflowRepository;
- _definitionRepository = definitionRepository;
- _workflowStepRepository = workflowStepRepository;
- _workflowTraceRepository = workflowTraceRepository;
- _userRepository = userRepository;
- _accountRepository = accountRepository;
- _organizeRepository = organizeRepository;
- _roleRepository = roleRepository;
- _wfModuleCacheManager = wfModuleCacheManager;
- _systemDomainService = systemDomainService;
- _timeLimitDomainService = timeLimitDomainService;
- _sessionContext = sessionContext;
- _mapper = mapper;
- }
- public async Task<string> StartWorkflowAsync(StartWorkflowDto dto, string externalId,
- TimeResult? expiredTime = null, CancellationToken cancellationToken = default)
- {
- var validator = new StartWorkflowDtoValidator();
- var validResult = validator.Validate(dto);
- if (!validResult.IsValid)
- throw new UserFriendlyException(
- $"非法参数, {string.Join(',', validResult.Errors.Select(d => d.ErrorMessage))}");
- var wfModule = await GetWorkflowModuleAsync(dto.DefinitionModuleCode, cancellationToken);
- var definition = wfModule.Definition;
- if (definition == null)
- throw new UserFriendlyException("无效模板编码");
- if (definition.Status is not EDefinitionStatus.Enable)
- throw new UserFriendlyException("该模板不可用");
- //如果发起会签需检查是否支持发起会签
- var startStepDefine = definition.FindStartStepDefine();
- var firstStepDefine = startStepDefine.InstanceMode is EInstanceMode.Dynamic
- ? startStepDefine
- : definition.FindStepDefine(dto.NextStepCode);
- if (firstStepDefine is null)
- throw new UserFriendlyException("未查询到下一步节点配置");
- //1. 如果不是按角色指派,handlers必填 2. 如果按角色指派,handlers可以不选
- if (firstStepDefine.HandlerType is not EHandlerType.Role && !dto.NextHandlers.Any())
- throw UserFriendlyException.SameMessage("未指派办理人");
- if (dto.IsStartCountersign)
- {
- if (!startStepDefine.CanStartCountersign)
- throw new UserFriendlyException("当前节点不支持发起会签");
- //if (startStepDefine.HandlerType is EHandlerType.Role)
- // throw new UserFriendlyException("当前节点不支持发起会签");
- //即使当前节点支持发起会签,但下一节点为信息汇总节点、结束节点时也不可发起会签
- if (firstStepDefine.StepType is EStepType.Summary or EStepType.End)
- throw new UserFriendlyException("下一节点不允许发起会签");
- //下一节点是会签汇总节点也不允许发起会签
- if (dto.BackToCountersignEnd)
- throw new UserFriendlyException("下一节点不允许发起会签");
- }
- //todo
- var workflow = await _workflowDomainService.CreateWorkflowAsync(wfModule, dto.Title,
- _sessionContext.RequiredUserId, _sessionContext.RequiredOrgId, externalId, expiredTime?.RuleStr,
- expiredTime?.EndTime, cancellationToken);
- //startstep
- var nextSteps = _mapper.Map<List<StepSimple>>(startStepDefine.NextSteps);
- if (startStepDefine.InstanceMode is EInstanceMode.Config)
- nextSteps.First(d => d.Code == dto.NextStepCode).Selected = true;
- var startStep = new WorkflowStep
- {
- WorkflowId = workflow.Id,
- Handlers = new List<Kv> { new(_sessionContext.RequiredUserId, _sessionContext.UserName) },
- NextSteps = nextSteps,
- IsMain = true,
- IsOrigin = true,
- Status = EWorkflowStepStatus.WaitForHandle,
- PrevChosenStepCode = null,
- };
- var startDefine = workflow.WorkflowDefinition.FindStartStepDefine();
- _mapper.Map(startDefine, startStep);
- await _workflowStepRepository.AddAsync(startStep, cancellationToken);
- workflow.Steps.Add(startStep);
- //starttrace
- var startTrace = _mapper.Map<WorkflowTrace>(startStep);
- startTrace.StepId = startStep.Id;
- startTrace.Status = EWorkflowTraceStatus.Normal;
- _mapper.Map(dto, startTrace);
- await _workflowTraceRepository.AddAsync(startTrace, cancellationToken);
- workflow.Traces.Add(startTrace);
- var flowAssignInfo =
- await GetNextStepFlowAssignInfoAsync(workflow, startStep, firstStepDefine, dto, cancellationToken);
- await _workflowDomainService.StartAsync(workflow, startStep, dto, firstStepDefine, flowAssignInfo,
- cancellationToken);
- return workflow.Id;
- }
- /// <summary>
- /// 流转至下一节点(节点办理)
- /// </summary>
- public async Task NextAsync(NextWorkflowDto dto, CancellationToken cancellationToken)
- {
- var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true, withCountersigns: true,
- cancellationToken: cancellationToken);
- //await NextAsync(workflow, dto, dto.ExpiredTime, dto.IsStartCountersign, cancellationToken);
- ////未超期工单,节点超期时间不能小于当前时间,不能大于流程整体超期时间
- //if (workflow.ExpiredTime > DateTime.Now &&
- // (dto.StepExpiredTime <= DateTime.Now || dto.StepExpiredTime > workflow.ExpiredTime))
- // throw UserFriendlyException.SameMessage("节点期满时间无效");
- var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow);
- if (currentStep.Status is EWorkflowStepStatus.Handled)
- throw new UserFriendlyException("该状态不支持继续办理");
- var currentStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, currentStep.Code);
- StepDefine nextStepDefine;
- if ((currentStep.InstanceMode is EInstanceMode.Dynamic && !DynamicShouldTerminal(currentStep))
- || (currentStep.IsInCountersign() && !currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
- || dto.IsStartCountersign)
- {
- //下一步配置为当前节点配置
- nextStepDefine = currentStepDefine;
- }
- else
- {
- //下一步配置为下一步节点配置
- nextStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
- }
- //需求:按角色选择办理人可以不选,表示该角色下所有人都可以办理,同时依据配置:是否本部门人办理显示待选办理人。角色下只要一人办理即可(即:角色下不发起会签)
- if (nextStepDefine.HandlerType != EHandlerType.Role && !dto.NextHandlers.Any())
- throw new UserFriendlyException("未指定节点处理者");
- if (dto.IsStartCountersign)
- {
- if (!currentStepDefine.CanStartCountersign)
- throw new UserFriendlyException("当前节点不支持发起会签");
- //if (currentStepDefine.HandlerType is EHandlerType.Role)
- // throw new UserFriendlyException("当前节点不支持发起会签");
- //即使当前节点支持发起会签,但下一节点为信息汇总节点、结束节点时也不可发起会签
- if (nextStepDefine.StepType is EStepType.Summary or EStepType.End)
- throw new UserFriendlyException("下一节点不允许发起会签");
- //下一节点是会签汇总节点也不允许发起会签
- if (dto.BackToCountersignEnd)
- throw new UserFriendlyException("下一节点不允许发起会签");
- }
- var flowAssignInfo =
- await GetNextStepFlowAssignInfoAsync(workflow, currentStep, nextStepDefine, dto, cancellationToken);
- await _workflowDomainService.NextAsync(workflow, currentStep, dto, nextStepDefine, flowAssignInfo,
- cancellationToken);
- }
- /// <summary>
- /// 撤回至任意节点
- /// </summary>
- public async Task RecallAsync(RecallDto dto, CancellationToken cancellationToken)
- {
- var workflow =
- await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true,
- cancellationToken: cancellationToken);
- await _orderDomainService.ReadyToRecallAsync(workflow.ExternalId, cancellationToken);
- var targetStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
- //var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
- var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign,
- dto.NextHandlers, cancellationToken);
- await _workflowDomainService.RecallAsync(workflow, dto, targetStepDefine, flowAssignInfo, cancellationToken);
- }
- /// <summary>
- /// 跳转至任意节点
- /// </summary>
- public async Task JumpAsync(RecallDto dto, CancellationToken cancellationToken)
- {
- var workflow =
- await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true,
- cancellationToken: cancellationToken);
- await _orderDomainService.ReadyToRecallAsync(workflow.ExternalId, cancellationToken);
- var targetStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
- //var isStartCountersign = targetStepDefine.CouldPrevStartCountersign(dto.NextHandlers.Count);
- var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign,
- dto.NextHandlers, cancellationToken);
- await _workflowDomainService.JumpAsync(workflow, dto, targetStepDefine, flowAssignInfo, cancellationToken);
- }
- /// <summary>
- /// 重办
- /// </summary>
- public async Task RedoAsync(RecallDto dto, CancellationToken cancellationToken)
- {
- var workflow =
- await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true,
- cancellationToken: cancellationToken);
- var targetStepDefine = _workflowDomainService.GetStepDefine(workflow.WorkflowDefinition, dto.NextStepCode);
- var flowAssignInfo = await GetNextStepFlowAssignInfoByDefineAsync(targetStepDefine, dto.IsStartCountersign,
- dto.NextHandlers, cancellationToken);
- await _workflowDomainService.RedoAsync(workflow, dto, targetStepDefine, flowAssignInfo, cancellationToken);
- }
- public async Task<DefinedStepDto> GetStartOptionsAsync(string moduleCode, CancellationToken cancellationToken)
- {
- var wfModule = await GetWorkflowModuleAsync(moduleCode, cancellationToken);
- var definition = wfModule.Definition;
- if (definition == null)
- throw new UserFriendlyException("无效模板编码");
- if (definition.Status is not EDefinitionStatus.Enable)
- throw new UserFriendlyException("该模板不可用");
- var startStep = definition.Steps.FirstOrDefault(d => d.StepType == EStepType.Start);
- if (startStep == null)
- throw new UserFriendlyException("未正确配置发起人节点");
- var firstStepDefines = definition.FindStepDefines(startStep.NextSteps.Select(d => d.Code));
- if (!firstStepDefines.Any())
- throw new UserFriendlyException("未正确配置首个办理节点");
- return new DefinedStepDto
- {
- DefinitionId = definition.Id,
- Steps = firstStepDefines
- // Components = firstStepDefine.Components
- };
- }
- /// <summary>
- /// 根据节点配置查询待选参数
- /// </summary>
- /// <param name="stepDefine"></param>
- /// <param name="cancellationToken"></param>
- /// <returns></returns>
- /// <exception cref="ArgumentOutOfRangeException"></exception>
- public async Task<IReadOnlyList<Kv>> GetNextStepOptionsAsync(StepDefineBasic stepDefine,
- CancellationToken cancellationToken)
- {
- //if (stepDefine.StepType == EStepType.End)
- // throw new UserFriendlyException("结束节点无待选项");
- //var handlers = new List<Kv>();
- //switch (stepDefine.HandlerType)
- //{
- // // case EHandlerType.AssignedUser:
- // // var users = await _userRepository.Queryable()
- // // .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Id).Contains(d.Id))
- // // .ToListAsync(cancellationToken);
- // // handlers = users.Select(d => new Kv(d.Id, d.Name)).ToList();
- // // break;
- // // case EHandlerType.AssignedOrg:
- // // var orgs = await _organizeRepository.QueryAsync(d =>
- // // d.IsEnable &&
- // // stepDefine.HandlerTypeItems.Select(d => d.Id).Contains(d.Id));
- // // handlers = orgs.Select(d => new Kv(d.Id, d.OrgName))
- // // .ToList();
- // // break;
- // case EHandlerType.AssignedUser:
- // case EHandlerType.AssignedOrg:
- // handlers = stepDefine.HandlerTypeItems;
- // break;
- // case EHandlerType.Role:
- // //当前操作人所属部门的下级部门并且属于配置包含角色
- // var roles = await _roleRepository.Queryable()
- // .Includes(d => d.Accounts.Where(x => !x.IsDeleted && x.Status == EAccountStatus.Normal).ToList(),
- // x => x.User)
- // .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
- // .ToListAsync(cancellationToken);
- // var users1 = roles.SelectMany(d => d.Accounts).Select(d => d.User);
- // handlers = users1.Select(d => new Kv(d.Id, d.Name)).ToList();
- // break;
- // case EHandlerType.OrgLevel:
- // //当前操作人所属部门的下级部门并且属于配置orgLevel的部门
- // var levels = stepDefine.HandlerTypeItems.Select(d => d.Key).Select(d => int.Parse(d));
- // var levelOneOrg = _sessionContext.RequiredOrgId.GetHigherOrgCode();
- // //var orgs1 = await _organizeRepository.QueryAsync(d =>
- // // d.IsEnable && d.OrgCode.StartsWith(levelOneOrg) &&
- // // levels.Contains(d.OrgLevel));
- // var orgs1 = await _organizeRepository.Queryable()
- // .Where(d => d.IsEnable && levels.Contains(d.Level))
- // .WhereIF(!levelOneOrg.IsCenter(), d => d.Id.StartsWith(levelOneOrg))
- // .ToListAsync(cancellationToken);
- // handlers = orgs1.Select(d => new Kv(d.Id, d.Name)).ToList();
- // break;
- // case EHandlerType.OrgType:
- // var types = stepDefine.HandlerTypeItems.Select(d => d.Key)
- // .Select(d => Enum.Parse<EOrgType>(d));
- // var levelOneOrg1 = _sessionContext.RequiredOrgId.GetHigherOrgCode();
- // //var org2 = await _organizeRepository.QueryAsync(d =>
- // // d.IsEnable && d.OrgCode.StartsWith(levelOneOrg1) &&
- // // types.Contains(d.OrgType));
- // var orgs2 = await _organizeRepository.Queryable()
- // .Where(d => d.IsEnable && types.Contains(d.OrgType))
- // .WhereIF(!levelOneOrg1.IsCenter(), d => d.Id.StartsWith(levelOneOrg1))
- // .ToListAsync(cancellationToken);
- // handlers = orgs2.Select(d => new Kv(d.Id, d.Name)).ToList();
- // break;
- // default:
- // throw new ArgumentOutOfRangeException();
- //}
- //var dto = new NextStepOptionDto { Handlers = handlers };
- //if (stepDefine.Components.Contains(SysDicTypeConsts.OrderRedoReason))
- //{
- // var orderRedoReasons =
- // await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.OrderRedoReason,
- // cancellationToken);
- // dto.OrderRedoReasonOptions = orderRedoReasons.Select(d => new Kv(d.DicDataValue, d.DicDataName)).ToList();
- //}
- //return dto;
- throw new NotImplementedException();
- }
- /// <summary>
- /// 查询开始流程的下一步待选节点
- /// </summary>
- public async Task<NextStepsDto> GetStartStepsAsync(string moduleCode, CancellationToken cancellationToken)
- {
- var wfModule = await GetWorkflowModuleAsync(moduleCode, cancellationToken);
- var definition = wfModule.Definition;
- if (definition == null)
- throw new UserFriendlyException("无效模板编码");
- if (definition.Status is not EDefinitionStatus.Enable)
- throw new UserFriendlyException("该模板不可用");
- var startStep = definition.FindStartStepDefine();
- //var dto = new NextStepsDto
- //{
- // DefinitionId = definition.Id,
- // InstanceMode = startStep.InstanceMode,
- // DynamicPolicy = startStep.InstancePolicy
- //};
- if (startStep.InstanceMode is EInstanceMode.Dynamic)
- {
- //var nextStepOption = CreateDynamicStep(startStep.InstancePolicy);
- //dto.Steps = new List<NextStepOption> { nextStepOption };
- //return dto;
- var nextStepOption = await GetDynamicStepAsync(startStep.InstancePolicy.Value, cancellationToken);
- return new NextStepsDto
- {
- Steps = new List<NextStepOption> { nextStepOption }
- };
- }
- var firstStepDefines = definition.FindStepDefines(startStep.NextSteps.Select(d => d.Code));
- if (!firstStepDefines.Any())
- throw new UserFriendlyException("未正确配置首个办理节点");
- //var steps = firstStepDefines
- // .Select(d => new NextStepOption { Key = d.Code, Value = d.Name })
- // .ToList();
- return new NextStepsDto
- {
- Steps = await GetConfigStepsAsync(startStep.StepType, startStep.BusinessType, firstStepDefines, cancellationToken)
- };
- //dto.Steps = steps;
- //return dto;
- }
- /// <summary>
- /// 查询办理流程的下一步待选节点
- /// </summary>
- public async Task<NextStepsDto> GetNextStepsAsync(string workflowId, CancellationToken cancellationToken)
- {
- var workflow =
- await _workflowDomainService.GetWorkflowAsync(workflowId, true, true, cancellationToken: cancellationToken);
- var currentStep = _workflowDomainService.FindCurrentStepWaitForHandle(workflow);
- if (currentStep.StepType is EStepType.End)
- throw new UserFriendlyException("结束节点无需办理");
- var dto = new NextStepsDto
- {
- CanReject = currentStep.CanReject,
- ExpiredTime = workflow.ExpiredTime,
- RealCommunicationModeOptions = EnumExts.GetDescriptions<ERealCommunicationMode>().ToList(),
- };
- if (currentStep.InstanceMode is EInstanceMode.Dynamic && !DynamicShouldTerminal(currentStep))
- {
- //动态生成下一步
- var nextStepOption = await GetDynamicStepAsync(currentStep.InstancePolicy.Value, cancellationToken);
- dto.Steps = new List<NextStepOption> { nextStepOption };
- return dto;
- }
- if (currentStep.IsInCountersign())
- {
- if (currentStep.IsCountersignEndStep)
- {
- //当前待办节点为会签汇总节点时:检查是否为顶级会签汇总节点,t:按配置往下走,f:继续往上汇总,不需要重复往下指派
- if (!currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
- {
- //查找当前节点对应会签开始节点的上级作为下一个cs汇总节点的汇总对象
- var startCountersignStep =
- workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);
- if (startCountersignStep is null)
- throw new UserFriendlyException(
- $"未查询到会签开始节点,workflowId: {workflow.Id}, startStepId: {currentStep.CountersignStartStepId}",
- "未查询到会签开始节点,数据异常");
- var countersignEndOption = GetCsEndStepByPrev(workflow.Steps, startCountersignStep);
- dto.Steps = new List<NextStepOption> { countersignEndOption };
- return dto;
- }
- }
- else
- {
- //汇总节点
- var countersignEndOption = GetCsEndStepByPrev(workflow.Steps, currentStep);
- //按会签策略
- var nextStepOption =
- await GetDynamicStepAsync(currentStep.CountersignPolicy.Value, currentStep.IsOrigin, currentStep.BusinessType, cancellationToken);
- dto.Steps = new List<NextStepOption> { nextStepOption, countersignEndOption };
- return dto;
- }
- }
- var nextDefines = workflow.WorkflowDefinition.FindStepDefines(currentStep.NextSteps.Select(d => d.Code));
- if (!nextDefines.Any())
- throw new UserFriendlyException("未正确配置下一节点");
- dto.Steps = await GetConfigStepsAsync(currentStep.StepType, currentStep.BusinessType, nextDefines, cancellationToken);
- if (currentStep.IsInCountersign() && currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
- {
- foreach (var nextStepOption in dto.Steps)
- {
- nextStepOption.InputRealHandler = true;
- }
- }
- return dto;
- //return new NextStepsDto
- //{
- // Steps = nextDefines.Select(d => new NextStepOption { Key = d.Code, Value = d.Name }).ToList()
- //};
- }
- /// <summary>
- /// 查询撤回可选节点
- /// </summary>
- public async Task<NextStepsDto> GetRecallStepsAsync(string workflowId, CancellationToken cancellationToken)
- {
- var workflow =
- await _workflowDomainService.GetWorkflowAsync(workflowId, true, true, cancellationToken: cancellationToken);
- var stepCodes = workflow.Steps.Where(d => d.StepType != EStepType.End && d.IsOrigin)
- .Select(d => d.Code).ToList();
- var stepDefines = workflow.WorkflowDefinition.FindStepDefines(stepCodes);
- return new NextStepsDto
- {
- Steps = await GetRecallConfigStepsAsync(stepDefines, cancellationToken)
- };
- }
- private async Task<IReadOnlyList<NextStepOption>> GetRecallConfigStepsAsync(List<StepDefine> stepDefines, CancellationToken cancellationToken)
- {
- var stepOptions = new List<NextStepOption>();
- foreach (var stepDefine in stepDefines)
- {
- var nextStepOption = await GetConfigStepAsync(stepDefine, cancellationToken);
- if (stepDefine.StepType is EStepType.End)
- {
- stepOptions.Add(nextStepOption);
- continue;
- }
- nextStepOption.InputRealHandler = false;
- //todo thk 派单->坐席, 会签中怎么界定当前节点?
- nextStepOption.FlowDirection =
- stepDefine.BusinessType is EBusinessType.Center or EBusinessType.Send
- ? EFlowDirection.OrgToCenter
- : stepDefine.BusinessType is EBusinessType.Department
- ? EFlowDirection.CenterToOrg
- : null;
- stepOptions.Add(nextStepOption);
- }
- return stepOptions;
- }
- /// <summary>
- /// 查询跳转可选节点
- /// </summary>
- public async Task<NextStepsDto> GetJumpStepsAsync(string workflowId, CancellationToken cancellationToken)
- {
- var workflow =
- await _workflowDomainService.GetWorkflowAsync(workflowId, true, cancellationToken: cancellationToken);
- return new NextStepsDto
- {
- //Steps = await GetConfigStepsAsync(null, workflow.WorkflowDefinition.Steps, cancellationToken)
- };
- }
- /// <summary>
- /// 查询重办可选节点
- /// </summary>
- public async Task<NextStepsDto> GetRedoStepsAsync(string workflowId, CancellationToken cancellationToken)
- {
- var workflow =
- await _workflowDomainService.GetWorkflowAsync(workflowId, true, true, cancellationToken: cancellationToken);
- var steps = workflow.Steps.Where(d => d.StepType is EStepType.Normal && d.IsOrigin && d.IsOrg());
- var stepDefines = workflow.WorkflowDefinition.FindStepDefines(steps.Select(d => d.Code));
- return new NextStepsDto
- {
- //Steps = await GetConfigStepsAsync(null, stepDefines, cancellationToken)
- };
- }
- /// <summary>
- /// 否决
- /// </summary>
- public async Task RejectAsync(RejectDto dto, CancellationToken cancellationToken)
- {
- var workflow = await _workflowDomainService.GetWorkflowAsync(dto.WorkflowId, true, true,
- cancellationToken: cancellationToken);
- var basicDto = _mapper.Map<BasicWorkflowDto>(dto);
- basicDto.NextStepCode = string.Empty;
- basicDto.IsStartCountersign = false;
- await _workflowDomainService.RejectAsync(workflow, basicDto, cancellationToken);
- }
- private async Task<List<NextStepOption>> GetConfigStepsAsync(EStepType? currentStepType,
- EBusinessType? currentBusinessType, List<StepDefine> stepDefines, CancellationToken cancellationToken)
- {
- var stepOptions = new List<NextStepOption>();
- foreach (var stepDefine in stepDefines)
- {
- var nextStepOption = await GetConfigStepAsync(stepDefine, cancellationToken);
- if (stepDefine.StepType is EStepType.End)
- {
- stepOptions.Add(nextStepOption);
- continue;
- }
- nextStepOption.InputRealHandler = currentStepType.HasValue &&
- (currentStepType != EStepType.Summary && stepDefine.StepType == EStepType.Summary);
- nextStepOption.FlowDirection = currentBusinessType.HasValue
- ? CheckFlowDirection(currentBusinessType.Value, stepDefine.BusinessType)
- : null;
- stepOptions.Add(nextStepOption);
- }
- return stepOptions;
- }
- public async Task<NextStepOption> GetConfigStepAsync(StepDefine stepDefine, CancellationToken cancellationToken)
- {
- var handlers = new List<Kv>();
- if (stepDefine.StepType is EStepType.End)
- {
- return new NextStepOption
- {
- Key = stepDefine.Code,
- Value = stepDefine.Name,
- Items = handlers
- };
- }
- var levelOneOrgCode = _sessionContext.RequiredOrgId.GetHigherOrgCode();
- switch (stepDefine.HandlerType)
- {
- case EHandlerType.AssignedUser:
- case EHandlerType.AssignedOrg:
- handlers = stepDefine.HandlerTypeItems;
- break;
- case EHandlerType.Role:
- //当前操作人所属部门的下级部门并且属于配置包含角色
- var roles = await _roleRepository.Queryable()
- .Includes(
- d => d.Accounts.Where(
- x => !x.IsDeleted && x.Status == EAccountStatus.Normal).ToList(),
- x => x.User)
- .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
- .ToListAsync(cancellationToken);
- var users1 = roles.SelectMany(d => d.Accounts).Select(d => d.User);
- //解决当前为一级部门选择中心汇总
- if (stepDefine.StepType != EStepType.Summary || stepDefine.BusinessType != EBusinessType.Center)
- users1 = users1.Where(d => d.OrgId.StartsWith(levelOneOrgCode));
- handlers = users1.Select(d => new Kv(d.Id, d.Name)).ToList();
- break;
- case EHandlerType.OrgLevel:
- //当前操作人所属部门的垂直部门并且属于配置orgLevel的部门
- var levels = stepDefine.HandlerTypeItems.Select(d => d.Key).Select(d => int.Parse(d));
- var orgs1 = await _organizeRepository.Queryable()
- .Where(d => d.IsEnable && levels.Contains(d.Level))
- .WhereIF(!levelOneOrgCode.IsCenter(), d => d.Id.StartsWith(levelOneOrgCode))
- .ToListAsync(cancellationToken);
- handlers = orgs1.Select(d => new Kv(d.Id, d.Name)).ToList();
- break;
- case EHandlerType.OrgType:
- var types = stepDefine.HandlerTypeItems.Select(d => d.Key)
- .Select(d => Enum.Parse<EOrgType>(d));
- var orgs2 = await _organizeRepository.Queryable()
- .Where(d => d.IsEnable && types.Contains(d.OrgType))
- .WhereIF(!levelOneOrgCode.IsCenter(), d => d.Id.StartsWith(levelOneOrgCode))
- .ToListAsync(cancellationToken);
- handlers = orgs2.Select(d => new Kv(d.Id, d.Name)).ToList();
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- return new NextStepOption
- {
- Key = stepDefine.Code,
- Value = stepDefine.Name,
- Items = handlers
- };
- }
- private EFlowDirection? CheckFlowDirection(EBusinessType sourceStepBusinessType, EBusinessType directionStepBusinessType)
- {
- switch (sourceStepBusinessType)
- {
- case EBusinessType.Center:
- case EBusinessType.Send:
- return directionStepBusinessType is EBusinessType.Department
- ? EFlowDirection.CenterToOrg
- : directionStepBusinessType is EBusinessType.File
- ? EFlowDirection.CenterToFile
- : EFlowDirection.CenterToCenter;
- case EBusinessType.Department:
- return directionStepBusinessType is EBusinessType.Center or EBusinessType.Send
- ? EFlowDirection.OrgToCenter
- : directionStepBusinessType is EBusinessType.Department
- ? EFlowDirection.OrgToOrg
- : null;
- case EBusinessType.File:
- return null;
- default:
- throw new ArgumentOutOfRangeException(nameof(sourceStepBusinessType), sourceStepBusinessType, null);
- }
- }
- private bool DynamicShouldTerminal(WorkflowStep step)
- {
- if (step.InstanceMode is not EInstanceMode.Dynamic)
- throw new UserFriendlyException("非动态节点");
- switch (step.InstancePolicy)
- {
- case EDynamicPolicy.OrgUpCenterTop:
- case EDynamicPolicy.OrgUp:
- case EDynamicPolicy.OrgDownCenterTop:
- case EDynamicPolicy.OrgDown:
- return step.DynamicShouldTerminal();
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
- /// <summary>
- /// 查询下一步所选节点对应待选项
- /// </summary>
- public async Task<IReadOnlyList<Kv>> GetNextStepOptionsAsync(GetNextStepItemsDto dto,
- CancellationToken cancellationToken)
- {
- List<Kv> nextStepOptions;
- if (dto.InstanceMode is EInstanceMode.Config)
- {
- nextStepOptions = await NextStepOptionsByConfigAsync(dto, cancellationToken);
- }
- else
- {
- nextStepOptions = await CreateNextStepOptionsDynamicAsync(dto, cancellationToken);
- }
- return nextStepOptions;
- }
- private async Task<List<Kv>> CreateNextStepOptionsDynamicAsync(GetNextStepItemsDto dto,
- CancellationToken cancellationToken)
- {
- if (!int.TryParse(dto.Step.Key, out int orgLevel))
- throw new UserFriendlyException("无效参数");
- List<Kv> items;
- var firstLevelOrgCode = _sessionContext.RequiredOrgId.GetHigherOrgCode();
- if (dto.Step.BackToCountersignEnd)
- {
- //todo 限定返回发起会签的办理人
- //items =
- }
- switch (dto.DynamicPolicy)
- {
- case EDynamicPolicy.OrgUpCenterTop:
- if (orgLevel == 0)
- {
- items = await _organizeRepository.Queryable()
- .Where(d => d.IsCenter)
- .Select(d => new Kv(d.Id, d.Name))
- .ToListAsync(cancellationToken);
- }
- else
- {
- items = await _organizeRepository.Queryable()
- .Where(d => !d.IsCenter && d.Level == orgLevel && d.Id.StartsWith(firstLevelOrgCode))
- .Select(d => new Kv(d.Id, d.Name))
- .ToListAsync(cancellationToken);
- }
- break;
- case EDynamicPolicy.OrgUp:
- items = await _organizeRepository.Queryable()
- .Where(d => d.Level == orgLevel && d.Id.StartsWith(firstLevelOrgCode))
- .Select(d => new Kv(d.Id, d.Name))
- .ToListAsync(cancellationToken);
- break;
- case EDynamicPolicy.OrgDownCenterTop:
- if (_sessionContext.OrgIsCenter)
- {
- items = await _organizeRepository.Queryable()
- .Where(d => !d.IsCenter && d.Level == orgLevel)
- .Select(d => new Kv(d.Id, d.Name))
- .ToListAsync(cancellationToken);
- }
- else
- {
- items = await _organizeRepository.Queryable()
- .Where(d => !d.IsCenter && d.Level == orgLevel && d.Id.StartsWith(firstLevelOrgCode))
- .Select(d => new Kv(d.Id, d.Name))
- .ToListAsync(cancellationToken);
- }
- break;
- case EDynamicPolicy.OrgDown:
- items = await _organizeRepository.Queryable()
- .Where(d => d.Level == orgLevel && d.Id.StartsWith(firstLevelOrgCode))
- .Select(d => new Kv(d.Id, d.Name))
- .ToListAsync(cancellationToken);
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- return items;
- }
- private async Task<List<Kv>> NextStepOptionsByConfigAsync(GetNextStepItemsDto dto,
- CancellationToken cancellationToken)
- {
- var definition = await _definitionRepository.GetAsync(dto.DefinitionId, cancellationToken);
- if (definition == null)
- throw new UserFriendlyException("无效DefineId");
- var stepDefine = definition.FindStepDefine(dto.Step.Key);
- if (stepDefine is null)
- throw UserFriendlyException.SameMessage("未查询到对应节点配置");
- if (stepDefine.StepType == EStepType.End)
- throw new UserFriendlyException("结束节点无待选项");
- var handlers = new List<Kv>();
- var firstLevelOrgCode = _sessionContext.RequiredOrgId.GetHigherOrgCode();
- switch (stepDefine.HandlerType)
- {
- case EHandlerType.AssignedUser:
- case EHandlerType.AssignedOrg:
- handlers = stepDefine.HandlerTypeItems;
- break;
- case EHandlerType.Role:
- //当前操作人所属部门的下级部门并且属于配置包含角色
- var roles = await _roleRepository.Queryable()
- .Includes(
- d => d.Accounts.Where(x =>
- !x.IsDeleted && x.Status == EAccountStatus.Normal &&
- x.User.OrgId.StartsWith(firstLevelOrgCode)).ToList(),
- x => x.User)
- .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
- .ToListAsync(cancellationToken);
- var users1 = roles.SelectMany(d => d.Accounts).Select(d => d.User);
- handlers = users1.Select(d => new Kv(d.Id, d.Name)).ToList();
- break;
- case EHandlerType.OrgLevel:
- //当前操作人所属部门的垂直部门并且属于配置orgLevel的部门
- var levels = stepDefine.HandlerTypeItems.Select(d => d.Key).Select(d => int.Parse(d));
- var orgs1 = await _organizeRepository.Queryable()
- .Where(d => d.IsEnable && levels.Contains(d.Level))
- .WhereIF(!firstLevelOrgCode.IsCenter(), d => d.Id.StartsWith(firstLevelOrgCode))
- .ToListAsync(cancellationToken);
- handlers = orgs1.Select(d => new Kv(d.Id, d.Name)).ToList();
- break;
- case EHandlerType.OrgType:
- var types = stepDefine.HandlerTypeItems.Select(d => d.Key)
- .Select(d => Enum.Parse<EOrgType>(d));
- var orgs2 = await _organizeRepository.Queryable()
- .Where(d => d.IsEnable && types.Contains(d.OrgType))
- .WhereIF(!firstLevelOrgCode.IsCenter(), d => d.Id.StartsWith(firstLevelOrgCode))
- .ToListAsync(cancellationToken);
- handlers = orgs2.Select(d => new Kv(d.Id, d.Name)).ToList();
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
- return handlers;
- }
- private NextStepOption GetCsEndStepByPrev(List<WorkflowStep> steps, WorkflowStep step)
- {
- var prevStep = steps.FirstOrDefault(d => d.Id == step.PrevStepId);
- if (prevStep is null)
- throw new UserFriendlyException("未查找到会签上级节点");
- var text = prevStep.HandlerOrgIsCenter.Value
- ? "热线中心汇总"
- : $"{prevStep.HandlerOrgId.CalcOrgLevel().ToChinese()}级部门汇总";
- var handlers = prevStep.Handlers
- .Where(d => d.Key == prevStep.HandlerId || d.Key == prevStep.HandlerOrgId).ToList();
- return new NextStepOption
- {
- Key = prevStep.Code,
- Value = text, //parentStep.Name,//todo name不对,目前为definition.name,需改为x级部门办理
- BackToCountersignEnd = true,
- BusinessType = prevStep.BusinessType,
- Items = handlers //new List<Kv> { new(prevStep.HandlerId, prevStep.HandlerName) },
- };
- }
- /// <summary>
- /// 依据当前操作人及动态策略生成下一步节点
- /// </summary>
- private NextStepOption CreateDynamicStep(EDynamicPolicy policy)
- {
- int orgLevel;
- switch (policy)
- {
- case EDynamicPolicy.OrgUpCenterTop:
- orgLevel = _sessionContext.OrgLevel - 1;
- if (orgLevel < 0) orgLevel = 0;
- break;
- case EDynamicPolicy.OrgUp:
- orgLevel = _sessionContext.OrgLevel - 1;
- if (orgLevel <= 0) orgLevel = 1;
- break;
- case EDynamicPolicy.OrgDownCenterTop:
- orgLevel = _sessionContext.OrgIsCenter
- ? 1
- : _sessionContext.OrgLevel + 1;
- break;
- case EDynamicPolicy.OrgDown:
- orgLevel = _sessionContext.OrgLevel + 1;
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(policy), policy, null);
- }
- return new NextStepOption
- {
- Key = orgLevel.ToString(),
- Value = orgLevel == 0 ? "热线中心" : $"{orgLevel.ToChinese()}级部门",
- };
- }
- private async Task<NextStepOption> GetDynamicStepAsync(EDynamicPolicy policy, bool isOrigin,
- EBusinessType currentBusinessType, CancellationToken cancellationToken)
- {
- int orgLevel;
- List<Kv> items;
- EFlowDirection flowDirection;
- var levelOneOrgCode = _sessionContext.RequiredOrgId.GetHigherOrgCode();
- switch (policy)
- {
- case EDynamicPolicy.OrgUpCenterTop:
- orgLevel = _sessionContext.OrgLevel - 1;
- if (orgLevel < 0) orgLevel = 0;
- if (orgLevel == 0)
- {
- items = await _organizeRepository.Queryable()
- .Where(d => d.IsCenter)
- .Select(d => new Kv { Key = d.Id, Value = d.Name })
- .ToListAsync(cancellationToken);
- flowDirection =
- }
- else
- {
- items = await _organizeRepository.Queryable()
- .Where(d => !d.IsCenter && d.Level == orgLevel && d.Id.StartsWith(levelOneOrgCode))
- .Select(d => new Kv { Key = d.Id, Value = d.Name })
- .ToListAsync(cancellationToken);
- businessType = EBusinessType.Department;
- }
- break;
- case EDynamicPolicy.OrgUp:
- orgLevel = _sessionContext.OrgLevel - 1;
- if (orgLevel <= 0) orgLevel = 1;
- items = await _organizeRepository.Queryable()
- .Where(d => d.Level == orgLevel && d.Id.StartsWith(levelOneOrgCode))
- .Select(d => new Kv { Key = d.Id, Value = d.Name })
- .ToListAsync(cancellationToken);
- businessType = _sessionContext.OrgIsCenter
- ? EBusinessType.Center
- : _sessionContext.OrgLevel == 1
- ? EBusinessType.Center
- : EBusinessType.Department;
- break;
- case EDynamicPolicy.OrgDownCenterTop:
- if (_sessionContext.OrgIsCenter)
- {
- orgLevel = 1;
- items = await _organizeRepository.Queryable()
- .Where(d => !d.IsCenter && d.Level == orgLevel)
- .Select(d => new Kv { Key = d.Id, Value = d.Name })
- .ToListAsync(cancellationToken);
- }
- else
- {
- orgLevel = _sessionContext.OrgLevel + 1;
- items = await _organizeRepository.Queryable()
- .Where(d => !d.IsCenter && d.Level == orgLevel && d.Id.StartsWith(levelOneOrgCode))
- .Select(d => new Kv { Key = d.Id, Value = d.Name })
- .ToListAsync(cancellationToken);
- }
- businessType = EBusinessType.Department;
- break;
- case EDynamicPolicy.OrgDown:
- orgLevel = _sessionContext.OrgLevel + 1;
- items = await _organizeRepository.Queryable()
- .Where(d => d.Level == orgLevel && d.Id.StartsWith(levelOneOrgCode))
- .Select(d => new Kv { Key = d.Id, Value = d.Name })
- .ToListAsync(cancellationToken);
- businessType = EBusinessType.Department;
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(policy), policy, null);
- }
- return new NextStepOption
- {
- Key = orgLevel.ToString(),
- Value = orgLevel == 0 ? "热线中心" : $"{orgLevel.ToChinese()}级部门",
- BusinessType = businessType,
- Items = items
- };
- }
- //private async Task<IReadOnlyList<NextStepOption>> GetConfigStepsAsync(List<StepDefine> stepDefines,
- // CancellationToken cancellationToken)
- //{
- // foreach (var stepDefine in stepDefines)
- // {
- // if (stepDefine.StepType == EStepType.End)
- // throw new UserFriendlyException("结束节点无待选项");
- // var handlers = new List<Kv>();
- // switch (stepDefine.HandlerType)
- // {
- // case EHandlerType.AssignedUser:
- // case EHandlerType.AssignedOrg:
- // handlers = stepDefine.HandlerTypeItems;
- // break;
- // case EHandlerType.Role:
- // //当前操作人所属部门的下级部门并且属于配置包含角色
- // var roles = await _roleRepository.Queryable()
- // .Includes(d => d.Accounts.Where(x => !x.IsDeleted && x.Status == EAccountStatus.Normal).ToList(),
- // x => x.User)
- // .Where(d => stepDefine.HandlerTypeItems.Select(x => x.Key).Contains(d.Name))
- // .ToListAsync(cancellationToken);
- // var users1 = roles.SelectMany(d => d.Accounts).Select(d => d.User);
- // handlers = users1.Select(d => new Kv(d.Id, d.Name)).ToList();
- // break;
- // case EHandlerType.OrgLevel:
- // //当前操作人所属部门的下级部门并且属于配置orgLevel的部门
- // var levels = stepDefine.HandlerTypeItems.Select(d => d.Key).Select(d => int.Parse(d));
- // var levelOneOrg = _sessionContext.RequiredOrgId.GetHigherOrgCode();
- // //var orgs1 = await _organizeRepository.QueryAsync(d =>
- // // d.IsEnable && d.OrgCode.StartsWith(levelOneOrg) &&
- // // levels.Contains(d.OrgLevel));
- // var orgs1 = await _organizeRepository.Queryable()
- // .Where(d => d.IsEnable && levels.Contains(d.Level))
- // .WhereIF(!levelOneOrg.IsCenter(), d => d.Id.StartsWith(levelOneOrg))
- // .ToListAsync(cancellationToken);
- // handlers = orgs1.Select(d => new Kv(d.Id, d.Name)).ToList();
- // break;
- // case EHandlerType.OrgType:
- // var types = stepDefine.HandlerTypeItems.Select(d => d.Key)
- // .Select(d => Enum.Parse<EOrgType>(d));
- // var levelOneOrg1 = _sessionContext.RequiredOrgId.GetHigherOrgCode();
- // //var org2 = await _organizeRepository.QueryAsync(d =>
- // // d.IsEnable && d.OrgCode.StartsWith(levelOneOrg1) &&
- // // types.Contains(d.OrgType));
- // var orgs2 = await _organizeRepository.Queryable()
- // .Where(d => d.IsEnable && types.Contains(d.OrgType))
- // .WhereIF(!levelOneOrg1.IsCenter(), d => d.Id.StartsWith(levelOneOrg1))
- // .ToListAsync(cancellationToken);
- // handlers = orgs2.Select(d => new Kv(d.Id, d.Name)).ToList();
- // break;
- // default:
- // throw new ArgumentOutOfRangeException();
- // }
- // var dto = new NextStepOptionDto { Handlers = handlers };
- // if (stepDefine.Components.Contains(SysDicTypeConsts.OrderRedoReason))
- // {
- // var orderRedoReasons =
- // await _systemDomainService.GetSysDicDataByCodeAsync(SysDicTypeConsts.OrderRedoReason,
- // cancellationToken);
- // dto.OrderRedoReasonOptions = orderRedoReasons.Select(d => new Kv(d.DicDataValue, d.DicDataName)).ToList();
- // }
- // return dto;
- // }
- // throw new NotImplementedException();
- //}
- /// <summary>
- /// 查询下一节点办理对象类型(user or org)及实际办理对象
- /// </summary>
- public async Task<FlowAssignInfo> GetNextStepFlowAssignInfoAsync(Workflow workflow, WorkflowStep currentStep,
- StepDefine nextStepDefine, BasicWorkflowDto dto, CancellationToken cancellationToken)
- {
- if (nextStepDefine.StepType is EStepType.End) return new();
- var isStartCountersign = dto.IsStartCountersign;
- var handlers = dto.NextHandlers;
- if (isStartCountersign)
- //按会签策略判断,目前所有策略为org
- return FlowAssignInfo.Create(EFlowAssignType.Org, handlers, isStartCountersign);
- //if (currentStep.IsInCountersign() && !currentStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
- // return FlowAssignInfo.Create(EFlowAssignType.Org, handlers, isStartCountersign);
- if (currentStep.IsInCountersign())
- {
- if (dto.BackToCountersignEnd)
- {
- var prevStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.PrevStepId);
- if (prevStep is null)
- throw new UserFriendlyException($"未查询到当前节点的上级节点");
- return FlowAssignInfo.Create(prevStep.FlowAssignType.Value, prevStep.Handlers, isStartCountersign);
- }
- else
- {
- //按会签策略判断,目前所有策略为org
- return FlowAssignInfo.Create(EFlowAssignType.Org, handlers, isStartCountersign);
- }
- }
- if (currentStep.InstanceMode is EInstanceMode.Dynamic && !currentStep.DynamicShouldTerminal())
- return FlowAssignInfo.Create(EFlowAssignType.Org, handlers, isStartCountersign);
- return await GetNextStepFlowAssignInfoByDefineAsync(nextStepDefine, isStartCountersign, handlers,
- cancellationToken);
- }
- /// <summary>
- /// 按流程模板配置创建下一步办理对象
- /// </summary>
- private async Task<FlowAssignInfo> GetNextStepFlowAssignInfoByDefineAsync(StepDefine nextStepDefine,
- bool isStartCountersign,
- List<Kv> handlers, CancellationToken cancellationToken)
- {
- switch (nextStepDefine.HandlerType)
- {
- case EHandlerType.Role:
- if (!handlers.Any())
- {
- var roles = await _roleRepository.Queryable()
- .Includes(d => d.Accounts, x => x.User)
- .Where(d => nextStepDefine.HandlerTypeItems.Select(d => d.Key).Contains(d.Name))
- .ToListAsync(cancellationToken);
- handlers = roles.SelectMany(d => d.Accounts).Distinct()
- .Select(d => new Kv(d.Id, d.User.Name))
- .ToList();
- }
- return FlowAssignInfo.Create(EFlowAssignType.User, handlers, isStartCountersign);
- case EHandlerType.OrgLevel:
- case EHandlerType.OrgType:
- case EHandlerType.AssignedOrg:
- return FlowAssignInfo.Create(EFlowAssignType.Org, handlers, isStartCountersign);
- case EHandlerType.AssignedUser:
- return FlowAssignInfo.Create(EFlowAssignType.User, handlers, isStartCountersign);
- default:
- throw new ArgumentOutOfRangeException();
- }
- }
- #region private
- /// <summary>
- /// 查询流程业务模块
- /// </summary>
- /// <param name="code"></param>
- /// <param name="cancellationToken"></param>
- /// <returns></returns>
- /// <exception cref="UserFriendlyException"></exception>
- private async Task<WorkflowModule> GetWorkflowModuleAsync(string code, CancellationToken cancellationToken)
- {
- var wfModule = await _wfModuleCacheManager.GetWorkflowModuleAsync(code, cancellationToken);
- if (wfModule == null)
- throw UserFriendlyException.SameMessage("无效流程模块编码");
- if (wfModule.Definition is null)
- throw new UserFriendlyException($"{code} 未配置流程模板", "未配置流程模板");
- return wfModule;
- }
- #endregion
- }
|