using Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow; namespace Admin.NET.Plugin.AiDOP.SeedData; /// /// S8-ORDER-CHAIN-PRODUCT-DESIGN-20ORDER-GENERATION-CONSISTENCY-AUDIT-1: /// S8 订单链路产品设计图号种子,按订单父级 actual_days 守恒生成(不再使用全局聚合口径)。 /// /// 守恒约束(核心业务规则): /// AVG(drawing.actual_days WHERE order_code = X) /// = ado_s8_order_flow_stage.actual_days WHERE order_code = X AND order_flow_code = 'PRODUCT_DESIGN' /// 即 SUM(all drawing.actual_days) = stage.actual_days × drawing_count(简单平均,非台数加权)。 /// /// 守恒模型(按 stage.actual_days × 是否有非标 5 类分类): /// A) pending(stage.status=pending) → 3 张 STANDARD,actual_days=NULL,status=pending /// B) green 无非标(stage.actual_days=A=3) → 3 张 STANDARD,actual_days=A=3.00,status=green /// C) green 有非标(A=3) → 6 张 STANDARD (1.25 green) + 1 张 NON_STANDARD (13.50 red) /// AVG=(6×1.25 + 13.50)/7 = 21/7 = 3.00;非标显著超期,常规摊平 /// D) red 无非标(A=5) → 5 张 STANDARD,actual_days=A=5.00,status=red /// E) red 有非标(A=5) → 6 张 STANDARD (4.50 red) + 1 张 NON_STANDARD (8.00 red) /// AVG=(6×4.50 + 8.00)/7 = 35/7 = 5.00;全部 red 支撑父 red /// /// 图号编码:常规 D-{OrderCode}-G{NN};非标 D-{OrderCode}-X{NN}。 /// 责任人按全局序号 seq 在 6 桶(李海峰 / 陈思远 / 王明华 / 赵建国 / 刘振宇 / 周启明)循环。 /// 总图号数:106 = A(2×3) + B(5×3) + C(9×7) + D(3×5) + E(1×7) = 6 + 15 + 63 + 15 + 7。 /// [IncreSeed] public class S8OrderFlowProductDesignDrawingSeedData : ISqlSugarEntitySeedData { public IEnumerable HasData() => S8OrderFlowProductDesignDrawingDataset.BuildDrawings(); } internal static class S8OrderFlowProductDesignDrawingDataset { /// 图号 id 基址(与其他 S8 种子号段隔离;本表新设计行数 106,使用 IdBase+1..106)。 internal const long IdBase = 1329909130000L; internal const string ProductTypeStandard = "STANDARD"; internal const string ProductTypeNonStandard = "NON_STANDARD"; /// PRODUCT_DESIGN 阶段统一 KPI=3 天,常规与非标共用同一阈值。 internal const decimal KpiDays = 3.00m; /// 常规图号统一 product_quantity=7(设计阶段每张图号承载 7 台)。 internal const int StandardQuantity = 7; /// 非标图号统一 product_quantity=2(非标少量定制)。 internal const int NonStandardQuantity = 2; /// 责任人 6 桶;按全局递增序号 seq 循环分配,sort_no 仅订单内序号。 private static readonly string[] Designers = { "李海峰", "陈思远", "王明华", "赵建国", "刘振宇", "周启明", }; /// /// 每订单是否含非标产品(与 stage 派生 layout 共同决定 std/nstd 数量)。 /// 11 单含非标(沿用原业务直觉:大客户 / P1 优先级 / completed 订单),9 单无非标。 /// pending 父级订单(016, 017)按守恒约束统一不分配非标(产品设计阶段尚未进入或刚开始)。 /// private static readonly bool[] HasNonStandardByIdx = { // SO-2026-001..005 true, true, true, false, false, // SO-2026-006..010 true, true, true, false, false, // SO-2026-011..015 false, true, false, false, false, // SO-2026-016..020 false, false, true, true, true, }; /// 单订单图号布局:std/nstd 数量 + 各自 actual_days + 各自 status。null actual=pending。 internal readonly record struct OrderLayout( int StdN, int NstdN, decimal? StdActualDays, decimal? NstdActualDays, string StdStatus, string NstdStatus); /// /// 按 PRODUCT_DESIGN stage 派生订单布局。守恒前提:SUM(actual_days) = stage.actual_days × drawing_count。 /// stage seed 引用:S8OrderFlowStageDataset.BuildLifecycleValues(spec)[1] 即 PRODUCT_DESIGN 阶段。 /// internal static OrderLayout DeriveLayout(S8OrderFlowDataset.OrderSpec spec, int idx) { var lifecycle = S8OrderFlowStageDataset.BuildLifecycleValues(spec); var stage = lifecycle[1]; // 索引 1 = PRODUCT_DESIGN(lifecycle[0]=ORDER_REVIEW_PLAN_CALC) // 类别 A:pending 父级 → 3 std NULL pending if (stage.status == "pending") { return new OrderLayout(3, 0, null, null, "pending", "pending"); } var A = stage.actualDays; var hasNonStandard = HasNonStandardByIdx[idx]; if (A <= KpiDays) { // 类别 C:green 有非标 → 6 std 1.25 + 1 nstd 13.50;AVG=(6×1.25 + 13.50)/7=3.00 if (hasNonStandard) { return new OrderLayout(6, 1, 1.25m, 13.50m, "green", "red"); } // 类别 B:green 无非标 → 3 std 各 A green;AVG=A return new OrderLayout(3, 0, A, null, "green", "green"); } else { // 类别 E:red 有非标 → 6 std 4.50 + 1 nstd 8.00;AVG=(6×4.50 + 8.00)/7=5.00;全 red if (hasNonStandard) { return new OrderLayout(6, 1, 4.50m, 8.00m, "red", "red"); } // 类别 D:red 无非标 → 5 std 各 A red;AVG=A;多张图号都超期支撑父 red return new OrderLayout(5, 0, A, null, "red", "red"); } } public static IEnumerable BuildDrawings() { long seq = 0; // 图号粒度计划开始 = release_at + 5 天(ORDER_REVIEW KPI=5 天结束后进入 PRODUCT_DESIGN) var plannedStart = S8OrderFlowDataset.ReleaseBase.AddDays(5); var plannedEnd = plannedStart.AddDays((double)KpiDays); for (var i = 0; i < S8OrderFlowDataset.Specs.Length; i++) { var orderSpec = S8OrderFlowDataset.Specs[i]; var layout = DeriveLayout(orderSpec, i); var sortNo = 0; for (var g = 0; g < layout.StdN; g++) { sortNo++; yield return BuildDrawing( seq: ++seq, orderSpec: orderSpec, sortNo: sortNo, drawingNo: $"D-{orderSpec.OrderCode}-G{g + 1:D2}", productType: ProductTypeStandard, productQuantity: StandardQuantity, plannedStart: plannedStart, plannedEnd: plannedEnd, actualDays: layout.StdActualDays, status: layout.StdStatus); } for (var x = 0; x < layout.NstdN; x++) { sortNo++; yield return BuildDrawing( seq: ++seq, orderSpec: orderSpec, sortNo: sortNo, drawingNo: $"D-{orderSpec.OrderCode}-X{x + 1:D2}", productType: ProductTypeNonStandard, productQuantity: NonStandardQuantity, plannedStart: plannedStart, plannedEnd: plannedEnd, actualDays: layout.NstdActualDays, status: layout.NstdStatus); } } } private static AdoS8OrderFlowProductDesignDrawing BuildDrawing( long seq, S8OrderFlowDataset.OrderSpec orderSpec, int sortNo, string drawingNo, string productType, int productQuantity, DateTime plannedStart, DateTime plannedEnd, decimal? actualDays, string status) { // 完成态:actualStart=plannedStart,actualEnd=plannedStart + actualDays // pending:actualStart=plannedStart 表示已起步但未完工,actualEnd=NULL(与 stage seed pending 路径一致) DateTime? actualStart = plannedStart; DateTime? actualEnd = actualDays.HasValue ? plannedStart.AddDays((double)actualDays.Value) : (DateTime?)null; // is_achieved:actual_days <= kpi_days;pending 时为 false(entity bool 不可 null) var isAchieved = actualDays.HasValue && actualDays.Value <= KpiDays; var responsible = Designers[(seq - 1) % Designers.Length]; return new AdoS8OrderFlowProductDesignDrawing { Id = IdBase + seq, TenantId = 1, FactoryId = 1, OrderCode = orderSpec.OrderCode, DrawingNo = drawingNo, ProductType = productType, ProductQuantity = productQuantity, ResponsiblePerson = responsible, PlannedStartDate = plannedStart, PlannedEndDate = plannedEnd, ActualStartDate = actualStart, ActualEndDate = actualEnd, KpiDays = KpiDays, ActualDays = actualDays, IsAchieved = isAchieved, Status = status, SortNo = sortNo, IsDeleted = false, CreateTime = S8OrderFlowDataset.CreatedAt, UpdateTime = null, }; } }