20261008-ide1.0发布 #1
@ -317,6 +317,25 @@ public partial class SalesProductService
|
|||||||
return priceSnapshot;
|
return priceSnapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 同步态待发布快照:价区只解析哈希/已有包,不 Ensure 写库。
|
||||||
|
/// </summary>
|
||||||
|
private async Task<SalesProductPricePublishSnapshotDto> BuildPricePublishSnapshotForSyncAsync(int salesProductId)
|
||||||
|
{
|
||||||
|
var product = await GetProductOrThrowAsync(salesProductId);
|
||||||
|
var priceSnapshot = new SalesProductPricePublishSnapshot
|
||||||
|
{
|
||||||
|
SalesProductId = salesProductId,
|
||||||
|
Prices = (await GetPriceOutputsAsync(salesProductId)).Select(PublishSnapshotSlimmer.SlimPrice).ToList()
|
||||||
|
};
|
||||||
|
await PriceAreaSnapshotHelper.ApplyPriceAreaRefsForSyncAsync(
|
||||||
|
priceSnapshot,
|
||||||
|
product,
|
||||||
|
KpiAreaRepository,
|
||||||
|
KpiAreaPackService);
|
||||||
|
return priceSnapshot;
|
||||||
|
}
|
||||||
|
|
||||||
private string ResolvePublishUser() =>
|
private string ResolvePublishUser() =>
|
||||||
string.IsNullOrWhiteSpace(CurrentUser.UserName)
|
string.IsNullOrWhiteSpace(CurrentUser.UserName)
|
||||||
? CurrentUser.GetId<int>().ToString()
|
? CurrentUser.GetId<int>().ToString()
|
||||||
|
|||||||
@ -420,14 +420,13 @@ public partial class SalesProductService : ApplicationService
|
|||||||
var normalized = NormalizeOperatorType(operatorType);
|
var normalized = NormalizeOperatorType(operatorType);
|
||||||
await GetProductOrThrowAsync(salesProductId);
|
await GetProductOrThrowAsync(salesProductId);
|
||||||
|
|
||||||
// 两侧都走「序列化 → 反序列化规范化 → 再序列化」,避免刚发布仍误判待发布
|
// 待发布:同步态不 Ensure 分区包;对比时忽略 PackVersion/AreaName,只比价格项 + 分区 ContentHash
|
||||||
// (价格项排序、FactorValuesJson 的 Dictionary/JsonElement 形态差异等)
|
|
||||||
object pendingSnapshot = normalized == PriceOperatorType
|
object pendingSnapshot = normalized == PriceOperatorType
|
||||||
? await BuildPricePublishSnapshotAsync(salesProductId)
|
? await BuildPricePublishSnapshotForSyncAsync(salesProductId)
|
||||||
: await BuildRulesPublishSnapshotAsync(salesProductId);
|
: await BuildRulesPublishSnapshotAsync(salesProductId);
|
||||||
var pendingCanon = normalized == PriceOperatorType
|
var pendingCanon = normalized == PriceOperatorType
|
||||||
? OmsDocHelper.CanonicalizeSalesProductPriceSnapshotJson(pendingSnapshot)
|
? OmsDocHelper.HashSalesProductPriceSnapshotForSync(pendingSnapshot)
|
||||||
: OmsDocHelper.CanonicalizeSalesProductRulesSnapshotJson(pendingSnapshot);
|
: OmsDocHelper.HashSalesProductRulesSnapshotForSync(pendingSnapshot);
|
||||||
var pendingHash = ComputeContentHash(pendingCanon);
|
var pendingHash = ComputeContentHash(pendingCanon);
|
||||||
|
|
||||||
var headers = await SalesProductRepository.GetAllPublishRecordHeadersAsync(salesProductId, normalized);
|
var headers = await SalesProductRepository.GetAllPublishRecordHeadersAsync(salesProductId, normalized);
|
||||||
@ -451,9 +450,9 @@ public partial class SalesProductService : ApplicationService
|
|||||||
var onlineRecord = await SalesProductRepository.GetPublishRecordByIdAsync(onlineHeader.Id);
|
var onlineRecord = await SalesProductRepository.GetPublishRecordByIdAsync(onlineHeader.Id);
|
||||||
var onlineJson = onlineRecord?.Content ?? string.Empty;
|
var onlineJson = onlineRecord?.Content ?? string.Empty;
|
||||||
var onlineCanon = normalized == PriceOperatorType
|
var onlineCanon = normalized == PriceOperatorType
|
||||||
? OmsDocHelper.CanonicalizeSalesProductPriceSnapshotJson(
|
? OmsDocHelper.HashSalesProductPriceSnapshotForSync(
|
||||||
OmsDocHelper.DeserializePriceSnapshot(onlineJson))
|
OmsDocHelper.DeserializePriceSnapshot(onlineJson))
|
||||||
: OmsDocHelper.CanonicalizeSalesProductRulesSnapshotJson(
|
: OmsDocHelper.HashSalesProductRulesSnapshotForSync(
|
||||||
OmsDocHelper.DeserializeRulesSnapshot(onlineJson));
|
OmsDocHelper.DeserializeRulesSnapshot(onlineJson));
|
||||||
var onlineHash = ComputeContentHash(onlineCanon);
|
var onlineHash = ComputeContentHash(onlineCanon);
|
||||||
|
|
||||||
|
|||||||
@ -262,6 +262,25 @@ public partial class ServiceChannelService
|
|||||||
return snapshot;
|
return snapshot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 买价同步态:不 Ensure 新分区包。
|
||||||
|
/// </summary>
|
||||||
|
private async Task<ServiceChannelPricePublishSnapshotDto> BuildPricePublishSnapshotForSyncAsync(int serviceChannelId)
|
||||||
|
{
|
||||||
|
var snapshot = new ServiceChannelPricePublishSnapshotDto
|
||||||
|
{
|
||||||
|
ServiceChannelId = serviceChannelId,
|
||||||
|
Prices = (await GetPriceOutputsAsync(serviceChannelId))
|
||||||
|
.Select(PublishSnapshotSlimmer.SlimChannelPrice)
|
||||||
|
.ToList()
|
||||||
|
};
|
||||||
|
await PriceAreaSnapshotHelper.ApplyChannelPriceAreaRefsForSyncAsync(
|
||||||
|
snapshot,
|
||||||
|
KpiAreaRepository,
|
||||||
|
KpiAreaPackService);
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 组装渠道规则发布快照(不落库):钉偏远分区包。
|
/// 组装渠道规则发布快照(不落库):钉偏远分区包。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -414,10 +414,10 @@ public partial class ServiceChannelService : ApplicationService
|
|||||||
await GetEntityOrThrowAsync(serviceChannelId);
|
await GetEntityOrThrowAsync(serviceChannelId);
|
||||||
|
|
||||||
object pendingSnapshot = normalized == PriceOperatorType
|
object pendingSnapshot = normalized == PriceOperatorType
|
||||||
? await BuildPricePublishSnapshotAsync(serviceChannelId)
|
? await BuildPricePublishSnapshotForSyncAsync(serviceChannelId)
|
||||||
: await BuildRulesPublishSnapshotAsync(serviceChannelId);
|
: await BuildRulesPublishSnapshotAsync(serviceChannelId);
|
||||||
var pendingCanon = normalized == PriceOperatorType
|
var pendingCanon = normalized == PriceOperatorType
|
||||||
? OmsDocHelper.CanonicalizeChannelPriceSnapshotJson(pendingSnapshot)
|
? OmsDocHelper.HashChannelPriceSnapshotForSync(pendingSnapshot)
|
||||||
: OmsDocHelper.SerializeSnapshotJson(pendingSnapshot) ?? string.Empty;
|
: OmsDocHelper.SerializeSnapshotJson(pendingSnapshot) ?? string.Empty;
|
||||||
var pendingHash = ComputeContentHash(pendingCanon);
|
var pendingHash = ComputeContentHash(pendingCanon);
|
||||||
|
|
||||||
@ -439,7 +439,7 @@ public partial class ServiceChannelService : ApplicationService
|
|||||||
|
|
||||||
var onlineJson = onlineRecord.Content ?? string.Empty;
|
var onlineJson = onlineRecord.Content ?? string.Empty;
|
||||||
var onlineCanon = normalized == PriceOperatorType
|
var onlineCanon = normalized == PriceOperatorType
|
||||||
? OmsDocHelper.CanonicalizeChannelPriceSnapshotJson(
|
? OmsDocHelper.HashChannelPriceSnapshotForSync(
|
||||||
OmsDocHelper.DeserializeChannelPriceSnapshot(onlineJson))
|
OmsDocHelper.DeserializeChannelPriceSnapshot(onlineJson))
|
||||||
: OmsDocHelper.SerializeSnapshotJson(
|
: OmsDocHelper.SerializeSnapshotJson(
|
||||||
OmsDocHelper.DeserializeJson<ServiceChannelRulesPublishSnapshotDto>(onlineJson))
|
OmsDocHelper.DeserializeJson<ServiceChannelRulesPublishSnapshotDto>(onlineJson))
|
||||||
|
|||||||
@ -41,6 +41,67 @@ public class KpiAreaPackService : IScopedDependency
|
|||||||
string? publishUser = null,
|
string? publishUser = null,
|
||||||
string? description = null,
|
string? description = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var prepared = await PreparePackContentAsync(areaId, cancellationToken);
|
||||||
|
var existing = await _kpiAreaRepository.FindPublishByAreaIdAndContentHashAsync(
|
||||||
|
areaId,
|
||||||
|
prepared.ContentHash,
|
||||||
|
cancellationToken);
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
return ToRef(existing, prepared.AreaName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var version = DateTime.Now.ToString("yyyyMMddHHmmssfff");
|
||||||
|
var record = new KpiAreaPublishRecord
|
||||||
|
{
|
||||||
|
AreaId = areaId,
|
||||||
|
AreaType = string.IsNullOrWhiteSpace(areaType) ? prepared.AreaType : areaType.Trim(),
|
||||||
|
Version = version,
|
||||||
|
Status = EsSnapshotStatus.Active,
|
||||||
|
ContentHash = prepared.ContentHash,
|
||||||
|
Content = prepared.ContentJson,
|
||||||
|
PublishUser = string.IsNullOrWhiteSpace(publishUser) ? "system" : publishUser.Trim(),
|
||||||
|
PublishTime = DateTime.Now,
|
||||||
|
Description = description
|
||||||
|
};
|
||||||
|
record = await _kpiAreaRepository.InsertPublishRecordAsync(record, cancellationToken);
|
||||||
|
PackCache.Set(CacheKey(areaId, record.Version), prepared.Rules, new MemoryCacheEntryOptions
|
||||||
|
{
|
||||||
|
Size = 1,
|
||||||
|
SlidingExpiration = TimeSpan.FromHours(6)
|
||||||
|
});
|
||||||
|
return ToRef(record, prepared.AreaName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 同步态专用:只解析当前库明细哈希并回填已有包 Version;不落新包(避免 GET sync-status 写库)。
|
||||||
|
/// </summary>
|
||||||
|
public async Task<KpiAreaPackRefDto> ResolvePackRefForSyncAsync(
|
||||||
|
int areaId,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var prepared = await PreparePackContentAsync(areaId, cancellationToken);
|
||||||
|
var existing = await _kpiAreaRepository.FindPublishByAreaIdAndContentHashAsync(
|
||||||
|
areaId,
|
||||||
|
prepared.ContentHash,
|
||||||
|
cancellationToken);
|
||||||
|
if (existing != null)
|
||||||
|
{
|
||||||
|
return ToRef(existing, prepared.AreaName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new KpiAreaPackRefDto
|
||||||
|
{
|
||||||
|
AreaId = areaId,
|
||||||
|
AreaName = prepared.AreaName,
|
||||||
|
PackVersion = string.Empty,
|
||||||
|
ContentHash = prepared.ContentHash
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(string AreaType, string? AreaName, string ContentJson, string ContentHash, List<KpiAreaSnapshotRuleDto> Rules)>
|
||||||
|
PreparePackContentAsync(int areaId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (areaId <= 0)
|
if (areaId <= 0)
|
||||||
{
|
{
|
||||||
@ -57,36 +118,7 @@ public class KpiAreaPackService : IScopedDependency
|
|||||||
|
|
||||||
var contentJson = OmsDocHelper.SerializeSnapshotJson(rules) ?? "[]";
|
var contentJson = OmsDocHelper.SerializeSnapshotJson(rules) ?? "[]";
|
||||||
var contentHash = ComputeSha256Hex(contentJson);
|
var contentHash = ComputeSha256Hex(contentJson);
|
||||||
|
return (area.AreaType, area.Name, contentJson, contentHash, rules);
|
||||||
var existing = await _kpiAreaRepository.FindPublishByAreaIdAndContentHashAsync(
|
|
||||||
areaId,
|
|
||||||
contentHash,
|
|
||||||
cancellationToken);
|
|
||||||
if (existing != null)
|
|
||||||
{
|
|
||||||
return ToRef(existing, area.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
var version = DateTime.Now.ToString("yyyyMMddHHmmssfff");
|
|
||||||
var record = new KpiAreaPublishRecord
|
|
||||||
{
|
|
||||||
AreaId = areaId,
|
|
||||||
AreaType = string.IsNullOrWhiteSpace(areaType) ? area.AreaType : areaType.Trim(),
|
|
||||||
Version = version,
|
|
||||||
Status = EsSnapshotStatus.Active,
|
|
||||||
ContentHash = contentHash,
|
|
||||||
Content = contentJson,
|
|
||||||
PublishUser = string.IsNullOrWhiteSpace(publishUser) ? "system" : publishUser.Trim(),
|
|
||||||
PublishTime = DateTime.Now,
|
|
||||||
Description = description
|
|
||||||
};
|
|
||||||
record = await _kpiAreaRepository.InsertPublishRecordAsync(record, cancellationToken);
|
|
||||||
PackCache.Set(CacheKey(areaId, record.Version), rules, new MemoryCacheEntryOptions
|
|
||||||
{
|
|
||||||
Size = 1,
|
|
||||||
SlidingExpiration = TimeSpan.FromHours(6)
|
|
||||||
});
|
|
||||||
return ToRef(record, area.Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -177,6 +177,30 @@ public static class OmsDocHelper
|
|||||||
return SerializeSnapshotJson(DeserializeChannelPriceSnapshot(raw)) ?? string.Empty;
|
return SerializeSnapshotJson(DeserializeChannelPriceSnapshot(raw)) ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发布同步态哈希:canonical + 去掉 PackVersion/AreaName 等钉包展示字段。
|
||||||
|
/// </summary>
|
||||||
|
public static string HashSalesProductPriceSnapshotForSync(object? snapshot)
|
||||||
|
{
|
||||||
|
var dto = DeserializePriceSnapshot(SerializeSnapshotJson(snapshot));
|
||||||
|
PublishSnapshotNormalizer.StripVolatilePackPinsForSyncCompare(dto);
|
||||||
|
return SerializeSnapshotJson(dto) ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string HashSalesProductRulesSnapshotForSync(object? snapshot)
|
||||||
|
{
|
||||||
|
var dto = DeserializeRulesSnapshot(SerializeSnapshotJson(snapshot));
|
||||||
|
PublishSnapshotNormalizer.StripVolatilePackPinsForSyncCompare(dto);
|
||||||
|
return SerializeSnapshotJson(dto) ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string HashChannelPriceSnapshotForSync(object? snapshot)
|
||||||
|
{
|
||||||
|
var dto = DeserializeChannelPriceSnapshot(SerializeSnapshotJson(snapshot));
|
||||||
|
PublishSnapshotNormalizer.StripVolatilePackPinsForSyncCompare(dto);
|
||||||
|
return SerializeSnapshotJson(dto) ?? string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 解析渠道买价发布 Content,供列表/对比 API 使用(兼容旧快照审计字段)。
|
/// 解析渠道买价发布 Content,供列表/对比 API 使用(兼容旧快照审计字段)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -46,6 +46,46 @@ public static class PriceAreaSnapshotHelper
|
|||||||
cancellationToken));
|
cancellationToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssignPriceAreaRefs(snapshot, refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 同步态:解析价区 ContentHash / 已有包 Version,不 Ensure 新包。
|
||||||
|
/// </summary>
|
||||||
|
public static async Task ApplyPriceAreaRefsForSyncAsync(
|
||||||
|
SalesProductPricePublishSnapshotDto snapshot,
|
||||||
|
SalesProduct product,
|
||||||
|
IKpiAreaRepository kpiAreaRepository,
|
||||||
|
KpiAreaPackService packService,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var areaIds = await CollectResolvedPriceAreaIdsAsync(
|
||||||
|
product,
|
||||||
|
snapshot,
|
||||||
|
kpiAreaRepository,
|
||||||
|
cancellationToken);
|
||||||
|
snapshot.PriceAreaInfos = [];
|
||||||
|
if (areaIds.Count == 0)
|
||||||
|
{
|
||||||
|
snapshot.PriceAreaId = null;
|
||||||
|
snapshot.PriceAreaName = null;
|
||||||
|
snapshot.PriceAreaRefs = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var refs = new List<KpiAreaPackRefDto>();
|
||||||
|
foreach (var areaId in areaIds)
|
||||||
|
{
|
||||||
|
refs.Add(await packService.ResolvePackRefForSyncAsync(areaId, cancellationToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignPriceAreaRefs(snapshot, refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AssignPriceAreaRefs(
|
||||||
|
SalesProductPricePublishSnapshotDto snapshot,
|
||||||
|
List<KpiAreaPackRefDto> refs)
|
||||||
|
{
|
||||||
snapshot.PriceAreaRefs = refs;
|
snapshot.PriceAreaRefs = refs;
|
||||||
if (refs.Count == 1)
|
if (refs.Count == 1)
|
||||||
{
|
{
|
||||||
@ -161,6 +201,44 @@ public static class PriceAreaSnapshotHelper
|
|||||||
cancellationToken));
|
cancellationToken));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssignChannelPriceAreaRefs(snapshot, refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 渠道买价同步态:不 Ensure 新包。
|
||||||
|
/// </summary>
|
||||||
|
public static async Task ApplyChannelPriceAreaRefsForSyncAsync(
|
||||||
|
ServiceChannelPricePublishSnapshotDto snapshot,
|
||||||
|
IKpiAreaRepository kpiAreaRepository,
|
||||||
|
KpiAreaPackService packService,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var areaIds = await CollectResolvedChannelPriceAreaIdsAsync(
|
||||||
|
snapshot,
|
||||||
|
kpiAreaRepository,
|
||||||
|
cancellationToken);
|
||||||
|
snapshot.PriceAreaInfos = [];
|
||||||
|
if (areaIds.Count == 0)
|
||||||
|
{
|
||||||
|
snapshot.PriceAreaId = null;
|
||||||
|
snapshot.PriceAreaName = null;
|
||||||
|
snapshot.PriceAreaRefs = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var refs = new List<KpiAreaPackRefDto>();
|
||||||
|
foreach (var areaId in areaIds)
|
||||||
|
{
|
||||||
|
refs.Add(await packService.ResolvePackRefForSyncAsync(areaId, cancellationToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
AssignChannelPriceAreaRefs(snapshot, refs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AssignChannelPriceAreaRefs(
|
||||||
|
ServiceChannelPricePublishSnapshotDto snapshot,
|
||||||
|
List<KpiAreaPackRefDto> refs)
|
||||||
|
{
|
||||||
snapshot.PriceAreaRefs = refs;
|
snapshot.PriceAreaRefs = refs;
|
||||||
if (refs.Count == 1)
|
if (refs.Count == 1)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -44,6 +44,61 @@ public static class PublishSnapshotNormalizer
|
|||||||
snapshot.Prices = SortChannelPriceItems(snapshot.Prices);
|
snapshot.Prices = SortChannelPriceItems(snapshot.Prices);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 同步态对比:分区包只比 AreaId+ContentHash(PackVersion 是钉包戳,AreaName 是展示名)。
|
||||||
|
/// </summary>
|
||||||
|
public static void StripVolatilePackPinsForSyncCompare(SalesProductPricePublishSnapshotDto? snapshot)
|
||||||
|
{
|
||||||
|
if (snapshot is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot.PriceAreaName = null;
|
||||||
|
foreach (var packRef in snapshot.PriceAreaRefs ?? [])
|
||||||
|
{
|
||||||
|
StripPackPin(packRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void StripVolatilePackPinsForSyncCompare(ServiceChannelPricePublishSnapshotDto? snapshot)
|
||||||
|
{
|
||||||
|
if (snapshot is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot.PriceAreaName = null;
|
||||||
|
foreach (var packRef in snapshot.PriceAreaRefs ?? [])
|
||||||
|
{
|
||||||
|
StripPackPin(packRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void StripVolatilePackPinsForSyncCompare(SalesProductRulesPublishSnapshotDto? snapshot)
|
||||||
|
{
|
||||||
|
if (snapshot is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot.BlacklistAreaName = null;
|
||||||
|
snapshot.RemoteAreaName = null;
|
||||||
|
StripPackPin(snapshot.BlacklistAreaRef);
|
||||||
|
StripPackPin(snapshot.RemoteAreaRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StripPackPin(KpiAreaPackRefDto? packRef)
|
||||||
|
{
|
||||||
|
if (packRef is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
packRef.PackVersion = string.Empty;
|
||||||
|
packRef.AreaName = null;
|
||||||
|
}
|
||||||
|
|
||||||
public static void NormalizeKpiAreas(List<KpiAreaSnapshotRuleDto>? areas)
|
public static void NormalizeKpiAreas(List<KpiAreaSnapshotRuleDto>? areas)
|
||||||
{
|
{
|
||||||
if (areas is null)
|
if (areas is null)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user