1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[PM-22565]Prevent credit addition when trialing org has no payment (#15167)

* changes for no billing location when adding credit

* Use the existing taxInfor from getOrganizationPaymentMethod

* refactor the biling location check
This commit is contained in:
cyprain-okeke
2025-06-24 16:56:44 +01:00
committed by GitHub
parent 012ce25e49
commit 67e55379d7
2 changed files with 28 additions and 1 deletions

View File

@@ -15,6 +15,7 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions"; import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
import { PaymentMethodType } from "@bitwarden/common/billing/enums"; import { PaymentMethodType } from "@bitwarden/common/billing/enums";
import { TaxInformation } from "@bitwarden/common/billing/models/domain";
import { VerifyBankAccountRequest } from "@bitwarden/common/billing/models/request/verify-bank-account.request"; import { VerifyBankAccountRequest } from "@bitwarden/common/billing/models/request/verify-bank-account.request";
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response"; import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
import { PaymentSourceResponse } from "@bitwarden/common/billing/models/response/payment-source.response"; import { PaymentSourceResponse } from "@bitwarden/common/billing/models/response/payment-source.response";
@@ -54,6 +55,8 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
protected readonly Math = Math; protected readonly Math = Math;
launchPaymentModalAutomatically = false; launchPaymentModalAutomatically = false;
protected taxInformation: TaxInformation;
constructor( constructor(
private activatedRoute: ActivatedRoute, private activatedRoute: ActivatedRoute,
private billingApiService: BillingApiServiceAbstraction, private billingApiService: BillingApiServiceAbstraction,
@@ -108,6 +111,12 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
} }
protected addAccountCredit = async (): Promise<void> => { protected addAccountCredit = async (): Promise<void> => {
if (this.subscriptionStatus === "trialing") {
const hasValidBillingAddress = await this.checkBillingAddressForTrialingOrg();
if (!hasValidBillingAddress) {
return;
}
}
const dialogRef = openAddCreditDialog(this.dialogService, { const dialogRef = openAddCreditDialog(this.dialogService, {
data: { data: {
organizationId: this.organizationId, organizationId: this.organizationId,
@@ -124,11 +133,12 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
protected load = async (): Promise<void> => { protected load = async (): Promise<void> => {
this.loading = true; this.loading = true;
try { try {
const { accountCredit, paymentSource, subscriptionStatus } = const { accountCredit, paymentSource, subscriptionStatus, taxInformation } =
await this.billingApiService.getOrganizationPaymentMethod(this.organizationId); await this.billingApiService.getOrganizationPaymentMethod(this.organizationId);
this.accountCredit = accountCredit; this.accountCredit = accountCredit;
this.paymentSource = paymentSource; this.paymentSource = paymentSource;
this.subscriptionStatus = subscriptionStatus; this.subscriptionStatus = subscriptionStatus;
this.taxInformation = taxInformation;
if (this.organizationId) { if (this.organizationId) {
const organizationSubscriptionPromise = this.organizationApiService.getSubscription( const organizationSubscriptionPromise = this.organizationApiService.getSubscription(
@@ -247,4 +257,17 @@ export class OrganizationPaymentMethodComponent implements OnDestroy {
const key = this.paymentSource == null ? "addPaymentMethod" : "changePaymentMethod"; const key = this.paymentSource == null ? "addPaymentMethod" : "changePaymentMethod";
return this.i18nService.t(key); return this.i18nService.t(key);
} }
private async checkBillingAddressForTrialingOrg(): Promise<boolean> {
const hasBillingAddress = this.taxInformation != null;
if (!hasBillingAddress) {
this.toastService.showToast({
variant: "error",
title: null,
message: this.i18nService.t("billingAddressRequiredToAddCredit"),
});
return false;
}
return true;
}
} }

View File

@@ -10659,5 +10659,9 @@
"example": "12/31/2024" "example": "12/31/2024"
} }
} }
},
"billingAddressRequiredToAddCredit": {
"message": "Billing address required to add credit.",
"description": "Error message shown when trying to add credit to a trialing organization without a billing address."
} }
} }