mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 22:03:36 +00:00
[PM-26947] Fix Billing Address Defect (#16872)
* fix(billing): Add Billing Address component * fix(billing): Update tax refresh logic and swap billing address component * fix(billing): Fix headers * fix(billing): Do not show bank payment option for premium upgrade
This commit is contained in:
@@ -31,11 +31,19 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div class="tw-pb-8 !tw-mx-0">
|
<div class="tw-pb-8 !tw-mx-0">
|
||||||
|
<h5 bitTypography="h5">{{ "paymentMethod" | i18n }}</h5>
|
||||||
<app-enter-payment-method
|
<app-enter-payment-method
|
||||||
|
[showBankAccount]="isFamiliesPlan"
|
||||||
[group]="formGroup.controls.paymentForm"
|
[group]="formGroup.controls.paymentForm"
|
||||||
[includeBillingAddress]="true"
|
[includeBillingAddress]="false"
|
||||||
#paymentComponent
|
#paymentComponent
|
||||||
></app-enter-payment-method>
|
></app-enter-payment-method>
|
||||||
|
<h5 bitTypography="h5" class="tw-pt-4 tw-pb-2">{{ "billingAddress" | i18n }}</h5>
|
||||||
|
<app-enter-billing-address
|
||||||
|
[group]="formGroup.controls.billingAddress"
|
||||||
|
[scenario]="{ type: 'checkout', supportsTaxId: false }"
|
||||||
|
>
|
||||||
|
</app-enter-billing-address>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||||
import { debounceTime, Observable } from "rxjs";
|
import { catchError, debounceTime, from, Observable, of, switchMap } from "rxjs";
|
||||||
|
|
||||||
import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
import { Account } from "@bitwarden/common/auth/abstractions/account.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@@ -20,7 +20,10 @@ import { LogService } from "@bitwarden/logging";
|
|||||||
import { CartSummaryComponent, LineItem } from "@bitwarden/pricing";
|
import { CartSummaryComponent, LineItem } from "@bitwarden/pricing";
|
||||||
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
import { SharedModule } from "@bitwarden/web-vault/app/shared";
|
||||||
|
|
||||||
import { EnterPaymentMethodComponent } from "../../../payment/components";
|
import {
|
||||||
|
EnterBillingAddressComponent,
|
||||||
|
EnterPaymentMethodComponent,
|
||||||
|
} from "../../../payment/components";
|
||||||
import { BillingServicesModule } from "../../../services";
|
import { BillingServicesModule } from "../../../services";
|
||||||
import { SubscriptionPricingService } from "../../../services/subscription-pricing.service";
|
import { SubscriptionPricingService } from "../../../services/subscription-pricing.service";
|
||||||
import { BitwardenSubscriber } from "../../../types";
|
import { BitwardenSubscriber } from "../../../types";
|
||||||
@@ -65,6 +68,7 @@ export type UpgradePaymentParams = {
|
|||||||
CartSummaryComponent,
|
CartSummaryComponent,
|
||||||
ButtonModule,
|
ButtonModule,
|
||||||
EnterPaymentMethodComponent,
|
EnterPaymentMethodComponent,
|
||||||
|
EnterBillingAddressComponent,
|
||||||
BillingServicesModule,
|
BillingServicesModule,
|
||||||
],
|
],
|
||||||
providers: [UpgradePaymentService],
|
providers: [UpgradePaymentService],
|
||||||
@@ -83,6 +87,7 @@ export class UpgradePaymentComponent implements OnInit, AfterViewInit {
|
|||||||
protected formGroup = new FormGroup({
|
protected formGroup = new FormGroup({
|
||||||
organizationName: new FormControl<string>("", [Validators.required]),
|
organizationName: new FormControl<string>("", [Validators.required]),
|
||||||
paymentForm: EnterPaymentMethodComponent.getFormGroup(),
|
paymentForm: EnterPaymentMethodComponent.getFormGroup(),
|
||||||
|
billingAddress: EnterBillingAddressComponent.getFormGroup(),
|
||||||
});
|
});
|
||||||
|
|
||||||
protected loading = signal(true);
|
protected loading = signal(true);
|
||||||
@@ -140,9 +145,16 @@ export class UpgradePaymentComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.formGroup.valueChanges
|
this.formGroup.controls.billingAddress.valueChanges
|
||||||
.pipe(debounceTime(1000), takeUntilDestroyed(this.destroyRef))
|
.pipe(
|
||||||
.subscribe(() => this.refreshSalesTax());
|
debounceTime(1000),
|
||||||
|
// Only proceed when form has required values
|
||||||
|
switchMap(() => this.refreshSalesTax$()),
|
||||||
|
takeUntilDestroyed(this.destroyRef),
|
||||||
|
)
|
||||||
|
.subscribe((tax) => {
|
||||||
|
this.estimatedTax = tax;
|
||||||
|
});
|
||||||
this.loading.set(false);
|
this.loading.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,8 +211,8 @@ export class UpgradePaymentComponent implements OnInit, AfterViewInit {
|
|||||||
|
|
||||||
private async processUpgrade(): Promise<UpgradePaymentResult> {
|
private async processUpgrade(): Promise<UpgradePaymentResult> {
|
||||||
// Get common values
|
// Get common values
|
||||||
const country = this.formGroup.value?.paymentForm?.billingAddress?.country;
|
const country = this.formGroup.value?.billingAddress?.country;
|
||||||
const postalCode = this.formGroup.value?.paymentForm?.billingAddress?.postalCode;
|
const postalCode = this.formGroup.value?.billingAddress?.postalCode;
|
||||||
|
|
||||||
if (!this.selectedPlan) {
|
if (!this.selectedPlan) {
|
||||||
throw new Error("No plan selected");
|
throw new Error("No plan selected");
|
||||||
@@ -246,19 +258,20 @@ export class UpgradePaymentComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async refreshSalesTax(): Promise<void> {
|
// Create an observable for tax calculation
|
||||||
|
private refreshSalesTax$(): Observable<number> {
|
||||||
const billingAddress = {
|
const billingAddress = {
|
||||||
country: this.formGroup.value.paymentForm?.billingAddress?.country,
|
country: this.formGroup.value?.billingAddress?.country,
|
||||||
postalCode: this.formGroup.value.paymentForm?.billingAddress?.postalCode,
|
postalCode: this.formGroup.value?.billingAddress?.postalCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!this.selectedPlan || !billingAddress.country || !billingAddress.postalCode) {
|
if (!this.selectedPlan || !billingAddress.country || !billingAddress.postalCode) {
|
||||||
this.estimatedTax = 0;
|
return of(0);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.upgradePaymentService
|
// Convert Promise to Observable
|
||||||
.calculateEstimatedTax(this.selectedPlan, {
|
return from(
|
||||||
|
this.upgradePaymentService.calculateEstimatedTax(this.selectedPlan, {
|
||||||
line1: null,
|
line1: null,
|
||||||
line2: null,
|
line2: null,
|
||||||
city: null,
|
city: null,
|
||||||
@@ -266,17 +279,16 @@ export class UpgradePaymentComponent implements OnInit, AfterViewInit {
|
|||||||
country: billingAddress.country,
|
country: billingAddress.country,
|
||||||
postalCode: billingAddress.postalCode,
|
postalCode: billingAddress.postalCode,
|
||||||
taxId: null,
|
taxId: null,
|
||||||
})
|
}),
|
||||||
.then((tax) => {
|
).pipe(
|
||||||
this.estimatedTax = tax;
|
catchError((error: unknown) => {
|
||||||
})
|
|
||||||
.catch((error: unknown) => {
|
|
||||||
this.logService.error("Tax calculation failed:", error);
|
this.logService.error("Tax calculation failed:", error);
|
||||||
this.toastService.showToast({
|
this.toastService.showToast({
|
||||||
variant: "error",
|
variant: "error",
|
||||||
message: this.i18nService.t("taxCalculationError"),
|
message: this.i18nService.t("taxCalculationError"),
|
||||||
});
|
});
|
||||||
this.estimatedTax = 0;
|
return of(0); // Return default value on error
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user