using System.Diagnostics;
using System.Text.Json;
using Admin.NET.Core;
using Admin.NET.Plugin.AiDOP.Service;
using Admin.NET.Plugin.ApprovalFlow;
using Admin.NET.Plugin.ApprovalFlow.Service;
using Yitter.IdGenerator;
using ApprovalFlowEntity = Admin.NET.Plugin.ApprovalFlow.ApprovalFlow;
namespace Admin.NET.Plugin.AiDOP.Infrastructure;
///
/// 智慧诊断改善计划正式审批流与角色基线。
///
public static class AidopImprovementApprovalSeed
{
public static void EnsureSeed(ISqlSugarClient db)
{
try
{
db.CodeFirst.InitTables(
typeof(ApprovalBizType),
typeof(ApprovalFlowEntity),
typeof(ApprovalFlowVersion));
EnsureBizType(db);
EnsureBaselineRoles(db);
EnsurePublishedFlow(db);
}
catch (Exception ex)
{
Trace.TraceWarning("Ai-DOP improvement approval seed: " + ex);
}
}
public static void EnsureBaselineRoles(ISqlSugarClient db, long? onlyTenantId = null)
{
var tenantIds = onlyTenantId is > 0
? new List { onlyTenantId.Value }
: db.Queryable()
.ClearFilter()
.Where(x => x.Id > 1 && x.Id != SqlSugarConst.DefaultTenantId)
.Select(x => x.Id)
.ToList();
var now = DateTime.Now;
foreach (var tenantId in tenantIds.Where(x => x > 1 && x != SqlSugarConst.DefaultTenantId).Distinct())
{
foreach (var (code, name, orderNo) in SmartOpsImprovementApprovalRules.BaselineRoles)
{
var exists = db.Queryable()
.ClearFilter()
.Any(r => r.TenantId == tenantId && r.Code == code);
if (exists) continue;
db.Insertable(new SysRole
{
Id = YitIdHelper.NextId(),
TenantId = tenantId,
Name = name,
Code = code,
OrderNo = orderNo,
DataScope = DataScopeEnum.Self,
Status = StatusEnum.Enable,
Remark = "智慧诊断改善计划审批角色基线",
CreateTime = now,
}).ExecuteCommand();
}
}
}
private static void EnsureBizType(ISqlSugarClient db)
{
var exists = db.Queryable()
.Any(x => x.Code == SmartOpsImprovementBizHandler.BizTypeCode);
if (exists) return;
db.Insertable(new ApprovalBizType
{
Id = YitIdHelper.NextId(),
Code = SmartOpsImprovementBizHandler.BizTypeCode,
Name = "智慧诊断改善计划",
Remark = "智慧运营诊断问题生成的改善计划审批",
IsEnabled = true,
CreateTime = DateTime.Now,
UpdateTime = DateTime.Now,
}).ExecuteCommand();
}
private static void EnsurePublishedFlow(ISqlSugarClient db)
{
var orgIds = db.Queryable()
.Select(x => x.Id)
.ToList()
.Where(x => x > 0)
.Distinct()
.ToList();
if (orgIds.Count == 0) orgIds.Add(0);
var now = DateTime.Now;
var flowJson = BuildFormalFlowJson();
foreach (var orgId in orgIds)
{
var existing = db.Queryable()
.Where(x => x.BizType == SmartOpsImprovementBizHandler.BizTypeCode && x.OrgId == orgId && !x.IsDelete)
.OrderByDescending(x => x.IsPublished)
.OrderByDescending(x => x.Version)
.First();
if (existing == null)
{
InsertFlow(db, orgId, flowJson, 2, now);
continue;
}
if (!SmartOpsImprovementApprovalRules.IsLegacyInitiatorFallback(existing.FlowJson)
&& existing.FlowJson != null
&& existing.FlowJson.Contains(SmartOpsImprovementApprovalRules.DeptHeadRole, StringComparison.Ordinal))
{
if (!existing.IsPublished)
{
existing.IsPublished = true;
existing.UpdateTime = now;
db.Updateable(existing).ExecuteCommand();
}
continue;
}
existing.FlowJson = flowJson;
existing.Version = Math.Max(existing.Version, 1) + 1;
existing.IsPublished = true;
existing.Status = 1;
existing.Remark = "正式流程:黄/红/跨部门网关,按角色解析审批人";
existing.UpdateTime = now;
db.Updateable(existing).ExecuteCommand();
db.Insertable(new ApprovalFlowVersion
{
Id = YitIdHelper.NextId(),
FlowId = existing.Id,
Version = existing.Version,
FlowJson = existing.FlowJson,
FormJson = existing.FormJson,
PublishTime = now,
PublisherName = "系统升级",
CreateTime = now,
UpdateTime = now,
}).ExecuteCommand();
}
}
private static void InsertFlow(ISqlSugarClient db, long orgId, string flowJson, int version, DateTime now)
{
var flow = new ApprovalFlowEntity
{
Id = YitIdHelper.NextId(),
Code = $"SOI_{orgId}",
Name = "智慧诊断改善计划审批",
BizType = SmartOpsImprovementBizHandler.BizTypeCode,
FormJson = "{}",
FlowJson = flowJson,
Status = 1,
Remark = "正式流程:黄/红/跨部门网关,按角色解析审批人",
Version = version,
IsPublished = true,
OrgId = orgId,
CreateTime = now,
UpdateTime = now,
};
db.Insertable(flow).ExecuteCommand();
db.Insertable(new ApprovalFlowVersion
{
Id = YitIdHelper.NextId(),
FlowId = flow.Id,
Version = flow.Version,
FlowJson = flow.FlowJson,
FormJson = flow.FormJson,
PublishTime = now,
PublisherName = "系统初始化",
CreateTime = now,
UpdateTime = now,
}).ExecuteCommand();
}
public static string BuildFormalFlowJson()
{
var item = new ApprovalFlowItem
{
Nodes = new List
{
Node("start", "bpmn:startEvent", 80, 200, "开始"),
new()
{
Id = "routeGw",
Type = "bpmn:exclusiveGateway",
X = 220,
Y = 200,
Properties = new FlowProperties
{
NodeName = "问题分级",
Conditions = new List
{
new() { TargetNodeId = "deptHeadYellow", Expression = "route == yellow", Label = "黄色" },
new() { TargetNodeId = "deptHeadRed", Expression = "route == red", Label = "红色" },
new() { TargetNodeId = "deptHeadGlobal", Expression = "", Label = "跨部门/S9", IsDefault = true },
},
},
Text = new FlowTextItem { X = 220, Y = 234, Value = "问题分级" },
},
RoleNode("deptHeadYellow", 420, 80, "责任部门负责人", SmartOpsImprovementApprovalRules.DeptHeadRole),
RoleNode("deptHeadRed", 420, 200, "责任部门负责人", SmartOpsImprovementApprovalRules.DeptHeadRole),
RoleNode("opsRed", 620, 200, "运营负责人", SmartOpsImprovementApprovalRules.OpsOwnerRole),
RoleNode("deptHeadGlobal", 420, 320, "责任部门负责人", SmartOpsImprovementApprovalRules.DeptHeadRole),
RoleNode("moduleGlobal", 620, 320, "模块负责人", SmartOpsImprovementApprovalRules.ModuleOwnerRole),
RoleNode("opsGlobal", 820, 320, "运营负责人", SmartOpsImprovementApprovalRules.OpsOwnerRole),
Node("end", "bpmn:endEvent", 1020, 200, "结束"),
},
Edges = new List
{
BuildEdge("e-start-gw", "start", "routeGw", 120, 200, 180, 200),
BuildEdge("e-gw-y", "routeGw", "deptHeadYellow", 250, 180, 380, 80),
BuildEdge("e-gw-r", "routeGw", "deptHeadRed", 260, 200, 380, 200),
BuildEdge("e-gw-g", "routeGw", "deptHeadGlobal", 250, 220, 380, 320),
BuildEdge("e-y-end", "deptHeadYellow", "end", 460, 80, 980, 180),
BuildEdge("e-r-ops", "deptHeadRed", "opsRed", 460, 200, 580, 200),
BuildEdge("e-ops-end", "opsRed", "end", 660, 200, 980, 200),
BuildEdge("e-g-mod", "deptHeadGlobal", "moduleGlobal", 460, 320, 580, 320),
BuildEdge("e-mod-ops", "moduleGlobal", "opsGlobal", 660, 320, 780, 320),
BuildEdge("e-gops-end", "opsGlobal", "end", 860, 320, 980, 220),
}
};
return JsonSerializer.Serialize(item);
}
private static ApprovalFlowNodeItem Node(string id, string type, float x, float y, string name) => new()
{
Id = id,
Type = type,
X = x,
Y = y,
Properties = new FlowProperties { NodeName = name },
Text = new FlowTextItem { X = x, Y = y + 34, Value = name },
};
private static ApprovalFlowNodeItem RoleNode(string id, float x, float y, string name, string roleCode) => new()
{
Id = id,
Type = "bpmn:userTask",
X = x,
Y = y,
Properties = new FlowProperties
{
NodeName = name,
ApproverType = nameof(ApproverTypeEnum.Role),
ApproverIds = roleCode,
ApproverNames = name,
MultiApproveMode = "Any",
TimeoutHours = 72,
TimeoutAction = "Notify",
},
Text = new FlowTextItem { X = x, Y = y + 34, Value = name },
};
private static ApprovalFlowEdgeItem BuildEdge(string id, string source, string target, float sx, float sy, float ex, float ey)
{
return new ApprovalFlowEdgeItem
{
Id = id,
Type = "bpmn:sequenceFlow",
SourceNodeId = source,
TargetNodeId = target,
StartPoint = new FlowEdgePointItem { X = sx, Y = sy },
EndPoint = new FlowEdgePointItem { X = ex, Y = ey },
Properties = new FlowProperties(),
PointsList = new List
{
new() { X = sx, Y = sy },
new() { X = ex, Y = ey },
},
};
}
}