diff --git a/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.html b/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.html index baf15c7bd01..e4707e495c3 100644 --- a/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.html +++ b/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.html @@ -77,7 +77,7 @@

-
+
diff --git a/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.spec.ts b/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.spec.ts index 505e8782429..432275a3cc0 100644 --- a/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.spec.ts +++ b/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.spec.ts @@ -6,7 +6,11 @@ import { PaymentType } from '@spartacus/cart/base/root'; import { CheckoutPaymentTypeFacade } from '@spartacus/checkout/b2b/root'; import { CheckoutStepService } from '@spartacus/checkout/base/components'; import { CheckoutStepType } from '@spartacus/checkout/base/root'; -import { I18nTestingModule, QueryState } from '@spartacus/core'; +import { + GlobalMessageService, + I18nTestingModule, + QueryState, +} from '@spartacus/core'; import { BehaviorSubject, of } from 'rxjs'; import { take } from 'rxjs/operators'; import { CheckoutPaymentTypeComponent } from './checkout-payment-type.component'; @@ -18,6 +22,9 @@ import createSpy = jasmine.createSpy; }) class MockSpinnerComponent {} +class MockGlobalMessageService { + add = createSpy(); +} class MockCheckoutPaymentTypeService implements Partial { @@ -92,6 +99,10 @@ describe('CheckoutOnePaymentTypeComponent', () => { useClass: MockCheckoutStepService, }, { provide: ActivatedRoute, useValue: mockActivatedRoute }, + { + provide: GlobalMessageService, + useClass: MockGlobalMessageService, + }, ], }).compileComponents(); @@ -145,6 +156,10 @@ describe('CheckoutPaymentTypeComponent', () => { useClass: MockCheckoutStepService, }, { provide: ActivatedRoute, useValue: mockActivatedRoute }, + { + provide: GlobalMessageService, + useClass: MockGlobalMessageService, + }, ], }).compileComponents(); diff --git a/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.ts b/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.ts index 859cf31e525..55069a21be2 100644 --- a/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.ts +++ b/feature-libs/checkout/b2b/components/checkout-payment-type/checkout-payment-type.component.ts @@ -8,6 +8,7 @@ import { ChangeDetectionStrategy, Component, ElementRef, + Optional, ViewChild, } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @@ -18,9 +19,22 @@ import { } from '@spartacus/checkout/b2b/root'; import { CheckoutStepService } from '@spartacus/checkout/base/components'; import { CheckoutStepType } from '@spartacus/checkout/base/root'; -import { getLastValueSync, isNotUndefined } from '@spartacus/core'; -import { BehaviorSubject, combineLatest, Observable } from 'rxjs'; -import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators'; +import { + GlobalMessageService, + GlobalMessageType, + HttpErrorModel, + OccHttpErrorType, + getLastValueSync, + isNotUndefined, +} from '@spartacus/core'; +import { BehaviorSubject, Observable, combineLatest, of } from 'rxjs'; +import { + catchError, + distinctUntilChanged, + filter, + map, + tap, +} from 'rxjs/operators'; @Component({ selector: 'cx-payment-type', @@ -34,6 +48,7 @@ export class CheckoutPaymentTypeComponent { protected busy$ = new BehaviorSubject(false); typeSelected?: string; + paymentTypesError = false; isUpdating$ = combineLatest([ this.busy$, @@ -45,8 +60,24 @@ export class CheckoutPaymentTypeComponent { distinctUntilChanged() ); - paymentTypes$: Observable = - this.checkoutPaymentTypeFacade.getPaymentTypes(); + paymentTypes$: Observable = this.checkoutPaymentTypeFacade + .getPaymentTypes() + .pipe( + tap(() => (this.paymentTypesError = false)), + catchError((error: HttpErrorModel) => { + if ( + error.details?.[0]?.type === OccHttpErrorType.CLASS_MISMATCH_ERROR && + this.globalMessageService + ) { + this.globalMessageService.add( + { key: 'httpHandlers.forbidden' }, + GlobalMessageType.MSG_TYPE_ERROR + ); + this.paymentTypesError = true; + } + return of([]); + }) + ); typeSelected$: Observable = combineLatest([ this.checkoutPaymentTypeFacade.getSelectedPaymentTypeState().pipe( @@ -105,10 +136,30 @@ export class CheckoutPaymentTypeComponent { distinctUntilChanged() ); + // TODO(CXSPA-3334): make globalMessageService a required dependency + constructor( + checkoutPaymentTypeFacade: CheckoutPaymentTypeFacade, + checkoutStepService: CheckoutStepService, + activatedRoute: ActivatedRoute, + // eslint-disable-next-line @typescript-eslint/unified-signatures + globalMessageService?: GlobalMessageService + ); + + /** + * @deprecated since 6.3 + */ + constructor( + checkoutPaymentTypeFacade: CheckoutPaymentTypeFacade, + checkoutStepService: CheckoutStepService, + activatedRoute: ActivatedRoute, + globalMessageService: GlobalMessageService + ); + constructor( protected checkoutPaymentTypeFacade: CheckoutPaymentTypeFacade, protected checkoutStepService: CheckoutStepService, - protected activatedRoute: ActivatedRoute + protected activatedRoute: ActivatedRoute, + @Optional() protected globalMessageService?: GlobalMessageService ) {} changeType(code: string): void { diff --git a/feature-libs/checkout/b2b/core/facade/checkout-payment-type.service.ts b/feature-libs/checkout/b2b/core/facade/checkout-payment-type.service.ts index a78be7f3333..5cb0805efb0 100644 --- a/feature-libs/checkout/b2b/core/facade/checkout-payment-type.service.ts +++ b/feature-libs/checkout/b2b/core/facade/checkout-payment-type.service.ts @@ -19,6 +19,7 @@ import { CommandService, CommandStrategy, EventService, + HttpErrorModel, OCC_USER_ID_ANONYMOUS, Query, QueryNotifier, @@ -26,8 +27,8 @@ import { QueryState, UserIdService, } from '@spartacus/core'; -import { combineLatest, Observable } from 'rxjs'; -import { filter, map, switchMap, take, tap } from 'rxjs/operators'; +import { Observable, combineLatest, of, throwError } from 'rxjs'; +import { concatMap, filter, map, switchMap, take, tap } from 'rxjs/operators'; import { CheckoutPaymentTypeConnector } from '../connectors/checkout-payment-type/checkout-payment-type.connector'; @Injectable() @@ -119,7 +120,14 @@ export class CheckoutPaymentTypeService implements CheckoutPaymentTypeFacade { } getPaymentTypes(): Observable { - return this.getPaymentTypesState().pipe(map((state) => state.data ?? [])); + return this.getPaymentTypesState().pipe( + concatMap((state) => + (state?.error as HttpErrorModel) + ? throwError(state.error as HttpErrorModel) + : of(state) + ), + map((state) => state.data ?? []) + ); } setPaymentType( diff --git a/projects/core/src/util/occ-http-error-constants.ts b/projects/core/src/util/occ-http-error-constants.ts index b491c68ad07..bd8d4efc6c8 100644 --- a/projects/core/src/util/occ-http-error-constants.ts +++ b/projects/core/src/util/occ-http-error-constants.ts @@ -8,6 +8,7 @@ export declare const enum OccHttpErrorType { NOT_FOUND_ERROR = 'NotFoundError', + CLASS_MISMATCH_ERROR = 'ClassMismatchError', } export declare const enum OccHttpErrorReason {