using DS.Module.Core; using DS.Module.Core.Extensions; using DS.Module.UserModule; using DS.WMS.Core.Flow.Dtos; using DS.WMS.Core.Flow.Entity; using DS.WMS.Core.Flow.Interface; using DS.WMS.Core.System.Entity; using DS.WMS.Core.System.Interface; using Mapster; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using SqlSugar; namespace DS.WMS.Core.Flow.Method; /// /// /// public class FlowInstanceService : IFlowInstanceService { private readonly IServiceProvider _serviceProvider; private readonly ISqlSugarClient db; private readonly IUser user; private readonly ICommonService _commonService; /// /// /// /// public FlowInstanceService(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; db = _serviceProvider.GetRequiredService(); user = _serviceProvider.GetRequiredService(); _commonService = _serviceProvider.GetRequiredService(); } public DataResult> GetListByPage(PageRequest request) { //序列化查询条件 var whereList = db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition); var data = db.Queryable().Where(a => (a.MakerList == "1" || a.MakerList.Contains(user.UserId))) .LeftJoin((a, b) => a.PermissionId == b.Id) .Select() .Where(whereList).ToQueryPage(request.PageCondition); return data; } public DataResult EditFlowInstance(FlowInstanceReq req) { if (req.Id == 0) { return DataResult.Failed("非法请求!",MultiLanguageConst.IllegalRequest); } else { var info = db.Queryable().Where(x => x.Id == req.Id).First(); if(!(info.FlowStatus == FlowStatusEnum.Draft.ToEnumInt() || info.FlowStatus == FlowStatusEnum.Ready.ToEnumInt())) { return DataResult.Failed("只能修改【就绪】和【撤销】状态的流程",MultiLanguageConst.FlowEditOnlyReadyAndCancel); } info = req.Adapt(info); db.Updateable(info).IgnoreColumns(ignoreAllNullColumns: true).EnableDiffLogEvent().ExecuteCommand(); return DataResult.Successed("更新成功!",MultiLanguageConst.DataUpdateSuccess); } } /// /// 创建工作流实例 /// /// /// public DataResult CreateFlowInstance(CreateFlowInstanceReq req) { FlowTemplate template = null; var userInfo = db.Queryable().First(x => x.Id == long.Parse(user.UserId)); if (!string.IsNullOrEmpty(req.TemplateId.ToString())) { template = db.Queryable().First(x => x.Id == req.TemplateId); } if (template == null) { return DataResult.Failed("该流程模板已不存在,请重新设计流程!",MultiLanguageConst.FlowTemplateNotExist); } var flowInstance = new FlowInstance { CustomName = template.Name, TemplateId = template.Id, BusinessId = req.BusinessId, PermissionId = template.PermissionId, ColumnView = template.ColumnView, Content = template.Content, }; //创建运行实例 var wfruntime = new FlowRuntimeService(flowInstance, db); if (wfruntime.CurrentNode is { AssigneeType: "user", Users.Count: > 0 }) { if (!wfruntime.CurrentNode.Users.Contains(user.UserId)) { return DataResult.Failed("该工作流指定用户非本人!",MultiLanguageConst.FlowInstanceAssignUser); } } if (wfruntime.CurrentNode is { AssigneeType: "role", Roles.Count: > 0 }) { var userRoles = db.Queryable().Where(x => x.UserId == long.Parse(user.UserId)) .Select(n => n.RoleId.ToString()).ToList(); var intersectRoles = wfruntime.CurrentNode.Roles.Intersect(userRoles).ToList(); if (intersectRoles.Count == 0) { return DataResult.Failed("该工作流指定角色非本人!",MultiLanguageConst.FlowInstanceAssignRole); } } #region 根据运行实例改变当前节点状态 flowInstance.ActivityId = wfruntime.CurrentNodeId; flowInstance.ActivityType = wfruntime.GetNodeType(wfruntime.StartNodeId); flowInstance.ActivityName = wfruntime.CurrentNode.Name; flowInstance.PreviousId = ""; flowInstance.MakerList = GetCurrentMakers(wfruntime); flowInstance.FlowStatus = FlowStatusEnum.Ready.ToEnumInt(); wfruntime.FlowInstanceId = flowInstance.Id; #endregion 根据运行实例改变当前节点状态 db.Insertable(flowInstance).ExecuteCommand(); var history = new FlowInstanceHistory { InstanceId = flowInstance.Id, Content = "【创建】" + userInfo.UserName + "创建了一个流程进程【" + flowInstance.CustomName + "】" }; db.Insertable(history).ExecuteCommand(); // var info = db.Queryable().Where(x => x.Id == req.Id).First(); // // info = req.Adapt(info); // // db.Updateable(info).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand(); return DataResult.Successed("创建工作流实例成功!",MultiLanguageConst.FlowInstanceCreateSuccess); } /// /// 撤销 /// /// /// public DataResult CancelFlowInstance(CancelFlowInstanceReq req) { var instance = db.Queryable().First(x => x.Id == req.Id); if (instance.IsNull()) { return DataResult.Failed("该工作流不存在!",MultiLanguageConst.FlowInstanceNotExist); } if (instance.FlowStatus == FlowStatusEnum.Approve.ToEnumInt()) { return DataResult.Failed("该工作流已完成!",MultiLanguageConst.FlowInstanceFinished); } instance.ActivityId = ""; //创建运行实例 var wfruntime = new FlowRuntimeService(instance, db); wfruntime.Cancel(); #region 根据运行实例改变当前节点状态 string startNodeId = wfruntime.StartNodeId; //起始节点 instance.PreviousId = instance.ActivityId; instance.ActivityId = startNodeId; instance.ActivityType = wfruntime.GetNodeType(startNodeId); instance.ActivityName = wfruntime.ChildNodes.First(x => x.Id == startNodeId).Name; instance.MakerList = (wfruntime.GetNextNodeType() != 4 ? GetCurrentMakers(wfruntime) : "1"); instance.FlowStatus = FlowStatusEnum.Draft.ToEnumInt(); wfruntime.FlowInstanceId = instance.Id; #endregion 根据运行实例改变当前节点状态 var serializerSettings = new JsonSerializerSettings { // 设置为驼峰命名 ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() }; instance.Content = JsonConvert.SerializeObject(wfruntime.ToFlowRoot(),Formatting.None, serializerSettings); db.Updateable(instance).ExecuteCommand(); var userInfo = db.Queryable().First(x => x.Id == long.Parse(user.UserId)); var history = new FlowInstanceHistory { InstanceId = instance.Id, Content =$"【撤销】由{ userInfo.UserName }撤销,备注:{req.Note}" }; db.Insertable(history).ExecuteCommand(); return DataResult.Successed("撤销成功!",MultiLanguageConst.FlowInstanceCancelSuccess); } /// /// 获取流程操作历史 /// /// /// public DataResult> GetFlowInstanceHistoryList(string id) { var data = db.Queryable() .Where(a => a.InstanceId == long.Parse(id)) .Select() .ToList(); return DataResult>.Success(data); } public DataResult StartFlowInstance(string id) { var instance = db.Queryable().First(x => x.Id == long.Parse(id)); if (instance.IsNull()) { return DataResult.Failed("该工作流不存在!",MultiLanguageConst.FlowInstanceNotExist); } if (instance.FlowStatus == FlowStatusEnum.Approve.ToEnumInt()) { return DataResult.Failed("该工作流已完成!",MultiLanguageConst.FlowInstanceFinished); } //创建运行实例 var wfruntime = new FlowRuntimeService(instance, db); #region 根据运行实例改变当前节点状态 instance.ActivityId = wfruntime.NextNodeId; instance.ActivityType = wfruntime.GetNextNodeType(); instance.ActivityName = wfruntime.NextNode.Name; instance.PreviousId = wfruntime.CurrentNodeId; instance.MakerList = (wfruntime.GetNextNodeType() != 4 ? GetNextMakers(wfruntime) : "1"); instance.FlowStatus = (wfruntime.GetNextNodeType() == 4 ? FlowStatusEnum.Approve.ToEnumInt() : FlowStatusEnum.Running.ToEnumInt()); wfruntime.FlowInstanceId = instance.Id; #endregion 根据运行实例改变当前节点状态 db.Updateable(instance).ExecuteCommand(); var userInfo = db.Queryable().First(x => x.Id == long.Parse(user.UserId)); var history = new FlowInstanceHistory { InstanceId = instance.Id, Content =$"【启动】由{ userInfo.UserName }启动该流程。" }; db.Insertable(history).ExecuteCommand(); return DataResult.Successed("更新成功!",MultiLanguageConst.FlowInstanceUpdateSuccess); } public DataResult AuditFlowInstance(FlowInstanceAuditReq req) { var userId = user.UserId; var userName = db.Queryable().First(x => x.Id == long.Parse(userId)).UserName; var instance = db.Queryable().First(x => x.Id == req.Id); if (instance.IsNull()) { return DataResult.Failed("该工作流不存在!",MultiLanguageConst.FlowInstanceNotExist); } if (instance.FlowStatus == FlowStatusEnum.Approve.ToEnumInt()) { return DataResult.Failed("该工作流已完成!",MultiLanguageConst.FlowInstanceFinished); } var tag = new FlowTag { UserName = userName, UserId = user.UserId, Description = req.AuditNote, Taged = req.Status }; var wfruntime = new FlowRuntimeService(instance, db); if (wfruntime.CurrentNodeId != req.NodeId) { return DataResult.Failed("该工作流审批节点与当前节点不一致!",MultiLanguageConst.FlowInstanceNodeIdConflict); } #region 会签 if (instance.ActivityType == 0) //当前节点是会签节点 { //会签时的【当前节点】一直是会签开始节点 wfruntime.MakeTagNode(wfruntime.CurrentNodeId, tag); //标记审核节点状态 string res = wfruntime.NodeConfluence(wfruntime.CurrentNodeId, tag); if (res == TagState.No.ToString("D")) { instance.FlowStatus = FlowStatusEnum.Reject.ToEnumInt(); } else if (!string.IsNullOrEmpty(res)) { instance.PreviousId = instance.ActivityId; instance.ActivityId = wfruntime.NextNodeId; instance.ActivityType = wfruntime.NextNodeType; instance.ActivityName = wfruntime.NextNode.Name; instance.FlowStatus = (wfruntime.NextNodeType == 4 ? FlowStatusEnum.Approve.ToEnumInt() : FlowStatusEnum.Running.ToEnumInt()); instance.MakerList = (wfruntime.NextNodeType == 4 ? "1" : GetNextMakers(wfruntime)); // AddTransHistory(wfruntime); } else { //会签过程中,需要更新用户 instance.MakerList = GetForkNodeMakers(wfruntime, wfruntime.CurrentNodeId); // AddTransHistory(wfruntime); } } #endregion 会签 #region 一般审核 else { wfruntime.MakeTagNode(wfruntime.CurrentNodeId, tag); if (tag.Taged == (int)TagState.Ok) { instance.PreviousId = instance.ActivityId; instance.ActivityId = wfruntime.NextNodeId; instance.ActivityType = wfruntime.NextNodeType; instance.ActivityName = wfruntime.NextNode.Name; instance.MakerList = wfruntime.NextNodeType == 4 ? "1" : GetNextMakers(wfruntime); instance.FlowStatus = (wfruntime.NextNodeType == 4 ? FlowStatusEnum.Approve.ToEnumInt() : FlowStatusEnum.Running.ToEnumInt()); } else { instance.FlowStatus = FlowStatusEnum.Reject.ToEnumInt(); //表示该节点不同意 wfruntime.NextNodeId = "-1"; wfruntime.NextNodeType = 4; } } #endregion 一般审核 var serializerSettings = new JsonSerializerSettings { // 设置为驼峰命名 ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() }; instance.Content = JsonConvert.SerializeObject(wfruntime.ToFlowRoot(),Formatting.None, serializerSettings); db.Updateable(instance).ExecuteCommand(); var history = new FlowInstanceHistory { InstanceId = instance.Id, Content = "【" + wfruntime.CurrentNode.Name + "】【" + DateTime.Now.ToString("yyyy-MM-dd HH:mm") + "】" + (tag.Taged == 1 ? "同意" : "不同意") + ",备注:" + tag.Description }; db.Insertable(history).ExecuteCommand(); return DataResult.Successed("审批成功!",MultiLanguageConst.FlowInstanceAuditSuccess); } public DataResult GetFlowInstanceInfo(string id) { var data = db.Queryable() // .LeftJoin((a, b) => a.PermissionId == b.Id) .Where(a => a.Id == long.Parse(id)) .Select() .First(); return DataResult.Success(data); } /// /// 寻找下一步的执行人 /// 一般用于本节点审核完成后,修改流程实例的当前执行人,可以做到通知等功能 /// /// private string GetCurrentMakers(FlowRuntimeService wfruntime, CreateFlowInstanceReq request = null) { string makerList = ""; if (wfruntime.NextNodeId == "-1") { throw (new Exception("无法寻找到下一个节点")); } if (wfruntime.CurrentNodeType == 0) //如果是会签节点 { makerList = GetForkNodeMakers(wfruntime, wfruntime.NextNodeId); } else if (wfruntime.CurrentNode.AssigneeType == "role") { var users = db.Queryable().Where(x => wfruntime.CurrentNode.Roles.Contains(x.RoleId.ToString())) .Select(x => x.UserId).Distinct().ToList(); makerList = GenericHelper.ArrayToString(users, makerList); } else if (wfruntime.CurrentNode.AssigneeType == "user") { makerList = string.Join(",", wfruntime.CurrentNode.Users); } else { makerList = GetNodeMarkers(wfruntime.CurrentNode); if (string.IsNullOrEmpty(makerList)) { throw (new Exception("无法寻找到节点的审核者,请查看流程设计是否有问题!")); } } return makerList; } /// /// 寻找下一步的执行人 /// 一般用于本节点审核完成后,修改流程实例的当前执行人,可以做到通知等功能 /// /// private string GetNextMakers(FlowRuntimeService wfruntime, CreateFlowInstanceReq request = null) { string makerList = ""; if (wfruntime.NextNodeId == "-1") { throw (new Exception("无法寻找到下一个节点")); } // if (wfruntime.NextNodeType == 0) //如果是会签节点 // { // makerList = GetForkNodeMakers(wfruntime, wfruntime.NextNodeId); // } else if (wfruntime.NextNode.AssigneeType == "role") { var users = db.Queryable().Where(x => wfruntime.NextNode.Roles.Contains(x.RoleId.ToString())) .Select(x => x.UserId).Distinct().ToList(); makerList = GenericHelper.ArrayToString(users, makerList); } else if (wfruntime.NextNode.AssigneeType == "user") { makerList = string.Join(",", wfruntime.NextNode.Users); } else { makerList = GetNodeMarkers(wfruntime.NextNode); if (string.IsNullOrEmpty(makerList)) { throw (new Exception("无法寻找到节点的审核者,请查看流程设计是否有问题!")); } } return makerList; } /// /// 获取会签开始节点的所有可执行者 /// /// 会签开始节点 /// private string GetForkNodeMakers(FlowRuntimeService wfruntime, string forkNodeId) { string makerList = ""; var nextNode = wfruntime.NextNode; var nextConditionNodeId = wfruntime.GetNextConditionNodeId(nextNode); var nextConditionNode = wfruntime.ChildNodes.First(x => x.Id == nextConditionNodeId); if (nextConditionNode.AssigneeType == "role") { var users = db.Queryable().Where(x => nextConditionNode.Roles.Contains(x.RoleId.ToString())) .Select(x => x.UserId).Distinct().ToList(); makerList = GenericHelper.ArrayToString(users, makerList); } else if (nextConditionNode.AssigneeType == "user") { makerList = string.Join(",", nextConditionNode.Users); } // 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 GetNodeMarkers(FlowChild node, string flowinstanceCreateUserId = "") { string makerList = ""; if (node.Type == FlowChild.START && (!string.IsNullOrEmpty(flowinstanceCreateUserId))) //如果是开始节点,通常情况下是驳回到开始了 { makerList = flowinstanceCreateUserId; } else if (node.AssigneeType != null) { if (node.AssigneeType == "role") { var users = db.Queryable().Where(x => node.Roles.Contains(x.RoleId.ToString())) .Select(x => x.UserId).Distinct().ToList(); makerList = GenericHelper.ArrayToString(users, makerList); } else if (node.AssigneeType == "user") { makerList = node.Users.ToString(); } } else //如果没有设置节点信息,默认所有人都可以审核 { makerList = "1"; } return makerList; } }