fix(ccgo): GOAT 计划月度额度映射 + 详情页月度重置倒计时修复
- PLANS 新增 individual-goat→$70(官网 GOAT 计划,5h $14 / weekly $35 / monthly $70), 修正 individual-pro 30→80,planDisplayName 映射 GOAT - 抽 internal planMonthlyQuota/planDisplayName(大小写不敏感、未知计划安全降级) - 详情页月度重置倒计时改用仓库已算好的 monthly.resetInSec(原按 ISO 解析 epoch 毫秒的 billingPeriodEnd 恒失败,倒计时永不显示) - 新增 7 个计划映射测试
This commit is contained in:
parent
6cd54a3a8f
commit
24eb3e190c
@ -65,7 +65,7 @@ class CommandCodeGoRepository(
|
||||
|
||||
// 从订阅信息拿计划名称,查 plan catalog 拿总量
|
||||
val monthlyTotal = subResult.getOrNull()?.let { sub ->
|
||||
PLANS[sub.planId.lowercase()]
|
||||
planMonthlyQuota(sub.planId)
|
||||
}
|
||||
val billingPeriodEndMillis = subResult.getOrNull()?.let { parseIsoToEpoch(it.currentPeriodEnd) }
|
||||
|
||||
@ -187,24 +187,35 @@ class CommandCodeGoRepository(
|
||||
} catch (_: Exception) { null }
|
||||
}
|
||||
|
||||
private fun planDisplayName(planId: String): String =
|
||||
PLAN_NAMES[planId.lowercase()] ?: planId
|
||||
|
||||
companion object {
|
||||
/** 计划 → 月度额度(美元)。2026-08 起官网新计划体系:
|
||||
* Go $1 → $10、GOAT $10 → $70、Pro $20 → $80、Max 10× $100 → $150、Max 20× $200 → $300。
|
||||
* 旧值 individual-go=10 与 individual-goat=70 并存(goat 是当前主流计划)。
|
||||
*/
|
||||
private val PLANS = mapOf(
|
||||
"individual-go" to 10.0,
|
||||
"individual-pro" to 30.0,
|
||||
"individual-goat" to 70.0,
|
||||
"individual-pro" to 80.0,
|
||||
"individual-max" to 150.0,
|
||||
"individual-ultra" to 300.0
|
||||
)
|
||||
|
||||
private val PLAN_NAMES = mapOf(
|
||||
"individual-go" to "Go",
|
||||
"individual-goat" to "GOAT",
|
||||
"individual-pro" to "Pro",
|
||||
"individual-max" to "Max",
|
||||
"individual-ultra" to "Ultra"
|
||||
)
|
||||
|
||||
/** 按 planId 查月度额度(美元);未知计划返回 null(调用方安全降级)。 */
|
||||
internal fun planMonthlyQuota(planId: String?): Double? =
|
||||
planId?.lowercase()?.let { PLANS[it] }
|
||||
|
||||
/** 按 planId 查展示名;未知计划原样返回。 */
|
||||
internal fun planDisplayName(planId: String?): String =
|
||||
planId?.lowercase()?.let { PLAN_NAMES[it] } ?: planId ?: ""
|
||||
|
||||
/** API 返回的是 epoch millis,转为距现在的剩余秒数 */
|
||||
private fun epochToRemainingSec(epochMillis: Long): Long =
|
||||
maxOf(0L, (epochMillis - System.currentTimeMillis()) / 1000)
|
||||
|
||||
@ -314,7 +314,8 @@ private fun CommandCodeGoUsageCard(state: State) {
|
||||
UsageWindowRow(
|
||||
label = stringResource(R.string.window_monthly),
|
||||
pct = pct,
|
||||
resetInSec = extras["billingPeriodEnd"]?.let { parseIsoDuration(it) }
|
||||
// 仓库已把账单周期结束转成剩余秒写入 monthly.resetInSec(billingPeriodEnd 是 epoch 毫秒,不能按 ISO 解析)
|
||||
resetInSec = extras["monthly.resetInSec"]?.toLongOrNull()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
Text(
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
package com.rainy.token.data.repository
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Unit tests for [CommandCodeGoRepository] 的计划 → 月度额度映射。
|
||||
*
|
||||
* 2026-08 官网更新了计划体系(GOAT 等新计划),旧映射缺少
|
||||
* individual-goat 会导致 GOAT 用户月度总量/已用计算缺失。
|
||||
*/
|
||||
class CommandCodeGoPlanMappingTest {
|
||||
|
||||
@Test
|
||||
fun `goat plan maps to 70 usd monthly quota`() {
|
||||
assertEquals(70.0, CommandCodeGoRepository.planMonthlyQuota("individual-goat")!!, 0.001)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `go plan maps to 10 usd monthly quota`() {
|
||||
assertEquals(10.0, CommandCodeGoRepository.planMonthlyQuota("individual-go")!!, 0.001)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `pro plan maps to 80 usd monthly quota`() {
|
||||
assertEquals(80.0, CommandCodeGoRepository.planMonthlyQuota("individual-pro")!!, 0.001)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `max plans map to 150 and 300 usd monthly quota`() {
|
||||
assertEquals(150.0, CommandCodeGoRepository.planMonthlyQuota("individual-max")!!, 0.001)
|
||||
assertEquals(300.0, CommandCodeGoRepository.planMonthlyQuota("individual-ultra")!!, 0.001)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unknown plan returns null quota`() {
|
||||
assertNull(CommandCodeGoRepository.planMonthlyQuota("individual-unknown"))
|
||||
assertNull(CommandCodeGoRepository.planMonthlyQuota(null))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `plan id lookup is case insensitive`() {
|
||||
assertEquals(70.0, CommandCodeGoRepository.planMonthlyQuota("INDIVIDUAL-GOAT")!!, 0.001)
|
||||
assertEquals("GOAT", CommandCodeGoRepository.planDisplayName("Individual-Goat"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `unknown plan display name falls back to raw id`() {
|
||||
assertEquals("mystery-plan", CommandCodeGoRepository.planDisplayName("mystery-plan"))
|
||||
assertEquals("", CommandCodeGoRepository.planDisplayName(null))
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user