S8OrderFlowProductDesignDrawingSeedData.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. using Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
  2. namespace Admin.NET.Plugin.AiDOP.SeedData;
  3. /// <summary>
  4. /// S8-ORDER-CHAIN-PRODUCT-DESIGN-DRAWING-PERSIST-1:S8 订单链路产品设计阶段基准业务初始化数据种子。
  5. /// 20 单 × 63 图号;严格满足七项不变量约束:
  6. /// 1) COUNT(DISTINCT drawing_no) = 63;STANDARD=52 / NON_STANDARD=11
  7. /// 2) SUM(product_quantity ALL) = 382;STANDARD=357 / NON_STANDARD=25
  8. /// 3) AVG(actual_days WHERE product_type='STANDARD') 落在 [1.17, 1.21]
  9. /// 4) AVG(actual_days WHERE product_type='NON_STANDARD') 落在 [9.25, 9.31]
  10. /// 5) AVG(actual_days ALL) ≈ 2.60 天
  11. /// 6) SUM(product_quantity WHERE is_achieved=false) 落在 [14, 16]
  12. /// 7) 加权达成率 = 达标 quantity / 总 quantity ≈ 96%
  13. /// 图号编码:常规 D-{OrderCode}-G{NN};非标 D-{OrderCode}-X{NN}(绑定 SO-2026-001..020 真实 OrderCode)。
  14. /// 责任单位/岗位 5 选 1:研发中心 / 结构设计组 / 电气设计组 / 工艺设计组 / 设计审核组;不引入个人姓名。
  15. /// </summary>
  16. [IncreSeed]
  17. public class S8OrderFlowProductDesignDrawingSeedData
  18. : ISqlSugarEntitySeedData<AdoS8OrderFlowProductDesignDrawing>
  19. {
  20. public IEnumerable<AdoS8OrderFlowProductDesignDrawing> HasData()
  21. => S8OrderFlowProductDesignDrawingDataset.BuildDrawings();
  22. }
  23. internal static class S8OrderFlowProductDesignDrawingDataset
  24. {
  25. /// <summary>图号 id 基址(与其他 S8 种子号段隔离)。</summary>
  26. internal const long IdBase = 1329909130000L;
  27. internal const string ProductTypeStandard = "STANDARD";
  28. internal const string ProductTypeNonStandard = "NON_STANDARD";
  29. /// <summary>常规产品 KPI(天)。</summary>
  30. internal const decimal StandardKpiDays = 3.00m;
  31. /// <summary>非标产品 KPI(天)。业务允许非标设计周期更长,落库为图号粒度独立 KPI。</summary>
  32. internal const decimal NonStandardKpiDays = 12.00m;
  33. /// <summary>责任单位/岗位(5 选 1,按 sort_no 循环分配;不使用个人姓名)。</summary>
  34. private static readonly string[] ResponsibleUnits =
  35. {
  36. "研发中心",
  37. "结构设计组",
  38. "电气设计组",
  39. "工艺设计组",
  40. "设计审核组",
  41. };
  42. /// <summary>
  43. /// 每订单 (常规图号数, 非标图号数)。20 行合计 52 / 11;其中 4 单 4 图、16 单 3 图。
  44. /// 非标集中在大客户、P1 优先级与 in_progress 订单上,与业务直觉一致。
  45. /// </summary>
  46. private static readonly (int StdCount, int NonStdCount)[] PerOrderConfig =
  47. {
  48. // SO-2026-001..005
  49. (3, 1), (3, 1), (3, 1), (3, 0), (3, 0),
  50. // SO-2026-006..010
  51. (2, 1), (2, 1), (2, 1), (3, 0), (3, 0),
  52. // SO-2026-011..015
  53. (3, 0), (2, 1), (3, 0), (3, 0), (3, 0),
  54. // SO-2026-016..020
  55. (3, 0), (2, 1), (2, 1), (2, 1), (2, 1),
  56. };
  57. /// <summary>52 张常规图号 spec:合计 actual_days=61.88、qty=357、1 张超期 (qty=3)。</summary>
  58. private static readonly DrawingSpec[] StandardSequence = BuildStandardSequence();
  59. /// <summary>11 张非标图号 spec:合计 actual_days=102.08、qty=25、2 张超期 (qty=6 each)。</summary>
  60. private static readonly DrawingSpec[] NonStandardSequence = BuildNonStandardSequence();
  61. /// <summary>单张图号的回卷规格:actual_days / quantity / is_achieved / status。</summary>
  62. internal readonly record struct DrawingSpec(decimal ActualDays, int Quantity, bool IsAchieved, string Status);
  63. private static DrawingSpec[] BuildStandardSequence()
  64. {
  65. // 52 张分布:24×(1.13, qty=7) + 24×(1.12, qty=7) + 2×(1.13, qty=6) + 1×(1.12, qty=6) + 1×(4.50, qty=3, red)
  66. // actual_days 合计 = 24×1.13 + 24×1.12 + 2×1.13 + 1×1.12 + 4.50
  67. // = 27.12 + 26.88 + 2.26 + 1.12 + 4.50 = 61.88 → avg 1.190 (在 [1.17, 1.21])
  68. // quantity 合计 = 24×7 + 24×7 + 2×6 + 1×6 + 3 = 168 + 168 + 12 + 6 + 3 = 357
  69. var seq = new DrawingSpec[52];
  70. for (var i = 0; i < 24; i++) seq[i] = new DrawingSpec(1.13m, 7, true, "green");
  71. for (var i = 24; i < 48; i++) seq[i] = new DrawingSpec(1.12m, 7, true, "green");
  72. seq[48] = new DrawingSpec(1.13m, 6, true, "green");
  73. seq[49] = new DrawingSpec(1.13m, 6, true, "green");
  74. seq[50] = new DrawingSpec(1.12m, 6, true, "green");
  75. // 唯一一张超期常规图号:actual=4.50 > kpi=3 → (4.5-3)/3 = 0.50 > 0.20 → red
  76. seq[51] = new DrawingSpec(4.50m, 3, false, "red");
  77. return seq;
  78. }
  79. private static DrawingSpec[] BuildNonStandardSequence()
  80. {
  81. // 11 张分布:5×(8.34, qty=1) + 4×(8.34, qty=2) + 2×(13.51, qty=6, yellow)
  82. // actual_days 合计 = 9×8.34 + 2×13.51 = 75.06 + 27.02 = 102.08 → avg 9.28 (在 [9.25, 9.31])
  83. // quantity 合计 = 5×1 + 4×2 + 2×6 = 5 + 8 + 12 = 25
  84. var seq = new DrawingSpec[11];
  85. for (var i = 0; i < 5; i++) seq[i] = new DrawingSpec(8.34m, 1, true, "green");
  86. for (var i = 5; i < 9; i++) seq[i] = new DrawingSpec(8.34m, 2, true, "green");
  87. // 两张超期非标图号:actual=13.51 > kpi=12 → (13.51-12)/12 ≈ 0.126 ≤ 0.20 → yellow
  88. seq[9] = new DrawingSpec(13.51m, 6, false, "yellow");
  89. seq[10] = new DrawingSpec(13.51m, 6, false, "yellow");
  90. return seq;
  91. }
  92. public static IEnumerable<AdoS8OrderFlowProductDesignDrawing> BuildDrawings()
  93. {
  94. int stdCursor = 0, nonStdCursor = 0;
  95. long seq = 0;
  96. for (var i = 0; i < S8OrderFlowDataset.Specs.Length; i++)
  97. {
  98. var orderSpec = S8OrderFlowDataset.Specs[i];
  99. var (stdN, nonStdN) = PerOrderConfig[i];
  100. // 图号粒度计划开始 = release_at + 5 天(ORDER_REVIEW KPI=5 天结束后进入 PRODUCT_DESIGN)。
  101. // 所有图号同基准开始,actualEnd 由 actualDays 派生,保证 actualEnd - actualStart 严格等于 actualDays。
  102. var plannedStart = S8OrderFlowDataset.ReleaseBase.AddDays(5);
  103. var sortNo = 0;
  104. for (var g = 0; g < stdN; g++)
  105. {
  106. sortNo++;
  107. var spec = StandardSequence[stdCursor++];
  108. yield return BuildDrawing(
  109. seq: ++seq,
  110. orderSpec: orderSpec,
  111. sortNo: sortNo,
  112. drawingNo: $"D-{orderSpec.OrderCode}-G{g + 1:D2}",
  113. productType: ProductTypeStandard,
  114. kpiDays: StandardKpiDays,
  115. plannedStart: plannedStart,
  116. spec: spec);
  117. }
  118. for (var x = 0; x < nonStdN; x++)
  119. {
  120. sortNo++;
  121. var spec = NonStandardSequence[nonStdCursor++];
  122. yield return BuildDrawing(
  123. seq: ++seq,
  124. orderSpec: orderSpec,
  125. sortNo: sortNo,
  126. drawingNo: $"D-{orderSpec.OrderCode}-X{x + 1:D2}",
  127. productType: ProductTypeNonStandard,
  128. kpiDays: NonStandardKpiDays,
  129. plannedStart: plannedStart,
  130. spec: spec);
  131. }
  132. }
  133. }
  134. private static AdoS8OrderFlowProductDesignDrawing BuildDrawing(
  135. long seq,
  136. S8OrderFlowDataset.OrderSpec orderSpec,
  137. int sortNo,
  138. string drawingNo,
  139. string productType,
  140. decimal kpiDays,
  141. DateTime plannedStart,
  142. DrawingSpec spec)
  143. {
  144. var plannedEnd = plannedStart.AddDays((double)kpiDays);
  145. var actualStart = plannedStart;
  146. var actualEnd = actualStart.AddDays((double)spec.ActualDays);
  147. var responsible = ResponsibleUnits[(sortNo - 1) % ResponsibleUnits.Length];
  148. return new AdoS8OrderFlowProductDesignDrawing
  149. {
  150. Id = IdBase + seq,
  151. TenantId = 1,
  152. FactoryId = 1,
  153. OrderCode = orderSpec.OrderCode,
  154. DrawingNo = drawingNo,
  155. ProductType = productType,
  156. ProductQuantity = spec.Quantity,
  157. ResponsiblePerson = responsible,
  158. PlannedStartDate = plannedStart,
  159. PlannedEndDate = plannedEnd,
  160. ActualStartDate = actualStart,
  161. ActualEndDate = actualEnd,
  162. KpiDays = kpiDays,
  163. ActualDays = spec.ActualDays,
  164. IsAchieved = spec.IsAchieved,
  165. Status = spec.Status,
  166. SortNo = sortNo,
  167. IsDeleted = false,
  168. CreateTime = S8OrderFlowDataset.CreatedAt,
  169. UpdateTime = null,
  170. };
  171. }
  172. }