fix(billing): surface wallet credits to pentest + bg-check UIs#2755
Merged
fix(billing): surface wallet credits to pentest + bg-check UIs#2755
Conversation
The backend already falls back from Stripe subscription to the BillingCreditBalance wallet when an active subscription is missing or exhausted, but `/v1/billing/status` only returned subscription data. Both the pentest page and the background-check wizard computed their "available scans" balance from subscription remainder alone, so admin- granted credits were invisible: the New Scan button rerouted to billing even though the create endpoint would have happily consumed a wallet credit. Now `getStatus` aggregates wallet balances per product and the two UIs add them to the displayed allowance, mirroring the backend's consumption decision. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
/v1/billing/statusnow returnscreditBalances(per-product wallet balances). Pentest page + BG-check wizard add wallet credits to their displayed allowance, matching the backend's actual consumption logic.Why this was wrong
BillingEntitlementsService.tryConsumeIncludedUsageForProductalready falls back toBillingCreditsService.tryConsumeForProductwhen the Stripe subscription is missing or exhausted (apps/api/src/billing/billing-entitlements.service.ts:43-83). The backend would happily run the scan.BillingService.getStatusonly returnedsubscriptions. Both the pentestSplitViewandgetBackgroundChecksRemainingcomputed allowance from subscription remainder alone, so admin grants were invisible to the customer UI./billing/add-ons/penetration-tests, blocking a request the API would have accepted.Fix
API
BillingStatus: addedcreditBalances: Array<{ productKey, balance }>.BillingService.getStatus: injectsBillingCreditsService(@Optional()so existing test ctors keep compiling), fetches balances, aggregates per product (multiple SKU-scoped rows can share aproductKey).Pentest UI
getPentestAllowance(billingStatus)—subscriptionRemaining + walletBalance.planRequiredis true only when neither exists.SplitView.tsxnow delegates to the helper.Background-check UI
getBackgroundChecksRemainingnow adds wallet credits and returns wallet-only when no subscription exists (instead ofnull), so the wizard reaches the form step.BackgroundCheckBillingStatusmirror gained the optionalcreditBalancesfield.Non-breaking guarantees
creditBalancesis purely additive on the API and optional on every frontend type — every existing consumer keeps compiling.BillingCreditsServiceinjection is@Optional(); the 11 existingnew BillingService(...)test calls work unchanged.walletBalance = 0→ identical pre-fix behavior.Tests
apps/api/src/billing/billing.service.spec.ts— 2 new jest cases:getStatusaggregates wallet balances per product (multiple rows summed).[]when credits service is absent.pentest-allowance.test.ts— 8 vitest cases (loading, no plan, trial, wallet only, sub exhausted + wallet, negative-clamp, wrong product, cancelled subscription).useEmployeeBackgroundCheckData.test.ts— 7 vitest cases (mirrors above for BG check).All 13 + 15 = 28 tests pass. No existing test was modified except adding new cases.
Test plan
/security/penetration-tests/new. Submit → scan starts; wallet drops to 4.POST /v1/admin/organizations/:orgId/credits{productKey:'background_check', quantity:5}→ BG-check wizard shows the request form and the request goes through.🤖 Generated with Claude Code
Summary by cubic
Surfaced admin-granted wallet credits in pentest and background-check UIs by adding aggregated credit balances to
/v1/billing/statusand updating allowance logic to match backend consumption. This fixes false paywalls when trials are exhausted but wallet credits exist.creditBalancestoBillingStatus;BillingService.getStatusaggregates wallet balances per product; injectedBillingCreditsServicewith@Optional(); returns[]when credits service is absent.getPentestAllowancehelper;SplitViewnow uses subscription remainder + wallet credits to choose between "+ New Scan" and "View plans".getBackgroundChecksRemainingadds wallet credits and enables wallet-only flows when no subscription exists; local billing types gained optionalcreditBalances.emptyBillingStatus(creditBalances: []); field is optional on frontend types and treated as 0 when absent.Written for commit 672e901. Summary will update on new commits.