You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

529 lines
20 KiB
C#

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;
/// <summary>
///
/// </summary>
public class FlowInstanceService : IFlowInstanceService
{
private readonly IServiceProvider _serviceProvider;
private readonly ISqlSugarClient db;
private readonly IUser user;
private readonly ICommonService _commonService;
/// <summary>
///
/// </summary>
/// <param name="serviceProvider"></param>
public FlowInstanceService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
db = _serviceProvider.GetRequiredService<ISqlSugarClient>();
user = _serviceProvider.GetRequiredService<IUser>();
_commonService = _serviceProvider.GetRequiredService<ICommonService>();
}
public DataResult<List<FlowInstanceRes>> GetListByPage(PageRequest request)
{
//序列化查询条件
var whereList = db.ConfigQuery.Context.Utilities.JsonToConditionalModels(request.QueryCondition);
10 months ago
var data = db.Queryable<FlowInstance>().Where(a => (a.MakerList == "1" || a.MakerList.Contains(user.UserId)))
.LeftJoin<SysPermission>((a, b) => a.PermissionId == b.Id)
.Select<FlowInstanceRes>()
.Where(whereList).ToQueryPage(request.PageCondition);
return data;
}
public DataResult EditFlowInstance(FlowInstanceReq req)
{
if (req.Id == 0)
{
10 months ago
return DataResult.Failed("非法请求!",MultiLanguageConst.IllegalRequest);
}
else
{
10 months ago
var info = db.Queryable<FlowInstance>().Where(x => x.Id == req.Id).First();
10 months ago
if (info.FlowStatus != FlowStatusEnum.Draft.ToEnumInt() || info.FlowStatus != FlowStatusEnum.Reject.ToEnumInt())
{
10 months ago
return DataResult.Failed("只能修改【草稿】和【驳回】状态的流程",MultiLanguageConst.FlowEditOnlyDraftAndReject);
10 months ago
}
info = req.Adapt(info);
db.Updateable(info).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand();
10 months ago
return DataResult.Successed("更新成功!",MultiLanguageConst.DataUpdateSuccess);
}
}
/// <summary>
/// 创建工作流实例
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public DataResult CreateFlowInstance(CreateFlowInstanceReq req)
{
FlowTemplate template = null;
10 months ago
var userInfo = db.Queryable<SysUser>().First(x => x.Id == long.Parse(user.UserId));
if (!string.IsNullOrEmpty(req.TemplateId.ToString()))
{
template = db.Queryable<FlowTemplate>().First(x => x.Id == req.TemplateId);
}
if (template == null)
{
10 months ago
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))
{
10 months ago
return DataResult.Failed("该工作流指定用户非本人!",MultiLanguageConst.FlowInstanceAssignUser);
}
}
if (wfruntime.CurrentNode is { AssigneeType: "role", Roles.Count: > 0 })
{
var userRoles = db.Queryable<SysRoleUser>().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)
{
10 months ago
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();
10 months ago
var history = new FlowInstanceHistory
{
InstanceId = flowInstance.Id,
Content = "【创建】"
+ userInfo.UserName
+ "创建了一个流程进程【"
+ flowInstance.CustomName + "】"
};
db.Insertable(history).ExecuteCommand();
// var info = db.Queryable<FlowInstance>().Where(x => x.Id == req.Id).First();
//
// info = req.Adapt(info);
//
// db.Updateable(info).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand();
10 months ago
return DataResult.Successed("创建工作流实例成功!",MultiLanguageConst.FlowInstanceCreateSuccess);
}
/// <summary>
/// 撤销
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public DataResult CancelFlowInstance(CancelFlowInstanceReq req)
{
var instance = db.Queryable<FlowInstance>().First(x => x.Id == req.Id);
if (instance.IsNull())
{
10 months ago
return DataResult.Failed("该工作流不存在!",MultiLanguageConst.FlowInstanceNotExist);
}
if (instance.FlowStatus == FlowStatusEnum.Approve.ToEnumInt())
{
10 months ago
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) : "");
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();
10 months ago
var userInfo = db.Queryable<SysUser>().First(x => x.Id == long.Parse(user.UserId));
var history = new FlowInstanceHistory
{
InstanceId = instance.Id,
Content =$"【撤销】由{ userInfo.UserName }撤销,备注:{req.Note}"
};
db.Insertable(history).ExecuteCommand();
10 months ago
return DataResult.Successed("撤销成功!",MultiLanguageConst.FlowInstanceCancelSuccess);
}
public DataResult StartFlowInstance(string id)
{
var instance = db.Queryable<FlowInstance>().First(x => x.Id == long.Parse(id));
if (instance.IsNull())
{
10 months ago
return DataResult.Failed("该工作流不存在!",MultiLanguageConst.FlowInstanceNotExist);
}
if (instance.FlowStatus == FlowStatusEnum.Approve.ToEnumInt())
{
10 months ago
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) : "");
instance.FlowStatus = (wfruntime.GetNextNodeType() == 4
? FlowStatusEnum.Approve.ToEnumInt()
: FlowStatusEnum.Running.ToEnumInt());
wfruntime.FlowInstanceId = instance.Id;
#endregion 根据运行实例改变当前节点状态
db.Updateable(instance).ExecuteCommand();
10 months ago
var userInfo = db.Queryable<SysUser>().First(x => x.Id == long.Parse(user.UserId));
var history = new FlowInstanceHistory
{
InstanceId = instance.Id,
Content =$"【启动】由{ userInfo.UserName }启动该流程。"
};
db.Insertable(history).ExecuteCommand();
10 months ago
return DataResult.Successed("更新成功!",MultiLanguageConst.FlowInstanceUpdateSuccess);
}
public DataResult AuditFlowInstance(FlowInstanceAuditReq req)
{
var userId = user.UserId;
var userName = db.Queryable<SysUser>().First(x => x.Id == long.Parse(userId)).UserName;
var instance = db.Queryable<FlowInstance>().First(x => x.Id == req.Id);
if (instance.IsNull())
{
10 months ago
return DataResult.Failed("该工作流不存在!",MultiLanguageConst.FlowInstanceNotExist);
}
if (instance.FlowStatus == FlowStatusEnum.Approve.ToEnumInt())
{
10 months ago
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)
{
10 months ago
return DataResult.Failed("该工作流审批节点与当前节点不一致!",MultiLanguageConst.FlowInstanceNodeIdConflict);
}
#region 会签
if (instance.ActivityType == 0) //当前节点是会签节点
{
//会签时的【当前节点】一直是会签开始节点
10 months ago
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 ? "" : 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 ? "" : 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();
10 months ago
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();
10 months ago
return DataResult.Successed("审批成功!",MultiLanguageConst.FlowInstanceAuditSuccess);
}
public DataResult<FlowInstanceRes> GetFlowInstanceInfo(string id)
{
var data = db.Queryable<FlowInstance>()
// .LeftJoin<SysPermission>((a, b) => a.PermissionId == b.Id)
.Where(a => a.Id == long.Parse(id))
.Select<FlowInstanceRes>()
.First();
return DataResult<FlowInstanceRes>.Success(data);
}
/// <summary>
/// 寻找下一步的执行人
/// 一般用于本节点审核完成后,修改流程实例的当前执行人,可以做到通知等功能
/// </summary>
/// <returns></returns>
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<SysRoleUser>().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;
}
/// <summary>
/// 寻找下一步的执行人
/// 一般用于本节点审核完成后,修改流程实例的当前执行人,可以做到通知等功能
/// </summary>
/// <returns></returns>
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<SysRoleUser>().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;
}
/// <summary>
/// 获取会签开始节点的所有可执行者
/// </summary>
/// <param name="forkNodeId">会签开始节点</param>
/// <returns></returns>
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<SysRoleUser>().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;
}
/// <summary>
/// 寻找该节点执行人
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
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<SysRoleUser>().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;
}
}