fix(会员结算): cycle_index==0 迁移行按 max(1) 归一,避免误判状态已变化

- frozen_membership_cycle_matches 比较双方都按 max(1) 归一(评审第 20 条)
- 存量 cycle_index 为 0 的会员行与投影的 Some(1) 快照现在判定一致,不再永久返回「会员状态已变化,请重新下单」
- 扩展 frozen_membership_cycle_identity_rejects_advanced_cycle 覆盖迁移行;已验证去掉 max(1) 时用例失败
This commit is contained in:
2026-10-04 21:51:42 +08:00
parent 284b656b59
commit 14c147722a
@@ -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;
}
}