From 9011c68b9d5de0d27b44988fd7e8b6b157abedc1 Mon Sep 17 00:00:00 2001 From: SmartUp Developer Date: Thu, 2 Jul 2026 20:45:40 +0800 Subject: [PATCH] fix: use equal weight sharing for remaining 15% and quantize min_rate floor comparison to 2 decimal places --- backend/app/services/website_client.py | 18 ++++++------------ backend/test_website_client.py | 13 +++++++++++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/backend/app/services/website_client.py b/backend/app/services/website_client.py index f61568e..8c348f0 100644 --- a/backend/app/services/website_client.py +++ b/backend/app/services/website_client.py @@ -71,15 +71,9 @@ def calculate_target_rate(values: list[Any], percent: Any = 0, algorithm: str = if N == 1: base = rates_sorted[0] else: - base = Decimal("0") - remaining = Decimal("1.0") - for i in range(N): - if i == N - 1: - weight = remaining - else: - weight = remaining * Decimal("0.85") - remaining -= weight - base += rates_sorted[i] * weight + w1 = Decimal("0.85") + w_others = Decimal("0.15") / Decimal(N - 1) + base = rates_sorted[0] * w1 + sum(rates_sorted[1:], Decimal("0")) * w_others else: raise WebsiteError(f"不支持的算法:{algorithm}") pct = Decimal(str(percent or 0)) @@ -87,9 +81,9 @@ def calculate_target_rate(values: list[Any], percent: Any = 0, algorithm: str = raise WebsiteError("百分比不能为负数") target_rate = (base * (Decimal("1") + pct / Decimal("100"))).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP) if algorithm == "priority_weighted_plus_percent": - min_rate = min(rates) - if target_rate < min_rate: - target_rate = min_rate + min_rate_2d = min(rates).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP) + if target_rate < min_rate_2d: + target_rate = min_rate_2d return target_rate diff --git a/backend/test_website_client.py b/backend/test_website_client.py index 6f6eeae..4e27aae 100644 --- a/backend/test_website_client.py +++ b/backend/test_website_client.py @@ -406,8 +406,17 @@ def test_calculate_target_rate_priority_weighted(): assert calculate_target_rate(["0.18", "0.25"], 50, "priority_weighted_plus_percent") == Decimal("0.29") # 单来源时等同于该来源倍率 + 百分比 assert calculate_target_rate(["0.18"], 50, "priority_weighted_plus_percent") == Decimal("0.27") - # 多来源时权重按低倍率优先,最高倍率不会主导价格 - assert calculate_target_rate(["0.18", "0.25", "0.38"], 50, "priority_weighted_plus_percent") == Decimal("0.29") + # 多来源时最低倍率占 85%,其余平分 15%: + # 0.18 * 0.85 + (0.25 + 0.38) * 0.075 = 0.20025 -> 0.20025 * 1.5 = 0.300375 -> 0.30 + assert calculate_target_rate(["0.18", "0.25", "0.38"], 50, "priority_weighted_plus_percent") == Decimal("0.30") + + # 4 个来源以锁定均分 15% 的权重语义: + # 0.18 * 0.85 + (0.24 + 0.30 + 0.36) * 0.05 = 0.198 -> 0.198 * 1.5 = 0.297 -> 0.30 + assert calculate_target_rate(["0.18", "0.24", "0.30", "0.36"], 50, "priority_weighted_plus_percent") == Decimal("0.30") + assert calculate_target_rate(["0.18", "0.24", "0.30", "0.36"], 0, "priority_weighted_plus_percent") == Decimal("0.20") + + # 验证保护线与精度保护:最低来源 0.124,应当四舍五入并返回两位小数 + assert calculate_target_rate(["0.124"], 0, "priority_weighted_plus_percent") == Decimal("0.12") # 无可用正数倍率时报错 with pytest.raises(WebsiteError, match="没有可用的正数上游倍率"):