Use slim DTOs without audit timestamps; migrate legacy LeftPostcode/RightPostcode on read. Co-authored-by: Cursor <cursoragent@cursor.com>
78 lines
2.6 KiB
C#
78 lines
2.6 KiB
C#
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;
|
||
|
||
namespace Oms.Application.Shared;
|
||
|
||
/// <summary>
|
||
/// 将价格分区(t_kpi_area + t_kpi_area_info)固化进卖价发布快照。
|
||
/// </summary>
|
||
public static class PriceAreaSnapshotHelper
|
||
{
|
||
/// <summary>
|
||
/// 按产品 PriceAreaId(或从卖价明细分区推断)加载分区头与明细写入快照。
|
||
/// </summary>
|
||
public static async Task ApplyPriceAreaToSnapshotAsync(
|
||
SalesProductPricePublishSnapshotDto snapshot,
|
||
SalesProduct product,
|
||
IKpiAreaRepository kpiAreaRepository,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
var priceAreaId = await ResolvePriceAreaIdAsync(
|
||
product,
|
||
snapshot,
|
||
kpiAreaRepository,
|
||
cancellationToken);
|
||
if (!priceAreaId.HasValue)
|
||
{
|
||
snapshot.PriceAreaId = null;
|
||
snapshot.PriceAreaName = null;
|
||
snapshot.PriceAreaInfos = [];
|
||
return;
|
||
}
|
||
|
||
snapshot.PriceAreaId = priceAreaId;
|
||
var area = await kpiAreaRepository.FirstOrDefaultAsync(x => x.Id == priceAreaId.Value, cancellationToken);
|
||
snapshot.PriceAreaName = area?.Name;
|
||
var infos = await kpiAreaRepository.GetAllInfosByAreaIdAsync(priceAreaId.Value, cancellationToken);
|
||
snapshot.PriceAreaInfos = infos.Select(KpiAreaSnapshotMapper.MapToSnapshotRule).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;
|
||
}
|
||
}
|