|
|
@@ -295,6 +295,69 @@ public sealed class AdoSmartOpsKpiDimensionConfigService : ITransient
|
|
|
return cap;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// 维度明细只读查询(当前生效维度版本):按 AggregationType 复算聚合值 + 分页明细。
|
|
|
+ /// 只读当前激活配置产生的维度结果,绝不读旧 Atomic。无激活配置 → NOT_CONFIGURED。
|
|
|
+ /// </summary>
|
|
|
+ public async Task<KpiDimensionDetailResultDto> QueryDetailAsync(
|
|
|
+ string metricCode, string moduleCode, DateTime? startDate, DateTime? endDate,
|
|
|
+ string? dimensionType, string? dimensionCode, int page, int pageSize)
|
|
|
+ {
|
|
|
+ var tenantId = AdoSmartOpsKpiCalcConfigService.ResolveKpiTenantId(moduleCode);
|
|
|
+ var active = await GetActiveAsync(tenantId, metricCode);
|
|
|
+ var result = new KpiDimensionDetailResultDto { MetricCode = metricCode };
|
|
|
+ if (active == null)
|
|
|
+ {
|
|
|
+ result.Status = "NOT_CONFIGURED";
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ result.SummaryConfigVersion = active.SummaryConfigVersion;
|
|
|
+ result.DimensionConfigVersion = active.DimensionConfigVersion;
|
|
|
+ result.AggregationType = active.AggregationType;
|
|
|
+
|
|
|
+ var sd = startDate?.Date;
|
|
|
+ var ed = endDate?.Date;
|
|
|
+ ISugarQueryable<AdoSmartOpsKpiDimensionValueDay> Build() =>
|
|
|
+ _db.Queryable<AdoSmartOpsKpiDimensionValueDay>().ClearFilter<ITenantIdFilter>()
|
|
|
+ .Where(x => x.TenantId == tenantId && x.MetricCode == metricCode
|
|
|
+ && x.DimensionConfigVersion == active.DimensionConfigVersion)
|
|
|
+ .WhereIF(sd.HasValue, x => x.ValueDate >= sd!.Value)
|
|
|
+ .WhereIF(ed.HasValue, x => x.ValueDate <= ed!.Value)
|
|
|
+ .WhereIF(!string.IsNullOrWhiteSpace(dimensionType), x => x.DimensionType == dimensionType)
|
|
|
+ .WhereIF(!string.IsNullOrWhiteSpace(dimensionCode), x => x.DimensionCode == dimensionCode);
|
|
|
+
|
|
|
+ result.AggregateValue = active.AggregationType switch
|
|
|
+ {
|
|
|
+ "AVERAGE_OF_SUMS" => Div(await Build().SumAsync(x => x.SumValue), (decimal?)await Build().SumAsync(x => x.SampleCount)),
|
|
|
+ "RATIO_OF_SUMS" => Div(await Build().SumAsync(x => x.Numerator), await Build().SumAsync(x => x.Denominator)),
|
|
|
+ "DIRECT_VALUE" => await Build().AvgAsync(x => x.MetricValue),
|
|
|
+ _ => null,
|
|
|
+ };
|
|
|
+
|
|
|
+ RefAsync<int> total = 0;
|
|
|
+ var list = await Build().OrderBy(x => x.ValueDate, OrderByType.Desc).OrderBy(x => x.DimensionCode)
|
|
|
+ .ToPageListAsync(page <= 0 ? 1 : page, pageSize <= 0 ? 20 : pageSize, total);
|
|
|
+ result.Total = total.Value;
|
|
|
+ result.List = list.Select(x => new KpiDimensionDetailRowDto
|
|
|
+ {
|
|
|
+ ValueDate = x.ValueDate.ToString("yyyy-MM-dd"),
|
|
|
+ DimensionType = x.DimensionType,
|
|
|
+ DimensionCode = x.DimensionCode,
|
|
|
+ DimensionName = x.DimensionName,
|
|
|
+ MetricValue = x.MetricValue,
|
|
|
+ Numerator = x.Numerator,
|
|
|
+ Denominator = x.Denominator,
|
|
|
+ SumValue = x.SumValue,
|
|
|
+ SampleCount = x.SampleCount,
|
|
|
+ SourceKey = x.SourceKey,
|
|
|
+ BatchId = x.BatchId,
|
|
|
+ }).ToList();
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static decimal? Div(decimal? a, decimal? b) =>
|
|
|
+ b.HasValue && b.Value != 0 ? (a ?? 0m) / b.Value : null;
|
|
|
+
|
|
|
/// <summary>已登记数据源列表(第一版仅本地中台库)。</summary>
|
|
|
public List<object> ListDataSources() => new()
|
|
|
{
|