Skip to content

Commit 4ee2e3b

Browse files
[backport cloud/1.47] fix: use annual credit pool total (#13828)
Backport of #13826 to `cloud/1.47` Automatically created by backport workflow. Co-authored-by: Dante <bunggl@naver.com>
1 parent 629b829 commit 4ee2e3b

2 files changed

Lines changed: 54 additions & 28 deletions

File tree

src/platform/cloud/subscription/components/CreditsTile.test.ts

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -194,37 +194,59 @@ describe('CreditsTile', () => {
194194
expect(container.textContent).toContain('422 left of 21K')
195195
})
196196

197-
it('uses the team credit stop monthly grant for the monthly total', () => {
197+
it('uses the full annual Team grant for the credit pool total', () => {
198198
state.isActiveSubscription = true
199199
state.subscription = {
200200
tier: 'TEAM',
201201
duration: 'ANNUAL',
202202
renewalDate: '2026-02-20T12:00:00Z'
203203
}
204204
state.currentTeamCreditStop = {
205-
id: 'team_2500',
206-
credits_monthly: 527500,
207-
stop_usd: 2500
205+
id: 'team_700',
206+
credits_monthly: 147700,
207+
stop_usd: 700
208+
}
209+
state.balance = {
210+
amountMicros: 840000,
211+
cloudCreditBalanceMicros: 840000
212+
}
213+
const { container } = renderTile()
214+
expect(container.textContent).toContain('1,772,400 left of 1,772,400')
215+
})
216+
217+
it('keeps the monthly Team grant as the monthly credit pool total', () => {
218+
state.isActiveSubscription = true
219+
state.subscription = {
220+
tier: 'TEAM',
221+
duration: 'MONTHLY',
222+
renewalDate: '2026-02-20T12:00:00Z'
223+
}
224+
state.currentTeamCreditStop = {
225+
id: 'team_700',
226+
credits_monthly: 147700,
227+
stop_usd: 700
228+
}
229+
state.balance = {
230+
amountMicros: 70000,
231+
cloudCreditBalanceMicros: 70000
208232
}
209-
state.balance = { amountMicros: 0, cloudCreditBalanceMicros: 200 }
210233
const { container } = renderTile()
211-
// Monthly total is the stop's raw monthly grant, not the tier fallback,
212-
// and is not multiplied by 12 for annual billing.
213-
expect(container.textContent).toContain('422 left of 527,500')
234+
expect(container.textContent).toContain('147,700 left of 147,700')
214235
})
215236

216-
it('uses the per-month nominal grant for an annual personal tier', () => {
237+
it('uses the full annual grant for a personal tier credit pool', () => {
217238
state.isActiveSubscription = true
218239
state.subscription = {
219240
tier: 'PRO',
220241
duration: 'ANNUAL',
221242
renewalDate: '2026-02-20T12:00:00Z'
222243
}
223-
state.balance = { amountMicros: 0, cloudCreditBalanceMicros: 200 }
244+
state.balance = {
245+
amountMicros: 120000,
246+
cloudCreditBalanceMicros: 120000
247+
}
224248
const { container } = renderTile()
225-
// Annual billing still grants the monthly nominal (21,100), not 12x.
226-
expect(container.textContent).toContain('422 left of 21,100')
227-
expect(container.textContent).not.toContain('253,200')
249+
expect(container.textContent).toContain('253,200 left of 253,200')
228250
})
229251

230252
it('falls back to a dateless refills label when renewal date is missing', () => {

src/platform/cloud/subscription/components/CreditsTile.vue

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
role="progressbar"
5858
:aria-valuenow="usage.used"
5959
:aria-valuemin="0"
60-
:aria-valuemax="monthlyTotalCredits ?? 0"
60+
:aria-valuemax="creditPoolTotalCredits ?? 0"
6161
:aria-valuetext="monthlyUsageLabel"
6262
class="h-2 w-full overflow-hidden rounded-full bg-secondary-background-hover"
6363
>
@@ -86,15 +86,15 @@
8686
{{
8787
$t('subscription.creditsLeftOfTotal', {
8888
remaining: monthlyBonusCredits,
89-
total: monthlyTotalDisplay
89+
total: creditPoolTotalDisplay
9090
})
9191
}}
9292
</span>
9393
<span class="hidden @max-[180px]:inline">
9494
{{
9595
$t('subscription.creditsLeftOfTotal', {
9696
remaining: monthlyRemainingCompact,
97-
total: monthlyTotalCompact
97+
total: creditPoolTotalCompact
9898
})
9999
}}
100100
</span>
@@ -233,16 +233,20 @@ const tierKey = computed(() => {
233233
return TIER_TO_KEY[tier] ?? DEFAULT_TIER_KEY
234234
})
235235
236-
const monthlyTotalCredits = computed<number | null>(() => {
237-
const teamStop = currentTeamCreditStop.value
238-
if (teamStop) return teamStop.credits_monthly
239-
return getTierCredits(tierKey.value)
236+
const creditPoolTotalCredits = computed<number | null>(() => {
237+
const monthlyCredits =
238+
currentTeamCreditStop.value?.credits_monthly ??
239+
getTierCredits(tierKey.value)
240+
if (monthlyCredits === null) return null
241+
return subscription.value?.duration === 'ANNUAL'
242+
? monthlyCredits * 12
243+
: monthlyCredits
240244
})
241245
242246
const usage = computed(() =>
243247
computeMonthlyUsage(
244248
monthlyBonusCreditsValue.value,
245-
monthlyTotalCredits.value ?? 0
249+
creditPoolTotalCredits.value ?? 0
246250
)
247251
)
248252
@@ -270,8 +274,8 @@ const formatCreditCount = (value: number) =>
270274
numberOptions: { maximumFractionDigits: 0 }
271275
})
272276
273-
const monthlyTotalDisplay = computed(() => {
274-
const total = monthlyTotalCredits.value
277+
const creditPoolTotalDisplay = computed(() => {
278+
const total = creditPoolTotalCredits.value
275279
return total === null ? '' : formatCreditCount(total)
276280
})
277281
@@ -283,8 +287,8 @@ const compactNumber = computed(
283287
const monthlyRemainingCompact = computed(() =>
284288
compactNumber.value.format(monthlyBonusCreditsValue.value)
285289
)
286-
const monthlyTotalCompact = computed(() => {
287-
const total = monthlyTotalCredits.value
290+
const creditPoolTotalCompact = computed(() => {
291+
const total = creditPoolTotalCredits.value
288292
return total === null ? '' : compactNumber.value.format(total)
289293
})
290294
@@ -296,16 +300,16 @@ const usedBarWidth = computed(
296300
const monthlyUsageLabel = computed(() =>
297301
t('subscription.monthlyUsageProgress', {
298302
used: usedDisplay.value,
299-
total: monthlyTotalDisplay.value
303+
total: creditPoolTotalDisplay.value
300304
})
301305
)
302306
303307
const showBreakdown = computed(() => isActiveSubscription.value && !zeroState)
304308
const showBar = computed(
305309
() =>
306310
showBreakdown.value &&
307-
monthlyTotalCredits.value !== null &&
308-
monthlyTotalCredits.value > 0
311+
creditPoolTotalCredits.value !== null &&
312+
creditPoolTotalCredits.value > 0
309313
)
310314
const showActionButton = computed(
311315
() => isActiveSubscription.value && !zeroState && permissions.value.canTopUp

0 commit comments

Comments
 (0)