SmartDiagnosisEvidenceService.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using Admin.NET.Plugin.AiDOP.Infrastructure;
  2. using SqlSugar;
  3. namespace Admin.NET.Plugin.AiDOP.SmartOps;
  4. public sealed class SmartDiagnosisEvidenceService : ITransient
  5. {
  6. private readonly ISqlSugarClient _db;
  7. public SmartDiagnosisEvidenceService(ISqlSugarClient db) => _db = db;
  8. public async Task<SmartDiagnosisEvidenceResult> QueryAsync(
  9. long tenantId,
  10. long factoryId,
  11. string moduleCode,
  12. SmartOpsDashboardFilter? filter = null,
  13. int limit = SmartDiagnosisEvidenceRegistry.DefaultLimit)
  14. {
  15. SmartOpsTrustedScopeRules.EnsureBusinessTenant(tenantId);
  16. var cap = Math.Clamp(limit, 1, SmartDiagnosisEvidenceRegistry.MaxLimit);
  17. var sources = SmartDiagnosisEvidenceRegistry.Resolve(moduleCode);
  18. var result = new SmartDiagnosisEvidenceResult
  19. {
  20. AsOf = DateTime.Today.ToString("yyyy-MM-dd"),
  21. Domain = string.Join(",", sources.Select(x => x.Domain.ToString()).Distinct()),
  22. };
  23. if (sources.Count == 0)
  24. {
  25. result.Scope = "unsupported";
  26. return result;
  27. }
  28. var items = new List<SmartDiagnosisEvidenceItem>();
  29. var total = 0;
  30. foreach (var source in sources)
  31. {
  32. var (sourceTotal, sourceItems) = await QuerySourceAsync(source, tenantId, factoryId, filter, cap);
  33. total += sourceTotal;
  34. result.Sources.Add(source.Key);
  35. items.AddRange(sourceItems);
  36. }
  37. result.Total = total;
  38. result.Items = items
  39. .OrderByDescending(x => Severity(x.Status))
  40. .ThenByDescending(x => x.Contribution ?? 0)
  41. .Take(cap)
  42. .ToList();
  43. result.Returned = result.Items.Count;
  44. result.Truncated = total > result.Returned;
  45. result.Scope = result.Returned == 0 ? "no_data" : "filtered_atomic";
  46. return result;
  47. }
  48. private async Task<(int Total, List<SmartDiagnosisEvidenceItem> Items)> QuerySourceAsync(
  49. SmartDiagnosisEvidenceSource source,
  50. long tenantId,
  51. long factoryId,
  52. SmartOpsDashboardFilter? filter,
  53. int limit)
  54. {
  55. var parameters = new List<SugarParameter>
  56. {
  57. new("@tenantId", tenantId),
  58. new("@factoryId", factoryId),
  59. new("@limit", limit),
  60. };
  61. var extraWhere = BuildFilterSql(source, filter, parameters);
  62. var countSql = InjectWhere(source.CountSql, extraWhere);
  63. var itemSql = InjectWhere(source.ItemSql, extraWhere);
  64. var total = await _db.Ado.GetIntAsync(countSql, parameters.ToArray());
  65. if (total <= 0)
  66. return (0, new List<SmartDiagnosisEvidenceItem>());
  67. var rows = await _db.Ado.SqlQueryAsync<SmartDiagnosisEvidenceSqlRow>(itemSql, parameters.ToArray());
  68. var items = rows.Select(row => new SmartDiagnosisEvidenceItem
  69. {
  70. ObjectType = source.ObjectType,
  71. ObjectCode = row.ObjectCode ?? "",
  72. Title = string.IsNullOrWhiteSpace(row.Title) ? row.ObjectCode ?? source.Key : row.Title,
  73. Contribution = row.Contribution,
  74. ContributionUnit = source.Domain == SmartDiagnosisEvidenceDomain.Quality ? "qty" : "qty",
  75. Status = string.IsNullOrWhiteSpace(row.Status) ? "green" : row.Status,
  76. OccurredAt = row.OccurredAt?.ToString("yyyy-MM-dd"),
  77. DrillPath = source.DrillPath,
  78. }).ToList();
  79. return (total, items);
  80. }
  81. private static string BuildFilterSql(
  82. SmartDiagnosisEvidenceSource source,
  83. SmartOpsDashboardFilter? filter,
  84. List<SugarParameter> parameters)
  85. {
  86. if (filter == null) return "";
  87. var values = filter.ToContextDictionary();
  88. var clauses = new List<string>();
  89. foreach (var map in source.Filters)
  90. {
  91. if (!values.TryGetValue(map.QueryKey, out var raw) || string.IsNullOrWhiteSpace(raw))
  92. continue;
  93. var param = "@f_" + map.QueryKey;
  94. clauses.Add($"{map.SqlColumn} = {param}");
  95. parameters.Add(new SugarParameter(param, raw.Trim()));
  96. }
  97. return clauses.Count == 0 ? "" : " AND " + string.Join(" AND ", clauses);
  98. }
  99. private static string InjectWhere(string sql, string extraWhere)
  100. {
  101. if (string.IsNullOrWhiteSpace(extraWhere)) return sql;
  102. var orderAt = sql.LastIndexOf("ORDER BY", StringComparison.OrdinalIgnoreCase);
  103. if (orderAt < 0)
  104. return sql + extraWhere;
  105. return sql[..orderAt] + extraWhere + " " + sql[orderAt..];
  106. }
  107. private static int Severity(string? status) => (status ?? "").ToLowerInvariant() switch
  108. {
  109. "red" => 3,
  110. "yellow" => 2,
  111. _ => 1
  112. };
  113. }