KpiTargetResolver.cs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. using Admin.NET.Plugin.AiDOP.Entity;
  2. using Microsoft.Extensions.Logging;
  3. namespace Admin.NET.Plugin.AiDOP.SmartOps;
  4. public sealed class KpiTargetResolver : IKpiTargetResolver, ITransient
  5. {
  6. private readonly IKpiTargetConfigStore _store;
  7. private readonly ILegacyKpiTargetProvider _legacy;
  8. private readonly ILogger<KpiTargetResolver> _logger;
  9. public KpiTargetResolver(
  10. IKpiTargetConfigStore store,
  11. ILegacyKpiTargetProvider legacy,
  12. ILogger<KpiTargetResolver> logger)
  13. {
  14. _store = store;
  15. _legacy = legacy;
  16. _logger = logger;
  17. }
  18. public async Task<KpiTargetSnapshot> ResolveAsync(
  19. long tenantId,
  20. long factoryId,
  21. string metricCode,
  22. string moduleCode,
  23. DateTime bizDate,
  24. CancellationToken ct = default)
  25. {
  26. var day = bizDate.Date;
  27. var now = DateTime.Now;
  28. var factoryHits = KpiTargetRules.ActiveOn(
  29. await _store.ListActiveScopeAsync(tenantId, factoryId, metricCode, ct),
  30. day);
  31. if (factoryHits.Count > 0)
  32. {
  33. var cfg = KpiTargetRules.PickSingle(factoryHits, $"工厂 {factoryId}/{metricCode}/{day:yyyy-MM-dd}");
  34. return Formal(cfg, KpiTargetSnapshotSource.FormalFactory, now);
  35. }
  36. if (factoryId != 0)
  37. {
  38. var tenantHits = KpiTargetRules.ActiveOn(
  39. await _store.ListActiveScopeAsync(tenantId, 0, metricCode, ct),
  40. day);
  41. if (tenantHits.Count > 0)
  42. {
  43. var cfg = KpiTargetRules.PickSingle(tenantHits, $"租户默认 {metricCode}/{day:yyyy-MM-dd}");
  44. return Formal(cfg, KpiTargetSnapshotSource.FormalTenantDefault, now);
  45. }
  46. }
  47. var legacy = await _legacy.TryResolveLegacyAsync(tenantId, factoryId, metricCode, moduleCode, day, ct);
  48. if (legacy != null && legacy.TargetValue is > 0)
  49. {
  50. _logger.LogWarning(
  51. "KPI 目标走兼容来源 {Source} tenant={TenantId} factory={FactoryId} metric={MetricCode} date={BizDate} value={Value}",
  52. legacy.TargetSource, tenantId, factoryId, metricCode, day, legacy.TargetValue);
  53. return legacy;
  54. }
  55. _logger.LogInformation(
  56. "KPI 目标缺失 tenant={TenantId} factory={FactoryId} metric={MetricCode} date={BizDate}",
  57. tenantId, factoryId, metricCode, day);
  58. return new KpiTargetSnapshot(null, null, KpiTargetSnapshotSource.Missing, now);
  59. }
  60. private static KpiTargetSnapshot Formal(AdoSmartOpsKpiTargetConfig cfg, string source, DateTime now) =>
  61. new(
  62. cfg.TargetValue,
  63. cfg.Id,
  64. source,
  65. now,
  66. DateOnly.FromDateTime(cfg.EffectiveFrom.Date),
  67. cfg.EffectiveTo.HasValue ? DateOnly.FromDateTime(cfg.EffectiveTo.Value.Date) : null);
  68. }