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";
}
}