fix: 价格发布从卖价明细分区推断 PriceAreaId 并写入快照

产品未配置 PriceAreaId 时,根据卖价明细「分区」值匹配 t_kpi_area 或 t_kpi_area_info 后固化 PriceAreaInfos。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-06-26 11:58:01 +08:00
parent 3a65e8c58f
commit 8aa6ceb677

View File

@ -1,5 +1,6 @@
using Oms.Application.Dtos.Channels; using Oms.Application.Dtos.Channels;
using Oms.Application.Dtos.Orders; using Oms.Application.Dtos.Orders;
using Oms.Application.Services.Orders;
using Oms.Domain.ChannelsAggregate.Entities; using Oms.Domain.ChannelsAggregate.Entities;
using Oms.Domain.ChannelsAggregate.Repositories; using Oms.Domain.ChannelsAggregate.Repositories;
@ -11,7 +12,7 @@ namespace Oms.Application.Shared;
public static class PriceAreaSnapshotHelper public static class PriceAreaSnapshotHelper
{ {
/// <summary> /// <summary>
/// 按产品 PriceAreaId 加载分区头与明细写入快照。 /// 按产品 PriceAreaId(或从卖价明细分区推断)加载分区头与明细写入快照。
/// </summary> /// </summary>
public static async Task ApplyPriceAreaToSnapshotAsync( public static async Task ApplyPriceAreaToSnapshotAsync(
SalesProductPricePublishSnapshotDto snapshot, SalesProductPricePublishSnapshotDto snapshot,
@ -19,7 +20,12 @@ public static class PriceAreaSnapshotHelper
IKpiAreaRepository kpiAreaRepository, IKpiAreaRepository kpiAreaRepository,
CancellationToken cancellationToken = default) 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.PriceAreaId = null;
snapshot.PriceAreaName = null; snapshot.PriceAreaName = null;
@ -27,13 +33,48 @@ public static class PriceAreaSnapshotHelper
return; return;
} }
snapshot.PriceAreaId = product.PriceAreaId; snapshot.PriceAreaId = priceAreaId;
var area = await kpiAreaRepository.FirstOrDefaultAsync(x => x.Id == product.PriceAreaId.Value, cancellationToken); var area = await kpiAreaRepository.FirstOrDefaultAsync(x => x.Id == priceAreaId.Value, cancellationToken);
snapshot.PriceAreaName = area?.Name; 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(); snapshot.PriceAreaInfos = infos.Select(MapInfoOutput).ToList();
} }
internal static async Task<int?> 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) => private static KpiAreaInfoOutput MapInfoOutput(KpiAreaInfo entity) =>
new() new()
{ {