| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- namespace Admin.NET.Plugin.AiDOP.SmartOps;
- public sealed class S1KpiDailySnapshotRow
- {
- public string MetricCode { get; set; } = string.Empty;
- public DateTime BizDate { get; set; }
- public decimal? MetricValue { get; set; }
- }
- public interface IS1KpiDailySnapshotStore
- {
- Task ExecuteInTransactionAsync(Func<Task> action, CancellationToken ct = default);
- Task<DateTime?> GetMaxBizDateAsync(int level, long tenantId, long factoryId, string moduleCode, CancellationToken ct = default);
- Task<List<S1KpiDailySnapshotRow>> ListLatestAsync(int level, long tenantId, long factoryId, DateTime bizDate, string moduleCode, CancellationToken ct = default);
- Task<int> UpdateTargetsAsync(
- int level,
- long tenantId,
- long factoryId,
- DateTime bizDate,
- string metricCode,
- KpiTargetSnapshot snap,
- string moduleCode,
- CancellationToken ct = default);
- }
- public sealed class S1KpiTargetSnapshotLevelResult
- {
- public int Level { get; set; }
- public string? BizDate { get; set; }
- public int UpdatedRows { get; set; }
- public int MissingRows { get; set; }
- }
- public sealed class S1KpiTargetSnapshotRefreshResult
- {
- public bool Ok { get; set; } = true;
- public string ModuleCode { get; set; } = "S1";
- public long FactoryId { get; set; }
- public int UpdatedRows { get; set; }
- public int MissingRows { get; set; }
- public List<S1KpiTargetSnapshotLevelResult> Levels { get; set; } = new();
- public int ElapsedMs { get; set; }
- public string Message { get; set; } = string.Empty;
- }
- public sealed class S1KpiTargetSnapshotRefreshService : ITransient
- {
- public const string ModuleCode = "S1";
- private readonly IS1KpiDailySnapshotStore _store;
- private readonly IKpiTargetResolver _resolver;
- public S1KpiTargetSnapshotRefreshService(IS1KpiDailySnapshotStore store, IKpiTargetResolver resolver)
- {
- _store = store;
- _resolver = resolver;
- }
- public async Task<S1KpiTargetSnapshotRefreshResult> RefreshAsync(long tenantId, long factoryId, CancellationToken ct = default) =>
- await RefreshAsync(ModuleCode, tenantId, factoryId, ct);
- public async Task<S1KpiTargetSnapshotRefreshResult> RefreshAsync(string moduleCode, long tenantId, long factoryId, CancellationToken ct = default)
- {
- var mc = string.IsNullOrWhiteSpace(moduleCode) ? ModuleCode : moduleCode.Trim().ToUpperInvariant();
- if (factoryId <= 0)
- throw new ArgumentOutOfRangeException(nameof(factoryId), "工厂必须大于 0");
- if (tenantId <= 0)
- throw new ArgumentOutOfRangeException(nameof(tenantId), "租户无效");
- var started = DateTime.Now;
- var result = new S1KpiTargetSnapshotRefreshResult { FactoryId = factoryId, ModuleCode = mc };
- await _store.ExecuteInTransactionAsync(async () =>
- {
- for (var level = 1; level <= 4; level++)
- {
- ct.ThrowIfCancellationRequested();
- var levelResult = await RefreshLevelAsync(mc, level, tenantId, factoryId, ct);
- result.Levels.Add(levelResult);
- result.UpdatedRows += levelResult.UpdatedRows;
- result.MissingRows += levelResult.MissingRows;
- }
- }, ct);
- result.ElapsedMs = (int)(DateTime.Now - started).TotalMilliseconds;
- result.Message = result.UpdatedRows == 0 && result.Levels.All(x => x.BizDate == null)
- ? $"{mc} 暂无可刷新的日值快照"
- : $"{mc} 看板目标快照已刷新";
- return result;
- }
- private async Task<S1KpiTargetSnapshotLevelResult> RefreshLevelAsync(string moduleCode, int level, long tenantId, long factoryId, CancellationToken ct)
- {
- var maxDate = await _store.GetMaxBizDateAsync(level, tenantId, factoryId, moduleCode, ct);
- var levelResult = new S1KpiTargetSnapshotLevelResult { Level = level };
- if (maxDate == null)
- return levelResult;
- var bizDate = maxDate.Value.Date;
- levelResult.BizDate = bizDate.ToString("yyyy-MM-dd");
- var rows = await _store.ListLatestAsync(level, tenantId, factoryId, bizDate, moduleCode, ct);
- foreach (var group in rows.GroupBy(x => x.MetricCode, StringComparer.OrdinalIgnoreCase))
- {
- ct.ThrowIfCancellationRequested();
- var snap = await _resolver.ResolveAsync(tenantId, factoryId, group.Key, moduleCode, bizDate, ct);
- if (snap.TargetSource == KpiTargetSnapshotSource.Missing || snap.TargetValue is null or <= 0)
- {
- levelResult.MissingRows += group.Count();
- continue;
- }
- var updated = await _store.UpdateTargetsAsync(level, tenantId, factoryId, bizDate, group.Key, snap, moduleCode, ct);
- levelResult.UpdatedRows += updated;
- }
- return levelResult;
- }
- }
|