feat: 卖价支持多价格分区表,列表返回创建/修改人
All checks were successful
Build and Deploy / deploy (push) Successful in 1m7s
All checks were successful
Build and Deploy / deploy (push) Successful in 1m7s
合并多 Area 分区规则进发布快照,计费用规则自身 AreaId 匹配;产品与渠道列表补 CreateBy/UpdateBy。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
f972a28d79
commit
6faadcf2a1
@ -100,8 +100,18 @@ public class SalesProductListOutput
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime CreateTime { get; set; }
|
public DateTime CreateTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建人展示名。
|
||||||
|
/// </summary>
|
||||||
|
public string? CreateBy { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 更新时间。
|
/// 更新时间。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? UpdateTime { get; set; }
|
public DateTime? UpdateTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修改人展示名。
|
||||||
|
/// </summary>
|
||||||
|
public string? UpdateBy { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,8 +70,18 @@ public class ServiceChannelListOutput
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime CreateTime { get; set; }
|
public DateTime CreateTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建人展示名。
|
||||||
|
/// </summary>
|
||||||
|
public string? CreateBy { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 更新时间。
|
/// 更新时间。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? UpdateTime { get; set; }
|
public DateTime? UpdateTime { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 修改人展示名。
|
||||||
|
/// </summary>
|
||||||
|
public string? UpdateBy { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,12 @@ public class KpiAreaSnapshotRuleDto
|
|||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>所属 KPI 分区表主键(多价格分区表合并快照时用于生成 zone 键)。</summary>
|
||||||
|
public int AreaId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>所属分区表名称(可选,便于展示与 zone 键兼容)。</summary>
|
||||||
|
public string? AreaName { get; set; }
|
||||||
|
|
||||||
public string? CountryCode { get; set; }
|
public string? CountryCode { get; set; }
|
||||||
|
|
||||||
public string? Province { get; set; }
|
public string? Province { get; set; }
|
||||||
|
|||||||
@ -282,7 +282,6 @@ public partial class SalesProductService
|
|||||||
var priceSnapshot = await BuildPricePublishSnapshotAsync(salesProductId);
|
var priceSnapshot = await BuildPricePublishSnapshotAsync(salesProductId);
|
||||||
ValidateBillingPriceItemRules(
|
ValidateBillingPriceItemRules(
|
||||||
priceSnapshot.Prices.Select(p => MapPriceSaveInput(p, salesProductId)).ToList());
|
priceSnapshot.Prices.Select(p => MapPriceSaveInput(p, salesProductId)).ToList());
|
||||||
await PriceAreaSnapshotHelper.EnsureSingleResolvedPriceAreaAsync(priceSnapshot, KpiAreaRepository);
|
|
||||||
snapshot = priceSnapshot;
|
snapshot = priceSnapshot;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -519,7 +518,9 @@ public partial class SalesProductService
|
|||||||
return normalized.Count == 0 ? null : OmsDocHelper.SerializeJson(normalized);
|
return normalized.Count == 0 ? null : OmsDocHelper.SerializeJson(normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SalesProductListOutput MapListOutput(SalesProduct entity)
|
private static SalesProductListOutput MapListOutput(
|
||||||
|
SalesProduct entity,
|
||||||
|
IReadOnlyDictionary<int, string> auditUserNameMap)
|
||||||
{
|
{
|
||||||
return new SalesProductListOutput
|
return new SalesProductListOutput
|
||||||
{
|
{
|
||||||
@ -542,7 +543,9 @@ public partial class SalesProductService
|
|||||||
IsActive = (byte)entity.IsActive,
|
IsActive = (byte)entity.IsActive,
|
||||||
Scheme = entity.Scheme,
|
Scheme = entity.Scheme,
|
||||||
CreateTime = entity.CreateTime,
|
CreateTime = entity.CreateTime,
|
||||||
UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime)
|
CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.CreateUserId, auditUserNameMap),
|
||||||
|
UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime),
|
||||||
|
UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.UpdateUserId, auditUserNameMap)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -45,9 +45,11 @@ public partial class SalesProductService : ApplicationService
|
|||||||
pageSize,
|
pageSize,
|
||||||
new Dictionary<string, bool> { [nameof(SalesProduct.UpdateTime)] = false, [nameof(SalesProduct.Id)] = false });
|
new Dictionary<string, bool> { [nameof(SalesProduct.UpdateTime)] = false, [nameof(SalesProduct.Id)] = false });
|
||||||
var total = await SalesProductRepository.CountAsync(predicate);
|
var total = await SalesProductRepository.CountAsync(predicate);
|
||||||
|
var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
|
||||||
|
entities.SelectMany(x => new[] { x.CreateUserId, x.UpdateUserId }));
|
||||||
return new OmsPageResult<SalesProductListOutput>
|
return new OmsPageResult<SalesProductListOutput>
|
||||||
{
|
{
|
||||||
Items = entities.Select(MapListOutput).ToList(),
|
Items = entities.Select(entity => MapListOutput(entity, auditUserNameMap)).ToList(),
|
||||||
Total = total
|
Total = total
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -268,9 +270,6 @@ public partial class SalesProductService : ApplicationService
|
|||||||
{
|
{
|
||||||
await GetProductOrThrowAsync(input.SalesProductId);
|
await GetProductOrThrowAsync(input.SalesProductId);
|
||||||
ValidateBillingPriceItemRules(input.Prices);
|
ValidateBillingPriceItemRules(input.Prices);
|
||||||
await PriceAreaSnapshotHelper.EnsureSingleResolvedPriceAreaAsync(
|
|
||||||
BuildPriceSnapshotFromSaveInputs(input.SalesProductId, input.Prices),
|
|
||||||
KpiAreaRepository);
|
|
||||||
var prices = new List<SalesProductPrice>();
|
var prices = new List<SalesProductPrice>();
|
||||||
var factors = new List<SalesProductPriceFactor>();
|
var factors = new List<SalesProductPriceFactor>();
|
||||||
var details = new List<SalesProductPriceDetail>();
|
var details = new List<SalesProductPriceDetail>();
|
||||||
|
|||||||
@ -416,7 +416,10 @@ public partial class ServiceChannelService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ServiceChannelListOutput MapListOutput(ServiceChannel entity, IReadOnlyDictionary<int, string> groupMap)
|
private static ServiceChannelListOutput MapListOutput(
|
||||||
|
ServiceChannel entity,
|
||||||
|
IReadOnlyDictionary<int, string> groupMap,
|
||||||
|
IReadOnlyDictionary<int, string> auditUserNameMap)
|
||||||
{
|
{
|
||||||
return new ServiceChannelListOutput
|
return new ServiceChannelListOutput
|
||||||
{
|
{
|
||||||
@ -433,7 +436,9 @@ public partial class ServiceChannelService
|
|||||||
RemoteAreaId = entity.RemoteAreaId,
|
RemoteAreaId = entity.RemoteAreaId,
|
||||||
IsActive = (byte)entity.IsActive,
|
IsActive = (byte)entity.IsActive,
|
||||||
CreateTime = entity.CreateTime,
|
CreateTime = entity.CreateTime,
|
||||||
UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime)
|
CreateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.CreateUserId, auditUserNameMap),
|
||||||
|
UpdateTime = OmsDocHelper.NullIfDefault(entity.UpdateTime),
|
||||||
|
UpdateBy = OmsRbacUserDisplayNameResolver.FormatUserId(entity.UpdateUserId, auditUserNameMap)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,9 +43,11 @@ public partial class ServiceChannelService : ApplicationService
|
|||||||
new Dictionary<string, bool> { [nameof(ServiceChannel.UpdateTime)] = false, [nameof(ServiceChannel.Id)] = false });
|
new Dictionary<string, bool> { [nameof(ServiceChannel.UpdateTime)] = false, [nameof(ServiceChannel.Id)] = false });
|
||||||
var total = await ServiceChannelRepository.CountAsync(predicate);
|
var total = await ServiceChannelRepository.CountAsync(predicate);
|
||||||
var groupMap = await GetGroupMapAsync();
|
var groupMap = await GetGroupMapAsync();
|
||||||
|
var auditUserNameMap = await UserDisplayNameResolver.ResolveManyAsync(
|
||||||
|
entities.SelectMany(x => new[] { x.CreateUserId, x.UpdateUserId }));
|
||||||
return new OmsPageResult<ServiceChannelListOutput>
|
return new OmsPageResult<ServiceChannelListOutput>
|
||||||
{
|
{
|
||||||
Items = entities.Select(entity => MapListOutput(entity, groupMap)).ToList(),
|
Items = entities.Select(entity => MapListOutput(entity, groupMap, auditUserNameMap)).ToList(),
|
||||||
Total = total
|
Total = total
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,7 +125,12 @@ internal static class ParcelBillingCalculator
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var keys = BuildPriceZoneKeys(matched, priceSnapshot.PriceAreaName, priceSnapshot.PriceAreaId);
|
// 多价格分区表时优先用规则自身 AreaId,避免落到快照单一 PriceAreaId
|
||||||
|
var areaId = matched.AreaId > 0 ? matched.AreaId : priceSnapshot.PriceAreaId;
|
||||||
|
var areaName = !string.IsNullOrWhiteSpace(matched.AreaName)
|
||||||
|
? matched.AreaName
|
||||||
|
: priceSnapshot.PriceAreaName;
|
||||||
|
var keys = BuildPriceZoneKeys(matched, areaName, areaId);
|
||||||
return keys.Count > 0 ? keys : null;
|
return keys.Count > 0 ? keys : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +160,11 @@ internal static class ParcelBillingCalculator
|
|||||||
var allowed = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
var allowed = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
foreach (var rule in countryRules)
|
foreach (var rule in countryRules)
|
||||||
{
|
{
|
||||||
foreach (var key in BuildPriceZoneKeys(rule, priceSnapshot.PriceAreaName, priceSnapshot.PriceAreaId))
|
var areaId = rule.AreaId > 0 ? rule.AreaId : priceSnapshot.PriceAreaId;
|
||||||
|
var areaName = !string.IsNullOrWhiteSpace(rule.AreaName)
|
||||||
|
? rule.AreaName
|
||||||
|
: priceSnapshot.PriceAreaName;
|
||||||
|
foreach (var key in BuildPriceZoneKeys(rule, areaName, areaId))
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(key))
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,10 +8,12 @@ namespace Oms.Application.Shared;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class KpiAreaSnapshotMapper
|
public static class KpiAreaSnapshotMapper
|
||||||
{
|
{
|
||||||
public static KpiAreaSnapshotRuleDto MapToSnapshotRule(KpiAreaInfo entity) =>
|
public static KpiAreaSnapshotRuleDto MapToSnapshotRule(KpiAreaInfo entity, string? areaName = null) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
|
AreaId = entity.AreaId,
|
||||||
|
AreaName = areaName,
|
||||||
CountryCode = entity.CountryCode,
|
CountryCode = entity.CountryCode,
|
||||||
Province = entity.Province,
|
Province = entity.Province,
|
||||||
City = entity.City,
|
City = entity.City,
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
using Fake.Application;
|
|
||||||
using Oms.Application.Dtos.Channels;
|
|
||||||
using Oms.Application.Dtos.Orders;
|
using Oms.Application.Dtos.Orders;
|
||||||
using Oms.Application.Services.Orders;
|
using Oms.Application.Services.Orders;
|
||||||
using Oms.Domain.ChannelsAggregate.Entities;
|
using Oms.Domain.ChannelsAggregate.Entities;
|
||||||
@ -9,11 +7,12 @@ namespace Oms.Application.Shared;
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 将价格分区(t_kpi_area + t_kpi_area_info)固化进卖价发布快照。
|
/// 将价格分区(t_kpi_area + t_kpi_area_info)固化进卖价发布快照。
|
||||||
|
/// 支持卖价明细引用多张价格分区表:合并各表明细规则写入快照。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class PriceAreaSnapshotHelper
|
public static class PriceAreaSnapshotHelper
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按产品 PriceAreaId(或从卖价明细分区推断)加载分区头与明细写入快照。
|
/// 按产品 PriceAreaId(或从卖价明细分区推断的全部 AreaId)加载分区头与明细写入快照。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static async Task ApplyPriceAreaToSnapshotAsync(
|
public static async Task ApplyPriceAreaToSnapshotAsync(
|
||||||
SalesProductPricePublishSnapshotDto snapshot,
|
SalesProductPricePublishSnapshotDto snapshot,
|
||||||
@ -21,14 +20,12 @@ public static class PriceAreaSnapshotHelper
|
|||||||
IKpiAreaRepository kpiAreaRepository,
|
IKpiAreaRepository kpiAreaRepository,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
await EnsureSingleResolvedPriceAreaAsync(snapshot, kpiAreaRepository, cancellationToken);
|
var areaIds = await CollectResolvedPriceAreaIdsAsync(
|
||||||
|
|
||||||
var priceAreaId = await ResolvePriceAreaIdAsync(
|
|
||||||
product,
|
product,
|
||||||
snapshot,
|
snapshot,
|
||||||
kpiAreaRepository,
|
kpiAreaRepository,
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
if (!priceAreaId.HasValue)
|
if (areaIds.Count == 0)
|
||||||
{
|
{
|
||||||
snapshot.PriceAreaId = null;
|
snapshot.PriceAreaId = null;
|
||||||
snapshot.PriceAreaName = null;
|
snapshot.PriceAreaName = null;
|
||||||
@ -36,84 +33,94 @@ public static class PriceAreaSnapshotHelper
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
snapshot.PriceAreaId = priceAreaId;
|
var mergedInfos = new List<KpiAreaSnapshotRuleDto>();
|
||||||
var area = await kpiAreaRepository.FirstOrDefaultAsync(x => x.Id == priceAreaId.Value, cancellationToken);
|
var seenInfoIds = new HashSet<int>();
|
||||||
snapshot.PriceAreaName = area?.Name;
|
var areaNames = new List<string>();
|
||||||
var infos = await kpiAreaRepository.GetAllInfosByAreaIdAsync(priceAreaId.Value, cancellationToken);
|
|
||||||
snapshot.PriceAreaInfos = infos.Select(KpiAreaSnapshotMapper.MapToSnapshotRule).ToList();
|
foreach (var areaId in areaIds)
|
||||||
|
{
|
||||||
|
var area = await kpiAreaRepository.FirstOrDefaultAsync(x => x.Id == areaId, cancellationToken);
|
||||||
|
var areaName = area?.Name;
|
||||||
|
if (!string.IsNullOrWhiteSpace(areaName))
|
||||||
|
{
|
||||||
|
areaNames.Add(areaName.Trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var infos = await kpiAreaRepository.GetAllInfosByAreaIdAsync(areaId, cancellationToken);
|
||||||
|
foreach (var info in infos)
|
||||||
|
{
|
||||||
|
if (!seenInfoIds.Add(info.Id))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mergedInfos.Add(KpiAreaSnapshotMapper.MapToSnapshotRule(info, areaName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot.PriceAreaInfos = mergedInfos;
|
||||||
|
if (areaIds.Count == 1)
|
||||||
|
{
|
||||||
|
snapshot.PriceAreaId = areaIds[0];
|
||||||
|
snapshot.PriceAreaName = areaNames.Count > 0 ? areaNames[0] : null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 多表:不再落单一 PriceAreaId,名称拼接便于人工查看
|
||||||
|
snapshot.PriceAreaId = null;
|
||||||
|
snapshot.PriceAreaName = areaNames.Count > 0 ? string.Join("、", areaNames) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 收集卖价明细(及产品 PriceAreaId)可解析到的全部价格分区表 Id,去重保序。
|
||||||
|
/// </summary>
|
||||||
|
internal static async Task<IReadOnlyList<int>> CollectResolvedPriceAreaIdsAsync(
|
||||||
|
SalesProduct product,
|
||||||
|
SalesProductPricePublishSnapshotDto snapshot,
|
||||||
|
IKpiAreaRepository kpiAreaRepository,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var result = new List<int>();
|
||||||
|
var seen = new HashSet<int>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 兼容旧调用:仅返回第一个可解析 AreaId(多表场景请用 CollectResolvedPriceAreaIdsAsync)。
|
||||||
|
/// </summary>
|
||||||
internal static async Task<int?> ResolvePriceAreaIdAsync(
|
internal static async Task<int?> ResolvePriceAreaIdAsync(
|
||||||
SalesProduct product,
|
SalesProduct product,
|
||||||
SalesProductPricePublishSnapshotDto snapshot,
|
SalesProductPricePublishSnapshotDto snapshot,
|
||||||
IKpiAreaRepository kpiAreaRepository,
|
IKpiAreaRepository kpiAreaRepository,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
if (product.PriceAreaId is > 0)
|
var ids = await CollectResolvedPriceAreaIdsAsync(
|
||||||
{
|
product,
|
||||||
return product.PriceAreaId;
|
snapshot,
|
||||||
}
|
kpiAreaRepository,
|
||||||
|
cancellationToken);
|
||||||
var zoneKeys = ParcelBillingCalculator.CollectDistinctDetailZoneKeys(snapshot);
|
return ids.Count > 0 ? ids[0] : null;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 校验卖价明细中可解析的分区因子键均指向同一 AreaId;混用多个分区表时抛业务异常。
|
|
||||||
/// 非数字/无法解析的分区名(如「美西」)跳过,与 ResolvePriceAreaIdAsync 一致。
|
|
||||||
/// </summary>
|
|
||||||
public static async Task EnsureSingleResolvedPriceAreaAsync(
|
|
||||||
SalesProductPricePublishSnapshotDto snapshot,
|
|
||||||
IKpiAreaRepository kpiAreaRepository,
|
|
||||||
CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
var zoneKeys = ParcelBillingCalculator.CollectDistinctDetailZoneKeys(snapshot);
|
|
||||||
if (zoneKeys.Count == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int? resolvedAreaId = null;
|
|
||||||
foreach (var zoneKey in zoneKeys)
|
|
||||||
{
|
|
||||||
var areaId = await TryResolveZoneKeyToAreaIdAsync(zoneKey, kpiAreaRepository, cancellationToken);
|
|
||||||
if (!areaId.HasValue)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resolvedAreaId == null)
|
|
||||||
{
|
|
||||||
resolvedAreaId = areaId;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resolvedAreaId.Value != areaId.Value)
|
|
||||||
{
|
|
||||||
throw new BusinessException(
|
|
||||||
$"卖价明细分区混用了多个价格分区(AreaId={resolvedAreaId} 与 {areaId}),请统一分区后再发布");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<int?> TryResolveZoneKeyToAreaIdAsync(
|
private static async Task<int?> TryResolveZoneKeyToAreaIdAsync(
|
||||||
|
|||||||
@ -98,7 +98,7 @@ public static class RulesSnapshotHelper
|
|||||||
snapshot,
|
snapshot,
|
||||||
areaId,
|
areaId,
|
||||||
area?.Name,
|
area?.Name,
|
||||||
infos.Select(KpiAreaSnapshotMapper.MapToSnapshotRule).ToList());
|
infos.Select(info => KpiAreaSnapshotMapper.MapToSnapshotRule(info)).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task ApplyWeightRuleToSnapshotAsync(
|
private static async Task ApplyWeightRuleToSnapshotAsync(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user