From 36b18c3e597e299f1619b867502a7287c503ecc2 Mon Sep 17 00:00:00 2001 From: Alex Morask <144709477+amorask-bitwarden@users.noreply.github.com> Date: Thu, 31 Oct 2024 11:05:05 -0400 Subject: [PATCH] [PM-14275] Resolve reseller & CB MSP organization owner experience for subscription page (#11797) * Fixed issue with Resellers and CB MSP Org Owners on subscription page * Hide billing sync from Families --- ...nization-subscription-cloud.component.html | 17 ++++++++-- ...ganization-subscription-cloud.component.ts | 31 ++++++++++--------- .../organization-billing-metadata.response.ts | 2 ++ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html index 68090b50e5..cd95e88704 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html +++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html @@ -264,7 +264,12 @@ - +

{{ "manageSubscription" | i18n }}

{{ "manageSubscriptionFromThe" | i18n }} @@ -281,7 +286,7 @@ - +

{{ "billingManagedByProvider" | i18n: userOrg.providerName }}

@@ -303,7 +308,13 @@ -
diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts index 591371db08..1000084df9 100644 --- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts +++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts @@ -5,8 +5,7 @@ import { concatMap, firstValueFrom, lastValueFrom, Observable, Subject, takeUnti import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; -import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service"; -import { OrganizationApiKeyType, ProviderStatusType } from "@bitwarden/common/admin-console/enums"; +import { OrganizationApiKeyType } from "@bitwarden/common/admin-console/enums"; import { Organization } from "@bitwarden/common/admin-console/models/domain/organization"; import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions"; import { PlanType, ProductTierType } from "@bitwarden/common/billing/enums"; @@ -57,7 +56,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy preSelectedProductTier: ProductTierType = ProductTierType.Free; showSubscription = true; showSelfHost = false; - providerIsOnConsolidatedBilling = false; + organizationIsManagedByConsolidatedBillingMSP = false; protected readonly subscriptionHiddenIcon = SubscriptionHiddenIcon; protected readonly teamsStarter = ProductTierType.TeamsStarter; @@ -91,7 +90,6 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy private configService: ConfigService, private toastService: ToastService, private billingApiService: BillingApiServiceAbstraction, - private providerService: ProviderService, ) {} async ngOnInit() { @@ -134,23 +132,22 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy const consolidatedBillingEnabled = await firstValueFrom(this.enableConsolidatedBilling$); - const provider = this.userOrg.hasProvider - ? await this.providerService.get(this.userOrg.providerId) - : null; - - this.providerIsOnConsolidatedBilling = - consolidatedBillingEnabled && provider?.providerStatus === ProviderStatusType.Billable; - const isIndependentOrganizationOwner = !this.userOrg.hasProvider && this.userOrg.isOwner; - const isProviderUser = this.userOrg.hasProvider && this.userOrg.isProviderUser; - - this.showSubscription = - isIndependentOrganizationOwner || (isProviderUser && !this.providerIsOnConsolidatedBilling); + const isResoldOrganizationOwner = this.userOrg.hasReseller && this.userOrg.isOwner; + const isMSPUser = this.userOrg.hasProvider && this.userOrg.isProviderUser; const metadata = await this.billingApiService.getOrganizationBillingMetadata( this.organizationId, ); + this.organizationIsManagedByConsolidatedBillingMSP = + consolidatedBillingEnabled && this.userOrg.hasProvider && metadata.isManaged; + + this.showSubscription = + isIndependentOrganizationOwner || + isResoldOrganizationOwner || + (isMSPUser && !this.organizationIsManagedByConsolidatedBillingMSP); + this.showSelfHost = metadata.isEligibleForSelfHost; if (this.showSubscription) { @@ -525,6 +522,10 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy get showChangePlanButton() { return this.sub.plan.productTier !== ProductTierType.Enterprise && !this.showChangePlan; } + + get canUseBillingSync() { + return this.userOrg.productTierType === ProductTierType.Enterprise; + } } /** diff --git a/libs/common/src/billing/models/response/organization-billing-metadata.response.ts b/libs/common/src/billing/models/response/organization-billing-metadata.response.ts index 4831d29069..3d846e6c98 100644 --- a/libs/common/src/billing/models/response/organization-billing-metadata.response.ts +++ b/libs/common/src/billing/models/response/organization-billing-metadata.response.ts @@ -2,11 +2,13 @@ import { BaseResponse } from "../../../models/response/base.response"; export class OrganizationBillingMetadataResponse extends BaseResponse { isEligibleForSelfHost: boolean; + isManaged: boolean; isOnSecretsManagerStandalone: boolean; constructor(response: any) { super(response); this.isEligibleForSelfHost = this.getResponseProperty("IsEligibleForSelfHost"); + this.isManaged = this.getResponseProperty("IsManaged"); this.isOnSecretsManagerStandalone = this.getResponseProperty("IsOnSecretsManagerStandalone"); } }