diff --git a/OpenAuth.App/FlowApproverApp/FlowApproverApp.cs b/OpenAuth.App/FlowApproverApp/FlowApproverApp.cs index 0e1a0e45..fcc5a59a 100644 --- a/OpenAuth.App/FlowApproverApp/FlowApproverApp.cs +++ b/OpenAuth.App/FlowApproverApp/FlowApproverApp.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Infrastructure; using OpenAuth.App.Interface; @@ -68,6 +69,53 @@ namespace OpenAuth.App data = objs }; } + + /// + /// 获取当前可以审批的加签人ID列表 + /// 如果是顺序执行,取第一个人 + /// 否则并行且/并行或都是返回所有加签人 + /// + public string[] GetApproverIds(QueryApproverReq req) + { + var approvers = GetApprovers(req); + //否则并行且/并行或都是返回所有加签人 + return approvers.Select(u => u.ApproverId).ToArray(); + } + + public FlowApprover[] GetApprovers(QueryApproverReq req) + { + var query= Repository.AsQueryable() + .Where(u => u.InstanceId == req.FlowInstanceId + && u.ActivityId == req.ActivityId && u.Status == 0); //本节点待审批的加签人 + if (query.Count() == 0) + { + return null; + } + + //如果是顺序执行,取第一个人 + if (query.First().ApproveType == 0) + { + var result = query.OrderBy(u => u.OrderNo).First(); + return new[] { result }; + } + //否则并行且/并行或都是返回所有加签人 + return query.ToArray(); + } + + /// + /// 审批加签节点 + /// + public void Verify(VerifyApproverReq verifyApproverReq) + { + Repository.Update(u => new FlowApprover() + { + Status = verifyApproverReq.Status, + VerifyComment = verifyApproverReq.VerifyComment, + VerifyDate = DateTime.Now + }, u => u.Id == verifyApproverReq.Id); + + //TODO:需要判断节点是否已经全部审批通过,如果通过则修改节点状态为通过 + } public FlowApproverApp(ISqlSugarClient client, IAuth auth) : base(client, auth) { diff --git a/OpenAuth.App/FlowApproverApp/Request/VerifyApproverReq.cs b/OpenAuth.App/FlowApproverApp/Request/VerifyApproverReq.cs index f0cf193f..ca26f214 100644 --- a/OpenAuth.App/FlowApproverApp/Request/VerifyApproverReq.cs +++ b/OpenAuth.App/FlowApproverApp/Request/VerifyApproverReq.cs @@ -24,12 +24,7 @@ namespace OpenAuth.App.Request ///审批意见 /// public string VerifyComment { get; set; } - - /// - ///审批日期 - /// - public DateTime? VerifyDate { get; set; } - + /// ///状态(0未处理,1通过,2未通过,3驳回) /// diff --git a/OpenAuth.App/FlowInstance/FlowInstanceApp.cs b/OpenAuth.App/FlowInstance/FlowInstanceApp.cs deleted file mode 100644 index c07e6482..00000000 --- a/OpenAuth.App/FlowInstance/FlowInstanceApp.cs +++ /dev/null @@ -1,1031 +0,0 @@ -// *********************************************************************** -// Assembly : OpenAuth.App -// Author : 李玉宝 -// Created : 07-19-2018 -// -// Last Modified By : 李玉宝 -// Last Modified On : 07-19-2018 -// *********************************************************************** -// -// Copyright (c) http://www.openauth.net.cn. All rights reserved. -// -// -// *********************************************************************** - -using Infrastructure; -using OpenAuth.App.Flow; -using OpenAuth.App.Interface; -using OpenAuth.App.Request; -using OpenAuth.App.Response; -using OpenAuth.Repository.Domain; -using OpenAuth.Repository.Interface; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Net.Http; -using System.Threading.Tasks; -using Infrastructure.Const; -using Infrastructure.Extensions; -using Infrastructure.Helpers; -using Microsoft.EntityFrameworkCore; -using Newtonsoft.Json.Linq; -using OpenAuth.Repository; -using OpenAuth.Repository.QueryObj; -using Yitter.IdGenerator; - -namespace OpenAuth.App -{ - /// - /// 工作流实例表操作 - /// - public class FlowInstanceApp : BaseStringApp - { - private RevelanceManagerApp _revelanceApp; - private FlowSchemeApp _flowSchemeApp; - private FormApp _formApp; - private IHttpClientFactory _httpClientFactory; - private IServiceProvider _serviceProvider; - private SysMessageApp _messageApp; - private DbExtension _dbExtension; - private UserManagerApp _userManagerApp; - private OrgManagerApp _orgManagerApp; - - public FlowInstanceApp(IUnitWork unitWork, - IRepository repository - , RevelanceManagerApp app, FlowSchemeApp flowSchemeApp, FormApp formApp, - IHttpClientFactory httpClientFactory, IAuth auth, IServiceProvider serviceProvider, - SysMessageApp messageApp, DbExtension dbExtension, UserManagerApp userManagerApp, - OrgManagerApp orgManagerApp) - : base(unitWork, repository, auth) - { - _revelanceApp = app; - _flowSchemeApp = flowSchemeApp; - _formApp = formApp; - _httpClientFactory = httpClientFactory; - _serviceProvider = serviceProvider; - _messageApp = messageApp; - _dbExtension = dbExtension; - _userManagerApp = userManagerApp; - _orgManagerApp = orgManagerApp; - } - - #region 流程处理API - - /// - /// 创建一个实例 - /// - /// - public bool CreateInstance(AddFlowInstanceReq addFlowInstanceReq) - { - CheckNodeDesignate(addFlowInstanceReq); - FlowScheme scheme = null; - if (!string.IsNullOrEmpty(addFlowInstanceReq.SchemeId)) - { - scheme = _flowSchemeApp.Get(addFlowInstanceReq.SchemeId); - } - - if ((scheme == null) && !string.IsNullOrEmpty(addFlowInstanceReq.SchemeCode)) - { - scheme = _flowSchemeApp.FindByCode(addFlowInstanceReq.SchemeCode); - } - - if (scheme == null) - { - throw new Exception("该流程模板已不存在,请重新设计流程"); - } - - addFlowInstanceReq.SchemeContent = scheme.SchemeContent; - - var form = _formApp.FindSingle(scheme.FrmId); - if (form == null) - { - throw new Exception("该流程模板对应的表单已不存在,请重新设计流程"); - } - - addFlowInstanceReq.FrmContentData = form.ContentData; - addFlowInstanceReq.FrmContentParse = form.ContentParse; - addFlowInstanceReq.FrmType = form.FrmType; - addFlowInstanceReq.FrmId = form.Id; - - var flowInstance = addFlowInstanceReq.MapTo(); - - //创建运行实例 - var wfruntime = new FlowRuntime(flowInstance); - var user = _auth.GetCurrentUser(); - - #region 根据运行实例改变当前节点状态 - - flowInstance.ActivityId = wfruntime.nextNodeId; - flowInstance.ActivityType = wfruntime.GetNextNodeType(); - flowInstance.ActivityName = wfruntime.nextNode.name; - flowInstance.PreviousId = wfruntime.currentNodeId; - flowInstance.CreateUserId = user.User.Id; - addFlowInstanceReq.CreateUserId = user.User.Id; - flowInstance.CreateUserName = user.User.Account; - addFlowInstanceReq.CreateUserName = user.User.Account; - - flowInstance.MakerList = - (wfruntime.GetNextNodeType() != 4 ? GetNextMakers(wfruntime, addFlowInstanceReq) : ""); - flowInstance.IsFinish = (wfruntime.GetNextNodeType() == 4 - ? FlowInstanceStatus.Finished - : FlowInstanceStatus.Running); - - UnitWork.Add(flowInstance); - wfruntime.flowInstanceId = flowInstance.Id; - - if (flowInstance.FrmType == 1) //如果是开发者自定义的表单 - { - var t = Type.GetType("OpenAuth.App." + flowInstance.DbName + "App"); - ICustomerForm icf = (ICustomerForm)_serviceProvider.GetService(t); - try - { - icf.Add(flowInstance.Id, flowInstance.FrmData); - } - catch (Exception e) - { - throw new Exception("流程表单数据解析失败,请检查表单是否填写完整"); - } - } - - //如果工作流配置的表单配置有对应的数据库 - if (!string.IsNullOrEmpty(form.DbName)) - { - var dbcolumns = _dbExtension.GetDbTableStructure(form.DbName); - var json = JsonHelper.Instance.Deserialize(addFlowInstanceReq.FrmData); - var columnstr = string.Empty; //字段 - var valstr = string.Empty; //值字符串 - - - foreach (var column in dbcolumns) - { - if (column.ColumnName == "Id" || column.ColumnName == "id") - { - var options = new IdGeneratorOptions() - { - Method = 1, - WorkerId = 1 - }; - - YitIdHelper.SetIdGenerator(options); - columnstr += "Id,"; - valstr += "'" + YitIdHelper.NextId().ToString() + "',"; - continue; - } - - //讲流程实例ID赋值到表单数据表中,实现表单记录与流程实例关联 - if (column.ColumnName == Define.DEFAULT_FORM_INSTANCE_ID_NAME) - { - columnstr += $"{Define.DEFAULT_FORM_INSTANCE_ID_NAME},"; - valstr += "'" + flowInstance.Id + "',"; - continue; - } - - var val = json[column.ColumnName]; - if (val == null) - { - switch (column.EntityType) - { - case "int": - val = 0; - break; - case "string": - val = ""; - break; - case "DateTime": - val = DateTime.Now.ToString("yyyy-MM-dd"); - break; - } - } - - if (val == null) continue; - columnstr += column.ColumnName + ","; - valstr += "'" + val + "',"; - } - - columnstr = columnstr.TrimEnd(','); - valstr = valstr.TrimEnd(','); - var sql = $"insert into {form.DbName}({columnstr}) values ({valstr})"; - UnitWork.ExecuteSql(sql); - } - - #endregion 根据运行实例改变当前节点状态 - - #region 流程操作记录 - - FlowInstanceOperationHistory processOperationHistoryEntity = new FlowInstanceOperationHistory - { - InstanceId = flowInstance.Id, - CreateUserId = user.User.Id, - CreateUserName = user.User.Name, - CreateDate = DateTime.Now, - Content = "【创建】" - + user.User.Name - + "创建了一个流程进程【" - + addFlowInstanceReq.Code + "/" - + addFlowInstanceReq.CustomName + "】" - }; - UnitWork.Add(processOperationHistoryEntity); - - #endregion 流程操作记录 - - AddTransHistory(wfruntime); - UnitWork.Save(); - return true; - } - - /// - /// 更新流程 - /// 更新时可以修改表单内容,可以修改流程基本信息,但不能更换表单模版 - /// - /// - public void Update(UpdateFlowInstanceReq req) - { - var flowinstance = Get(req.Id); - - if (flowinstance.IsFinish != FlowInstanceStatus.Draft && - flowinstance.IsFinish != FlowInstanceStatus.Rejected) - { - throw new Exception("只能修改【草稿】和【驳回】状态的流程"); - } - - var form = _formApp.Get(flowinstance.FrmId); - - if (form != null) - { - if (form.FrmType == 1) //如果是开发者自定义的表单,更新对应数据库表数据 - { - var t = Type.GetType("OpenAuth.App." + req.DbName + "App"); - ICustomerForm icf = (ICustomerForm)_serviceProvider.GetService(t); - icf.Update(req.Id, req.FrmData); - } - else if (form.FrmType == 2 && !string.IsNullOrEmpty(form.DbName)) //拖拽表单定义了关联数据库 - { - var dbcolumns = _dbExtension.GetDbTableStructure(form.DbName); - var json = JsonHelper.Instance.Deserialize(req.FrmData); - var updatestr = string.Empty; //字段 - - foreach (var column in dbcolumns) - { - if (column.ColumnName == "Id" || column.ColumnName == "id") - { - continue; - } - - //流程实例ID不能修改 - if (column.ColumnName == Define.DEFAULT_FORM_INSTANCE_ID_NAME) - { - continue; - } - - var val = json[column.ColumnName]; - if (val == null) - { - continue; - } - - updatestr += $"{column.ColumnName} = '{val}',"; - } - - updatestr = updatestr.TrimEnd(','); - if (!string.IsNullOrEmpty(updatestr)) - { - var sql = - $"update {form.DbName} set {updatestr} where {Define.DEFAULT_FORM_INSTANCE_ID_NAME}='{req.Id}'"; - UnitWork.ExecuteSql(sql); - } - } - } - - flowinstance.Description = req.Description; - flowinstance.Code = req.Code; - flowinstance.FrmData = req.FrmData; - flowinstance.DbName = req.DbName; - flowinstance.CustomName = req.CustomName; - UnitWork.Update(flowinstance); - UnitWork.Save(); - } - - /// - /// 节点审核 - /// - /// - /// - public bool NodeVerification(VerificationReq request) - { - var user = _auth.GetCurrentUser().User; - var instanceId = request.FlowInstanceId; - - var tag = new Tag - { - UserName = user.Name, - UserId = user.Id, - Description = request.VerificationOpinion, - Taged = Int32.Parse(request.VerificationFinally) - }; - - FlowInstance flowInstance = Get(instanceId); - - if (flowInstance.MakerList != "1" && !flowInstance.MakerList.Contains(user.Id)) - { - throw new Exception("当前用户没有审批该节点权限"); - } - - FlowRuntime wfruntime = new FlowRuntime(flowInstance); - - #region 会签 - - if (flowInstance.ActivityType == 0) //当前节点是会签节点 - { - //会签时的【当前节点】一直是会签开始节点 - //TODO: 标记会签节点的状态,这个地方感觉怪怪的 - wfruntime.MakeTagNode(wfruntime.currentNodeId, tag); - - string canCheckId = ""; //寻找当前登录用户可审核的节点Id - foreach (string fromForkStartNodeId in wfruntime.FromNodeLines[wfruntime.currentNodeId] - .Select(u => u.to)) - { - var fromForkStartNode = wfruntime.Nodes[fromForkStartNodeId]; //与会前开始节点直接连接的节点 - canCheckId = GetOneForkLineCanCheckNodeId(fromForkStartNode, wfruntime, tag); - if (!string.IsNullOrEmpty(canCheckId)) break; - } - - if (canCheckId == "") - { - throw (new Exception("审核异常,找不到审核节点")); - } - - var content = - $"{user.Account}-{DateTime.Now.ToString("yyyy-MM-dd HH:mm")}审批了【{wfruntime.Nodes[canCheckId].name}】" + - $"结果:{(tag.Taged == 1 ? "同意" : "不同意")},备注:{tag.Description}"; - AddOperationHis(instanceId, tag, content); - - wfruntime.MakeTagNode(canCheckId, tag); //标记审核节点状态 - string res = wfruntime.NodeConfluence(canCheckId, tag); - if (res == TagState.No.ToString("D")) - { - flowInstance.IsFinish = FlowInstanceStatus.Disagree; - } - else if (!string.IsNullOrEmpty(res)) - { - flowInstance.PreviousId = flowInstance.ActivityId; - flowInstance.ActivityId = wfruntime.nextNodeId; - flowInstance.ActivityType = wfruntime.nextNodeType; - flowInstance.ActivityName = wfruntime.nextNode.name; - flowInstance.IsFinish = (wfruntime.nextNodeType == 4 - ? FlowInstanceStatus.Finished - : FlowInstanceStatus.Running); - flowInstance.MakerList = - (wfruntime.nextNodeType == 4 ? "" : GetNextMakers(wfruntime)); - - AddTransHistory(wfruntime); - } - else - { - //会签过程中,需要更新用户 - flowInstance.MakerList = GetForkNodeMakers(wfruntime, wfruntime.currentNodeId); - AddTransHistory(wfruntime); - } - - flowInstance.SchemeContent = JsonHelper.Instance.Serialize(wfruntime.ToSchemeObj()); - } - - #endregion 会签 - - #region 一般审核 - - else - { - VerifyNode(request, tag, flowInstance); - } - - #endregion 一般审核 - - //自定义开发表单,需要更新对应的数据库 - if (!string.IsNullOrEmpty(request.FrmData) && flowInstance.FrmType == 1) - { - var t = Type.GetType("OpenAuth.App." + flowInstance.DbName + "App"); - ICustomerForm icf = (ICustomerForm)_serviceProvider.GetService(t); - icf.Update(flowInstance.Id, flowInstance.FrmData); - } - - UnitWork.Update(flowInstance); - //给流程创建人发送通知信息 - _messageApp.SendMsgTo(flowInstance.CreateUserId, - $"你的流程[{flowInstance.CustomName}]已被{user.Name}处理。"); - - UnitWork.Save(); - - wfruntime.NotifyThirdParty(_httpClientFactory.CreateClient(), tag); - return true; - } - - /// - /// 普通的节点审批 - /// - private void VerifyNode(VerificationReq request, Tag tag, FlowInstance flowInstance) - { - var user = _auth.GetCurrentUser().User; - - if (!string.IsNullOrEmpty(request.FrmData)) - { - flowInstance.FrmData = request.FrmData; - } - - FlowRuntime wfruntime = new FlowRuntime(flowInstance); - wfruntime.MakeTagNode(wfruntime.currentNodeId, tag); - if (tag.Taged == (int)TagState.Ok) - { - bool canNext = true; - if (wfruntime.currentNode.setInfo.NodeDesignate == Setinfo.RUNTIME_MANY_PARENTS) - { - var roles = _auth.GetCurrentUser().Roles; - //如果是连续多级直属上级且还没到指定的角色,只改变执行人,不到下一个节点 - if (!wfruntime.currentNode.setInfo.NodeDesignateData.roles.Intersect(roles.Select(u => u.Id)).Any()) - { - canNext = false; - var parentId = _userManagerApp.GetParent(user.Id); - flowInstance.MakerList = parentId; - } - } - - if (canNext) - { - flowInstance.PreviousId = flowInstance.ActivityId; - flowInstance.ActivityId = wfruntime.nextNodeId; - flowInstance.ActivityType = wfruntime.nextNodeType; - flowInstance.ActivityName = wfruntime.nextNode.name; - flowInstance.MakerList = wfruntime.nextNodeType == 4 ? "" : GetNextMakers(wfruntime, request); - flowInstance.IsFinish = (wfruntime.nextNodeType == 4 - ? FlowInstanceStatus.Finished - : FlowInstanceStatus.Running); - } - } - else //审批结果为不同意 - { - flowInstance.IsFinish = FlowInstanceStatus.Disagree; - wfruntime.nextNodeId = "-1"; - wfruntime.nextNodeType = 4; - } - - var content = - $"{user.Account}-{DateTime.Now.ToString("yyyy-MM-dd HH:mm")}审批了【{wfruntime.currentNode.name}】" + - $"结果:{(tag.Taged == 1 ? "同意" : "不同意")},备注:{tag.Description}"; - AddOperationHis(flowInstance.Id, tag, content); - flowInstance.SchemeContent = JsonHelper.Instance.Serialize(wfruntime.ToSchemeObj()); - - //如果审批通过,且下一个审批人是自己,则自动审批 - if (tag.Taged == (int)TagState.Ok) - { - if (flowInstance.MakerList != "1" && (!flowInstance.MakerList.Contains(user.Id))) - { - return; - } - - VerifyNode(request, tag, flowInstance); - } - } - - //会签时,获取一条会签分支上面是否有用户可审核的节点 - private string GetOneForkLineCanCheckNodeId(FlowNode fromForkStartNode, FlowRuntime wfruntime, Tag tag) - { - string canCheckId = ""; - var node = fromForkStartNode; - do //沿一条分支线路执行,直到遇到会签结束节点 - { - var makerList = GetNodeMarkers(node); - - if (node.setInfo.Taged == null && !string.IsNullOrEmpty(makerList) && - makerList.Split(',').Any(one => tag.UserId == one)) - { - canCheckId = node.id; - break; - } - - node = wfruntime.GetNextNode(node.id); - } while (node.type != FlowNode.JOIN); - - return canCheckId; - } - - /// - /// 驳回 - /// 如果NodeRejectStep不为空,优先使用;否则按照NodeRejectType驳回 - /// - /// - public bool NodeReject(VerificationReq reqest) - { - var user = _auth.GetCurrentUser().User; - FlowInstance flowInstance = Get(reqest.FlowInstanceId); - if (flowInstance.MakerList != "1" && !flowInstance.MakerList.Contains(user.Id)) - { - throw new Exception("当前用户没有驳回该节点权限"); - } - - FlowRuntime wfruntime = new FlowRuntime(flowInstance); - - string rejectNode = ""; //驳回的节点 - rejectNode = string.IsNullOrEmpty(reqest.NodeRejectStep) - ? wfruntime.RejectNode(reqest.NodeRejectType) - : reqest.NodeRejectStep; - - var tag = new Tag - { - Description = reqest.VerificationOpinion, - Taged = (int)TagState.Reject, - UserId = user.Id, - UserName = user.Name - }; - - wfruntime.MakeTagNode(wfruntime.currentNodeId, tag); - flowInstance.IsFinish = FlowInstanceStatus.Rejected; //4表示驳回(需要申请者重新提交表单) - if (rejectNode != "") - { - flowInstance.PreviousId = flowInstance.ActivityId; - flowInstance.ActivityId = rejectNode; - flowInstance.ActivityType = wfruntime.GetNodeType(rejectNode); - flowInstance.ActivityName = wfruntime.Nodes[rejectNode].name; - flowInstance.MakerList = GetNodeMarkers(wfruntime.Nodes[rejectNode], flowInstance.CreateUserId); - - AddTransHistory(wfruntime); - } - - flowInstance.SchemeContent = JsonHelper.Instance.Serialize(wfruntime.ToSchemeObj()); - UnitWork.Update(flowInstance); - - UnitWork.Add(new FlowInstanceOperationHistory - { - InstanceId = reqest.FlowInstanceId, - CreateUserId = user.Id, - CreateUserName = user.Name, - CreateDate = DateTime.Now, - Content = "【" - + wfruntime.currentNode.name - + "】【" + DateTime.Now.ToString("yyyy-MM-dd HH:mm") + "】驳回,备注:" - + reqest.VerificationOpinion - }); - - //给流程创建人发送通知信息 - _messageApp.SendMsgTo(flowInstance.CreateUserId, - $"你的流程[{flowInstance.CustomName}]已被{user.Name}驳回。备注信息:{reqest.VerificationOpinion}"); - - UnitWork.Save(); - - wfruntime.NotifyThirdParty(_httpClientFactory.CreateClient(), tag); - - return true; - } - - #endregion 流程处理API - - #region 获取各种节点的流程审核者 - - /// - /// 寻找下一步的执行人 - /// 一般用于本节点审核完成后,修改流程实例的当前执行人,可以做到通知等功能 - /// - /// - private string GetNextMakers(FlowRuntime wfruntime, NodeDesignateReq request = null) - { - string makerList = ""; - if (wfruntime.nextNodeId == "-1") - { - throw (new Exception("无法寻找到下一个节点")); - } - - if (wfruntime.nextNodeType == 0) //如果是会签节点 - { - makerList = GetForkNodeMakers(wfruntime, wfruntime.nextNodeId); - } - else if (wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_ROLE) - { - //如果是运行时指定角色 - if (wfruntime.nextNode.setInfo.NodeDesignate != request.NodeDesignateType) - { - throw new Exception("前端提交的节点权限类型异常,请检查流程"); - } - - var users = _revelanceApp.Get(Define.USERROLE, false, request.NodeDesignates); - makerList = GenericHelpers.ArrayToString(users, makerList); - } - else if (wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_USER) - { - //如果是运行时指定用户 - if (wfruntime.nextNode.setInfo.NodeDesignate != request.NodeDesignateType) - { - throw new Exception("前端提交的节点权限类型异常,请检查流程"); - } - - makerList = GenericHelpers.ArrayToString(request.NodeDesignates, makerList); - } - else if (wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_PARENT - || wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_MANY_PARENTS) - { - //如果是上一节点执行人的直属上级或连续多级直属上级 - if (wfruntime.nextNode.setInfo.NodeDesignate != request.NodeDesignateType) - { - throw new Exception("前端提交的节点权限类型异常,请检查流程"); - } - - //当创建流程时,肯定执行的开始节点,登录用户就是创建用户 - //当审批流程时,能进到这里,表明当前登录用户已经有审批当前节点的权限,完全可以直接用登录用户的直接上级 - var user = _auth.GetCurrentUser().User; - var parentId = _userManagerApp.GetParent(user.Id); - if (StringExtension.IsNullOrEmpty(parentId)) - { - throw new Exception("无法找到当前用户的直属上级"); - } - - makerList = GenericHelpers.ArrayToString(new[] { parentId }, makerList); - } - else if (wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_CHAIRMAN) - { - //如果是发起人的部门负责人 - if (wfruntime.nextNode.setInfo.NodeDesignate != request.NodeDesignateType) - { - throw new Exception("前端提交的节点权限类型异常,请检查流程"); - } - - FlowInstance flowInstance = Get(wfruntime.flowInstanceId); - var chairmanIds = _orgManagerApp.GetChairmanId(wfruntime.nextNode.setInfo.NodeDesignateData.orgs); - makerList = GenericHelpers.ArrayToString(chairmanIds, makerList); - } - else - { - makerList = GetNodeMarkers(wfruntime.nextNode); - if (string.IsNullOrEmpty(makerList)) - { - throw (new Exception("无法寻找到节点的审核者,请查看流程设计是否有问题!")); - } - } - - return makerList; - } - - /// - /// 获取会签开始节点的所有可执行者 - /// - /// 会签开始节点 - /// - private string GetForkNodeMakers(FlowRuntime wfruntime, string forkNodeId) - { - string makerList = ""; - foreach (string fromForkStartNodeId in wfruntime.FromNodeLines[forkNodeId].Select(u => u.to)) - { - var fromForkStartNode = wfruntime.Nodes[fromForkStartNodeId]; //与会前开始节点直接连接的节点 - if (makerList != "") - { - makerList += ","; - } - - makerList += GetOneForkLineMakers(fromForkStartNode, wfruntime); - } - - return makerList; - } - - //获取会签一条线上的审核者,该审核者应该是已审核过的节点的下一个人 - private string GetOneForkLineMakers(FlowNode fromForkStartNode, FlowRuntime wfruntime) - { - string markers = ""; - var node = fromForkStartNode; - do //沿一条分支线路执行,直到遇到第一个没有审核的节点 - { - if (node.setInfo != null && node.setInfo.Taged != null) - { - if (node.type != FlowNode.FORK && node.setInfo.Taged != (int)TagState.Ok) //如果节点是不同意或驳回,则不用再找了 - { - break; - } - - node = wfruntime.GetNextNode(node.id); //下一个节点 - continue; - } - - var marker = GetNodeMarkers(node); - if (marker == "") - { - throw (new Exception($"节点{node.name}没有审核者,请检查!")); - } - - if (marker == "1") - { - throw (new Exception($"节点{node.name}是会签节点,不能用所有人,请检查!")); - } - - if (markers != "") - { - markers += ","; - } - - markers += marker; - break; - } while (node.type != FlowNode.JOIN); - - return markers; - } - - /// - /// 寻找该节点执行人 - /// - /// - /// - private string GetNodeMarkers(FlowNode node, string flowinstanceCreateUserId = "") - { - string makerList = ""; - if (node.type == FlowNode.START && (!string.IsNullOrEmpty(flowinstanceCreateUserId))) //如果是开始节点,通常情况下是驳回到开始了 - { - makerList = flowinstanceCreateUserId; - } - else if (node.setInfo != null) - { - if (string.IsNullOrEmpty(node.setInfo.NodeDesignate) || - node.setInfo.NodeDesignate == Setinfo.ALL_USER) //所有成员 - { - makerList = "1"; - } - else if (node.setInfo.NodeDesignate == Setinfo.SPECIAL_USER) //指定成员 - { - makerList = GenericHelpers.ArrayToString(node.setInfo.NodeDesignateData.users, makerList); - } - else if (node.setInfo.NodeDesignate == Setinfo.SPECIAL_ROLE) //指定角色 - { - var users = _revelanceApp.Get(Define.USERROLE, false, node.setInfo.NodeDesignateData.roles); - makerList = GenericHelpers.ArrayToString(users, makerList); - } - else if (node.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_ROLE - || node.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_USER) - { - //如果是运行时选定的用户,则暂不处理。由上个节点审批时选定 - } - } - else //如果没有设置节点信息,默认所有人都可以审核 - { - makerList = "1"; - } - - return makerList; - } - - #endregion - - /// - /// 审核流程 - /// 李玉宝于2017-01-20 15:44:45 - /// - public void Verification(VerificationReq request) - { - //如果是同意,需要判断是否为运行时选定下一步执行角色/执行人 - if (request.VerificationFinally == "1") - { - CheckNodeDesignate(request); - } - - bool isReject = TagState.Reject.Equals((TagState)Int32.Parse(request.VerificationFinally)); - if (isReject) //驳回 - { - NodeReject(request); - } - else - { - NodeVerification(request); - } - } - - /// - /// 判定节点需要选择执行人或执行角色 - /// - /// - /// - private void CheckNodeDesignate(NodeDesignateReq request) - { - if ((request.NodeDesignateType == Setinfo.RUNTIME_SPECIAL_ROLE - || request.NodeDesignateType == Setinfo.RUNTIME_SPECIAL_USER) && request.NodeDesignates.Length == 0) - { - throw new Exception("下个节点需要选择执行人或执行角色"); - } - } - - /// - /// 返回用于处理流程节点 - /// - /// - /// - public FlowVerificationResp GetForVerification(string id) - { - var flowinstance = Get(id); - var resp = flowinstance.MapTo(); - var runtime = new FlowRuntime(flowinstance); - if (runtime.currentNode != null && runtime.currentNode.setInfo != null) - { - resp.CanWriteFormItemIds = runtime.currentNode.setInfo.CanWriteFormItemIds; - } - - if (runtime.nextNode != null && runtime.nextNode.setInfo != null && runtime.nextNodeType != 4) - { - resp.NextNodeDesignateType = runtime.nextNode.setInfo.NodeDesignate; - resp.CanWriteFormItemIds = runtime.currentNode.setInfo.CanWriteFormItemIds; - } - - return resp; - } - - public async Task Load(QueryFlowInstanceListReq request) - { - var result = new TableData(); - var user = _auth.GetCurrentUser(); - - if (request.type == "wait") //待办事项 - { - Expression> waitExp = u => (u.MakerList == "1" - || u.MakerList.Contains(user.User.Id)) && - (u.IsFinish == FlowInstanceStatus.Running || - u.IsFinish == FlowInstanceStatus.Rejected); - - // 加入搜索自定义标题 - if (!string.IsNullOrEmpty(request.key)) - { - waitExp = PredicateBuilder.And(waitExp, t => t.CustomName.Contains(request.key)); - } - - result.count = await UnitWork.Find(waitExp).CountAsync(); - - result.data = await UnitWork.Find(request.page, request.limit, "CreateDate descending", waitExp) - .ToListAsync(); - } - else if (request.type == "disposed") //已办事项(即我参与过的流程) - { - var instances = UnitWork.Find(u => u.CreateUserId == user.User.Id) - .Select(u => u.InstanceId).Distinct(); - var query = from ti in instances - join ct in UnitWork.Find(null) on ti equals ct.Id - select ct; - - // 加入搜索自定义标题 - if (!string.IsNullOrEmpty(request.key)) - { - query = query.Where(t => t.CustomName.Contains(request.key)); - } - - result.data = await query.OrderByDescending(u => u.CreateDate) - .Skip((request.page - 1) * request.limit) - .Take(request.limit).ToListAsync(); - result.count = await instances.CountAsync(); - } - else //我的流程 - { - Expression> myFlowExp = u => u.CreateUserId == user.User.Id; - - // 加入搜索自定义标题 - if (!string.IsNullOrEmpty(request.key)) - { - myFlowExp = PredicateBuilder.And(myFlowExp, t => t.CustomName.Contains(request.key)); - } - - result.count = await UnitWork.Find(myFlowExp).CountAsync(); - result.data = await UnitWork.Find(request.page, request.limit, - "CreateDate descending", myFlowExp).ToListAsync(); - } - - return result; - } - - /// - /// 添加扭转记录 - /// - private void AddTransHistory(FlowRuntime wfruntime) - { - var tag = _auth.GetCurrentUser().User; - UnitWork.Add(new FlowInstanceTransitionHistory - { - InstanceId = wfruntime.flowInstanceId, - CreateUserId = tag.Id, - CreateUserName = tag.Name, - FromNodeId = wfruntime.currentNodeId, - FromNodeName = wfruntime.currentNode.name, - FromNodeType = wfruntime.currentNodeType, - ToNodeId = wfruntime.nextNodeId, - ToNodeName = wfruntime.nextNode?.name, - ToNodeType = wfruntime.nextNodeType, - IsFinish = wfruntime.nextNodeType == 4 ? FlowInstanceStatus.Finished : FlowInstanceStatus.Running, - TransitionSate = 0 - }); - } - - private void AddOperationHis(string instanceId, Tag tag, string content) - { - FlowInstanceOperationHistory flowInstanceOperationHistory = new FlowInstanceOperationHistory - { - InstanceId = instanceId, - CreateUserId = tag.UserId, - CreateUserName = tag.UserName, - CreateDate = DateTime.Now, - Content = content - }; //操作记录 - - UnitWork.Add(flowInstanceOperationHistory); - } - - public List QueryHistories(QueryFlowInstanceHistoryReq request) - { - return UnitWork.Find(u => u.InstanceId == request.FlowInstanceId) - .OrderByDescending(u => u.CreateDate).ToList(); - } - - /// - /// 召回流程 - /// - public void ReCall(RecallFlowInstanceReq request) - { - var user = _auth.GetCurrentUser().User; - FlowInstance flowInstance = Get(request.FlowInstanceId); - if (flowInstance.IsFinish == FlowInstanceStatus.Draft - || flowInstance.IsFinish == FlowInstanceStatus.Finished) - { - throw new Exception("当前流程状态不能召回"); - } - - FlowRuntime wfruntime = new FlowRuntime(flowInstance); - - string startNodeId = wfruntime.startNodeId; //起始节点 - - wfruntime.ReCall(); - - flowInstance.IsFinish = FlowInstanceStatus.Draft; - flowInstance.PreviousId = flowInstance.ActivityId; - flowInstance.ActivityId = startNodeId; - flowInstance.ActivityType = wfruntime.GetNodeType(startNodeId); - flowInstance.ActivityName = wfruntime.Nodes[startNodeId].name; - flowInstance.MakerList = GetNodeMarkers(wfruntime.Nodes[startNodeId], flowInstance.CreateUserId); - - AddTransHistory(wfruntime); - - UnitWork.Update(flowInstance); - - UnitWork.Add(new FlowInstanceOperationHistory - { - InstanceId = request.FlowInstanceId, - CreateUserId = user.Id, - CreateUserName = user.Name, - CreateDate = DateTime.Now, - Content = $"【撤销】由{user.Name}撤销,备注:{request.Description}" - }); - - UnitWork.Save(); - } - - /// 启动流程 - /// 通常是对状态为【草稿】的流程进行操作,进入运行状态 - public void Start(StartFlowInstanceReq request) - { - FlowInstance flowInstance = Get(request.FlowInstanceId); - if (flowInstance.IsFinish != FlowInstanceStatus.Draft) - { - throw new Exception("当前流程不是草稿状态,不能启动"); - } - - var wfruntime = new FlowRuntime(flowInstance); - var user = _auth.GetCurrentUser(); - - if (wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_USER - || wfruntime.nextNode.setInfo.NodeDesignate == Setinfo.RUNTIME_SPECIAL_ROLE) - { - throw new Exception("暂不支持【第二执行节点为运行时指定角色/账号执行】的流程恢复"); - } - - #region 根据运行实例改变当前节点状态 - - flowInstance.ActivityId = wfruntime.nextNodeId; - flowInstance.ActivityType = wfruntime.GetNextNodeType(); - flowInstance.ActivityName = wfruntime.nextNode.name; - flowInstance.PreviousId = wfruntime.currentNodeId; - flowInstance.CreateUserId = user.User.Id; - flowInstance.CreateUserName = user.User.Account; - flowInstance.MakerList = (wfruntime.GetNextNodeType() != 4 ? GetNextMakers(wfruntime) : ""); - flowInstance.IsFinish = (wfruntime.GetNextNodeType() == 4 - ? FlowInstanceStatus.Finished - : FlowInstanceStatus.Running); - - UnitWork.Update(flowInstance); - - #endregion 根据运行实例改变当前节点状态 - - #region 流程操作记录 - - FlowInstanceOperationHistory processOperationHistoryEntity = new FlowInstanceOperationHistory - { - InstanceId = flowInstance.Id, - CreateUserId = user.User.Id, - CreateUserName = user.User.Name, - CreateDate = DateTime.Now, - Content = $"【启动】由用户{user.User.Name}启动" - }; - UnitWork.Add(processOperationHistoryEntity); - - #endregion 流程操作记录 - - AddTransHistory(wfruntime); - UnitWork.Save(); - } - } -} \ No newline at end of file