MissingKpiPipelineContractTests.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. using Xunit;
  2. namespace Admin.NET.Plugin.AiDOP.Tests.SmartOps;
  3. public class MissingKpiPipelineContractTests
  4. {
  5. [Fact]
  6. public void S2AndS4Pipelines_BackfillFourteenDayTrends()
  7. {
  8. var s2 = ReadSource("Production", "S2MdpSyncTransformService.cs");
  9. var s4 = ReadSource("ProcurementExecution", "S4MdpSyncTransformService.cs");
  10. Assert.Contains("for (var dayOffset = 13; dayOffset >= 0; dayOffset--)", s2);
  11. Assert.Contains("for (var dayOffset = 13; dayOffset >= 0; dayOffset--)", s4);
  12. Assert.Contains("YitIdHelper.NextId()", s2);
  13. Assert.Contains("YitIdHelper.NextId()", s4);
  14. Assert.Contains("factoryId: _runScope.FactoryId", s4);
  15. Assert.DoesNotContain("SELECT COALESCE(MAX(id), 0) + 1", s2);
  16. Assert.DoesNotContain("SELECT COALESCE(MAX(id), 0) + 1", s4);
  17. }
  18. [Fact]
  19. public void S3MaterialTurnover_UsesTenantScopedInboundAndIssueFacts()
  20. {
  21. var source = ReadSource("Supply", "S3MdpSyncTransformService.cs");
  22. Assert.Contains("MetricCode = \"S3_L1_004\"", source);
  23. Assert.Contains("h.tenant_id=@TenantId", source);
  24. Assert.Contains("h.lbs IN ('采购入库','生产领料')", source);
  25. Assert.Contains("NULLIF(SUM(issue_qty), 0)", source);
  26. Assert.Contains("'S3_L2_001' AS MetricCode", source);
  27. Assert.Contains("'S3_L2_006' AS MetricCode", source);
  28. Assert.Contains("p.gw='计划'", source);
  29. Assert.Contains("for (var dayOffset = 13; dayOffset >= 0; dayOffset--)", source);
  30. Assert.Contains("GlobalRunGate.WaitAsync", source);
  31. Assert.Contains("GlobalRunGate.Release", source);
  32. }
  33. [Fact]
  34. public void S9QualityReturnRate_UsesS7BusinessTransactionsAndPpmScale()
  35. {
  36. var source = ReadSource("FinishedWarehouse", "S7MdpSyncTransformService.cs");
  37. Assert.Contains("result.MergeSub(\"S9_L1_001\"", source);
  38. Assert.Contains("h.lbs IN ('销售退货','销售出库')", source);
  39. Assert.Contains("* 1_000_000m", source);
  40. Assert.Contains("option, \"S9\")", source);
  41. }
  42. [Fact]
  43. public void GenericDashboard_UsesLatestValuePerMetric()
  44. {
  45. var source = ReadSource("Controllers", "AidopKanbanController.Generic.cs");
  46. Assert.Contains("v2.metric_code=v.metric_code", source);
  47. Assert.DoesNotContain("is_deleted=0 AND biz_date=@d", source);
  48. }
  49. [Fact]
  50. public void MonthlyKpis_CarryForwardLatestWhenDateFilterHasNoValue()
  51. {
  52. var source = ReadSource("Controllers", "AidopKanbanController.SmartOpsFilter.cs");
  53. Assert.Contains("MonthlyCarryForwardMetricCodes", source);
  54. Assert.Contains("\"S5_L1_003\"", source);
  55. Assert.Contains("\"S6_L1_003\"", source);
  56. Assert.Contains("\"S6_L2_003\"", source);
  57. Assert.Contains("\"S7_L1_003\"", source);
  58. Assert.Contains("\"S9_L1_001\"", source);
  59. Assert.Contains("monthly_latest", source);
  60. Assert.Contains("HasBusinessDimension", source);
  61. Assert.Contains("SuppressUnfilteredValuesWhenBusinessFilter", source);
  62. Assert.Contains("IsAuthoritativeFilteredMode", source);
  63. }
  64. [Fact]
  65. public void S5StageKpis_UseReceiptAndIqcFacts()
  66. {
  67. var source = ReadSource("MaterialWarehouse", "S5MdpSyncTransformService.cs");
  68. Assert.Contains("result.MergeSub(\"S5_L2_001\"", source);
  69. Assert.Contains("result.MergeSub(\"S5_L2_003\"", source);
  70. Assert.Contains("source_table='PurOrdRctMaster'", source);
  71. Assert.Contains("STR_TO_DATE(NULLIF(JSON_UNQUOTE(JSON_EXTRACT(raw_data,'$.PerformDate'))", source);
  72. Assert.Contains("FINSPESTARTDATE", source);
  73. Assert.Contains("ado_s9_kpi_value_l2_day", source);
  74. Assert.Contains("\"S5_L2_015\"", source);
  75. Assert.Contains("\"S5_L3_005\"", source);
  76. Assert.Contains("mdp_std_inv_trans", source);
  77. Assert.Contains("_purchaseReceiptMdpSync.RunInboundAsync", source);
  78. Assert.Contains("const int backfillDays = 14", source);
  79. Assert.Contains("warehouseFallback", source);
  80. Assert.DoesNotContain("COPY_PARENT_VALUE", source);
  81. }
  82. [Fact]
  83. public void S6WorkOrderCycle_GroupsByWorkOrderNotOrder()
  84. {
  85. var source = ReadSource("Manufacturing", "S6MdpSyncTransformService.cs");
  86. Assert.Contains("result.MergeSub(\"S6_L2_001\"", source);
  87. Assert.Contains("group by rwnoid", source);
  88. Assert.Contains("NO_COMPLETED_WORK_ORDER", source);
  89. Assert.Contains("L2ValueTable", source);
  90. Assert.Contains("\"S6_L2_004\"", source);
  91. Assert.Contains("\"S6_L3_007\"", source);
  92. Assert.Contains("WorkOrdRouting", source);
  93. Assert.Contains("OpTransEmployee", source);
  94. Assert.Contains("const int backfillDays = 14", source);
  95. }
  96. [Fact]
  97. public void S7StageKpis_UseFqcShipmentAndInventoryFacts()
  98. {
  99. var source = ReadSource("FinishedWarehouse", "S7MdpSyncTransformService.cs");
  100. Assert.Contains("Enumerable.Range(1, 16)", source);
  101. Assert.Contains("FROM qms_fqcbj q", source);
  102. Assert.Contains("mdp_std_inv_trans", source);
  103. Assert.Contains("\"S7_L2_016\"", source);
  104. Assert.Contains("L2ValueTable", source);
  105. Assert.Contains("const int backfillDays = 14", source);
  106. Assert.Contains("result.MergeSub(\"S9_L1_001\"", source);
  107. }
  108. [Fact]
  109. public void S1ProcessAndDeliveryReviewBranches_UseDistinctBusinessFlows()
  110. {
  111. var source = ReadSource("Order", "S1MdpSyncTransformService.cs");
  112. Assert.Contains("'S1_L2_007' AS MetricCode", source);
  113. Assert.Contains("LIKE 'UAT-PROC-%'", source);
  114. Assert.Contains("LIKE 'UAT-DEL-%'", source);
  115. Assert.Contains("CONCAT('S1_L3_',branch_code", source);
  116. Assert.Contains("CONCAT('S1_L4_',branch_code", source);
  117. Assert.Contains("for (var dayOffset = 13; dayOffset >= 0; dayOffset--)", source);
  118. }
  119. [Fact]
  120. public void S8Snapshot_RefreshesFourteenDayTrendThroughFormalAggregator()
  121. {
  122. var source = ReadSource("Service/S8", "S8KpiSnapshotService.cs");
  123. Assert.Contains("for (var dayOffset = 13; dayOffset >= 0; dayOffset--)", source);
  124. Assert.Contains("RefreshAsync(", source);
  125. Assert.Contains("_kpiTargetResolver.ResolveAsync", source);
  126. }
  127. [Fact]
  128. public void ModuleRebuildWorker_RechecksStaleJobsWhileRunning()
  129. {
  130. var source = ReadSource("DataPlatform/MdpRebuild", "ModuleRebuildWorker.cs");
  131. Assert.Contains("StaleSweepInterval", source);
  132. Assert.Contains("DateTimeOffset.UtcNow >= nextStaleSweepAt", source);
  133. Assert.Contains("await FailStaleAsync(stoppingToken)", source);
  134. }
  135. [Fact]
  136. public void S8Snapshot_UsesExceptionTableAndKeepsNullTimeliness()
  137. {
  138. var source = ReadSource("Service/S8", "S8KpiSnapshotService.cs");
  139. Assert.Contains("FROM ado_s8_exception", source);
  140. Assert.Contains("S8_L1_001", source);
  141. Assert.Contains("S8_L1_002", source);
  142. Assert.Contains("avgHours > 0 ? avgHours : null", source);
  143. Assert.DoesNotContain("metric_value=0", source);
  144. }
  145. private static string ReadSource(string folder, string fileName)
  146. {
  147. var dir = new DirectoryInfo(AppContext.BaseDirectory);
  148. while (dir != null)
  149. {
  150. var candidate = Path.Combine(
  151. dir.FullName,
  152. "server",
  153. "Plugins",
  154. "Admin.NET.Plugin.AiDOP",
  155. folder,
  156. fileName);
  157. if (File.Exists(candidate)) return File.ReadAllText(candidate);
  158. dir = dir.Parent;
  159. }
  160. throw new FileNotFoundException(fileName);
  161. }
  162. }