From 168028d5e554ba466bcad71e52e8b0e85d4fff34 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 11:21:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3(=E4=BC=9A=E5=91=98=E8=B4=A6?= =?UTF-8?q?=E6=9C=9F)=EF=BC=9A=E6=9C=9F=E5=8F=B7=E6=B0=B4=E4=BD=8D?= =?UTF-8?q?=E7=BC=BA=E5=A4=B1=E4=B8=8D=E5=86=8D=E8=A2=AB=E5=BD=93=E6=88=90?= =?UTF-8?q?=E6=8D=A2=E6=9C=9F=E9=87=8D=E5=8F=91=E9=A2=9D=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - advance_profile_membership_cycle_to 只在 cycle_resets_at 缺失时判定需要初始化写库 - cycle_index == 0(新列默认值)只补写期号水位,不重置 cycle_granted/remaining_points - 补测试覆盖 cycle_index=0 且账期窗口已存在时保留本期余额 --- .../src/runtime/active/profile.rs | 20 ++++++++++++++++++- 1 file changed, 19 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 fff05e9dd..e37eed3dc 100644 --- a/server-rs/crates/spacetime-module/src/runtime/active/profile.rs +++ b/server-rs/crates/spacetime-module/src/runtime/active/profile.rs @@ -4192,6 +4192,18 @@ mod tests { assert_eq!(same_period.row.cycle_index, 1); assert_eq!(same_period.row.cycle_remaining_points, 120); + // 期号水位为 0(新列默认值)但账期窗口已存在:只补水期号,不重发本期额度。 + let mut stale_watermark = row(); + stale_watermark.cycle_index = 0; + let backfilled = advance_profile_membership_cycle_to( + stale_watermark, + Timestamp::from_micros_since_unix_epoch(anchor + 10 * day), + 400, + ); + assert!(!backfilled.advanced, "期号水位缺失不应被当成换期"); + assert_eq!(backfilled.row.cycle_index, 1); + assert_eq!(backfilled.row.cycle_remaining_points, 120); + let next_period = advance_profile_membership_cycle_to( row(), Timestamp::from_micros_since_unix_epoch(anchor + 28 * day), @@ -9424,7 +9436,13 @@ fn advance_profile_membership_cycle_to( // 起点取已落库的期号(水位下限),保证只前进、不后退。 let mut cycle_index = row.cycle_index.max(1); let mut window = membership_cycle_window(anchor_micros, cycle_index); - let mut advanced = row.cycle_resets_at.is_none() || row.cycle_index == 0; + // `cycle_resets_at` 缺失 = 账期窗口尚未初始化,需要写库补种并发放本期额度; + // `cycle_index == 0` 只是期号水位没写(新列默认值),不能据此判定越界、重发额度。 + let mut advanced = row.cycle_resets_at.is_none(); + if row.cycle_index == 0 { + // 仅补写期号水位:账期额度只应在真正越过边界时重置。 + row.cycle_index = 1; + } // 仅当 `at` 已越过当前窗口结束时刻才推进;时钟回拨时条件不成立,整行保持原状。 while window.1 <= at_micros && cycle_index < max_index { cycle_index = cycle_index.saturating_add(1);