## ADDED Requirements ### Requirement: 套餐流量对外语义统一 系统 SHALL 以套餐使用记录为事实源,对外统一返回 `real_total_mb`、`real_used_mb`、`virtual_total_mb`、`virtual_used_mb` 和 `reduction_pct`,不再要求调用方从旧字段或 live `tb_package` 值自行拼接流量语义。 **字段语义**: - `real_total_mb`: 套餐真实总量 - `real_used_mb`: 套餐真实已用量 - `virtual_total_mb`: 套餐业务停机阈值 - `virtual_used_mb`: 将 `real_used_mb` 映射到 `real_total_mb` 刻度后的展示值 - `reduction_pct`: 默认按 `(real_total_mb / virtual_total_mb) - 1` 计算,字段名继续沿用业务口语“缩减比例”,接口返回值使用 `0.428571` 这种比例小数格式 #### Scenario: 启用虚流量时返回统一五字段 - **WHEN** 某条套餐使用记录的 `real_total_mb=100`、`real_used_mb=50`、`virtual_total_mb=70` - **THEN** 系统返回 `virtual_used_mb=71.43` - **AND** 同时返回 `reduction_pct=0.428571...` #### Scenario: 未启用虚流量时退化为真流量视图 - **WHEN** 某条套餐使用记录未启用虚流量 - **THEN** 系统返回 `virtual_total_mb = real_total_mb` - **AND** `virtual_used_mb = real_used_mb` - **AND** `reduction_pct=0` ### Requirement: 虚已用展示公式统一 系统 SHALL 使用统一公式计算 `virtual_used_mb`:`min(real_used_mb * (real_total_mb / virtual_total_mb), real_total_mb)`。 #### Scenario: 真已用接近虚阈值时展示接近满量程 - **WHEN** `real_total_mb=100`、`virtual_total_mb=70`、`real_used_mb=69` - **THEN** 系统返回 `virtual_used_mb=98.57` #### Scenario: 真已用达到虚阈值时展示封顶 - **WHEN** `real_total_mb=100`、`virtual_total_mb=70`、`real_used_mb=70` - **THEN** 系统返回 `virtual_used_mb=100` ### Requirement: 套餐耗尽阈值统一 系统 SHALL 将套餐业务耗尽阈值统一定义为:启用虚流量时使用 `virtual_total_mb`,未启用虚流量时使用 `real_total_mb`。 #### Scenario: 启用虚流量时按虚阈值耗尽 - **WHEN** 某条套餐使用记录 `real_total_mb=100`、`virtual_total_mb=70`、`real_used_mb=70` - **THEN** 系统将该套餐判定为已用完 #### Scenario: 未启用虚流量时按真总量耗尽 - **WHEN** 某条套餐使用记录未启用虚流量且 `real_used_mb=real_total_mb` - **THEN** 系统将该套餐判定为已用完 ### Requirement: 历史套餐流量快照可回放 系统 SHALL 在 `tb_package_usage` 上持久化虚总量与展示映射所需快照,以保证历史流量展示不继续依赖 live `tb_package` 值。 #### Scenario: 创建新套餐使用记录时写入快照 - **WHEN** 系统创建新的 `PackageUsage` - **THEN** 同步写入 `virtual_total_mb_snapshot`、展示倍率快照和虚流量开关快照 #### Scenario: 历史套餐记录执行一次性回填 - **WHEN** 本次变更上线执行历史数据迁移 - **THEN** 系统为已有 `PackageUsage` 回填虚总量与展示倍率快照 - **AND** 后续读链路优先读取快照值而不是 `tb_package` 当前值