using Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow; namespace Admin.NET.Plugin.AiDOP.SeedData; /// /// S8-ORDER-CHAIN-ASSEMBLY-DELIVERY-DATA-LINEAGE-AUDIT-1: /// 总装发货「主门禁里程碑 / 并行准备」两表 seed 算法 SOT。 /// /// ────────────────────────────────────────────────────────────────────── /// SEED 落地路径(关键): /// 本项目 SEED 数据落地走 UpdateScripts SQL(DELETE+INSERT),不是 SqlSugar IncreSeed 自动写入。 /// 这与 procurement 1.0.148.sql / UpdateScripts SQL 模式一致。 /// 本类只作为算法 SOT,本批次实际行数据由 /// UpdateScripts/1.0.153.sql /// 的 INSERT 语句落地(DDL 创建表 + DELETE 幂等清理 + INSERT 144 行)。 /// 因此本类不挂 [IncreSeed];保留算法 owner 身份,便于未来 IMPORT/AGG 接入对账。 /// ────────────────────────────────────────────────────────────────────── /// /// 业务口径(拍板版本): /// 父级:ado_s8_order_flow_stage 中 stage_code=FINAL_ASSEMBLY_DELIVERY 行的 planned_days=3.0、actual_days/status。 /// 非 pending 订单 = 14 green (actual=3.0) + 1 yellow (SO-2026-011 actual=4.0);5 pending 不生成 ORDER_LEVEL 行。 /// /// Gate baseline 5 行: /// planned_offset_days = (0.6, 1.2, 1.8, 2.4, 3.0)(累计里程碑)。 /// actual_offset_days = planned_offset_days、variance_days = 0、status = green(清洁 PPT 基线)。 /// impacted_order_count = 0、risk_order_count = 0(baseline 视图不暴露单订单分布)。 /// top_risk_type/label = NULL(baseline 行无风险摘要)。 /// /// Gate order-level:每个非 pending 单 5 行: /// scale = stage.actual_days / 3.0 /// 前 4 个门禁 actual_offset_days = planned_offset_days × scale, /// 末位 SHIPMENT_CONFIRMATION 尾差修正:actual_offset_days = stage.actual_days。 /// variance_days = actual_offset_days - planned_offset_days。 /// status:variance≤0 green / ≤0.3 yellow / 否则 red(seed 时固化)。 /// impacted_order_count = (status != green) ? 1 : 0。 /// risk_order_count = (status == red) ? 1 : 0。 /// top_risk_type/label:status != green 时取 GateRiskMap,否则 NULL。 /// /// Parallel baseline 4 行: /// kitting_rate = (0.9500, 0.9700, 0.9200, 0.9600)。 /// status 按 ≥0.95 green / ≥0.85 yellow / 否则 red 派生(SHIPPING_PLAN 0.92 = yellow,其它 3 项 green)。 /// impacted/risk = 0,top_risk_type/label = NULL。 /// /// Parallel order-level:每个非 pending 单 4 行: /// stage.status == "green" → kitting_rate = baseline(无调整)。 /// stage.status == "yellow" → kitting_rate = baseline - 0.0500(4 项统一下调,保 yellow 范围)。 /// status 按相同阈值派生。 /// impacted/risk/top_risk_type/label 同 Gate 规则。 /// /// 真实数据源(IMPORT / AGG)接入后,service 优先采用 IMPORT/AGG,同 (order_code, gate/prep_code) SEED 行仅兜底。 /// // 不挂 [IncreSeed]:实际数据落地路径见 1.0.153.sql。 public class S8OrderFlowFinalAssemblyGateSeedData : ISqlSugarEntitySeedData { public IEnumerable HasData() => S8OrderFlowFinalAssemblyDataset.BuildGateBaselineRows() .Concat(S8OrderFlowFinalAssemblyDataset.BuildGateOrderLevelRows()); } // 不挂 [IncreSeed]:实际数据落地路径见 1.0.153.sql。 public class S8OrderFlowFinalAssemblyParallelSeedData : ISqlSugarEntitySeedData { public IEnumerable HasData() => S8OrderFlowFinalAssemblyDataset.BuildParallelBaselineRows() .Concat(S8OrderFlowFinalAssemblyDataset.BuildParallelOrderLevelRows()); } internal static class S8OrderFlowFinalAssemblyDataset { // ─────────────── ID base ranges(接续 manufacturing 1329909210000 段) ─────────────── internal const long GateBaselineIdBase = 1329909220000L; internal const long GateOrderLevelIdBase = 1329909230000L; internal const long ParallelBaselineIdBase = 1329909240000L; internal const long ParallelOrderLevelIdBase = 1329909250000L; internal const string ScenarioBaseline = "BASELINE_PPT"; internal const string ScenarioOrderLevel = "ORDER_LEVEL"; // FINAL_ASSEMBLY_DELIVERY 在 5 阶段流水中固定为索引 4(order_review→product_design→material_procurement→body_production→final_assembly_shipping)。 private const int FinalAssemblyStageIndex = 4; private const decimal StageBaselineDays = 3.0m; // ─────────────── Gate baseline 真值(累计里程碑) ─────────────── private sealed record GateBaseline( int SortNo, string Code, string Name, decimal PlannedOffsetDays, string OwnerSideText, string RiskType, string RiskLabel); private static readonly GateBaseline[] GateBaselines = { new(10, "ASSEMBLY_COMPLETION", "总装完工", 0.6m, "总装线", "ASSEMBLY_DELAY", "总装节拍偏差"), new(20, "QUALITY_RELEASE", "质量放行", 1.2m, "质量·终检", "QUALITY_RELEASE_DELAY", "质量放行等待"), new(30, "PACKAGING_COMPLETION", "包装完成", 1.8m, "包装线", "PACKAGING_DELAY", "包装完成偏差"), new(40, "GOODS_HANDOVER", "成品交接", 2.4m, "成品库", "HANDOVER_DELAY", "成品交接等待"), new(50, "SHIPMENT_CONFIRMATION", "发运确认", 3.0m, "发运协调", "SHIPMENT_DELAY", "发运确认等待"), }; // ─────────────── Parallel baseline 真值(齐套率) ─────────────── private sealed record ParallelBaseline( int SortNo, string Code, string Name, decimal KittingRate, string OwnerSideText, string RiskType, string RiskLabel); private static readonly ParallelBaseline[] ParallelBaselines = { new(10, "PACKAGING_MATERIAL_PREP", "包装材料准备", 0.9500m, "包装线·物料", "PACKAGING_MATERIAL_SHORTAGE", "包装材料齐套"), new(20, "LABEL_DOC_PREP", "标签随箱资料准备", 0.9700m, "技术·质量", "LABEL_DOC_PENDING", "标签随箱资料齐套"), new(30, "SHIPPING_PLAN", "发运计划准备", 0.9200m, "发运协调", "SHIPPING_PLAN_PENDING", "发运计划齐套"), new(40, "SHIPPING_DOC_PREP", "出货单据准备", 0.9600m, "计划·商务", "SHIPPING_DOC_PENDING", "出货单据齐套"), }; /// yellow 单 kitting_rate 统一下调量(保 ≥0.85 yellow 阈值)。 private const decimal YellowKittingPenalty = 0.0500m; // ──────────────────────────────────────────────────────────── // Gate 行 // ──────────────────────────────────────────────────────────── public static IEnumerable BuildGateBaselineRows() { long seq = 0; foreach (var g in GateBaselines) { yield return new AdoS8OrderFlowFinalAssemblyGate { Id = GateBaselineIdBase + (++seq), OrderId = null, OrderCode = null, GateCode = g.Code, GateName = g.Name, PlannedOffsetDays = g.PlannedOffsetDays, ActualOffsetDays = g.PlannedOffsetDays, VarianceDays = 0m, Status = "green", ImpactedOrderCount = 0, RiskOrderCount = 0, TopRiskType = null, TopRiskLabel = null, OwnerSideText = g.OwnerSideText, SortNo = g.SortNo, ScenarioCode = ScenarioBaseline, DataSource = "SEED", TenantId = 1, FactoryId = 1, CreatedAt = S8OrderFlowDataset.CreatedAt, UpdatedAt = null, IsDeleted = false, }; } } public static IEnumerable BuildGateOrderLevelRows() { long seq = 0; foreach (var spec in S8OrderFlowDataset.Specs) { var lifecycle = S8OrderFlowStageDataset.BuildLifecycleValues(spec); var stage = lifecycle[FinalAssemblyStageIndex]; if (stage.status == "pending") continue; var A = stage.actualDays; var scale = A / StageBaselineDays; var orderId = S8OrderFlowDataset.OrderIdBase + spec.Idx; for (var i = 0; i < GateBaselines.Length; i++) { var g = GateBaselines[i]; decimal actualOffset; if (i == GateBaselines.Length - 1) { // 末位门禁尾差修正,确保 SHIPMENT_CONFIRMATION.actual_offset_days = stage.actual_days。 actualOffset = decimal.Round(A, 3); } else { actualOffset = decimal.Round(g.PlannedOffsetDays * scale, 3); } var variance = decimal.Round(actualOffset - g.PlannedOffsetDays, 3); var status = ClassifyGateStatus(variance); var (riskType, riskLabel) = status == "green" ? (null, null) : ((string?)g.RiskType, (string?)g.RiskLabel); yield return new AdoS8OrderFlowFinalAssemblyGate { Id = GateOrderLevelIdBase + (++seq), OrderId = orderId, OrderCode = spec.OrderCode, GateCode = g.Code, GateName = g.Name, PlannedOffsetDays = g.PlannedOffsetDays, ActualOffsetDays = actualOffset, VarianceDays = variance, Status = status, ImpactedOrderCount = status == "green" ? 0 : 1, RiskOrderCount = status == "red" ? 1 : 0, TopRiskType = riskType, TopRiskLabel = riskLabel, OwnerSideText = g.OwnerSideText, SortNo = g.SortNo, ScenarioCode = ScenarioOrderLevel, DataSource = "SEED", TenantId = 1, FactoryId = 1, CreatedAt = S8OrderFlowDataset.CreatedAt, UpdatedAt = null, IsDeleted = false, }; } } } // ──────────────────────────────────────────────────────────── // Parallel 行 // ──────────────────────────────────────────────────────────── public static IEnumerable BuildParallelBaselineRows() { long seq = 0; foreach (var p in ParallelBaselines) { yield return new AdoS8OrderFlowFinalAssemblyParallel { Id = ParallelBaselineIdBase + (++seq), OrderId = null, OrderCode = null, PrepCode = p.Code, PrepName = p.Name, KittingRate = p.KittingRate, Status = ClassifyParallelStatus(p.KittingRate), ImpactedOrderCount = 0, RiskOrderCount = 0, TopRiskType = null, TopRiskLabel = null, OwnerSideText = p.OwnerSideText, SortNo = p.SortNo, ScenarioCode = ScenarioBaseline, DataSource = "SEED", TenantId = 1, FactoryId = 1, CreatedAt = S8OrderFlowDataset.CreatedAt, UpdatedAt = null, IsDeleted = false, }; } } public static IEnumerable BuildParallelOrderLevelRows() { long seq = 0; foreach (var spec in S8OrderFlowDataset.Specs) { var lifecycle = S8OrderFlowStageDataset.BuildLifecycleValues(spec); var stage = lifecycle[FinalAssemblyStageIndex]; if (stage.status == "pending") continue; var orderId = S8OrderFlowDataset.OrderIdBase + spec.Idx; var stageStatus = stage.status; foreach (var p in ParallelBaselines) { var kittingRate = stageStatus switch { "yellow" => decimal.Round(p.KittingRate - YellowKittingPenalty, 4), _ => p.KittingRate, // green:保持 baseline }; var status = ClassifyParallelStatus(kittingRate); var (riskType, riskLabel) = status == "green" ? (null, null) : ((string?)p.RiskType, (string?)p.RiskLabel); yield return new AdoS8OrderFlowFinalAssemblyParallel { Id = ParallelOrderLevelIdBase + (++seq), OrderId = orderId, OrderCode = spec.OrderCode, PrepCode = p.Code, PrepName = p.Name, KittingRate = kittingRate, Status = status, ImpactedOrderCount = status == "green" ? 0 : 1, RiskOrderCount = status == "red" ? 1 : 0, TopRiskType = riskType, TopRiskLabel = riskLabel, OwnerSideText = p.OwnerSideText, SortNo = p.SortNo, ScenarioCode = ScenarioOrderLevel, DataSource = "SEED", TenantId = 1, FactoryId = 1, CreatedAt = S8OrderFlowDataset.CreatedAt, UpdatedAt = null, IsDeleted = false, }; } } } // ──────────────────────────────────────────────────────────── // status classifiers(seed-time 一次性,运行期不再重判) // ──────────────────────────────────────────────────────────── /// gate status:variance ≤ 0 green / ≤ 0.3 yellow / 否则 red。 private static string ClassifyGateStatus(decimal variance) { if (variance <= 0m) return "green"; if (variance <= 0.3m) return "yellow"; return "red"; } /// parallel status:kitting_rate ≥ 0.95 green / ≥ 0.85 yellow / 否则 red。 private static string ClassifyParallelStatus(decimal kittingRate) { if (kittingRate >= 0.95m) return "green"; if (kittingRate >= 0.85m) return "yellow"; return "red"; } }