using Oms.Application.Dtos.Orders; using Oms.Application.Services.Orders; using Oms.Domain.ChannelsAggregate.Entities; using Oms.Domain.ChannelsAggregate.Repositories; namespace Oms.Application.Shared; /// /// 卖价发布:解析价区表 Id 并钉分区包引用(不内嵌 Infos)。 /// public static class PriceAreaSnapshotHelper { /// /// 写入 PriceAreaRefs(Ensure 分区包);Infos 仅 LIVE 路径由 PackService.LoadLive 填充。 /// public static async Task ApplyPriceAreaToSnapshotAsync( SalesProductPricePublishSnapshotDto snapshot, SalesProduct product, IKpiAreaRepository kpiAreaRepository, KpiAreaPackService packService, string? publishUser = null, 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(); foreach (var areaId in areaIds) { refs.Add(await packService.EnsurePackAsync( areaId, KpiAreaPackService.AreaTypePrice, publishUser, description: "sales-product-price-publish", cancellationToken)); } AssignPriceAreaRefs(snapshot, refs); } /// /// 同步态:解析价区 ContentHash / 已有包 Version,不 Ensure 新包。 /// 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(); foreach (var areaId in areaIds) { refs.Add(await packService.ResolvePackRefForSyncAsync(areaId, cancellationToken)); } AssignPriceAreaRefs(snapshot, refs); } private static void AssignPriceAreaRefs( SalesProductPricePublishSnapshotDto snapshot, List refs) { snapshot.PriceAreaRefs = refs; if (refs.Count == 1) { snapshot.PriceAreaId = refs[0].AreaId; snapshot.PriceAreaName = refs[0].AreaName; } else { snapshot.PriceAreaId = null; snapshot.PriceAreaName = string.Join( "、", refs.Select(x => x.AreaName).Where(x => !string.IsNullOrWhiteSpace(x))); } } /// /// LIVE/模拟:不钉包,直接从当前库装载 Infos。 /// public static async Task ApplyLivePriceAreaInfosAsync( SalesProductPricePublishSnapshotDto snapshot, SalesProduct product, IKpiAreaRepository kpiAreaRepository, KpiAreaPackService packService, CancellationToken cancellationToken = default) { var areaIds = await CollectResolvedPriceAreaIdsAsync( product, snapshot, kpiAreaRepository, cancellationToken); await packService.LoadLiveInfosIntoPriceSnapshotAsync(snapshot, areaIds, cancellationToken); } /// /// 收集卖价明细(及产品 PriceAreaId)可解析到的全部价格分区表 Id,去重保序。 /// internal static async Task> CollectResolvedPriceAreaIdsAsync( SalesProduct product, SalesProductPricePublishSnapshotDto snapshot, IKpiAreaRepository kpiAreaRepository, CancellationToken cancellationToken = default) { var result = new List(); var seen = new HashSet(); void Add(int? areaId) { if (areaId is > 0 && seen.Add(areaId.Value)) { result.Add(areaId.Value); } } if (product.PriceAreaId is > 0) { Add(product.PriceAreaId); } var zoneKeys = ParcelBillingCalculator.CollectDistinctDetailZoneKeys(snapshot); foreach (var zoneKey in zoneKeys) { Add(await TryResolveZoneKeyToAreaIdAsync(zoneKey, kpiAreaRepository, cancellationToken)); } return result; } internal static async Task ResolvePriceAreaIdAsync( SalesProduct product, SalesProductPricePublishSnapshotDto snapshot, IKpiAreaRepository kpiAreaRepository, CancellationToken cancellationToken = default) { var ids = await CollectResolvedPriceAreaIdsAsync( product, snapshot, kpiAreaRepository, cancellationToken); return ids.Count > 0 ? ids[0] : null; } /// /// 渠道买价发布:从明细推断价区表并钉包(与产品卖价分区独立)。 /// public static async Task ApplyChannelPriceAreaToSnapshotAsync( ServiceChannelPricePublishSnapshotDto snapshot, IKpiAreaRepository kpiAreaRepository, KpiAreaPackService packService, string? publishUser = null, 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(); foreach (var areaId in areaIds) { refs.Add(await packService.EnsurePackAsync( areaId, KpiAreaPackService.AreaTypePrice, publishUser, description: "service-channel-price-publish", cancellationToken)); } AssignChannelPriceAreaRefs(snapshot, refs); } /// /// 渠道买价同步态:不 Ensure 新包。 /// 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(); foreach (var areaId in areaIds) { refs.Add(await packService.ResolvePackRefForSyncAsync(areaId, cancellationToken)); } AssignChannelPriceAreaRefs(snapshot, refs); } private static void AssignChannelPriceAreaRefs( ServiceChannelPricePublishSnapshotDto snapshot, List refs) { snapshot.PriceAreaRefs = refs; if (refs.Count == 1) { snapshot.PriceAreaId = refs[0].AreaId; snapshot.PriceAreaName = refs[0].AreaName; } else { snapshot.PriceAreaId = null; snapshot.PriceAreaName = string.Join( "、", refs.Select(x => x.AreaName).Where(x => !string.IsNullOrWhiteSpace(x))); } } /// /// 渠道买价 LIVE:不钉包,从当前库装 Infos。 /// public static async Task ApplyLiveChannelPriceAreaInfosAsync( ServiceChannelPricePublishSnapshotDto snapshot, IKpiAreaRepository kpiAreaRepository, KpiAreaPackService packService, CancellationToken cancellationToken = default) { var areaIds = await CollectResolvedChannelPriceAreaIdsAsync( snapshot, kpiAreaRepository, cancellationToken); await packService.LoadLiveInfosIntoChannelPriceSnapshotAsync(snapshot, areaIds, cancellationToken); } internal static async Task> CollectResolvedChannelPriceAreaIdsAsync( ServiceChannelPricePublishSnapshotDto snapshot, IKpiAreaRepository kpiAreaRepository, CancellationToken cancellationToken = default) { var result = new List(); var seen = new HashSet(); void Add(int? areaId) { if (areaId is > 0 && seen.Add(areaId.Value)) { result.Add(areaId.Value); } } var zoneKeys = ParcelBillingCalculator.CollectDistinctDetailZoneKeys(snapshot); foreach (var zoneKey in zoneKeys) { Add(await TryResolveZoneKeyToAreaIdAsync(zoneKey, kpiAreaRepository, cancellationToken)); } return result; } private static async Task TryResolveZoneKeyToAreaIdAsync( string zoneKey, IKpiAreaRepository kpiAreaRepository, CancellationToken cancellationToken) { if (!int.TryParse(zoneKey.Trim(), out var zoneId) || zoneId <= 0) { return null; } var area = await kpiAreaRepository.FirstOrDefaultAsync(x => x.Id == zoneId, cancellationToken); if (area != null) { return zoneId; } var info = await kpiAreaRepository.GetInfoByIdAsync(zoneId, cancellationToken); return info?.AreaId; } }