领域层:新增会员档位、周期、模型权限与变更类型枚举
- 新增 RuntimeProfileMembershipPlan { Normal, Starter, Plus, Pro, Max } 作为档位权威身份,取代旧 RuntimeProfileMembershipTier
- 新增 RuntimeProfileMembershipCycleKind:月付 1 期、年付 12 期(每期仍为一个自然月)
- 新增 RuntimeProfileMembershipModelAccess { Basic, Full } 与 RuntimeProfileMembershipChangeKind { Purchase, Upgrade }
- 四个枚举各带 as_str 与 parse,未知对外 token 返回 None,由调用方显式拒绝
- 新增集成测试 tests/membership_plan_enum.rs:token 往返、Normal 不可购买、期数映射、未知 token 拒绝
Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -1255,6 +1255,131 @@ impl RuntimeProfileMembershipTier {
|
||||
}
|
||||
}
|
||||
|
||||
/// 会员档位身份。取代旧的 `RuntimeProfileMembershipTier`,作为唯一权威档位标识。
|
||||
///
|
||||
/// 变体顺序即排序基准(`Normal < Starter < Plus < Pro < Max`),升级比较不再依赖旧枚举别名。
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum RuntimeProfileMembershipPlan {
|
||||
Normal,
|
||||
Starter,
|
||||
Plus,
|
||||
Pro,
|
||||
Max,
|
||||
}
|
||||
|
||||
impl RuntimeProfileMembershipPlan {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Normal => "normal",
|
||||
Self::Starter => "starter",
|
||||
Self::Plus => "plus",
|
||||
Self::Pro => "pro",
|
||||
Self::Max => "max",
|
||||
}
|
||||
}
|
||||
|
||||
/// 严格解析对外 wire token;未知 token 返回 `None`,调用方必须显式拒绝,不接受自由字符串。
|
||||
pub fn parse(value: &str) -> Option<Self> {
|
||||
match value {
|
||||
"normal" => Some(Self::Normal),
|
||||
"starter" => Some(Self::Starter),
|
||||
"plus" => Some(Self::Plus),
|
||||
"pro" => Some(Self::Pro),
|
||||
"max" => Some(Self::Max),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// `Normal` 不是可售档位,其余档位可在充值中心购买。
|
||||
pub fn is_purchasable(&self) -> bool {
|
||||
!matches!(self, Self::Normal)
|
||||
}
|
||||
}
|
||||
|
||||
/// 会员购买周期类型。它只决定本次购买的总期数与到期日,单期窗口一律按自然月推进。
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum RuntimeProfileMembershipCycleKind {
|
||||
Monthly,
|
||||
Yearly,
|
||||
}
|
||||
|
||||
impl RuntimeProfileMembershipCycleKind {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Monthly => "monthly",
|
||||
Self::Yearly => "yearly",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(value: &str) -> Option<Self> {
|
||||
match value {
|
||||
"monthly" => Some(Self::Monthly),
|
||||
"yearly" => Some(Self::Yearly),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 本次购买的总期数:月付 1 期、年付 12 期(每期仍是一个自然月)。
|
||||
pub fn cycle_count(&self) -> u32 {
|
||||
match self {
|
||||
Self::Monthly => 1,
|
||||
Self::Yearly => 12,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 档位允许选择的模型范围。本期只落字段、只用于展示,服务端不做拦截。
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum RuntimeProfileMembershipModelAccess {
|
||||
Basic,
|
||||
Full,
|
||||
}
|
||||
|
||||
impl RuntimeProfileMembershipModelAccess {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Basic => "basic",
|
||||
Self::Full => "full",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(value: &str) -> Option<Self> {
|
||||
match value {
|
||||
"basic" => Some(Self::Basic),
|
||||
"full" => Some(Self::Full),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 会员订单产生的权益变更类型,用于订单快照区分「新购」与「补差升级」。
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum RuntimeProfileMembershipChangeKind {
|
||||
Purchase,
|
||||
Upgrade,
|
||||
}
|
||||
|
||||
impl RuntimeProfileMembershipChangeKind {
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Purchase => "purchase",
|
||||
Self::Upgrade => "upgrade",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(value: &str) -> Option<Self> {
|
||||
match value {
|
||||
"purchase" => Some(Self::Purchase),
|
||||
"upgrade" => Some(Self::Upgrade),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "spacetime-types", derive(SpacetimeType))]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum RuntimeProfileRechargeOrderStatus {
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
use module_runtime::{
|
||||
RuntimeProfileMembershipChangeKind, RuntimeProfileMembershipCycleKind,
|
||||
RuntimeProfileMembershipModelAccess, RuntimeProfileMembershipPlan,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn membership_plan_tokens_round_trip_strictly() {
|
||||
// 中文注释:对外 wire token 必须与枚举一一对应,未知 token 一律解析失败。
|
||||
let cases = [
|
||||
(RuntimeProfileMembershipPlan::Normal, "normal"),
|
||||
(RuntimeProfileMembershipPlan::Starter, "starter"),
|
||||
(RuntimeProfileMembershipPlan::Plus, "plus"),
|
||||
(RuntimeProfileMembershipPlan::Pro, "pro"),
|
||||
(RuntimeProfileMembershipPlan::Max, "max"),
|
||||
];
|
||||
for (plan, token) in cases {
|
||||
assert_eq!(plan.as_str(), token);
|
||||
assert_eq!(RuntimeProfileMembershipPlan::parse(token), Some(plan));
|
||||
}
|
||||
|
||||
assert_eq!(RuntimeProfileMembershipPlan::parse("basic"), None);
|
||||
assert_eq!(RuntimeProfileMembershipPlan::parse("ultimate"), None);
|
||||
assert_eq!(RuntimeProfileMembershipPlan::parse("PLUS"), None);
|
||||
assert_eq!(RuntimeProfileMembershipPlan::parse(""), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn membership_plan_normal_is_not_purchasable() {
|
||||
// 中文注释:Normal 是非会员占位档位,不允许被购买。
|
||||
assert!(!RuntimeProfileMembershipPlan::Normal.is_purchasable());
|
||||
for plan in [
|
||||
RuntimeProfileMembershipPlan::Starter,
|
||||
RuntimeProfileMembershipPlan::Plus,
|
||||
RuntimeProfileMembershipPlan::Pro,
|
||||
RuntimeProfileMembershipPlan::Max,
|
||||
] {
|
||||
assert!(plan.is_purchasable());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn membership_cycle_kind_maps_to_period_count() {
|
||||
// 中文注释:年付 12 期、月付 1 期,每期仍是一个自然月。
|
||||
assert_eq!(RuntimeProfileMembershipCycleKind::Monthly.cycle_count(), 1);
|
||||
assert_eq!(RuntimeProfileMembershipCycleKind::Yearly.cycle_count(), 12);
|
||||
assert_eq!(
|
||||
RuntimeProfileMembershipCycleKind::Monthly.as_str(),
|
||||
"monthly"
|
||||
);
|
||||
assert_eq!(RuntimeProfileMembershipCycleKind::Yearly.as_str(), "yearly");
|
||||
assert_eq!(
|
||||
RuntimeProfileMembershipCycleKind::parse("yearly"),
|
||||
Some(RuntimeProfileMembershipCycleKind::Yearly)
|
||||
);
|
||||
assert_eq!(RuntimeProfileMembershipCycleKind::parse("weekly"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn membership_model_access_and_change_kind_tokens_round_trip() {
|
||||
assert_eq!(RuntimeProfileMembershipModelAccess::Basic.as_str(), "basic");
|
||||
assert_eq!(RuntimeProfileMembershipModelAccess::Full.as_str(), "full");
|
||||
assert_eq!(
|
||||
RuntimeProfileMembershipModelAccess::parse("full"),
|
||||
Some(RuntimeProfileMembershipModelAccess::Full)
|
||||
);
|
||||
assert_eq!(RuntimeProfileMembershipModelAccess::parse("premium"), None);
|
||||
|
||||
assert_eq!(
|
||||
RuntimeProfileMembershipChangeKind::Purchase.as_str(),
|
||||
"purchase"
|
||||
);
|
||||
assert_eq!(
|
||||
RuntimeProfileMembershipChangeKind::Upgrade.as_str(),
|
||||
"upgrade"
|
||||
);
|
||||
assert_eq!(
|
||||
RuntimeProfileMembershipChangeKind::parse("upgrade"),
|
||||
Some(RuntimeProfileMembershipChangeKind::Upgrade)
|
||||
);
|
||||
assert_eq!(RuntimeProfileMembershipChangeKind::parse("downgrade"), None);
|
||||
}
|
||||
Reference in New Issue
Block a user