From 14c147722a2cef416318e0fa7bf3dfa7f6cbf50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sun, 4 Oct 2026 21:51:42 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E4=BC=9A=E5=91=98=E7=BB=93=E7=AE=97):=20cy?= =?UTF-8?q?cle=5Findex=3D=3D0=20=E8=BF=81=E7=A7=BB=E8=A1=8C=E6=8C=89=20max?= =?UTF-8?q?(1)=20=E5=BD=92=E4=B8=80=EF=BC=8C=E9=81=BF=E5=85=8D=E8=AF=AF?= =?UTF-8?q?=E5=88=A4=E7=8A=B6=E6=80=81=E5=B7=B2=E5=8F=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - frozen_membership_cycle_matches 比较双方都按 max(1) 归一(评审第 20 条) - 存量 cycle_index 为 0 的会员行与投影的 Some(1) 快照现在判定一致,不再永久返回「会员状态已变化,请重新下单」 - 扩展 frozen_membership_cycle_identity_rejects_advanced_cycle 覆盖迁移行;已验证去掉 max(1) 时用例失败 --- .../spacetime-module/src/runtime/active/profile.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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 6c0850b16..b41d69eb8 100644 --- a/server-rs/crates/spacetime-module/src/runtime/active/profile.rs +++ b/server-rs/crates/spacetime-module/src/runtime/active/profile.rs @@ -4578,6 +4578,16 @@ mod tests { &settlement(None, None), &row )); + // 中文注释:存量的 `cycle_index == 0` 迁移行与投影的 `max(1)` 归一值等价, + // 不能因为「原始行还是 0」把建单快照 `Some(1)` 判成账期已变化。 + let legacy_row = ProfileMembership { + cycle_index: 0, + ..row + }; + assert!(frozen_membership_cycle_matches( + &settlement(Some(1), Some(anchor + 28 * day)), + &legacy_row + )); } #[test] @@ -9553,7 +9563,9 @@ fn frozen_membership_cycle_matches( row: &ProfileMembership, ) -> bool { if let Some(cycle_index_before) = settlement.cycle_index_before { - if cycle_index_before != row.cycle_index { + // `cycle_index == 0` 是存量「水位未初始化」哨兵;只读投影统一 `max(1)` 归一到第 1 期。 + // 结算侧同样归一,否则迁移行会被永久判成「会员状态已变化」而无法结算(评审第 20 条)。 + if cycle_index_before.max(1) != row.cycle_index.max(1) { return false; } }