升级报价遇到目录倒挂时改为报错
quote_runtime_profile_membership_upgrade 用 checked_sub 替换 saturating_sub,价格或每期泥点倒挂时返回 InvalidQuoteInput 新增 inverted_catalog_price_and_points_are_rejected 覆盖原本会算成 0 元升级的场景 Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -158,8 +158,15 @@ pub fn quote_runtime_profile_membership_upgrade(
|
||||
input.now_micros,
|
||||
);
|
||||
|
||||
let price_delta_cents = target.price_cents.saturating_sub(current.price_cents);
|
||||
let points_delta = target.period_points.saturating_sub(current.period_points);
|
||||
// 目录价格 / 每期泥点必须严格随 rank 递增;倒挂时宁可报错,也不算出 0 元升级。
|
||||
let price_delta_cents = target
|
||||
.price_cents
|
||||
.checked_sub(current.price_cents)
|
||||
.ok_or(RuntimeProfileMembershipUpgradeRejection::InvalidQuoteInput)?;
|
||||
let points_delta = target
|
||||
.period_points
|
||||
.checked_sub(current.period_points)
|
||||
.ok_or(RuntimeProfileMembershipUpgradeRejection::InvalidQuoteInput)?;
|
||||
|
||||
let (amount_cents, granted_points_delta) = match target.cycle_kind {
|
||||
RuntimeProfileMembershipCycleKind::Monthly => (price_delta_cents, points_delta),
|
||||
@@ -401,6 +408,41 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inverted_catalog_price_and_points_are_rejected() {
|
||||
// 中文注释:后台把更高档位定得更便宜 / 给更少每期泥点时,报价必须报错,
|
||||
// 而不是被 saturating_sub 静默算成 0 元升级。
|
||||
let current = snapshot(
|
||||
RuntimeProfileMembershipPlan::Pro,
|
||||
RuntimeProfileMembershipCycleKind::Yearly,
|
||||
);
|
||||
let mut target = snapshot(
|
||||
RuntimeProfileMembershipPlan::Max,
|
||||
RuntimeProfileMembershipCycleKind::Yearly,
|
||||
);
|
||||
|
||||
target.price_cents = current.price_cents - 1;
|
||||
assert_eq!(
|
||||
quote_runtime_profile_membership_upgrade(RuntimeProfileMembershipUpgradeQuoteInput {
|
||||
current: current.clone(),
|
||||
target: target.clone(),
|
||||
..base_input()
|
||||
}),
|
||||
Err(RuntimeProfileMembershipUpgradeRejection::InvalidQuoteInput)
|
||||
);
|
||||
|
||||
target.price_cents = current.price_cents + 1;
|
||||
target.period_points = current.period_points - 1;
|
||||
assert_eq!(
|
||||
quote_runtime_profile_membership_upgrade(RuntimeProfileMembershipUpgradeQuoteInput {
|
||||
current,
|
||||
target,
|
||||
..base_input()
|
||||
}),
|
||||
Err(RuntimeProfileMembershipUpgradeRejection::InvalidQuoteInput)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cycle_kind_change_is_rejected() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user