diff --git a/src/Oms.Application/Shared/PriceAreaSnapshotHelper.cs b/src/Oms.Application/Shared/PriceAreaSnapshotHelper.cs
index d06e44f..ab0bd80 100644
--- a/src/Oms.Application/Shared/PriceAreaSnapshotHelper.cs
+++ b/src/Oms.Application/Shared/PriceAreaSnapshotHelper.cs
@@ -1,5 +1,6 @@
using Oms.Application.Dtos.Channels;
using Oms.Application.Dtos.Orders;
+using Oms.Application.Services.Orders;
using Oms.Domain.ChannelsAggregate.Entities;
using Oms.Domain.ChannelsAggregate.Repositories;
@@ -11,7 +12,7 @@ namespace Oms.Application.Shared;
public static class PriceAreaSnapshotHelper
{
///
- /// 按产品 PriceAreaId 加载分区头与明细写入快照。
+ /// 按产品 PriceAreaId(或从卖价明细分区推断)加载分区头与明细写入快照。
///
public static async Task ApplyPriceAreaToSnapshotAsync(
SalesProductPricePublishSnapshotDto snapshot,
@@ -19,7 +20,12 @@ public static class PriceAreaSnapshotHelper
IKpiAreaRepository kpiAreaRepository,
CancellationToken cancellationToken = default)
{
- if (!product.PriceAreaId.HasValue || product.PriceAreaId <= 0)
+ var priceAreaId = await ResolvePriceAreaIdAsync(
+ product,
+ snapshot,
+ kpiAreaRepository,
+ cancellationToken);
+ if (!priceAreaId.HasValue)
{
snapshot.PriceAreaId = null;
snapshot.PriceAreaName = null;
@@ -27,13 +33,48 @@ public static class PriceAreaSnapshotHelper
return;
}
- snapshot.PriceAreaId = product.PriceAreaId;
- var area = await kpiAreaRepository.FirstOrDefaultAsync(x => x.Id == product.PriceAreaId.Value, cancellationToken);
+ snapshot.PriceAreaId = priceAreaId;
+ var area = await kpiAreaRepository.FirstOrDefaultAsync(x => x.Id == priceAreaId.Value, cancellationToken);
snapshot.PriceAreaName = area?.Name;
- var infos = await kpiAreaRepository.GetAllInfosByAreaIdAsync(product.PriceAreaId.Value, cancellationToken);
+ var infos = await kpiAreaRepository.GetAllInfosByAreaIdAsync(priceAreaId.Value, cancellationToken);
snapshot.PriceAreaInfos = infos.Select(MapInfoOutput).ToList();
}
+ internal static async Task ResolvePriceAreaIdAsync(
+ SalesProduct product,
+ SalesProductPricePublishSnapshotDto snapshot,
+ IKpiAreaRepository kpiAreaRepository,
+ CancellationToken cancellationToken = default)
+ {
+ if (product.PriceAreaId is > 0)
+ {
+ return product.PriceAreaId;
+ }
+
+ var zoneKeys = ParcelBillingCalculator.CollectDistinctDetailZoneKeys(snapshot);
+ foreach (var zoneKey in zoneKeys)
+ {
+ if (!int.TryParse(zoneKey.Trim(), out var zoneId) || zoneId <= 0)
+ {
+ continue;
+ }
+
+ var area = await kpiAreaRepository.FirstOrDefaultAsync(x => x.Id == zoneId, cancellationToken);
+ if (area != null)
+ {
+ return zoneId;
+ }
+
+ var info = await kpiAreaRepository.GetInfoByIdAsync(zoneId, cancellationToken);
+ if (info != null)
+ {
+ return info.AreaId;
+ }
+ }
+
+ return null;
+ }
+
private static KpiAreaInfoOutput MapInfoOutput(KpiAreaInfo entity) =>
new()
{