S8OrderFlowProductDesignDrawingSeedData.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using Admin.NET.Plugin.AiDOP.Entity.S8.OrderFlow;
  2. namespace Admin.NET.Plugin.AiDOP.SeedData;
  3. /// <summary>
  4. /// S8-ORDER-CHAIN-PRODUCT-DESIGN-20ORDER-GENERATION-CONSISTENCY-AUDIT-1:
  5. /// S8 订单链路产品设计图号种子,按订单父级 actual_days 守恒生成(不再使用全局聚合口径)。
  6. ///
  7. /// 守恒约束(核心业务规则):
  8. /// AVG(drawing.actual_days WHERE order_code = X)
  9. /// = ado_s8_order_flow_stage.actual_days WHERE order_code = X AND order_flow_code = 'PRODUCT_DESIGN'
  10. /// 即 SUM(all drawing.actual_days) = stage.actual_days × drawing_count(简单平均,非台数加权)。
  11. ///
  12. /// 守恒模型(按 stage.actual_days × 是否有非标 5 类分类):
  13. /// A) pending(stage.status=pending) → 3 张 STANDARD,actual_days=NULL,status=pending
  14. /// B) green 无非标(stage.actual_days=A=3) → 3 张 STANDARD,actual_days=A=3.00,status=green
  15. /// C) green 有非标(A=3) → 6 张 STANDARD (1.25 green) + 1 张 NON_STANDARD (13.50 red)
  16. /// AVG=(6×1.25 + 13.50)/7 = 21/7 = 3.00;非标显著超期,常规摊平
  17. /// D) red 无非标(A=5) → 5 张 STANDARD,actual_days=A=5.00,status=red
  18. /// E) red 有非标(A=5) → 6 张 STANDARD (4.50 red) + 1 张 NON_STANDARD (8.00 red)
  19. /// AVG=(6×4.50 + 8.00)/7 = 35/7 = 5.00;全部 red 支撑父 red
  20. ///
  21. /// 图号编码:常规 D-{OrderCode}-G{NN};非标 D-{OrderCode}-X{NN}。
  22. /// 责任人按全局序号 seq 在 6 桶(李海峰 / 陈思远 / 王明华 / 赵建国 / 刘振宇 / 周启明)循环。
  23. /// 总图号数:106 = A(2×3) + B(5×3) + C(9×7) + D(3×5) + E(1×7) = 6 + 15 + 63 + 15 + 7。
  24. /// </summary>
  25. [IncreSeed]
  26. public class S8OrderFlowProductDesignDrawingSeedData
  27. : ISqlSugarEntitySeedData<AdoS8OrderFlowProductDesignDrawing>
  28. {
  29. public IEnumerable<AdoS8OrderFlowProductDesignDrawing> HasData()
  30. => S8OrderFlowProductDesignDrawingDataset.BuildDrawings();
  31. }
  32. internal static class S8OrderFlowProductDesignDrawingDataset
  33. {
  34. /// <summary>图号 id 基址(与其他 S8 种子号段隔离;本表新设计行数 106,使用 IdBase+1..106)。</summary>
  35. internal const long IdBase = 1329909130000L;
  36. internal const string ProductTypeStandard = "STANDARD";
  37. internal const string ProductTypeNonStandard = "NON_STANDARD";
  38. /// <summary>PRODUCT_DESIGN 阶段统一 KPI=3 天,常规与非标共用同一阈值。</summary>
  39. internal const decimal KpiDays = 3.00m;
  40. /// <summary>常规图号统一 product_quantity=7(设计阶段每张图号承载 7 台)。</summary>
  41. internal const int StandardQuantity = 7;
  42. /// <summary>非标图号统一 product_quantity=2(非标少量定制)。</summary>
  43. internal const int NonStandardQuantity = 2;
  44. /// <summary>责任人 6 桶;按全局递增序号 seq 循环分配,sort_no 仅订单内序号。</summary>
  45. private static readonly string[] Designers =
  46. {
  47. "李海峰",
  48. "陈思远",
  49. "王明华",
  50. "赵建国",
  51. "刘振宇",
  52. "周启明",
  53. };
  54. /// <summary>
  55. /// 每订单是否含非标产品(与 stage 派生 layout 共同决定 std/nstd 数量)。
  56. /// 11 单含非标(沿用原业务直觉:大客户 / P1 优先级 / completed 订单),9 单无非标。
  57. /// pending 父级订单(016, 017)按守恒约束统一不分配非标(产品设计阶段尚未进入或刚开始)。
  58. /// </summary>
  59. private static readonly bool[] HasNonStandardByIdx =
  60. {
  61. // SO-2026-001..005
  62. true, true, true, false, false,
  63. // SO-2026-006..010
  64. true, true, true, false, false,
  65. // SO-2026-011..015
  66. false, true, false, false, false,
  67. // SO-2026-016..020
  68. false, false, true, true, true,
  69. };
  70. /// <summary>单订单图号布局:std/nstd 数量 + 各自 actual_days + 各自 status。null actual=pending。</summary>
  71. internal readonly record struct OrderLayout(
  72. int StdN,
  73. int NstdN,
  74. decimal? StdActualDays,
  75. decimal? NstdActualDays,
  76. string StdStatus,
  77. string NstdStatus);
  78. /// <summary>
  79. /// 按 PRODUCT_DESIGN stage 派生订单布局。守恒前提:SUM(actual_days) = stage.actual_days × drawing_count。
  80. /// stage seed 引用:S8OrderFlowStageDataset.BuildLifecycleValues(spec)[1] 即 PRODUCT_DESIGN 阶段。
  81. /// </summary>
  82. internal static OrderLayout DeriveLayout(S8OrderFlowDataset.OrderSpec spec, int idx)
  83. {
  84. var lifecycle = S8OrderFlowStageDataset.BuildLifecycleValues(spec);
  85. var stage = lifecycle[1]; // 索引 1 = PRODUCT_DESIGN(lifecycle[0]=ORDER_REVIEW_PLAN_CALC)
  86. // 类别 A:pending 父级 → 3 std NULL pending
  87. if (stage.status == "pending")
  88. {
  89. return new OrderLayout(3, 0, null, null, "pending", "pending");
  90. }
  91. var A = stage.actualDays;
  92. var hasNonStandard = HasNonStandardByIdx[idx];
  93. if (A <= KpiDays)
  94. {
  95. // 类别 C:green 有非标 → 6 std 1.25 + 1 nstd 13.50;AVG=(6×1.25 + 13.50)/7=3.00
  96. if (hasNonStandard)
  97. {
  98. return new OrderLayout(6, 1, 1.25m, 13.50m, "green", "red");
  99. }
  100. // 类别 B:green 无非标 → 3 std 各 A green;AVG=A
  101. return new OrderLayout(3, 0, A, null, "green", "green");
  102. }
  103. else
  104. {
  105. // 类别 E:red 有非标 → 6 std 4.50 + 1 nstd 8.00;AVG=(6×4.50 + 8.00)/7=5.00;全 red
  106. if (hasNonStandard)
  107. {
  108. return new OrderLayout(6, 1, 4.50m, 8.00m, "red", "red");
  109. }
  110. // 类别 D:red 无非标 → 5 std 各 A red;AVG=A;多张图号都超期支撑父 red
  111. return new OrderLayout(5, 0, A, null, "red", "red");
  112. }
  113. }
  114. public static IEnumerable<AdoS8OrderFlowProductDesignDrawing> BuildDrawings()
  115. {
  116. long seq = 0;
  117. // 图号粒度计划开始 = release_at + 5 天(ORDER_REVIEW KPI=5 天结束后进入 PRODUCT_DESIGN)
  118. var plannedStart = S8OrderFlowDataset.ReleaseBase.AddDays(5);
  119. var plannedEnd = plannedStart.AddDays((double)KpiDays);
  120. for (var i = 0; i < S8OrderFlowDataset.Specs.Length; i++)
  121. {
  122. var orderSpec = S8OrderFlowDataset.Specs[i];
  123. var layout = DeriveLayout(orderSpec, i);
  124. var sortNo = 0;
  125. for (var g = 0; g < layout.StdN; g++)
  126. {
  127. sortNo++;
  128. yield return BuildDrawing(
  129. seq: ++seq,
  130. orderSpec: orderSpec,
  131. sortNo: sortNo,
  132. drawingNo: $"D-{orderSpec.OrderCode}-G{g + 1:D2}",
  133. productType: ProductTypeStandard,
  134. productQuantity: StandardQuantity,
  135. plannedStart: plannedStart,
  136. plannedEnd: plannedEnd,
  137. actualDays: layout.StdActualDays,
  138. status: layout.StdStatus);
  139. }
  140. for (var x = 0; x < layout.NstdN; x++)
  141. {
  142. sortNo++;
  143. yield return BuildDrawing(
  144. seq: ++seq,
  145. orderSpec: orderSpec,
  146. sortNo: sortNo,
  147. drawingNo: $"D-{orderSpec.OrderCode}-X{x + 1:D2}",
  148. productType: ProductTypeNonStandard,
  149. productQuantity: NonStandardQuantity,
  150. plannedStart: plannedStart,
  151. plannedEnd: plannedEnd,
  152. actualDays: layout.NstdActualDays,
  153. status: layout.NstdStatus);
  154. }
  155. }
  156. }
  157. private static AdoS8OrderFlowProductDesignDrawing BuildDrawing(
  158. long seq,
  159. S8OrderFlowDataset.OrderSpec orderSpec,
  160. int sortNo,
  161. string drawingNo,
  162. string productType,
  163. int productQuantity,
  164. DateTime plannedStart,
  165. DateTime plannedEnd,
  166. decimal? actualDays,
  167. string status)
  168. {
  169. // 完成态:actualStart=plannedStart,actualEnd=plannedStart + actualDays
  170. // pending:actualStart=plannedStart 表示已起步但未完工,actualEnd=NULL(与 stage seed pending 路径一致)
  171. DateTime? actualStart = plannedStart;
  172. DateTime? actualEnd = actualDays.HasValue
  173. ? plannedStart.AddDays((double)actualDays.Value)
  174. : (DateTime?)null;
  175. // is_achieved:actual_days <= kpi_days;pending 时为 false(entity bool 不可 null)
  176. var isAchieved = actualDays.HasValue && actualDays.Value <= KpiDays;
  177. var responsible = Designers[(seq - 1) % Designers.Length];
  178. return new AdoS8OrderFlowProductDesignDrawing
  179. {
  180. Id = IdBase + seq,
  181. TenantId = 1,
  182. FactoryId = 1,
  183. OrderCode = orderSpec.OrderCode,
  184. DrawingNo = drawingNo,
  185. ProductType = productType,
  186. ProductQuantity = productQuantity,
  187. ResponsiblePerson = responsible,
  188. PlannedStartDate = plannedStart,
  189. PlannedEndDate = plannedEnd,
  190. ActualStartDate = actualStart,
  191. ActualEndDate = actualEnd,
  192. KpiDays = KpiDays,
  193. ActualDays = actualDays,
  194. IsAchieved = isAchieved,
  195. Status = status,
  196. SortNo = sortNo,
  197. IsDeleted = false,
  198. CreateTime = S8OrderFlowDataset.CreatedAt,
  199. UpdateTime = null,
  200. };
  201. }
  202. }