diff --git a/apps/web/src/app/billing/organizations/change-plan-dialog.component.html b/apps/web/src/app/billing/organizations/change-plan-dialog.component.html index 1c92cbf663..c893f3832d 100644 --- a/apps/web/src/app/billing/organizations/change-plan-dialog.component.html +++ b/apps/web/src/app/billing/organizations/change-plan-dialog.component.html @@ -62,7 +62,7 @@ class="tw-px-2 tw-py-4" [ngClass]="{ 'tw-py-1': !(selectableProduct === selectedPlan), - 'tw-py-0': selectableProduct === selectedPlan, + 'tw-py-0': selectableProduct === selectedPlan }" >

@@ -308,9 +308,14 @@

+ + (); constructor( @@ -171,9 +179,15 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy { private messagingService: MessagingService, private formBuilder: FormBuilder, private organizationApiService: OrganizationApiServiceAbstraction, + private configService: ConfigService, + private billingApiService: BillingApiServiceAbstraction, ) {} async ngOnInit(): Promise { + this.deprecateStripeSourcesAPI = await this.configService.getFeatureFlag( + FeatureFlag.AC2476_DeprecateStripeSourcesAPI, + ); + if (this.dialogParams.organizationId) { this.currentPlanName = this.resolvePlanName(this.dialogParams.productTierType); this.sub = @@ -595,7 +609,16 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy { } changedCountry() { - if (this.paymentComponent && this.taxComponent) { + if (this.deprecateStripeSourcesAPI && this.paymentV2Component && this.taxComponent) { + this.paymentV2Component.showBankAccount = this.taxComponent.country === "US"; + + if ( + !this.paymentV2Component.showBankAccount && + this.paymentV2Component.selected === PaymentMethodType.BankAccount + ) { + this.paymentV2Component.select(PaymentMethodType.Card); + } + } else if (this.paymentComponent && this.taxComponent) { this.paymentComponent!.hideBank = this.taxComponent?.taxFormGroup?.value.country !== "US"; // Bank Account payments are only available for US customers if ( @@ -616,7 +639,7 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy { const doSubmit = async (): Promise => { let orgId: string = null; - orgId = await this.updateOrganization(orgId); + orgId = await this.updateOrganization(); this.toastService.showToast({ variant: "success", title: null, @@ -650,12 +673,15 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy { this.dialogRef.close(); }; - private async updateOrganization(orgId: string) { + private async updateOrganization() { const request = new OrganizationUpgradeRequest(); if (this.selectedPlan.productTier !== ProductTierType.Families) { request.additionalSeats = this.organization.seats; } - request.additionalStorageGb = this.organization.maxStorageGb; + if (this.organization.maxStorageGb > this.selectedPlan.PasswordManager.baseStorageGb) { + request.additionalStorageGb = + this.organization.maxStorageGb - this.selectedPlan.PasswordManager.baseStorageGb; + } request.premiumAccessAddon = this.selectedPlan.PasswordManager.hasPremiumAccessOption && this.formGroup.controls.premiumAccessAddon.value; @@ -669,13 +695,33 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy { this.buildSecretsManagerRequest(request); if (this.upgradeRequiresPaymentMethod || this.showPayment) { - const tokenResult = await this.paymentComponent.createPaymentToken(); - const paymentRequest = new PaymentRequest(); - paymentRequest.paymentToken = tokenResult[0]; - paymentRequest.paymentMethodType = tokenResult[1]; - paymentRequest.country = this.taxComponent.taxFormGroup?.value.country; - paymentRequest.postalCode = this.taxComponent.taxFormGroup?.value.postalCode; - await this.organizationApiService.updatePayment(this.organizationId, paymentRequest); + if (this.deprecateStripeSourcesAPI) { + const tokenizedPaymentSource = await this.paymentV2Component.tokenize(); + const updatePaymentMethodRequest = new UpdatePaymentMethodRequest(); + updatePaymentMethodRequest.paymentSource = tokenizedPaymentSource; + updatePaymentMethodRequest.taxInformation = { + country: this.taxComponent.country, + postalCode: this.taxComponent.postalCode, + taxId: this.taxComponent.taxId, + line1: this.taxComponent.line1, + line2: this.taxComponent.line2, + city: this.taxComponent.city, + state: this.taxComponent.state, + }; + + await this.billingApiService.updateOrganizationPaymentMethod( + this.organizationId, + updatePaymentMethodRequest, + ); + } else { + const tokenResult = await this.paymentComponent.createPaymentToken(); + const paymentRequest = new PaymentRequest(); + paymentRequest.paymentToken = tokenResult[0]; + paymentRequest.paymentMethodType = tokenResult[1]; + paymentRequest.country = this.taxComponent.taxFormGroup?.value.country; + paymentRequest.postalCode = this.taxComponent.taxFormGroup?.value.postalCode; + await this.organizationApiService.updatePayment(this.organizationId, paymentRequest); + } } // Backfill pub/priv key if necessary diff --git a/apps/web/src/app/billing/shared/payment/payment-v2.component.ts b/apps/web/src/app/billing/shared/payment/payment-v2.component.ts index 8d7e8d7a0c..fa2b53fc7b 100644 --- a/apps/web/src/app/billing/shared/payment/payment-v2.component.ts +++ b/apps/web/src/app/billing/shared/payment/payment-v2.component.ts @@ -86,7 +86,7 @@ export class PaymentV2Component implements OnInit, OnDestroy { /** Programmatically select the provided payment method. */ select = (paymentMethod: PaymentMethodType) => { - this.formGroup.value.paymentMethod = paymentMethod; + this.formGroup.get("paymentMethod").patchValue(paymentMethod); }; protected submit = async () => {