fix: restore country+weight price-check estimates for postcode zones.
When rules require postal codes, still quote by same-country snapshot zones as estimated; keep blocking countries not configured at all. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
c8d35a8ef5
commit
e2443ed6f8
@ -672,21 +672,68 @@ public partial class OrderService
|
||||
|
||||
await TryAddAsync(null, null, false);
|
||||
|
||||
// 如果按「仅目的国」都无法匹配到任何价格分区,则不要再用卖价快照的全量分区键兜底。
|
||||
// 否则会导致未配置国家也能返回参考价格(estimated),与预期不符。
|
||||
if (attempts.Count == 0)
|
||||
// 精确命中(如无邮编区间的国家级分区)后,仍可用快照内其它分区键作参考兜底
|
||||
if (attempts.Count > 0)
|
||||
{
|
||||
foreach (var zoneKey in ParcelBillingCalculator.CollectDistinctDetailZoneKeys(snapshotBinding.Price))
|
||||
{
|
||||
if (attempts.Any(x => x.ZoneKeys.Any(k => string.Equals(k, zoneKey, StringComparison.OrdinalIgnoreCase))))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
attempts.Add(new QuoteZoneAttempt([zoneKey], true, zoneKey));
|
||||
}
|
||||
|
||||
return attempts;
|
||||
}
|
||||
|
||||
foreach (var zoneKey in ParcelBillingCalculator.CollectDistinctDetailZoneKeys(snapshotBinding.Price))
|
||||
// 仅国家+重量:分区规则带邮编时无法精确命中,按「同国家」分区给出估算价;
|
||||
// 快照中完全没有该国家时不跨国家兜底。
|
||||
if (snapshotBinding.Price?.PriceAreaInfos is { Count: > 0 })
|
||||
{
|
||||
if (attempts.Any(x => x.ZoneKeys.Any(k => string.Equals(k, zoneKey, StringComparison.OrdinalIgnoreCase))))
|
||||
foreach (var zoneKey in ParcelBillingCalculator.CollectCountryEstimateZoneKeys(
|
||||
snapshotBinding.Price,
|
||||
context.CountryCode))
|
||||
{
|
||||
continue;
|
||||
attempts.Add(new QuoteZoneAttempt([zoneKey], true, zoneKey));
|
||||
}
|
||||
|
||||
attempts.Add(new QuoteZoneAttempt([zoneKey], true, zoneKey));
|
||||
return attempts;
|
||||
}
|
||||
|
||||
// 无快照分区明细时,退回库表:同国家且不要求邮编的规则
|
||||
var priceAreaId = ResolveEffectivePriceAreaId(product, snapshotBinding.Rules, snapshotBinding.Price);
|
||||
if (priceAreaId is > 0)
|
||||
{
|
||||
var area = await KpiAreaRepository.FirstOrDefaultAsync(x => x.Id == priceAreaId.Value);
|
||||
var rules = await KpiAreaRepository.GetAllInfosByAreaIdAsync(priceAreaId.Value);
|
||||
foreach (var rule in rules)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(rule.CountryCode)
|
||||
&& !string.Equals(rule.CountryCode, context.CountryCode, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(rule.Province) || !string.IsNullOrWhiteSpace(rule.City))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var keys = ParcelBillingCalculator.BuildPriceZoneKeys(rule, area);
|
||||
if (keys.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (attempts.Any(x => x.ZoneKeys.SequenceEqual(keys, StringComparer.OrdinalIgnoreCase)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
attempts.Add(new QuoteZoneAttempt(keys.ToList(), true, keys[0]));
|
||||
}
|
||||
}
|
||||
|
||||
return attempts;
|
||||
|
||||
@ -156,6 +156,32 @@ internal static class ParcelBillingCalculator
|
||||
return keys.Count > 0 ? keys : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查价仅填国家时:若快照已配置该目的国分区(即使规则带邮编区间),
|
||||
/// 则返回卖价明细中的分区键供估算报价;未配置该国家时返回空(不跨国家兜底)。
|
||||
/// </summary>
|
||||
public static IReadOnlyList<string> CollectCountryEstimateZoneKeys(
|
||||
SalesProductPricePublishSnapshotDto? priceSnapshot,
|
||||
string countryCode)
|
||||
{
|
||||
if (priceSnapshot?.PriceAreaInfos == null
|
||||
|| priceSnapshot.PriceAreaInfos.Count == 0
|
||||
|| string.IsNullOrWhiteSpace(countryCode))
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var countryConfigured = priceSnapshot.PriceAreaInfos.Any(rule =>
|
||||
string.IsNullOrWhiteSpace(rule.CountryCode)
|
||||
|| string.Equals(rule.CountryCode, countryCode, StringComparison.OrdinalIgnoreCase));
|
||||
if (!countryConfigured)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return CollectDistinctDetailZoneKeys(priceSnapshot);
|
||||
}
|
||||
|
||||
public static string? ResolveZoneName(KpiAreaInfo? matched, KpiArea? area)
|
||||
{
|
||||
if (matched == null)
|
||||
|
||||
@ -303,4 +303,45 @@ public class PriceCheckSnapshotVerificationTests
|
||||
|
||||
fees.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CountryEstimate_WhenCountryConfiguredWithPostcodeRules_ShouldReturnDetailZones()
|
||||
{
|
||||
var snapshot = BuildUserSnapshot();
|
||||
snapshot.PriceAreaInfos =
|
||||
[
|
||||
new KpiAreaSnapshotRuleDto
|
||||
{
|
||||
Id = 11,
|
||||
CountryCode = "US",
|
||||
PostcodeRange = "(90000,99999]"
|
||||
}
|
||||
];
|
||||
|
||||
// 精确匹配(无邮编)应失败
|
||||
ParcelBillingCalculator.TryResolveZoneKeysFromPriceSnapshot(snapshot, "US", null, null, null)
|
||||
.Should().BeNull();
|
||||
|
||||
// 国家估算应返回卖价明细分区键
|
||||
ParcelBillingCalculator.CollectCountryEstimateZoneKeys(snapshot, "US")
|
||||
.Should().Contain(["3"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CountryEstimate_WhenCountryNotConfigured_ShouldReturnEmpty()
|
||||
{
|
||||
var snapshot = BuildUserSnapshot();
|
||||
snapshot.PriceAreaInfos =
|
||||
[
|
||||
new KpiAreaSnapshotRuleDto
|
||||
{
|
||||
Id = 11,
|
||||
CountryCode = "US",
|
||||
PostcodeRange = "(90000,99999]"
|
||||
}
|
||||
];
|
||||
|
||||
ParcelBillingCalculator.CollectCountryEstimateZoneKeys(snapshot, "DE")
|
||||
.Should().BeEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user