diff --git a/apps/web/src/app/app.component.ts b/apps/web/src/app/app.component.ts index be3bd0860f..828fe8ea3f 100644 --- a/apps/web/src/app/app.component.ts +++ b/apps/web/src/app/app.component.ts @@ -2,17 +2,7 @@ import { DOCUMENT } from "@angular/common"; import { Component, Inject, NgZone, OnDestroy, OnInit } from "@angular/core"; import { NavigationEnd, Router } from "@angular/router"; import * as jq from "jquery"; -import { - Subject, - combineLatest, - filter, - firstValueFrom, - map, - switchMap, - takeUntil, - timeout, - timer, -} from "rxjs"; +import { Subject, filter, firstValueFrom, map, takeUntil, timeout } from "rxjs"; import { LogoutReason } from "@bitwarden/auth/common"; import { EventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service"; @@ -25,8 +15,6 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { KeyConnectorService } from "@bitwarden/common/auth/abstractions/key-connector.service"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; -import { PaymentMethodWarningsServiceAbstraction as PaymentMethodWarningService } from "@bitwarden/common/billing/abstractions/payment-method-warnings-service.abstraction"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; @@ -58,7 +46,6 @@ import { const BroadcasterSubscriptionId = "AppComponent"; const IdleTimeout = 60000 * 10; // 10 minutes -const PaymentMethodWarningsRefresh = 60000; // 1 Minute @Component({ selector: "app-root", @@ -69,7 +56,6 @@ export class AppComponent implements OnDestroy, OnInit { private idleTimer: number = null; private isIdle = false; private destroy$ = new Subject(); - private paymentMethodWarningsRefresh$ = timer(0, PaymentMethodWarningsRefresh); constructor( @Inject(DOCUMENT) private document: Document, @@ -98,7 +84,6 @@ export class AppComponent implements OnDestroy, OnInit { private dialogService: DialogService, private biometricStateService: BiometricStateService, private stateEventRunnerService: StateEventRunnerService, - private paymentMethodWarningService: PaymentMethodWarningService, private organizationService: InternalOrganizationServiceAbstraction, private accountService: AccountService, ) {} @@ -252,25 +237,6 @@ export class AppComponent implements OnDestroy, OnInit { new DisableSendPolicy(), new SendOptionsPolicy(), ]); - - combineLatest([ - this.configService.getFeatureFlag$(FeatureFlag.ShowPaymentMethodWarningBanners), - this.paymentMethodWarningsRefresh$, - ]) - .pipe( - filter(([showPaymentMethodWarningBanners]) => showPaymentMethodWarningBanners), - switchMap(() => this.organizationService.memberOrganizations$), - switchMap( - async (organizations) => - await Promise.all( - organizations.map((organization) => - this.paymentMethodWarningService.update(organization.id), - ), - ), - ), - takeUntil(this.destroy$), - ) - .subscribe(); } ngOnDestroy() { @@ -328,7 +294,6 @@ export class AppComponent implements OnDestroy, OnInit { this.folderService.clear(userId), this.collectionService.clear(userId), this.biometricStateService.logout(userId), - this.paymentMethodWarningService.clear(), ]); await this.stateEventRunnerService.handleEvent("logout", userId); diff --git a/apps/web/src/app/billing/shared/adjust-payment-dialog.component.ts b/apps/web/src/app/billing/shared/adjust-payment-dialog.component.ts index 1addf42629..08c9bf2766 100644 --- a/apps/web/src/app/billing/shared/adjust-payment-dialog.component.ts +++ b/apps/web/src/app/billing/shared/adjust-payment-dialog.component.ts @@ -1,14 +1,11 @@ import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog"; import { Component, Inject, ViewChild } from "@angular/core"; import { FormGroup } from "@angular/forms"; -import { firstValueFrom } from "rxjs"; import { ApiService } from "@bitwarden/common/abstractions/api.service"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; -import { PaymentMethodWarningsServiceAbstraction as PaymentMethodWarningService } from "@bitwarden/common/billing/abstractions/payment-method-warnings-service.abstraction"; import { PaymentMethodType } from "@bitwarden/common/billing/enums"; import { PaymentRequest } from "@bitwarden/common/billing/models/request/payment.request"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { DialogService, ToastService } from "@bitwarden/components"; @@ -46,7 +43,6 @@ export class AdjustPaymentDialogComponent { private apiService: ApiService, private i18nService: I18nService, private organizationApiService: OrganizationApiServiceAbstraction, - private paymentMethodWarningService: PaymentMethodWarningService, private configService: ConfigService, private toastService: ToastService, ) { @@ -78,12 +74,6 @@ export class AdjustPaymentDialogComponent { } }); await response; - const showPaymentMethodWarningBanners = await firstValueFrom( - this.configService.getFeatureFlag$(FeatureFlag.ShowPaymentMethodWarningBanners), - ); - if (this.organizationId && showPaymentMethodWarningBanners) { - await this.paymentMethodWarningService.removeSubscriptionRisk(this.organizationId); - } this.toastService.showToast({ variant: "success", title: null, diff --git a/apps/web/src/app/billing/shared/index.ts b/apps/web/src/app/billing/shared/index.ts index edaf3a1199..ae28e45f78 100644 --- a/apps/web/src/app/billing/shared/index.ts +++ b/apps/web/src/app/billing/shared/index.ts @@ -3,4 +3,3 @@ export * from "./payment-method.component"; export * from "./payment.component"; export * from "./sm-subscribe.component"; export * from "./tax-info.component"; -export * from "./payment-method-warnings/payment-method-warnings.module"; diff --git a/apps/web/src/app/billing/shared/payment-method-warnings/payment-method-warnings.component.html b/apps/web/src/app/billing/shared/payment-method-warnings/payment-method-warnings.component.html deleted file mode 100644 index 59dbc5f976..0000000000 --- a/apps/web/src/app/billing/shared/payment-method-warnings/payment-method-warnings.component.html +++ /dev/null @@ -1,15 +0,0 @@ - - - {{ "maintainYourSubscription" | i18n: warning.organizationName }} - {{ "addAPaymentMethod" | i18n }}. - - diff --git a/apps/web/src/app/billing/shared/payment-method-warnings/payment-method-warnings.component.ts b/apps/web/src/app/billing/shared/payment-method-warnings/payment-method-warnings.component.ts deleted file mode 100644 index d811961c0d..0000000000 --- a/apps/web/src/app/billing/shared/payment-method-warnings/payment-method-warnings.component.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Component } from "@angular/core"; -import { map, Observable } from "rxjs"; - -import { PaymentMethodWarningsServiceAbstraction as PaymentMethodWarningService } from "@bitwarden/common/billing/abstractions/payment-method-warnings-service.abstraction"; - -type Warning = { - organizationId: string; - organizationName: string; -}; - -@Component({ - selector: "app-payment-method-warnings", - templateUrl: "payment-method-warnings.component.html", -}) -export class PaymentMethodWarningsComponent { - constructor(private paymentMethodWarningService: PaymentMethodWarningService) {} - - protected warnings$: Observable = - this.paymentMethodWarningService.paymentMethodWarnings$.pipe( - map((warnings) => - Object.entries(warnings ?? []) - .filter(([_, warning]) => warning.risksSubscriptionFailure && !warning.acknowledged) - .map(([organizationId, { organizationName }]) => ({ - organizationId, - organizationName, - })), - ), - ); - - protected async closeWarning(organizationId: string): Promise { - await this.paymentMethodWarningService.acknowledge(organizationId); - } -} diff --git a/apps/web/src/app/billing/shared/payment-method-warnings/payment-method-warnings.module.ts b/apps/web/src/app/billing/shared/payment-method-warnings/payment-method-warnings.module.ts deleted file mode 100644 index c6303c878c..0000000000 --- a/apps/web/src/app/billing/shared/payment-method-warnings/payment-method-warnings.module.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NgModule } from "@angular/core"; - -import { BannerModule } from "@bitwarden/components"; - -import { SharedModule } from "../../../shared"; - -import { PaymentMethodWarningsComponent } from "./payment-method-warnings.component"; - -@NgModule({ - imports: [BannerModule, SharedModule], - declarations: [PaymentMethodWarningsComponent], - exports: [PaymentMethodWarningsComponent], -}) -export class PaymentMethodWarningsModule {} diff --git a/apps/web/src/app/layouts/web-layout.component.html b/apps/web/src/app/layouts/web-layout.component.html index 31a5e82688..fc318a6398 100644 --- a/apps/web/src/app/layouts/web-layout.component.html +++ b/apps/web/src/app/layouts/web-layout.component.html @@ -1,9 +1,4 @@ - - - diff --git a/apps/web/src/app/layouts/web-layout.component.ts b/apps/web/src/app/layouts/web-layout.component.ts index bb91e619aa..840beaa217 100644 --- a/apps/web/src/app/layouts/web-layout.component.ts +++ b/apps/web/src/app/layouts/web-layout.component.ts @@ -1,12 +1,8 @@ import { CommonModule } from "@angular/common"; import { Component } from "@angular/core"; -import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; -import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { LayoutComponent } from "@bitwarden/components"; -import { PaymentMethodWarningsModule } from "../billing/shared"; - import { ProductSwitcherModule } from "./product-switcher/product-switcher.module"; import { ToggleWidthComponent } from "./toggle-width.component"; @@ -14,18 +10,8 @@ import { ToggleWidthComponent } from "./toggle-width.component"; selector: "app-layout", templateUrl: "web-layout.component.html", standalone: true, - imports: [ - CommonModule, - LayoutComponent, - ProductSwitcherModule, - ToggleWidthComponent, - PaymentMethodWarningsModule, - ], + imports: [CommonModule, LayoutComponent, ProductSwitcherModule, ToggleWidthComponent], }) export class WebLayoutComponent { - protected showPaymentMethodWarningBanners$ = this.configService.getFeatureFlag$( - FeatureFlag.ShowPaymentMethodWarningBanners, - ); - - constructor(private configService: ConfigService) {} + constructor() {} } diff --git a/apps/web/src/app/shared/loose-components.module.ts b/apps/web/src/app/shared/loose-components.module.ts index 1a1daefb44..8e49c95e11 100644 --- a/apps/web/src/app/shared/loose-components.module.ts +++ b/apps/web/src/app/shared/loose-components.module.ts @@ -61,7 +61,6 @@ import { VerifyEmailTokenComponent } from "../auth/verify-email-token.component" import { VerifyRecoverDeleteComponent } from "../auth/verify-recover-delete.component"; import { SponsoredFamiliesComponent } from "../billing/settings/sponsored-families.component"; import { SponsoringOrgRowComponent } from "../billing/settings/sponsoring-org-row.component"; -import { PaymentMethodWarningsModule } from "../billing/shared"; import { DynamicAvatarComponent } from "../components/dynamic-avatar.component"; import { SelectableAvatarComponent } from "../components/selectable-avatar.component"; import { FrontendLayoutComponent } from "../layouts/frontend-layout.component"; @@ -113,7 +112,6 @@ import { SharedModule } from "./shared.module"; HeaderModule, OrganizationLayoutComponent, UserLayoutComponent, - PaymentMethodWarningsModule, VerifyRecoverDeleteOrgComponent, VaultTimeoutInputComponent, ], diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/providers.module.ts b/bitwarden_license/bit-web/src/app/admin-console/providers/providers.module.ts index 9733e91be7..37ef317360 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/providers.module.ts +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/providers.module.ts @@ -7,7 +7,6 @@ import { JslibModule } from "@bitwarden/angular/jslib.module"; import { SearchModule } from "@bitwarden/components"; import { DangerZoneComponent } from "@bitwarden/web-vault/app/auth/settings/account/danger-zone.component"; import { OrganizationPlansComponent, TaxInfoComponent } from "@bitwarden/web-vault/app/billing"; -import { PaymentMethodWarningsModule } from "@bitwarden/web-vault/app/billing/shared"; import { OssModule } from "@bitwarden/web-vault/app/oss.module"; import { @@ -53,7 +52,6 @@ import { SetupComponent } from "./setup/setup.component"; OrganizationPlansComponent, SearchModule, ProvidersLayoutComponent, - PaymentMethodWarningsModule, TaxInfoComponent, DangerZoneComponent, ScrollingModule, diff --git a/bitwarden_license/bit-web/src/app/admin-console/providers/setup/setup.component.html b/bitwarden_license/bit-web/src/app/admin-console/providers/setup/setup.component.html index 3b81d0564c..482b85b712 100644 --- a/bitwarden_license/bit-web/src/app/admin-console/providers/setup/setup.component.html +++ b/bitwarden_license/bit-web/src/app/admin-console/providers/setup/setup.component.html @@ -1,6 +1,3 @@ - Promise; - getOrganizationBillingStatus: (id: string) => Promise; - getPlans: () => Promise>; getProviderClientInvoiceReport: (providerId: string, invoiceId: string) => Promise; diff --git a/libs/common/src/billing/abstractions/index.ts b/libs/common/src/billing/abstractions/index.ts index 08a7a28fd9..c3ef8baca2 100644 --- a/libs/common/src/billing/abstractions/index.ts +++ b/libs/common/src/billing/abstractions/index.ts @@ -1,7 +1,6 @@ export * from "./account/billing-account-profile-state.service"; export * from "./billilng-api.service.abstraction"; export * from "./organization-billing.service"; -export * from "./payment-method-warnings-service.abstraction"; export * from "./payment-processors/braintree.service.abstraction"; export * from "./payment-processors/stripe.service.abstraction"; export * from "./provider-billing.service.abstraction"; diff --git a/libs/common/src/billing/abstractions/payment-method-warnings-service.abstraction.ts b/libs/common/src/billing/abstractions/payment-method-warnings-service.abstraction.ts deleted file mode 100644 index d7ba522c60..0000000000 --- a/libs/common/src/billing/abstractions/payment-method-warnings-service.abstraction.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Observable } from "rxjs"; - -import { PaymentMethodWarning } from "../models/domain/payment-method-warning"; - -export abstract class PaymentMethodWarningsServiceAbstraction { - /** - * An {@link Observable} record in the {@link ActiveUserState} of the user's organization IDs each mapped to their respective {@link PaymentMethodWarning}. - */ - paymentMethodWarnings$: Observable>; - /** - * Updates the {@link ActiveUserState} by setting `acknowledged` to `true` for the {@link PaymentMethodWarning} represented by the provided organization ID. - * @param organizationId - The ID of the organization whose warning you'd like to acknowledge. - */ - acknowledge: (organizationId: string) => Promise; - /** - * Updates the {@link ActiveUserState} by setting `risksSubscriptionFailure` to `false` for the {@link PaymentMethodWarning} represented by the provided organization ID. - * @param organizationId - The ID of the organization whose subscription risk you'd like to remove. - */ - removeSubscriptionRisk: (organizationId: string) => Promise; - /** - * Clears the {@link PaymentMethodWarning} record from the {@link ActiveUserState}. - */ - clear: () => Promise; - /** - * Tries to retrieve the {@link PaymentMethodWarning} for the provided organization ID from the {@link ActiveUserState}. - * If the warning does not exist, or if the warning has been in state for longer than a week, fetches the current {@link OrganizationBillingStatusResponse} for the organization - * from the API and uses it to update the warning in state. - * @param organizationId - The ID of the organization whose {@link PaymentMethodWarning} you'd like to update. - */ - update: (organizationId: string) => Promise; -} diff --git a/libs/common/src/billing/models/billing-keys.state.ts b/libs/common/src/billing/models/billing-keys.state.ts deleted file mode 100644 index 1d1cce6d0b..0000000000 --- a/libs/common/src/billing/models/billing-keys.state.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BILLING_DISK, UserKeyDefinition } from "../../platform/state"; -import { PaymentMethodWarning } from "../models/domain/payment-method-warning"; - -export const PAYMENT_METHOD_WARNINGS_KEY = UserKeyDefinition.record( - BILLING_DISK, - "paymentMethodWarnings", - { - deserializer: (warnings) => ({ - ...warnings, - savedAt: new Date(warnings.savedAt), - }), - clearOn: ["logout"], - }, -); diff --git a/libs/common/src/billing/models/domain/index.ts b/libs/common/src/billing/models/domain/index.ts index 19be9c1aeb..66d7e29c10 100644 --- a/libs/common/src/billing/models/domain/index.ts +++ b/libs/common/src/billing/models/domain/index.ts @@ -1,5 +1,4 @@ export * from "./bank-account"; export * from "./masked-payment-method"; -export * from "./payment-method-warning"; export * from "./tax-information"; export * from "./tokenized-payment-method"; diff --git a/libs/common/src/billing/models/domain/payment-method-warning.ts b/libs/common/src/billing/models/domain/payment-method-warning.ts deleted file mode 100644 index dd3f0f8581..0000000000 --- a/libs/common/src/billing/models/domain/payment-method-warning.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type PaymentMethodWarning = { - organizationName: string; - risksSubscriptionFailure: boolean; - acknowledged: boolean; - savedAt: Date; -}; diff --git a/libs/common/src/billing/models/response/organization-billing-status.response.ts b/libs/common/src/billing/models/response/organization-billing-status.response.ts deleted file mode 100644 index 916bebe4bc..0000000000 --- a/libs/common/src/billing/models/response/organization-billing-status.response.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { BaseResponse } from "../../../models/response/base.response"; - -export class OrganizationBillingStatusResponse extends BaseResponse { - organizationId: string; - organizationName: string; - risksSubscriptionFailure: boolean; - - constructor(response: any) { - super(response); - - this.organizationId = this.getResponseProperty("OrganizationId"); - this.organizationName = this.getResponseProperty("OrganizationName"); - this.risksSubscriptionFailure = this.getResponseProperty("RisksSubscriptionFailure"); - } -} diff --git a/libs/common/src/billing/services/billing-api.service.ts b/libs/common/src/billing/services/billing-api.service.ts index a5841fc5b5..822e6d1687 100644 --- a/libs/common/src/billing/services/billing-api.service.ts +++ b/libs/common/src/billing/services/billing-api.service.ts @@ -12,7 +12,6 @@ import { SubscriptionCancellationRequest } from "../../billing/models/request/su import { TokenizedPaymentMethodRequest } from "../../billing/models/request/tokenized-payment-method.request"; import { VerifyBankAccountRequest } from "../../billing/models/request/verify-bank-account.request"; import { OrganizationBillingMetadataResponse } from "../../billing/models/response/organization-billing-metadata.response"; -import { OrganizationBillingStatusResponse } from "../../billing/models/response/organization-billing-status.response"; import { PaymentInformationResponse } from "../../billing/models/response/payment-information.response"; import { PlanResponse } from "../../billing/models/response/plan.response"; import { ListResponse } from "../../models/response/list.response"; @@ -72,17 +71,6 @@ export class BillingApiService implements BillingApiServiceAbstraction { return response as string; } - async getOrganizationBillingStatus(id: string): Promise { - const r = await this.apiService.send( - "GET", - "/organizations/" + id + "/billing-status", - null, - true, - true, - ); - return new OrganizationBillingStatusResponse(r); - } - async getOrganizationBillingMetadata( organizationId: string, ): Promise { diff --git a/libs/common/src/billing/services/payment-method-warnings.service.spec.ts b/libs/common/src/billing/services/payment-method-warnings.service.spec.ts deleted file mode 100644 index 6e37821ef5..0000000000 --- a/libs/common/src/billing/services/payment-method-warnings.service.spec.ts +++ /dev/null @@ -1,186 +0,0 @@ -import { any, mock, MockProxy } from "jest-mock-extended"; -import { firstValueFrom } from "rxjs"; - -import { FakeAccountService, FakeStateProvider, mockAccountServiceWith } from "../../../spec"; -import { FakeActiveUserState } from "../../../spec/fake-state"; -import { Utils } from "../../platform/misc/utils"; -import { UserId } from "../../types/guid"; -import { BillingApiServiceAbstraction as BillingApiService } from "../abstractions/billilng-api.service.abstraction"; -import { PAYMENT_METHOD_WARNINGS_KEY } from "../models/billing-keys.state"; -import { PaymentMethodWarning } from "../models/domain/payment-method-warning"; -import { OrganizationBillingStatusResponse } from "../models/response/organization-billing-status.response"; - -import { PaymentMethodWarningsService } from "./payment-method-warnings.service"; - -describe("Payment Method Warnings Service", () => { - let paymentMethodWarningsService: PaymentMethodWarningsService; - let billingApiService: MockProxy; - - const mockUserId = Utils.newGuid() as UserId; - let accountService: FakeAccountService; - let stateProvider: FakeStateProvider; - let activeUserState: FakeActiveUserState>; - - function getPastDate(daysAgo: number) { - const date = new Date(); - date.setDate(date.getDate() - daysAgo); - return date; - } - - const getBillingStatusResponse = (organizationId: string) => - new OrganizationBillingStatusResponse({ - OrganizationId: organizationId, - OrganizationName: "Teams Organization", - RisksSubscriptionFailure: true, - }); - - beforeEach(() => { - accountService = mockAccountServiceWith(mockUserId); - stateProvider = new FakeStateProvider(accountService); - activeUserState = stateProvider.activeUser.getFake(PAYMENT_METHOD_WARNINGS_KEY); - - billingApiService = mock(); - paymentMethodWarningsService = new PaymentMethodWarningsService( - billingApiService, - stateProvider, - ); - }); - - it("acknowledge", async () => { - const organizationId = "1"; - const state: Record = { - [organizationId]: { - organizationName: "Teams Organization", - risksSubscriptionFailure: true, - acknowledged: false, - savedAt: getPastDate(3), - }, - }; - activeUserState.nextState(state); - await paymentMethodWarningsService.acknowledge(organizationId); - expect(await firstValueFrom(paymentMethodWarningsService.paymentMethodWarnings$)).toEqual({ - [organizationId]: { - ...state[organizationId], - acknowledged: true, - }, - }); - }); - - it("clear", async () => { - const state: Record = { - "1": { - organizationName: "Teams Organization", - risksSubscriptionFailure: true, - acknowledged: false, - savedAt: getPastDate(3), - }, - }; - activeUserState.nextState(state); - await paymentMethodWarningsService.clear(); - expect(await firstValueFrom(paymentMethodWarningsService.paymentMethodWarnings$)).toEqual({}); - }); - - it("removeSubscriptionRisk", async () => { - const organizationId = "1"; - const state: Record = { - [organizationId]: { - organizationName: "Teams Organization", - risksSubscriptionFailure: true, - acknowledged: false, - savedAt: getPastDate(3), - }, - }; - activeUserState.nextState(state); - await paymentMethodWarningsService.removeSubscriptionRisk(organizationId); - expect(await firstValueFrom(paymentMethodWarningsService.paymentMethodWarnings$)).toEqual({ - [organizationId]: { - ...state[organizationId], - risksSubscriptionFailure: false, - }, - }); - }); - - describe("update", () => { - it("Does nothing if the stored payment method warning is less than a week old", async () => { - const organizationId = "1"; - const state: Record = { - [organizationId]: { - organizationName: "Teams Organization", - risksSubscriptionFailure: true, - acknowledged: false, - savedAt: getPastDate(3), - }, - }; - activeUserState.nextState(state); - await paymentMethodWarningsService.update(organizationId); - expect(billingApiService.getOrganizationBillingStatus).not.toHaveBeenCalled(); - }); - - it("Retrieves the billing status from the API and uses it to update the state if the state is null", async () => { - const organizationId = "1"; - activeUserState.nextState(null); - billingApiService.getOrganizationBillingStatus.mockResolvedValue( - getBillingStatusResponse(organizationId), - ); - await paymentMethodWarningsService.update(organizationId); - expect(await firstValueFrom(paymentMethodWarningsService.paymentMethodWarnings$)).toEqual({ - [organizationId]: { - organizationName: "Teams Organization", - risksSubscriptionFailure: true, - acknowledged: false, - savedAt: any(), - }, - }); - expect(billingApiService.getOrganizationBillingStatus).toHaveBeenCalledTimes(1); - }); - - it("Retrieves the billing status from the API and uses it to update the state if the stored warning is null", async () => { - const organizationId = "1"; - activeUserState.nextState({ - [organizationId]: null, - }); - billingApiService.getOrganizationBillingStatus.mockResolvedValue( - getBillingStatusResponse(organizationId), - ); - await paymentMethodWarningsService.update(organizationId); - expect(await firstValueFrom(paymentMethodWarningsService.paymentMethodWarnings$)).toEqual({ - [organizationId]: { - organizationName: "Teams Organization", - risksSubscriptionFailure: true, - acknowledged: false, - savedAt: any(), - }, - }); - expect(billingApiService.getOrganizationBillingStatus).toHaveBeenCalledTimes(1); - }); - - it("Retrieves the billing status from the API and uses it to update the state if the stored warning is older than a week", async () => { - const organizationId = "1"; - activeUserState.nextState({ - [organizationId]: { - organizationName: "Teams Organization", - risksSubscriptionFailure: false, - acknowledged: false, - savedAt: getPastDate(10), - }, - }); - billingApiService.getOrganizationBillingStatus.mockResolvedValue( - new OrganizationBillingStatusResponse({ - OrganizationId: organizationId, - OrganizationName: "Teams Organization", - RisksSubscriptionFailure: true, - }), - ); - await paymentMethodWarningsService.update(organizationId); - expect(await firstValueFrom(paymentMethodWarningsService.paymentMethodWarnings$)).toEqual({ - [organizationId]: { - organizationName: "Teams Organization", - risksSubscriptionFailure: true, - acknowledged: false, - savedAt: any(), - }, - }); - expect(billingApiService.getOrganizationBillingStatus).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/libs/common/src/billing/services/payment-method-warnings.service.ts b/libs/common/src/billing/services/payment-method-warnings.service.ts deleted file mode 100644 index 0dad48bb85..0000000000 --- a/libs/common/src/billing/services/payment-method-warnings.service.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { firstValueFrom, map, Observable } from "rxjs"; - -import { ActiveUserState, StateProvider } from "../../platform/state"; -import { BillingApiServiceAbstraction as BillingApiService } from "../abstractions/billilng-api.service.abstraction"; -import { PaymentMethodWarningsServiceAbstraction } from "../abstractions/payment-method-warnings-service.abstraction"; -import { PAYMENT_METHOD_WARNINGS_KEY } from "../models/billing-keys.state"; -import { PaymentMethodWarning } from "../models/domain/payment-method-warning"; - -export class PaymentMethodWarningsService implements PaymentMethodWarningsServiceAbstraction { - private paymentMethodWarningsState: ActiveUserState>; - paymentMethodWarnings$: Observable>; - - constructor( - private billingApiService: BillingApiService, - private stateProvider: StateProvider, - ) { - this.paymentMethodWarningsState = this.stateProvider.getActive(PAYMENT_METHOD_WARNINGS_KEY); - this.paymentMethodWarnings$ = this.paymentMethodWarningsState.state$; - } - - async acknowledge(organizationId: string): Promise { - await this.paymentMethodWarningsState.update((state) => { - const current = state[organizationId]; - state[organizationId] = { - ...current, - acknowledged: true, - }; - return state; - }); - } - - async removeSubscriptionRisk(organizationId: string): Promise { - await this.paymentMethodWarningsState.update((state) => { - const current = state[organizationId]; - state[organizationId] = { - ...current, - risksSubscriptionFailure: false, - }; - return state; - }); - } - - async clear(): Promise { - await this.paymentMethodWarningsState.update(() => ({})); - } - - async update(organizationId: string): Promise { - const warning = await firstValueFrom( - this.paymentMethodWarningsState.state$.pipe( - map((state) => (!state ? null : state[organizationId])), - ), - ); - if (!warning || warning.savedAt < this.getOneWeekAgo()) { - const { organizationName, risksSubscriptionFailure } = - await this.billingApiService.getOrganizationBillingStatus(organizationId); - await this.paymentMethodWarningsState.update((state) => { - state ??= {}; - state[organizationId] = { - organizationName, - risksSubscriptionFailure, - acknowledged: false, - savedAt: new Date(), - }; - return state; - }); - } - } - - private getOneWeekAgo = (): Date => { - const date = new Date(); - date.setDate(date.getDate() - 7); - return date; - }; -} diff --git a/libs/common/src/enums/feature-flag.enum.ts b/libs/common/src/enums/feature-flag.enum.ts index 583b699697..9edc14e7b0 100644 --- a/libs/common/src/enums/feature-flag.enum.ts +++ b/libs/common/src/enums/feature-flag.enum.ts @@ -7,7 +7,6 @@ export enum FeatureFlag { BrowserFilelessImport = "browser-fileless-import", ItemShare = "item-share", GeneratorToolsModernization = "generator-tools-modernization", - ShowPaymentMethodWarningBanners = "show-payment-method-warning-banners", EnableConsolidatedBilling = "enable-consolidated-billing", AC1795_UpdatedSubscriptionStatusSection = "AC-1795_updated-subscription-status-section", EnableDeleteProvider = "AC-1218-delete-provider", @@ -50,7 +49,6 @@ export const DefaultFeatureFlagValue = { [FeatureFlag.BrowserFilelessImport]: FALSE, [FeatureFlag.ItemShare]: FALSE, [FeatureFlag.GeneratorToolsModernization]: FALSE, - [FeatureFlag.ShowPaymentMethodWarningBanners]: FALSE, [FeatureFlag.EnableConsolidatedBilling]: FALSE, [FeatureFlag.AC1795_UpdatedSubscriptionStatusSection]: FALSE, [FeatureFlag.EnableDeleteProvider]: FALSE,