S8DemoOrderFlowSeedData.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. using Admin.NET.Plugin.AiDOP.Entity.S8.Demo;
  2. namespace Admin.NET.Plugin.AiDOP;
  3. /// <summary>
  4. /// ORDER-FLOW-BE-DEMO-DATASET-RESET-1:demo 订单执行档案种子(1 主表 + 阶段子表 + 1 快照)。
  5. /// 全局基线:tenant_id=0 / factory_id=0。SO-2026-001 = PPT 第 1 页标准案例;其余 19 单覆盖筛选维度。
  6. /// </summary>
  7. [IncreSeed]
  8. public class S8DemoOrderFlowSeedData : ISqlSugarEntitySeedData<AdoDemoOrderFlow>
  9. {
  10. public IEnumerable<AdoDemoOrderFlow> HasData() => S8DemoOrderFlowDataset.BuildOrders();
  11. }
  12. [IncreSeed]
  13. public class S8DemoOrderFlowStageSeedData : ISqlSugarEntitySeedData<AdoDemoOrderFlowStage>
  14. {
  15. public IEnumerable<AdoDemoOrderFlowStage> HasData() => S8DemoOrderFlowDataset.BuildStages();
  16. }
  17. [IncreSeed]
  18. public class S8DemoOrderFlowSnapshotSeedData : ISqlSugarEntitySeedData<AdoDemoOrderFlowSnapshot>
  19. {
  20. public IEnumerable<AdoDemoOrderFlowSnapshot> HasData() => S8DemoOrderFlowDataset.BuildSnapshot();
  21. }
  22. internal static class S8DemoOrderFlowDataset
  23. {
  24. private static readonly DateTime CreatedAt = DateTime.Parse("2026-05-11 00:00:00");
  25. private const long OrderIdBase = 1329909000000L;
  26. private const long StageIdBase = 1329909010000L;
  27. private const long SnapshotIdBase = 1329909020000L;
  28. private record OrderSpec(
  29. int Idx, string SoNo, string ProductName,
  30. string CustomerName, string CustomerCode, string CustomerType,
  31. string ProductLine, string MaterialCode, string Region,
  32. string Priority, string SupplierGroup,
  33. string WorkflowStatus, string CurrentNodeKey, string FocusNodeKey,
  34. int ExceptionCount, int? ResponseMinutes, int? ProcessingMinutes, int? TotalLossMinutes);
  35. // SO-2026-001 单独硬编码:必须严格匹配 PPT 第 1 页。其余 19 单按模板生成。
  36. private static readonly OrderSpec[] Specs =
  37. {
  38. new(1, "SO-2026-001", "高压接线盒", "电气设备厂A", "C001", "KA", "A产品线", "XX", "华北", "P2", "A", "completed", "final_assembly_shipping", "final_assembly_shipping", 2, 2880, 1440, 4320),
  39. new(2, "SO-2026-002", "转向机总成", "电气设备厂B", "C002", "KA", "B产品线", "YY", "华东", "P3", "B", "completed", "final_assembly_shipping", "material_procurement", 1, 110, 850, 960),
  40. new(3, "SO-2026-003", "电池箱横梁", "电气设备厂C", "C003", "KA", "C产品线", "ZZ", "华南", "P2", "C", "completed", "final_assembly_shipping", "body_production", 1, 80, 720, 800),
  41. new(4, "SO-2026-004", "高压接线盒", "电气设备厂D", "C004", "SMB", "A产品线", "XX", "华北", "P3", "A", "completed", "final_assembly_shipping", "product_design", 1, 95, 680, 775),
  42. new(5, "SO-2026-005", "电池箱横梁", "电气设备厂E", "C005", "MICRO", "C产品线", "ZZ", "华南", "P2", "B", "completed", "final_assembly_shipping", "product_design", 1, 70, 610, 680),
  43. new(6, "SO-2026-006", "驱动总成支架", "电气设备厂A", "C001", "KA", "A产品线", "XX", "华北", "P2", "C", "completed", "final_assembly_shipping", "material_procurement", 2, 130, 1240, 2350),
  44. new(7, "SO-2026-007", "减速器壳体", "电气设备厂B", "C002", "KA", "B产品线", "YY", "华东", "P2", "A", "completed", "final_assembly_shipping", "body_production", 2, 145, 1080, 2210),
  45. new(8, "SO-2026-008", "项目定制骨架", "电气设备厂C", "C003", "KA", "C产品线", "ZZ", "华南", "P1", "B", "completed", "final_assembly_shipping", "body_production", 2, 165, 1320, 2640),
  46. new(9, "SO-2026-009", "控制器外壳", "电气设备厂D", "C004", "SMB", "A产品线", "XX", "华北", "P2", "C", "completed", "final_assembly_shipping", "order_review", 1, 60, 540, 600),
  47. new(10, "SO-2026-010", "试制急单件", "电气设备厂E", "C005", "MICRO", "C产品线", "ZZ", "华南", "P2", "A", "completed", "final_assembly_shipping", "product_design", 1, 88, 730, 818),
  48. new(11, "SO-2026-011", "冷却模块框架", "电气设备厂A", "C001", "KA", "B产品线", "YY", "华东", "P2", "B", "completed", "final_assembly_shipping", "final_assembly_shipping", 1, 50, 410, 460),
  49. new(12, "SO-2026-012", "动力舱隔板", "电气设备厂B", "C002", "KA", "B产品线", "YY", "华东", "P2", "C", "completed", "final_assembly_shipping", "material_procurement", 1, 100, 920, 1020),
  50. new(13, "SO-2026-013", "模组支架", "电气设备厂C", "C003", "KA", "C产品线", "ZZ", "华南", "P2", "A", "completed", "final_assembly_shipping", "body_production", 1, 92, 860, 952),
  51. new(14, "SO-2026-014", "一体化支撑件", "电气设备厂D", "C004", "SMB", "A产品线", "XX", "华北", "P3", "B", "completed", "final_assembly_shipping", "material_procurement", 1, 75, 700, 775),
  52. new(15, "SO-2026-015", "项目定制骨架", "电气设备厂E", "C005", "MICRO", "C产品线", "ZZ", "华南", "P2", "C", "completed", "final_assembly_shipping", "order_review", 1, 65, 580, 645),
  53. new(16, "SO-2026-016", "控制器外壳", "电气设备厂A", "C001", "KA", "A产品线", "XX", "华北", "P2", "A", "in_progress", "order_review", "order_review", 1, 90, null, null),
  54. new(17, "SO-2026-017", "转向机总成", "电气设备厂B", "C002", "KA", "B产品线", "YY", "华东", "P2", "B", "in_progress", "product_design", "product_design", 1, 105, null, null),
  55. new(18, "SO-2026-018", "项目定制骨架", "电气设备厂C", "C003", "KA", "C产品线", "ZZ", "华南", "P2", "C", "in_progress", "material_procurement", "material_procurement", 1, 120, null, null),
  56. new(19, "SO-2026-019", "驱动总成支架", "电气设备厂D", "C004", "SMB", "A产品线", "XX", "华北", "P1", "A", "in_progress", "body_production", "body_production", 2, 140, null, null),
  57. new(20, "SO-2026-020", "试制急单件", "电气设备厂E", "C005", "MICRO", "C产品线", "ZZ", "华南", "P1", "B", "in_progress", "final_assembly_shipping", "final_assembly_shipping", 1, 55, null, null),
  58. };
  59. private static readonly (string key, string name, decimal kpi)[] StageDef =
  60. {
  61. ("order_review", "订单评审", 5m),
  62. ("product_design", "产品设计", 3m),
  63. ("material_procurement", "材料采购", 14m),
  64. ("body_production", "本体生产", 6m),
  65. ("final_assembly_shipping", "总装发货", 3m),
  66. };
  67. public static IEnumerable<AdoDemoOrderFlow> BuildOrders()
  68. {
  69. foreach (var spec in Specs)
  70. {
  71. var lifecycle = BuildLifecycleValues(spec);
  72. var release = new DateTime(2026, 4, 15, 9, 0, 0);
  73. var lastEnd = lifecycle.Last().actualEnd;
  74. var targetCycle = StageDef.Sum(s => s.kpi);
  75. decimal? currentCycleDays = null;
  76. decimal? actualCycleDays = null;
  77. if (spec.WorkflowStatus == "completed" && lastEnd.HasValue)
  78. {
  79. var days = decimal.Round((decimal)(lastEnd.Value - release).TotalDays, 1);
  80. currentCycleDays = days;
  81. actualCycleDays = days;
  82. }
  83. var currentStage = lifecycle.FirstOrDefault(x => x.key == spec.CurrentNodeKey);
  84. var nodeStatus = currentStage.status switch
  85. {
  86. "red" => "red",
  87. "yellow" => "yellow",
  88. "pending" => "yellow",
  89. _ => "green",
  90. };
  91. yield return new AdoDemoOrderFlow
  92. {
  93. Id = OrderIdBase + spec.Idx,
  94. SoNo = spec.SoNo,
  95. ProductName = spec.ProductName,
  96. ProductLine = spec.ProductLine,
  97. CustomerName = spec.CustomerName,
  98. CustomerCode = spec.CustomerCode,
  99. CustomerType = spec.CustomerType,
  100. Region = spec.Region,
  101. Priority = spec.Priority,
  102. MaterialCode = spec.MaterialCode,
  103. SupplierGroup = spec.SupplierGroup,
  104. WorkflowStatus = spec.WorkflowStatus,
  105. CurrentNodeKey = spec.CurrentNodeKey,
  106. FocusNodeKey = spec.FocusNodeKey,
  107. CurrentNodeLabel = NameOf(spec.CurrentNodeKey),
  108. NodeStatus = nodeStatus,
  109. ReleaseAt = release,
  110. TargetCycleDays = targetCycle,
  111. CurrentCycleDays = currentCycleDays,
  112. ActualCycleDays = actualCycleDays,
  113. NodeVarianceDays = currentStage.nodeVar,
  114. CumulativeVarianceDays = currentStage.cumVar,
  115. ExceptionCount = spec.ExceptionCount,
  116. ResponseMinutes = spec.ResponseMinutes,
  117. ProcessingMinutes = spec.ProcessingMinutes,
  118. TotalLossMinutes = spec.TotalLossMinutes,
  119. ExceptionStatus = spec.WorkflowStatus == "completed" ? "已闭环" : "处理中",
  120. SortNo = spec.Idx,
  121. TenantId = 0,
  122. FactoryId = 0,
  123. CreatedAt = CreatedAt,
  124. UpdatedAt = null,
  125. IsDeleted = false,
  126. };
  127. }
  128. }
  129. public static IEnumerable<AdoDemoOrderFlowStage> BuildStages()
  130. {
  131. long stageSeq = 0;
  132. foreach (var spec in Specs)
  133. {
  134. var orderId = OrderIdBase + spec.Idx;
  135. var lifecycle = BuildLifecycleValues(spec);
  136. for (var i = 0; i < lifecycle.Length; i++)
  137. {
  138. var s = lifecycle[i];
  139. yield return new AdoDemoOrderFlowStage
  140. {
  141. Id = StageIdBase + (++stageSeq),
  142. OrderId = orderId,
  143. StageKey = s.key,
  144. StageName = s.name,
  145. SortNo = i + 1,
  146. PlannedDays = s.kpi,
  147. ActualDays = s.actualDays,
  148. ExpectedDate = s.expected.Date,
  149. ActualStartAt = s.actualStart,
  150. ActualEndAt = s.actualEnd,
  151. Status = s.status,
  152. NodeVarianceDays = s.nodeVar,
  153. CumulativeVarianceDays = s.cumVar,
  154. TenantId = 0,
  155. FactoryId = 0,
  156. CreatedAt = CreatedAt,
  157. UpdatedAt = null,
  158. IsDeleted = false,
  159. };
  160. }
  161. }
  162. }
  163. public static IEnumerable<AdoDemoOrderFlowSnapshot> BuildSnapshot()
  164. {
  165. const string stageJson = """
  166. [
  167. {"stageKey":"order_review","stageName":"订单评审","ownerDept":"市场部","kpiAvgDays":5.0,"actualAvgDays":6.2,"onTimeRate":59,"green":62,"yellow":19,"red":24,"pending":0},
  168. {"stageKey":"product_design","stageName":"产品设计","ownerDept":"研发中心","kpiAvgDays":3.0,"actualAvgDays":2.6,"onTimeRate":96,"green":99,"yellow":2,"red":2,"pending":2},
  169. {"stageKey":"material_procurement","stageName":"材料采购","ownerDept":"供应链部","kpiAvgDays":14.0,"actualAvgDays":15.5,"onTimeRate":85,"green":86,"yellow":1,"red":14,"pending":4},
  170. {"stageKey":"body_production","stageName":"本体生产","ownerDept":"生产部","kpiAvgDays":6.0,"actualAvgDays":6.7,"onTimeRate":89,"green":87,"yellow":2,"red":9,"pending":7},
  171. {"stageKey":"final_assembly_shipping","stageName":"总装发货","ownerDept":"生产部","kpiAvgDays":3.0,"actualAvgDays":2.9,"onTimeRate":96,"green":92,"yellow":1,"red":3,"pending":9}
  172. ]
  173. """;
  174. yield return new AdoDemoOrderFlowSnapshot
  175. {
  176. Id = SnapshotIdBase + 1,
  177. SnapshotCode = "CHAIN_AGGREGATE_BASELINE",
  178. SnapshotLabel = "基线聚合 · 样本 105",
  179. TotalOrders = 105,
  180. TotalCustomers = 5,
  181. AvgResponseMinutes = 91.20m,
  182. AvgProcessingMinutes = 1060.50m,
  183. AvgLossMinutes = 1472.50m,
  184. StageSnapshotsJson = stageJson.Trim(),
  185. Remark = "演示基线快照,与明细 20 单不一致是预期",
  186. TenantId = 0,
  187. FactoryId = 0,
  188. CreatedAt = CreatedAt,
  189. UpdatedAt = null,
  190. IsDeleted = false,
  191. };
  192. }
  193. private static string NameOf(string key) => StageDef.First(s => s.key == key).name;
  194. private record StageRow(
  195. string key, string name, decimal kpi, decimal actualDays,
  196. DateTime expected, DateTime? actualStart, DateTime? actualEnd,
  197. string status, decimal? nodeVar, decimal? cumVar);
  198. /// <summary>
  199. /// SO-2026-001 严格按 PPT;其余 19 单按 spec.FocusNodeKey 套模板。
  200. /// </summary>
  201. private static StageRow[] BuildLifecycleValues(OrderSpec spec)
  202. {
  203. if (spec.SoNo == "SO-2026-001") return BuildSo001Lifecycle();
  204. // 模板:默认每阶段 actualDays=KPI, nodeVar=0, status=green;
  205. // 焦点阶段按一份固定偏差替换;total 5 阶段连续日期。
  206. var release = new DateTime(2026, 4, 15, 9, 0, 0);
  207. var (focusNodeVar, focusActual) = spec.FocusNodeKey switch
  208. {
  209. "order_review" => (+2m, 7m),
  210. "product_design" => (+2m, 5m),
  211. "material_procurement" => (+2m, 16m),
  212. "body_production" => (+2m, 8m),
  213. "final_assembly_shipping" => (+1m, 4m),
  214. _ => (0m, 0m),
  215. };
  216. var focusStatus = spec.FocusNodeKey switch
  217. {
  218. "order_review" => "red",
  219. "product_design" => "red",
  220. "material_procurement" => "yellow",
  221. "body_production" => "yellow",
  222. "final_assembly_shipping" => "yellow",
  223. _ => "green",
  224. };
  225. var rows = new StageRow[5];
  226. var cumVar = 0m;
  227. var cursor = release;
  228. for (var i = 0; i < 5; i++)
  229. {
  230. var (key, name, kpi) = StageDef[i];
  231. decimal actualDays = kpi;
  232. decimal nodeVar = 0;
  233. string status = "green";
  234. if (key == spec.FocusNodeKey)
  235. {
  236. actualDays = focusActual;
  237. nodeVar = focusNodeVar;
  238. status = focusStatus;
  239. }
  240. cumVar += nodeVar;
  241. DateTime? actualStart = null;
  242. DateTime? actualEnd = null;
  243. string currentNodeKey = spec.CurrentNodeKey;
  244. int currentNodeIdx = Array.FindIndex(StageDef, s => s.key == currentNodeKey);
  245. // in_progress 单:当前节点之前 actualEnd 都填;当前节点仅 actualStart;之后阶段都为 null
  246. if (spec.WorkflowStatus == "completed" || i < currentNodeIdx)
  247. {
  248. actualStart = cursor;
  249. actualEnd = cursor.AddDays((double)actualDays);
  250. cursor = actualEnd.Value;
  251. }
  252. else if (i == currentNodeIdx)
  253. {
  254. actualStart = cursor;
  255. actualEnd = null;
  256. actualDays = 0; // 仍未完成
  257. status = "pending";
  258. nodeVar = 0;
  259. cumVar = (i == 0) ? 0m : rows[i - 1].cumVar ?? 0m;
  260. }
  261. else
  262. {
  263. actualStart = null;
  264. actualEnd = null;
  265. actualDays = 0;
  266. status = "pending";
  267. nodeVar = 0;
  268. }
  269. DateTime expected = release.AddDays((double)StageDef.Take(i + 1).Sum(s => s.kpi));
  270. rows[i] = new StageRow(
  271. key, name, kpi,
  272. actualDays,
  273. expected,
  274. actualStart,
  275. actualEnd,
  276. status,
  277. status == "pending" ? null : nodeVar,
  278. status == "pending" ? null : cumVar);
  279. }
  280. return rows;
  281. }
  282. /// <summary>SO-2026-001 PPT 第 1 页 hard-coded 真值(不可改)。</summary>
  283. private static StageRow[] BuildSo001Lifecycle()
  284. {
  285. DateTime D(int m, int d, int h, int mi) => new(2026, m, d, h, mi, 0);
  286. return new[]
  287. {
  288. new StageRow("order_review", "订单评审", 5m, 5m, new DateTime(2026, 4, 20), D(4, 15, 9, 0), D(4, 20, 15, 0), "green", 0m, 0m),
  289. new StageRow("product_design", "产品设计", 3m, 5m, new DateTime(2026, 4, 23), D(4, 20, 15, 0), D(4, 25, 10, 0), "red", +2m, +2m),
  290. new StageRow("material_procurement", "材料采购", 14m, 13m, new DateTime(2026, 5, 6), D(4, 25, 10, 0), D(5, 7, 14, 0), "yellow",-1m, +1m),
  291. new StageRow("body_production", "本体生产", 6m, 5m, new DateTime(2026, 5, 12), D(5, 7, 14, 0), D(5, 12, 18, 0), "green", -1m, 0m),
  292. new StageRow("final_assembly_shipping", "总装发货", 3m, 3m, new DateTime(2026, 5, 15), D(5, 12, 18, 0), D(5, 15, 10, 0), "green", 0m, 0m),
  293. };
  294. }
  295. }