mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-31 09:37:15 +01:00
#4185 OLA Warenkorb - 500 Fix
This commit is contained in:
@@ -37,7 +37,7 @@ import {
|
||||
ResponseArgsOfValueTupleOfIEnumerableOfDisplayOrderDTOAndIEnumerableOfKeyValueDTOOfStringAndString,
|
||||
} from '@swagger/oms';
|
||||
import { isNullOrUndefined, memorize } from '@utils/common';
|
||||
import { combineLatest, Observable, of, concat, isObservable, throwError, interval, zip, EMPTY } from 'rxjs';
|
||||
import { combineLatest, Observable, of, concat, isObservable, throwError, interval, zip, EMPTY, Subscription } from 'rxjs';
|
||||
import {
|
||||
bufferCount,
|
||||
catchError,
|
||||
@@ -50,6 +50,7 @@ import {
|
||||
share,
|
||||
shareReplay,
|
||||
switchMap,
|
||||
take,
|
||||
tap,
|
||||
withLatestFrom,
|
||||
} from 'rxjs/operators';
|
||||
@@ -694,39 +695,56 @@ export class DomainCheckoutService {
|
||||
return availability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the availability of all items is valid
|
||||
* @param param0 Process Id
|
||||
* @returns true if the availability of all items is valid
|
||||
*/
|
||||
validateOlaStatus({ processId }: { processId: number }): Observable<boolean> {
|
||||
const enity$ = this.store.select(DomainCheckoutSelectors.selectCheckoutEntityByProcessId, { processId });
|
||||
return combineLatest([enity$, interval(250)]).pipe(
|
||||
mergeMap(([entity]) => {
|
||||
if (!entity || !entity.shoppingCart || !entity.shoppingCart.items) {
|
||||
return EMPTY;
|
||||
}
|
||||
return new Observable((observer) => {
|
||||
const enity$ = this.store.select(DomainCheckoutSelectors.selectCheckoutEntityByProcessId, { processId });
|
||||
|
||||
const availabilityHistory = entity.availabilityHistory ?? [];
|
||||
const shoppingCart = entity.shoppingCart;
|
||||
const olaExpiration = this.olaExpiration;
|
||||
|
||||
const now = Date.now();
|
||||
const exp = this.olaExpiration;
|
||||
let timeout: any;
|
||||
|
||||
for (const item of shoppingCart.items.map((i) => i.data)) {
|
||||
const latestAvailability = availabilityHistory
|
||||
.filter((h) => h.shoppingCartItemId === item.id && h.type === item.features.orderType)
|
||||
.reduce(
|
||||
(prev, curr) => {
|
||||
return prev.timestamp > curr.timestamp ? prev : curr;
|
||||
},
|
||||
{ timestamp: 0 }
|
||||
);
|
||||
let subscription: Subscription;
|
||||
|
||||
if (latestAvailability.timestamp + exp < now) {
|
||||
return of(false);
|
||||
function check() {
|
||||
const exp = Date.now() - olaExpiration;
|
||||
|
||||
subscription?.unsubscribe();
|
||||
subscription = enity$.pipe(take(1)).subscribe((entity) => {
|
||||
if (!entity || !entity.shoppingCart || !entity.shoppingCart.items) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return of(true);
|
||||
}),
|
||||
distinctUntilChanged(isEqual)
|
||||
);
|
||||
const itemAvailabilityTimestamp = entity.itemAvailabilityTimestamp ?? {};
|
||||
const shoppingCart = entity.shoppingCart;
|
||||
|
||||
const timestamps = shoppingCart.items
|
||||
?.map((i) => i.data)
|
||||
?.filter((item) => !!item?.features?.orderType)
|
||||
?.map((item) => itemAvailabilityTimestamp[`${item.id}_${item.features.orderType}`]);
|
||||
|
||||
if (timestamps?.length > 0) {
|
||||
const oldestTimestamp = Math.min(...timestamps);
|
||||
observer.next(exp < oldestTimestamp);
|
||||
}
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
check.call(this);
|
||||
}, olaExpiration);
|
||||
});
|
||||
}
|
||||
|
||||
check.call(this);
|
||||
|
||||
return () => {
|
||||
subscription?.unsubscribe();
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
validateAvailabilities({ processId }: { processId: number }): Observable<boolean> {
|
||||
|
||||
@@ -22,5 +22,5 @@ export interface CheckoutEntity {
|
||||
specialComment: string;
|
||||
notificationChannels: NotificationChannel;
|
||||
olaErrorIds: number[];
|
||||
availabilityHistory: Array<{ shoppingCartItemId: number; availability: AvailabilityDTO; timestamp: number; type: string }>;
|
||||
itemAvailabilityTimestamp: Record<string, number>;
|
||||
}
|
||||
|
||||
@@ -16,18 +16,14 @@ const _domainCheckoutReducer = createReducer(
|
||||
|
||||
entity.shoppingCart = shoppingCart;
|
||||
|
||||
for (let shoppingCartItem of addedShoppingCartItems) {
|
||||
if (!shoppingCartItem.features?.orderType) continue;
|
||||
entity.itemAvailabilityTimestamp = entity.itemAvailabilityTimestamp ?? {};
|
||||
|
||||
entity.availabilityHistory = [
|
||||
...(entity?.availabilityHistory ?? []),
|
||||
{
|
||||
availability: shoppingCartItem.availability,
|
||||
shoppingCartItemId: shoppingCartItem.id,
|
||||
timestamp: Date.now(),
|
||||
type: shoppingCartItem.features.orderType,
|
||||
},
|
||||
];
|
||||
const now = Date.now();
|
||||
|
||||
for (let shoppingCartItem of addedShoppingCartItems) {
|
||||
if (shoppingCartItem.features?.orderType) {
|
||||
entity.itemAvailabilityTimestamp[`${shoppingCartItem.id}_${shoppingCartItem.features.orderType}`] = now;
|
||||
}
|
||||
}
|
||||
|
||||
return storeCheckoutAdapter.setOne(entity, s);
|
||||
@@ -123,15 +119,15 @@ const _domainCheckoutReducer = createReducer(
|
||||
on(DomainCheckoutActions.addShoppingCartItemAvailabilityToHistory, (s, { processId, shoppingCartItemId, availability }) => {
|
||||
const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
|
||||
|
||||
const availabilityHistory = entity?.availabilityHistory ? [...entity?.availabilityHistory] : [];
|
||||
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp ? { ...entity?.itemAvailabilityTimestamp } : {};
|
||||
|
||||
const item = entity?.shoppingCart?.items?.find((i) => i.id === shoppingCartItemId)?.data;
|
||||
|
||||
if (!item?.features?.orderType) return s;
|
||||
|
||||
availabilityHistory.push({ availability, shoppingCartItemId, timestamp: Date.now(), type: item.features.orderType });
|
||||
itemAvailabilityTimestamp[`${item.id}_${item?.features?.orderType}`] = Date.now();
|
||||
|
||||
entity.availabilityHistory = availabilityHistory;
|
||||
entity.itemAvailabilityTimestamp = itemAvailabilityTimestamp;
|
||||
|
||||
return storeCheckoutAdapter.setOne(entity, s);
|
||||
}),
|
||||
@@ -140,15 +136,15 @@ const _domainCheckoutReducer = createReducer(
|
||||
(s, { shoppingCartId, shoppingCartItemId, availability }) => {
|
||||
const entity = getCheckoutEntityByShoppingCartId({ shoppingCartId, entities: s.entities });
|
||||
|
||||
const availabilityHistory = entity?.availabilityHistory ? [...entity?.availabilityHistory] : [];
|
||||
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp ? { ...entity?.itemAvailabilityTimestamp } : {};
|
||||
|
||||
const item = entity?.shoppingCart?.items?.find((i) => i.id === shoppingCartItemId)?.data;
|
||||
|
||||
if (!item?.features?.orderType) return s;
|
||||
|
||||
availabilityHistory.push({ availability, shoppingCartItemId, timestamp: Date.now(), type: item.features.orderType });
|
||||
itemAvailabilityTimestamp[`${item.id}_${item?.features?.orderType}`] = Date.now();
|
||||
|
||||
entity.availabilityHistory = availabilityHistory;
|
||||
entity.itemAvailabilityTimestamp = itemAvailabilityTimestamp;
|
||||
|
||||
return storeCheckoutAdapter.setOne(entity, s);
|
||||
}
|
||||
@@ -175,7 +171,8 @@ function getOrCreateCheckoutEntity({ entities, processId }: { entities: Dictiona
|
||||
notificationChannels: 0,
|
||||
olaErrorIds: [],
|
||||
customer: undefined,
|
||||
availabilityHistory: [],
|
||||
// availabilityHistory: [],
|
||||
itemAvailabilityTimestamp: {},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -232,6 +232,7 @@ export class CheckoutReviewComponent implements OnInit, OnDestroy {
|
||||
this.checkingOla$.next(true);
|
||||
for (let itemComp of this._shoppingCartItems.toArray()) {
|
||||
await itemComp.refreshAvailability();
|
||||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
}
|
||||
this.checkingOla$.next(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user