using System.Diagnostics;
using System.Text.Json;
using Admin.NET.Plugin.AiDOP.Entity;
using Admin.NET.Plugin.AiDOP.Manufacturing;
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;
///
/// S6 Phase 1D 过程检验单(Phase 1C bill)审核流程种子(幂等)。
///
/// 桥接:让 ado_s6_process_inspection_bill 接入 ApprovalFlow(BizType=S6_PROCESS_INSPECTION)。
/// 复用 IpqcInspectionFlowSeed 已建的角色(ROLE_S6_IPQC_SUPERVISOR/QUALITY_ENGINEER)与处置表 ado_s6_ipqc_quality_disposition,
/// 本种子只:① 确保引擎/处置表存在(CodeFirst 幂等)② 注册 BizType ③ 发布流程定义
/// (start→N1_SUBMIT(Initiator 发起人)→N2_SUP_REVIEW(主管)→GW_RESULT(disposition_required==1→N3 / 否则→end)→N3_QE_DISPOSITION(QE)→end)。
/// N1=发起人本人(提交审核人),无需检验员角色成员;N2/N3 复用 IPQC 主管/QE 角色。已发布则跳过(幂等)。
///
public static class S6ProcessInspectionFlowSeed
{
public static void EnsureSeed(ISqlSugarClient db)
{
try
{
db.CodeFirst.InitTables(
typeof(ApprovalBizType),
typeof(ApprovalFlowEntity),
typeof(ApprovalFlowVersion));
db.CodeFirst.InitTables(typeof(AdoS6IpqcQualityDisposition));
EnsureBizType(db);
EnsurePublishedFlow(db);
}
catch (Exception ex)
{
Trace.TraceWarning("S6 process inspection review flow seed: " + ex);
}
}
private static void EnsureBizType(ISqlSugarClient db)
{
var exists = db.Queryable().Any(x => x.Code == S6ProcessInspectionFlowConst.BizType);
if (exists) return;
db.Insertable(new ApprovalBizType
{
Id = YitIdHelper.NextId(),
Code = S6ProcessInspectionFlowConst.BizType,
Name = "过程检验单(Phase1C)审核",
Remark = "S6 过程检验单(ado_s6_process_inspection_bill) 提交审核→主管→质量处置 审批流",
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 = BuildFlowJson();
foreach (var orgId in orgIds)
{
var existing = db.Queryable()
.Where(x => x.BizType == S6ProcessInspectionFlowConst.BizType && x.OrgId == orgId && x.IsPublished && !x.IsDelete)
.OrderByDescending(x => x.Version)
.First();
if (existing != null) continue; // 已发布则跳过(幂等)
var flow = new ApprovalFlowEntity
{
Id = YitIdHelper.NextId(),
Code = $"S6PI_{orgId}",
Name = "过程检验单(Phase1C)审核",
BizType = S6ProcessInspectionFlowConst.BizType,
FormJson = "{}",
FlowJson = flowJson,
Status = 1,
Remark = "系统默认流程 v1:开始-提交审核(发起人)-检验主管审核-网关(质量结果)-质量处置-结束",
Version = 1,
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();
}
}
private static string BuildFlowJson()
{
var item = new ApprovalFlowItem
{
Nodes = new List
{
new()
{
Id = "start", Type = "bpmn:startEvent", X = 100, Y = 120,
Properties = new FlowProperties { NodeName = "开始" },
Text = new FlowTextItem { X = 100, Y = 154, Value = "开始" },
},
new()
{
Id = S6ProcessInspectionFlowConst.NodeSubmit, Type = "bpmn:userTask", X = 300, Y = 120,
Properties = new FlowProperties
{
NodeName = "提交审核",
ApproverType = nameof(ApproverTypeEnum.Initiator),
ApproverIds = "",
ApproverNames = "发起人",
MultiApproveMode = "Any",
},
Text = new FlowTextItem { X = 300, Y = 154, Value = "提交审核" },
},
new()
{
Id = S6ProcessInspectionFlowConst.NodeSupervisor, Type = "bpmn:userTask", X = 500, Y = 120,
Properties = new FlowProperties
{
NodeName = "检验主管审核",
ApproverType = nameof(ApproverTypeEnum.Role),
ApproverIds = S6ProcessInspectionFlowConst.RoleSupervisorId.ToString(),
ApproverNames = "过程检验主管",
MultiApproveMode = "Any",
},
Text = new FlowTextItem { X = 500, Y = 154, Value = "检验主管审核" },
},
new()
{
Id = S6ProcessInspectionFlowConst.GatewayResult, Type = "bpmn:exclusiveGateway", X = 660, Y = 120,
Properties = new FlowProperties
{
NodeName = "质量结果分流",
Conditions = new List
{
new()
{
Expression = "disposition_required == 1",
TargetNodeId = S6ProcessInspectionFlowConst.NodeDisposition,
IsDefault = false,
Label = "不合格转质量处置",
},
new()
{
TargetNodeId = "end",
IsDefault = true,
Label = "合格完成",
},
},
},
Text = new FlowTextItem { X = 660, Y = 154, Value = "质量结果分流" },
},
new()
{
Id = S6ProcessInspectionFlowConst.NodeDisposition, Type = "bpmn:userTask", X = 820, Y = 120,
Properties = new FlowProperties
{
NodeName = "质量处置",
ApproverType = nameof(ApproverTypeEnum.Role),
ApproverIds = S6ProcessInspectionFlowConst.RoleQualityEngineerId.ToString(),
ApproverNames = "过程检验质量工程师",
MultiApproveMode = "Any",
},
Text = new FlowTextItem { X = 820, Y = 154, Value = "质量处置" },
},
new()
{
Id = "end", Type = "bpmn:endEvent", X = 980, Y = 120,
Properties = new FlowProperties { NodeName = "结束" },
Text = new FlowTextItem { X = 980, Y = 154, Value = "结束" },
},
},
Edges = new List
{
BuildEdge("edge-start-n1", "start", S6ProcessInspectionFlowConst.NodeSubmit, 140, 120, 260, 120),
BuildEdge("edge-n1-n2", S6ProcessInspectionFlowConst.NodeSubmit, S6ProcessInspectionFlowConst.NodeSupervisor, 340, 120, 460, 120),
BuildEdge("edge-n2-gw", S6ProcessInspectionFlowConst.NodeSupervisor, S6ProcessInspectionFlowConst.GatewayResult, 540, 120, 640, 120),
BuildEdge("edge-gw-n3", S6ProcessInspectionFlowConst.GatewayResult, S6ProcessInspectionFlowConst.NodeDisposition, 680, 120, 780, 120),
BuildEdge("edge-gw-end", S6ProcessInspectionFlowConst.GatewayResult, "end", 680, 120, 960, 120),
BuildEdge("edge-n3-end", S6ProcessInspectionFlowConst.NodeDisposition, "end", 860, 120, 960, 120),
}
};
return JsonSerializer.Serialize(item);
}
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 } },
};
}
}