Skip to content

[PM-40440] fix: Source upgrade cart total from server invoice preview#21902

Open
amorask-bitwarden wants to merge 6 commits into
mainfrom
billing/PM-40440/teams-2020-upgrade-migration-defect
Open

[PM-40440] fix: Source upgrade cart total from server invoice preview#21902
amorask-bitwarden wants to merge 6 commits into
mainfrom
billing/PM-40440/teams-2020-upgrade-migration-defect

Conversation

@amorask-bitwarden

@amorask-bitwarden amorask-bitwarden commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

🎟️ Tracking

Resolves PM-40440

📔 Objective

The organization change-plan (upgrade) dialog computed the cart total on the client and re-applied the org's customerDiscount percentage to the newly selected plan. When an organization has an active price-migration schedule, the server surfaces the schedule's Phase 2 migration coupon as customerDiscount, so the dialog under-quoted the upgrade total by the coupon percentage (~20%) and rendered a misleading "provider discount" line. On confirm, the upgrade releases the schedule and drops the coupon, so the customer is charged the full price — the preview under-quoted them. (Display-only; no one was mischarged.)

This change stops computing the total on the client for this dialog and instead renders the Stripe invoice-preview Total the server already returns from the plan-change tax preview (estimatedTotal), falling back to the existing client total getter on error/first paint. The five client-side provider-discount rows and the now-dead discountPercentageFromSub field and calculateTotalAppliedDiscount() helper are removed. The server total applies genuine customer-level discounts but not the schedule coupon, so the quote is correct in both the migration and legitimate-discount cases.

Depends on a companion server fix — should not merge alone. The server plan-change tax preview (PreviewOrganizationTaxCommand) drops Secrets Manager line items across a tier change (it looks up SM seat/service-account prices by the new plan's IDs against the current subscription). Until that lands, sourcing the total from the server would under-quote SM-enabled Teams→Enterprise upgrades. Being handled separately in server.

📸 Screenshots

Screenshot 2026-07-16 at 2 42 20 PM

server PR: bitwarden/server#7995

The change-plan dialog computed the cart total client-side and reapplied
the org's customerDiscount to the target plan. When an org has an active
price-migration schedule, the server surfaces the schedule's Phase 2
migration coupon as customerDiscount, so the dialog under-quoted the
upgrade by the coupon percentage and rendered a bogus provider-discount
line — even though confirming the upgrade releases the schedule and
charges the full price.

Render the invoice-preview Total the server already returns instead of
recomputing it on the client, and remove the client-side discount rows.
The server applies genuine customer-level discounts but not the schedule
coupon, so the displayed total matches the actual charge in both the
migration and real-discount cases.
…n's total

Clears the server total synchronously when a new plan is selected so the
summary falls back to the client estimate during the preview request,
instead of briefly rendering the previously selected plan's total.
@amorask-bitwarden amorask-bitwarden added the ai-review Request a Claude code review label Jul 16, 2026
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

🤖 Bitwarden Claude Code Review

Overall Assessment: APPROVE

Reviewed the change-plan (upgrade) dialog fix that sources the cart total from the server invoice-preview Total (estimatedTotal) instead of recomputing it client-side and re-applying customerDiscount. Verified the estimatedTotal ?? total fallback in both template total bindings, the new isFromSchedule guard in isSecretsManagerTrial(), the removal of the dead discountPercentageFromSub field / calculateTotalAppliedDiscount() helper / provider-discount rows, and the accompanying response-model change. No security, correctness, or breaking-change issues found.

Code Review Details

No findings.

Notes from the review (no action required):

  • isFromSchedule defaults to false via getResponseProperty("IsFromSchedule") ?? false, so the client remains backward-compatible with server responses that predate the companion server fix.
  • The removed field, helper, and template rows have no remaining references in the dialog; the providerDiscount i18n key is still used by organization-subscription-cloud.component.html, so no key was orphaned.
  • estimatedTotal is cleared on plan switch and on preview error, correctly falling back to the client total getter until the server preview resolves.
  • The PR correctly documents its dependency on the companion server PR ([PM-40440] fix: Include Secrets Manager and storage in plan-change tax preview server#7995) and should not merge alone.

@amorask-bitwarden amorask-bitwarden added the t:bugfix Change Type - Bugfix label Jul 16, 2026
@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.66667% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.04%. Comparing base (d022cf1) to head (f907eca).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...ling/organizations/change-plan-dialog.component.ts 80.00% 0 Missing and 1 partial ⚠️
...els/response/organization-subscription.response.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21902      +/-   ##
==========================================
+ Coverage   52.03%   52.04%   +0.01%     
==========================================
  Files        4098     4098              
  Lines      129737   129740       +3     
  Branches    20350    20350              
==========================================
+ Hits        67514    67529      +15     
+ Misses      57234    57206      -28     
- Partials     4989     5005      +16     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review t:bugfix Change Type - Bugfix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants