From af0721fb78ed8f822b490636f5370f7af7f4db25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sat, 3 Oct 2026 17:24:00 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E4=BC=9A=E5=91=98):=20=E5=9B=9E=E7=81=8C?= =?UTF-8?q?=E5=90=8E=E6=94=B6=E6=95=9B=E5=85=85=E7=82=B9=E5=95=86=E5=93=81?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E5=B9=B6=E6=B8=85=E7=90=86=E9=80=80=E5=BD=B9?= =?UTF-8?q?=E4=BC=9A=E5=91=98=E5=95=86=E5=93=81=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - profile.rs 新增 converge_default_profile_recharge_product_config,在存量库读取路径补齐缺失的 points_1280 / points_3280 档位。 - 同一步骤删除已退役的 membership 类型充点商品配置行,避免冲突迁移把旧 member_* 行原样带回后残留。 - 存量库充值商品目录因此幂等收敛到当前六档点卡,不再停留在旧四档 + 四行会员商品。 --- .../src/runtime/active/profile.rs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/server-rs/crates/spacetime-module/src/runtime/active/profile.rs b/server-rs/crates/spacetime-module/src/runtime/active/profile.rs index 869fc7af6..f028340c5 100644 --- a/server-rs/crates/spacetime-module/src/runtime/active/profile.rs +++ b/server-rs/crates/spacetime-module/src/runtime/active/profile.rs @@ -8855,6 +8855,7 @@ pub fn init_profile_membership_plan_catalog(ctx: &ReducerContext) { fn ensure_default_profile_recharge_product_config(ctx: &ReducerContext) { if ctx.db.profile_recharge_product_config().count() > 0 { migrate_legacy_default_profile_recharge_product_config(ctx); + converge_default_profile_recharge_product_config(ctx); return; } @@ -8961,6 +8962,64 @@ fn migrate_legacy_default_profile_recharge_product_config(ctx: &ReducerContext) } } +/// 存量库 / 冲突迁移回灌后把充点商品收敛到当前六档目录。 +/// +/// 迁移目的:冲突迁移会清库发布再回灌旧 `profile_recharge_product_config`;旧库里的 +/// `member_*` 会员商品行会被原样带回,而新增的 `points_1280` / `points_3280` 不在旧包里, +/// [`migrate_legacy_default_profile_recharge_product_config`] 又只归一旧行、不补缺档。 +/// 这里在读取路径幂等补齐缺失档位并删除已退役的会员商品配置行。 +fn converge_default_profile_recharge_product_config(ctx: &ReducerContext) { + let now = ctx.timestamp; + for (sort_order, product) in runtime_profile_recharge_point_products() + .into_iter() + .enumerate() + { + let product_id = product.product_id.clone(); + if ctx + .db + .profile_recharge_product_config() + .product_id() + .find(&product_id) + .is_some() + { + continue; + } + ctx.db + .profile_recharge_product_config() + .insert(ProfileRechargeProductConfig { + product_id: product.product_id, + title: product.title, + price_cents: product.price_cents, + kind: product.kind, + points_amount: product.points_amount, + bonus_points: product.bonus_points, + duration_days: product.duration_days, + badge_label: product.badge_label, + description: product.description, + enabled: true, + sort_order: sort_order as i32, + created_by: PROFILE_RECHARGE_PRODUCT_SYSTEM_USER_ID.to_string(), + created_at: now, + updated_by: PROFILE_RECHARGE_PRODUCT_SYSTEM_USER_ID.to_string(), + updated_at: now, + }); + } + + let retired_membership_product_ids = ctx + .db + .profile_recharge_product_config() + .iter() + .filter(|row| row.kind == RuntimeProfileRechargeProductKind::Membership) + .map(|row| row.product_id) + .collect::>(); + for product_id in retired_membership_product_ids { + ctx.db + .profile_recharge_product_config() + .product_id() + .delete(&product_id); + } +} + fn profile_recharge_product_config_rows( ctx: &ReducerContext, include_disabled: bool,