diff --git a/server-rs/crates/module-runtime/src/commands.rs b/server-rs/crates/module-runtime/src/commands.rs index 02d11db91..22765aa15 100644 --- a/server-rs/crates/module-runtime/src/commands.rs +++ b/server-rs/crates/module-runtime/src/commands.rs @@ -410,12 +410,12 @@ pub fn build_runtime_profile_recharge_product_admin_upsert_input( return Err(RuntimeProfileFieldError::InvalidRechargeProductPoints); } if duration_days != 0 || bonus_points != 0 { - return Err(RuntimeProfileFieldError::InvalidRechargeProductTier); + return Err(RuntimeProfileFieldError::InvalidRechargeProductFields); } } // 中文注释:会员商品已迁移到 profile_membership_plan 目录,这里只保留泥点商品。 RuntimeProfileRechargeProductKind::Membership => { - return Err(RuntimeProfileFieldError::InvalidRechargeProductTier); + return Err(RuntimeProfileFieldError::InvalidRechargeProductKind); } } @@ -445,7 +445,8 @@ pub fn build_runtime_profile_membership_plan_admin_list_input( /// 后台会员档位改价 / 改权益入参校验。 /// -/// `normal` 是不可购买的非会员占位档位:它的价格与额度没有意义,一律按 0 落库。 +/// `normal` 是不可购买的非会员占位档位:价格与每期泥点一律按 0 落库; +/// 并发上限与模型权限固定为目录种子里的非会员基线,后台不能改。 #[allow(clippy::too_many_arguments)] pub fn build_runtime_profile_membership_plan_admin_upsert_input( admin_user_id: String, @@ -465,6 +466,9 @@ pub fn build_runtime_profile_membership_plan_admin_upsert_input( normalize_required_string(title).ok_or(RuntimeProfileFieldError::MissingProductTitle)?; if !plan.is_purchasable() { + // 中文注释:非会员基线固定取自目录种子,避免后台把「非会员」改成 0 并发或「不限并发」。 + let baseline = crate::resolve_runtime_profile_membership_plan_row(plan) + .ok_or(RuntimeProfileFieldError::InvalidMembershipPlan)?; return Ok(RuntimeProfileMembershipPlanAdminUpsertInput { admin_user_id, plan, @@ -472,15 +476,19 @@ pub fn build_runtime_profile_membership_plan_admin_upsert_input( month_price_cents: 0, year_price_cents: 0, period_points: 0, - model_access, - concurrent_job_limit, + model_access: baseline.model_access, + concurrent_job_limit: baseline.concurrent_job_limit, enabled: false, sort_order, updated_at_micros, }); } - if month_price_cents == 0 || year_price_cents == 0 || concurrent_job_limit == 0 { + if month_price_cents == 0 + || year_price_cents == 0 + || period_points == 0 + || concurrent_job_limit == 0 + { return Err(RuntimeProfileFieldError::InvalidMembershipPlan); } diff --git a/server-rs/crates/module-runtime/src/errors.rs b/server-rs/crates/module-runtime/src/errors.rs index f282bd0c4..99e43f685 100644 --- a/server-rs/crates/module-runtime/src/errors.rs +++ b/server-rs/crates/module-runtime/src/errors.rs @@ -90,7 +90,7 @@ pub enum RuntimeProfileFieldError { InvalidRechargeProductPoints, InvalidRechargeProductDuration, InvalidRechargeProductKind, - InvalidRechargeProductTier, + InvalidRechargeProductFields, InvalidMembershipPlan, MissingPaymentChannel, #[cfg(any())] @@ -185,8 +185,12 @@ impl std::fmt::Display for RuntimeProfileFieldError { Self::InvalidRechargeProductDuration => { f.write_str("会员商品 duration_days 必须大于 0") } - Self::InvalidRechargeProductKind => f.write_str("充值商品类型无效"), - Self::InvalidRechargeProductTier => f.write_str("会员商品 tier 无效"), + Self::InvalidRechargeProductKind => { + f.write_str("充值商品类型无效:会员商品已迁移到会员档位目录") + } + Self::InvalidRechargeProductFields => { + f.write_str("泥点商品不支持 duration_days 与 bonus_points 字段") + } Self::InvalidMembershipPlan => { f.write_str("会员档位配置无效:月价、年价、每期泥点与并发上限必须有效") }