| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- using Admin.NET.Plugin.AiDOP.Dto.SmartOps;
- namespace Admin.NET.Plugin.AiDOP.SmartOps;
- public sealed class KpiTargetMigrationPreviewDto
- {
- public List<KpiTargetCreateDto> WillCreate { get; set; } = new();
- public List<string> Skipped { get; set; } = new();
- public List<string> Conflicts { get; set; } = new();
- public List<string> Missing { get; set; } = new();
- public List<string> DemoSuspect { get; set; } = new();
- }
- public sealed class KpiTargetMigrationService : ITransient
- {
- private readonly ISqlSugarClient _db;
- private readonly IKpiTargetConfigStore _store;
- private readonly KpiTargetService _targets;
- private readonly UserManager _userManager;
- public KpiTargetMigrationService(
- ISqlSugarClient db,
- IKpiTargetConfigStore store,
- KpiTargetService targets,
- UserManager userManager)
- {
- _db = db;
- _store = store;
- _targets = targets;
- _userManager = userManager;
- }
- public async Task<KpiTargetMigrationPreviewDto> PreviewAsync(CancellationToken ct = default)
- {
- var tenantId = AidopTenantScope.ResolveOrThrow(_userManager);
- return await BuildAsync(tenantId, commit: false, ct);
- }
- public async Task<KpiTargetMigrationPreviewDto> CommitAsync(CancellationToken ct = default)
- {
- var tenantId = AidopTenantScope.ResolveOrThrow(_userManager);
- return await BuildAsync(tenantId, commit: true, ct);
- }
- private async Task<KpiTargetMigrationPreviewDto> BuildAsync(long tenantId, bool commit, CancellationToken ct)
- {
- var result = new KpiTargetMigrationPreviewDto();
- var rows = await _db.Ado.SqlQueryAsync<LegacyHit>(
- """
- SELECT factory_id AS FactoryId, metric_code AS MetricCode, module_code AS ModuleCode,
- target_value AS TargetValue, biz_date AS BizDate, target_source AS TargetSource
- FROM ado_s9_kpi_value_l1_day
- WHERE tenant_id=@TenantId AND is_deleted=0 AND target_value IS NOT NULL AND target_value>0
- ORDER BY metric_code, factory_id, biz_date DESC, id DESC
- """,
- new SugarParameter("@TenantId", tenantId));
- var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
- foreach (var row in rows)
- {
- var key = $"{row.FactoryId}|{row.MetricCode}";
- if (!seen.Add(key))
- continue;
- if (string.Equals(row.TargetSource, KpiTargetSnapshotSource.DemoImport, StringComparison.OrdinalIgnoreCase))
- {
- result.DemoSuspect.Add($"{row.MetricCode} factory={row.FactoryId}");
- continue;
- }
- var existing = await _store.ListActiveScopeAsync(tenantId, row.FactoryId, row.MetricCode, ct);
- if (existing.Count > 0)
- {
- result.Skipped.Add($"{row.MetricCode} factory={row.FactoryId}");
- continue;
- }
- var dto = new KpiTargetCreateDto
- {
- MetricCode = row.MetricCode,
- FactoryId = row.FactoryId,
- TargetValue = row.TargetValue,
- EffectiveFrom = DateTime.Today,
- ClosePrevious = false,
- Remark = $"LEGACY_MIGRATION from {row.BizDate:yyyy-MM-dd}"
- };
- result.WillCreate.Add(dto);
- if (!commit)
- continue;
- try
- {
- await _targets.CreateCoreAsync(tenantId, dto, KpiTargetConfigSource.LegacyMigration, null, _userManager.UserId, ct);
- }
- catch (KpiTargetConflictException ex)
- {
- result.Conflicts.Add($"{row.MetricCode}: {ex.Message}");
- }
- }
- var masters = await _db.Queryable<Entity.AdoSmartOpsKpiMaster>()
- .ClearFilter<ITenantIdFilter>()
- .Where(x => x.TenantId == tenantId && x.IsEnabled)
- .ToListAsync(ct);
- var createdKeys = result.WillCreate.Select(x => x.MetricCode).ToHashSet(StringComparer.OrdinalIgnoreCase);
- foreach (var m in masters)
- {
- if (createdKeys.Contains(m.MetricCode) || seen.Contains($"1|{m.MetricCode}") || seen.Contains($"0|{m.MetricCode}"))
- continue;
- result.Missing.Add($"{m.ModuleCode}:{m.MetricCode}");
- }
- return result;
- }
- private sealed class LegacyHit
- {
- public long FactoryId { get; set; }
- public string MetricCode { get; set; } = string.Empty;
- public string ModuleCode { get; set; } = string.Empty;
- public decimal TargetValue { get; set; }
- public DateTime BizDate { get; set; }
- public string? TargetSource { get; set; }
- }
- }
|