| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- using Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
- namespace Admin.NET.Plugin.AiDOP.SeedData;
- /// <summary>
- /// 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 行仅兜底。
- /// </summary>
- // 不挂 [IncreSeed]:实际数据落地路径见 1.0.153.sql。
- public class S8OrderFlowFinalAssemblyGateSeedData : ISqlSugarEntitySeedData<AdoS8OrderFlowFinalAssemblyGate>
- {
- public IEnumerable<AdoS8OrderFlowFinalAssemblyGate> HasData()
- => S8OrderFlowFinalAssemblyDataset.BuildGateBaselineRows()
- .Concat(S8OrderFlowFinalAssemblyDataset.BuildGateOrderLevelRows());
- }
- // 不挂 [IncreSeed]:实际数据落地路径见 1.0.153.sql。
- public class S8OrderFlowFinalAssemblyParallelSeedData : ISqlSugarEntitySeedData<AdoS8OrderFlowFinalAssemblyParallel>
- {
- public IEnumerable<AdoS8OrderFlowFinalAssemblyParallel> 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", "出货单据齐套"),
- };
- /// <summary>yellow 单 kitting_rate 统一下调量(保 ≥0.85 yellow 阈值)。</summary>
- private const decimal YellowKittingPenalty = 0.0500m;
- // ────────────────────────────────────────────────────────────
- // Gate 行
- // ────────────────────────────────────────────────────────────
- public static IEnumerable<AdoS8OrderFlowFinalAssemblyGate> 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<AdoS8OrderFlowFinalAssemblyGate> 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<AdoS8OrderFlowFinalAssemblyParallel> 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<AdoS8OrderFlowFinalAssemblyParallel> 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 一次性,运行期不再重判)
- // ────────────────────────────────────────────────────────────
- /// <summary>gate status:variance ≤ 0 green / ≤ 0.3 yellow / 否则 red。</summary>
- private static string ClassifyGateStatus(decimal variance)
- {
- if (variance <= 0m) return "green";
- if (variance <= 0.3m) return "yellow";
- return "red";
- }
- /// <summary>parallel status:kitting_rate ≥ 0.95 green / ≥ 0.85 yellow / 否则 red。</summary>
- private static string ClassifyParallelStatus(decimal kittingRate)
- {
- if (kittingRate >= 0.95m) return "green";
- if (kittingRate >= 0.85m) return "yellow";
- return "red";
- }
- }
|