mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Compare commits
4 Commits
83ad5f526e
...
fix/5537-A
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c7a78eec4 | ||
|
|
d9b653073b | ||
|
|
de3edaa0f9 | ||
|
|
964a6026a0 |
@@ -4,7 +4,10 @@ import { OrderItemsContext } from './order-items.context';
|
||||
import { UiModalService } from '@ui/modal';
|
||||
import { ReorderModalComponent, ReorderResult } from '@modal/reorder';
|
||||
import { DomainCheckoutService } from '@domain/checkout';
|
||||
import { AvailabilityDTO2, OrderItemListItemDTO } from '@generated/swagger/oms-api';
|
||||
import {
|
||||
AvailabilityDTO2,
|
||||
OrderItemListItemDTO,
|
||||
} from '@generated/swagger/oms-api';
|
||||
import { ToasterService } from '@shared/shell';
|
||||
|
||||
@Injectable()
|
||||
@@ -22,18 +25,36 @@ export class ReOrderActionHandler extends ActionHandler<OrderItemsContext> {
|
||||
const updatedItems: OrderItemListItemDTO[] = [];
|
||||
for (const orderItem of data.items) {
|
||||
const result = await this._uiModal
|
||||
.open<ReorderResult, { item: OrderItemListItemDTO; showReasons: boolean }>({
|
||||
.open<
|
||||
ReorderResult,
|
||||
{ item: OrderItemListItemDTO; showReasons: boolean }
|
||||
>({
|
||||
content: ReorderModalComponent,
|
||||
title: 'Artikel nachbestellen',
|
||||
data: {
|
||||
item: { ...orderItem, quantity: data.itemQuantity?.get(orderItem.orderItemSubsetId) ?? orderItem.quantity },
|
||||
item: {
|
||||
...orderItem,
|
||||
quantity:
|
||||
data.itemQuantity?.get(orderItem.orderItemSubsetId) ??
|
||||
orderItem.quantity,
|
||||
},
|
||||
showReasons: true,
|
||||
},
|
||||
})
|
||||
.afterClosed$.toPromise();
|
||||
|
||||
// #5537 - If no result or no data, skip to next item
|
||||
if (!result || !result.data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.data) {
|
||||
if (result.data.action === 'REORDER') {
|
||||
const reorderResult = await this.reorder(result.data.item, result.data.availability, result.data.comment);
|
||||
const reorderResult = await this.reorder(
|
||||
result.data.item,
|
||||
result.data.availability,
|
||||
result.data.comment,
|
||||
);
|
||||
const resItem = reorderResult.item1;
|
||||
|
||||
this.createToast(result?.data?.comment);
|
||||
@@ -57,8 +78,6 @@ export class ReOrderActionHandler extends ActionHandler<OrderItemsContext> {
|
||||
context = await this._command.handleCommand('NOTAVAILABLE', context);
|
||||
updatedItems.push(...context.items);
|
||||
}
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,24 +96,33 @@ export class ReOrderActionHandler extends ActionHandler<OrderItemsContext> {
|
||||
}
|
||||
}
|
||||
|
||||
async reorder(orderItem: OrderItemListItemDTO, availability: AvailabilityDTO2, comment: string) {
|
||||
async reorder(
|
||||
orderItem: OrderItemListItemDTO,
|
||||
availability: AvailabilityDTO2,
|
||||
comment: string,
|
||||
) {
|
||||
return await this._domainCheckoutService
|
||||
.reorder(orderItem.orderId, orderItem.orderItemId, orderItem.orderItemSubsetId, {
|
||||
quantity: orderItem.quantity,
|
||||
comment,
|
||||
availability: {
|
||||
availabilityType: availability.status,
|
||||
ssc: availability.ssc,
|
||||
sscText: availability.sscText,
|
||||
supplier: {
|
||||
id: availability.supplierId,
|
||||
.reorder(
|
||||
orderItem.orderId,
|
||||
orderItem.orderItemId,
|
||||
orderItem.orderItemSubsetId,
|
||||
{
|
||||
quantity: orderItem.quantity,
|
||||
comment,
|
||||
availability: {
|
||||
availabilityType: availability.status,
|
||||
ssc: availability.ssc,
|
||||
sscText: availability.sscText,
|
||||
supplier: {
|
||||
id: availability.supplierId,
|
||||
},
|
||||
isPrebooked: availability.isPrebooked,
|
||||
estimatedShippingDate: availability.at,
|
||||
price: availability.price,
|
||||
inStock: availability.qty,
|
||||
},
|
||||
isPrebooked: availability.isPrebooked,
|
||||
estimatedShippingDate: availability.at,
|
||||
price: availability.price,
|
||||
inStock: availability.qty,
|
||||
},
|
||||
})
|
||||
)
|
||||
.toPromise();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,6 +166,11 @@ export class DetailsMainViewBillingAddressesComponent
|
||||
customer as unknown as Customer,
|
||||
),
|
||||
);
|
||||
// Clear the selected payer ID when using customer address
|
||||
this.crmTabMetadataService.setSelectedPayerId(
|
||||
this.tabId(),
|
||||
undefined,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -191,6 +191,11 @@ export class DetailsMainViewDeliveryAddressesComponent
|
||||
customer as unknown as Customer,
|
||||
),
|
||||
);
|
||||
// Clear the selected shipping address ID when using customer address
|
||||
this.crmTabMetadataService.setSelectedShippingAddressId(
|
||||
this.tabId(),
|
||||
undefined,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { PickupShelfDetailsStore, PickupShelfStore } from './store';
|
||||
import { ActionHandlerService } from './services/action-handler.service';
|
||||
import { DBHOrderItemListItemDTO, KeyValueDTOOfStringAndString } from '@generated/swagger/oms-api';
|
||||
import {
|
||||
DBHOrderItemListItemDTO,
|
||||
KeyValueDTOOfStringAndString,
|
||||
} from '@generated/swagger/oms-api';
|
||||
import { OrderItemsContext } from '@domain/oms';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||
@@ -22,7 +25,9 @@ export abstract class PickupShelfDetailsBaseComponent {
|
||||
|
||||
get side() {
|
||||
if (this.activatedRoute.snapshot.queryParams.side !== undefined) {
|
||||
return coerceBooleanProperty(this.activatedRoute.snapshot.queryParams.side);
|
||||
return coerceBooleanProperty(
|
||||
this.activatedRoute.snapshot.queryParams.side,
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -37,23 +42,33 @@ export abstract class PickupShelfDetailsBaseComponent {
|
||||
);
|
||||
|
||||
constructor() {
|
||||
this.activatedRoute.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {
|
||||
// // Fix #4508 - Always Reset Cover Items before fetching new ones inside pickup-shelf-in-details.component
|
||||
if (this.store.coverOrderItems?.length) {
|
||||
this.store.resetCoverItems();
|
||||
}
|
||||
this.store.fetchOrder({ orderId: Number(params.orderId) });
|
||||
this.activatedRoute.params
|
||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
||||
.subscribe((params) => {
|
||||
// // Fix #4508 - Always Reset Cover Items before fetching new ones inside pickup-shelf-in-details.component
|
||||
if (this.store.coverOrderItems?.length) {
|
||||
this.store.resetCoverItems();
|
||||
}
|
||||
this.store.fetchOrder({ orderId: Number(params.orderId) });
|
||||
|
||||
this.store.fetchOrderItems({
|
||||
orderNumber: params.orderNumber ? decodeURIComponent(params.orderNumber) : undefined,
|
||||
compartmentCode: params.compartmentCode ? decodeURIComponent(params.compartmentCode) : undefined,
|
||||
compartmentInfo: params.compartmentInfo ? decodeURIComponent(params.compartmentInfo) : undefined,
|
||||
orderItemProcessingStatus: (params.orderItemProcessingStatus
|
||||
? +params.orderItemProcessingStatus
|
||||
: undefined) as any,
|
||||
orderItemSubsetId: params.orderItemSubsetId ? +params.orderItemSubsetId : undefined,
|
||||
this.store.fetchOrderItems({
|
||||
orderNumber: params.orderNumber
|
||||
? decodeURIComponent(params.orderNumber)
|
||||
: undefined,
|
||||
compartmentCode: params.compartmentCode
|
||||
? decodeURIComponent(params.compartmentCode)
|
||||
: undefined,
|
||||
compartmentInfo: params.compartmentInfo
|
||||
? decodeURIComponent(params.compartmentInfo)
|
||||
: undefined,
|
||||
orderItemProcessingStatus: (params.orderItemProcessingStatus
|
||||
? +params.orderItemProcessingStatus
|
||||
: undefined) as any,
|
||||
orderItemSubsetId: params.orderItemSubsetId
|
||||
? +params.orderItemSubsetId
|
||||
: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,23 +93,19 @@ export abstract class PickupShelfDetailsBaseComponent {
|
||||
action,
|
||||
items: this.store.selectedOrderItems,
|
||||
compartmentCode: latestCompartmentCode ?? undefined, // Ticket #4391 - if undefined, assign new compartmentCode to item (bei eingetroffen und drucken)
|
||||
compartmentInfo: latestCompartmentInfo ?? (this.store.selectedCompartmentInfo || this.store.compartmentInfo), // Ticket #4397
|
||||
compartmentInfo:
|
||||
latestCompartmentInfo ??
|
||||
(this.store.selectedCompartmentInfo || this.store.compartmentInfo), // Ticket #4397
|
||||
order: this.store.order,
|
||||
itemQuantity: this.store.selectedOrderItemQuantity,
|
||||
});
|
||||
|
||||
const ctxItem = ctx?.items[0];
|
||||
|
||||
// Ticket #4466 - Nach der nachbestellung wurde der Artikel in den Details nicht mehr angezeigt - änderung #4459 rückgängig gemacht
|
||||
// Ticket #4459 - Usecase Abholfach Nachbestellen - Wenn das selektierte Item nicht verändert wurde z.B. beim schließen des nachbestellen Modals
|
||||
// soll hier returned werden, da der unveränderte Stand angezeigt werden soll
|
||||
// if (
|
||||
// !ctxItem ||
|
||||
// (action.command.includes('REORDER') &&
|
||||
// ctxItem.orderItemSubsetId === this.store.selectedOrderItems.find((_) => true).orderItemSubsetId)
|
||||
// ) {
|
||||
// return;
|
||||
// }
|
||||
// #5537 - If REORDER action and no context item, return early to avoid unnecessary clearing and fetching
|
||||
if (action.command.includes('REORDER') && !ctxItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.store.setFetchPartial(false);
|
||||
this.store.resetSelectedOrderItems();
|
||||
@@ -104,20 +115,29 @@ export abstract class PickupShelfDetailsBaseComponent {
|
||||
|
||||
if (!ctxItem) return;
|
||||
|
||||
const updatedDetailsItems = await new Promise<DBHOrderItemListItemDTO[]>((resolve, reject) => {
|
||||
this.store.fetchOrderItems({
|
||||
orderNumber: ctxItem.orderNumber,
|
||||
compartmentCode: ctxItem.processingStatus === 128 ? ctxItem.compartmentCode : undefined,
|
||||
compartmentInfo: ctxItem.processingStatus === 128 ? ctxItem.compartmentInfo : undefined,
|
||||
orderItemProcessingStatus: ctxItem.processingStatus,
|
||||
orderItemSubsetId: ctxItem.orderItemSubsetId,
|
||||
done: { resolve, reject },
|
||||
});
|
||||
});
|
||||
const updatedDetailsItems = await new Promise<DBHOrderItemListItemDTO[]>(
|
||||
(resolve, reject) => {
|
||||
this.store.fetchOrderItems({
|
||||
orderNumber: ctxItem.orderNumber,
|
||||
compartmentCode:
|
||||
ctxItem.processingStatus === 128
|
||||
? ctxItem.compartmentCode
|
||||
: undefined,
|
||||
compartmentInfo:
|
||||
ctxItem.processingStatus === 128
|
||||
? ctxItem.compartmentInfo
|
||||
: undefined,
|
||||
orderItemProcessingStatus: ctxItem.processingStatus,
|
||||
orderItemSubsetId: ctxItem.orderItemSubsetId,
|
||||
done: { resolve, reject },
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
ctx.items.forEach((item) => {
|
||||
const updatedItem = updatedDetailsItems?.find(
|
||||
(detailsItem) => detailsItem?.orderItemSubsetId === item?.orderItemSubsetId,
|
||||
(detailsItem) =>
|
||||
detailsItem?.orderItemSubsetId === item?.orderItemSubsetId,
|
||||
);
|
||||
|
||||
if (!updatedItem) return;
|
||||
|
||||
@@ -4,12 +4,13 @@ import {
|
||||
} from '@isa/checkout/data-access';
|
||||
|
||||
/**
|
||||
* Creates a unique key for an item based on EAN, destination, and orderItemType.
|
||||
* Creates a unique key for an item based on EAN, targetBranchId, and orderItemType.
|
||||
* Items are only considered identical if all three match.
|
||||
*/
|
||||
export const getItemKey = (item: ShoppingCartItem): string => {
|
||||
const ean = item.product.ean ?? 'no-ean';
|
||||
const destinationId = item.destination?.data?.id ?? 'no-destination';
|
||||
const targetBranchId =
|
||||
item.destination?.data?.targetBranch?.id ?? 'no-target-branch-id';
|
||||
const orderType = getOrderTypeFeature(item.features) ?? 'no-orderType';
|
||||
return `${ean}|${destinationId}|${orderType}`;
|
||||
return `${ean}|${targetBranchId}|${orderType}`;
|
||||
};
|
||||
|
||||
@@ -66,7 +66,8 @@ export class RewardShoppingCartItemQuantityControlComponent {
|
||||
if (
|
||||
orderType === OrderTypeFeature.Delivery ||
|
||||
orderType === OrderTypeFeature.DigitalShipping ||
|
||||
orderType === OrderTypeFeature.B2BShipping
|
||||
orderType === OrderTypeFeature.B2BShipping ||
|
||||
orderType === OrderTypeFeature.Pickup
|
||||
) {
|
||||
return 999;
|
||||
}
|
||||
|
||||
@@ -37,11 +37,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (quantityControl.maxQuantity() < 2 && !isDownload()) {
|
||||
<div
|
||||
class="text-isa-accent-red isa-text-body-2-bold flex flex-row items-center gap-2"
|
||||
>
|
||||
<ng-icon name="isaOtherInfo" size="1.5rem"></ng-icon>
|
||||
<div>Geringer Bestand - Artikel holen vor Abschluss</div>
|
||||
</div>
|
||||
@if (!isDownload()) {
|
||||
@if (showLowStockMessage()) {
|
||||
<div
|
||||
class="text-isa-accent-red isa-text-body-2-bold flex flex-row items-center gap-2"
|
||||
>
|
||||
<ng-icon name="isaOtherInfo" size="1.5rem"></ng-icon>
|
||||
<div>{{ inStock() }} Exemplare sofort lieferbar</div>
|
||||
</div>
|
||||
} @else if (quantityControl.maxQuantity() < 2) {
|
||||
<div
|
||||
class="text-isa-accent-red isa-text-body-2-bold flex flex-row items-center gap-2"
|
||||
>
|
||||
<ng-icon name="isaOtherInfo" size="1.5rem"></ng-icon>
|
||||
<div>Geringer Bestand - Artikel holen vor Abschluss</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,16 @@ export class RewardShoppingCartItemComponent {
|
||||
hasOrderTypeFeature(this.item().features, ['Download']),
|
||||
);
|
||||
|
||||
isAbholung = computed(() =>
|
||||
hasOrderTypeFeature(this.item().features, ['Abholung']),
|
||||
);
|
||||
|
||||
inStock = computed(() => this.item().availability?.inStock ?? 0);
|
||||
|
||||
showLowStockMessage = computed(() => {
|
||||
return this.isAbholung() && this.inStock() < 2;
|
||||
});
|
||||
|
||||
async updatePurchaseOption() {
|
||||
const shoppingCartItemId = this.itemId();
|
||||
const shoppingCartId = this.shoppingCartId();
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
:host {
|
||||
@apply text-isa-accent-red isa-text-body-2-bold flex flex-row gap-2 items-center;
|
||||
@apply text-isa-accent-red isa-text-body-2-bold flex flex-col gap-2 items-start;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
@if (store.totalLoyaltyPointsNeeded() > store.customerRewardPoints()) {
|
||||
<ng-icon
|
||||
class="w-6 h-6 inline-flex items-center justify-center"
|
||||
size="1.5rem"
|
||||
name="isaOtherInfo"
|
||||
></ng-icon>
|
||||
<span>Lesepunkte reichen nicht für alle Artikel</span>
|
||||
<div class="flex flex-row gap-2 items-center">
|
||||
<ng-icon
|
||||
class="w-6 h-6 inline-flex items-center justify-center"
|
||||
size="1.5rem"
|
||||
name="isaOtherInfo"
|
||||
></ng-icon>
|
||||
<span>Lesepunkte reichen nicht für alle Artikel</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -41,10 +41,7 @@ export class RewardSelectionInputsComponent {
|
||||
|
||||
hasCorrectOrderType = computed(() => {
|
||||
const item = this.rewardSelectionItem().item;
|
||||
return hasOrderTypeFeature(item.features, [
|
||||
OrderTypeFeature.InStore,
|
||||
OrderTypeFeature.Pickup,
|
||||
]);
|
||||
return hasOrderTypeFeature(item.features, [OrderTypeFeature.InStore]);
|
||||
});
|
||||
|
||||
hasStock = computed(() => {
|
||||
|
||||
@@ -27,3 +27,16 @@
|
||||
|
||||
<lib-reward-selection-inputs></lib-reward-selection-inputs>
|
||||
</div>
|
||||
|
||||
@if (showLowStockMessage()) {
|
||||
<div
|
||||
class="flex flex-row gap-2 items-center text-isa-accent-red isa-text-body-2-bold"
|
||||
>
|
||||
<ng-icon
|
||||
class="w-6 h-6 inline-flex items-center justify-center"
|
||||
size="1.5rem"
|
||||
name="isaOtherInfo"
|
||||
></ng-icon>
|
||||
<span>{{ inStock() }} Exemplare sofort lieferbar</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
input,
|
||||
} from '@angular/core';
|
||||
import { ProductImageDirective } from '@isa/shared/product-image';
|
||||
import { ProductRouterLinkDirective } from '@isa/shared/product-router-link';
|
||||
import { RewardSelectionInputsComponent } from './reward-selection-inputs/reward-selection-inputs.component';
|
||||
import { RewardSelectionItem } from '@isa/checkout/data-access';
|
||||
import {
|
||||
hasOrderTypeFeature,
|
||||
RewardSelectionItem,
|
||||
} from '@isa/checkout/data-access';
|
||||
import { NgIcon, provideIcons } from '@ng-icons/core';
|
||||
import { isaOtherInfo } from '@isa/icons';
|
||||
|
||||
@Component({
|
||||
selector: 'lib-reward-selection-item',
|
||||
@@ -13,8 +23,24 @@ import { RewardSelectionItem } from '@isa/checkout/data-access';
|
||||
ProductImageDirective,
|
||||
ProductRouterLinkDirective,
|
||||
RewardSelectionInputsComponent,
|
||||
NgIcon,
|
||||
],
|
||||
providers: [provideIcons({ isaOtherInfo })],
|
||||
})
|
||||
export class RewardSelectionItemComponent {
|
||||
rewardSelectionItem = input.required<RewardSelectionItem>();
|
||||
|
||||
inStock = computed(
|
||||
() => this.rewardSelectionItem().item?.availability?.inStock ?? 0,
|
||||
);
|
||||
|
||||
isAbholung = computed(() =>
|
||||
hasOrderTypeFeature(this.rewardSelectionItem()?.item?.features, [
|
||||
'Abholung',
|
||||
]),
|
||||
);
|
||||
|
||||
showLowStockMessage = computed(() => {
|
||||
return this.isAbholung() && this.inStock() < 2;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -34,8 +34,15 @@ export const catchResponseArgsErrorPipe = <T>(): OperatorFunction<T, T> =>
|
||||
return throwError(() => err);
|
||||
}),
|
||||
mergeMap((response) => {
|
||||
if (isResponseArgs(response) && response.error === true) {
|
||||
return throwError(() => new ResponseArgsError(response));
|
||||
if (isResponseArgs(response)) {
|
||||
// Treat as error if error flag is true OR if invalidProperties has entries
|
||||
const hasInvalidProps =
|
||||
response.invalidProperties &&
|
||||
Object.keys(response.invalidProperties).length > 0;
|
||||
|
||||
if (response.error === true || hasInvalidProps) {
|
||||
return throwError(() => new ResponseArgsError(response));
|
||||
}
|
||||
}
|
||||
|
||||
return [response];
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Injectable, inject, resource, signal, computed } from '@angular/core';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { CustomerBonRedemptionFacade } from '../facades/customer-bon-redemption.facade';
|
||||
import { LoyaltyBonResponse } from '@generated/swagger/crm-api';
|
||||
import { ResponseArgsError } from '@isa/common/data-access';
|
||||
|
||||
/**
|
||||
* Resource for checking/validating Bon numbers.
|
||||
@@ -47,8 +48,24 @@ export class CustomerBonCheckResource {
|
||||
this.#logger.debug('Bon checked', () => ({
|
||||
bonNr,
|
||||
found: !!response?.result,
|
||||
hasInvalidProperties:
|
||||
!!response?.invalidProperties &&
|
||||
Object.keys(response.invalidProperties).length > 0,
|
||||
}));
|
||||
|
||||
// Check for invalidProperties even when error is false
|
||||
// Backend may return { error: false, invalidProperties: {...} } for validation issues
|
||||
if (
|
||||
response?.invalidProperties &&
|
||||
Object.keys(response.invalidProperties).length > 0
|
||||
) {
|
||||
this.#logger.warn('Bon check has invalid properties', () => ({
|
||||
bonNr,
|
||||
invalidProperties: response.invalidProperties,
|
||||
}));
|
||||
throw new ResponseArgsError(response);
|
||||
}
|
||||
|
||||
return response?.result;
|
||||
},
|
||||
defaultValue: undefined,
|
||||
|
||||
@@ -224,15 +224,10 @@ export class CrmSearchService {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
this.#logger.debug('Successfully fetched current booking partner store');
|
||||
const res = await firstValueFrom(req$);
|
||||
this.#logger.debug('Successfully fetched current booking partner store');
|
||||
|
||||
return res?.result;
|
||||
} catch (error) {
|
||||
this.#logger.error('Error fetching current booking partner store', error);
|
||||
return undefined;
|
||||
}
|
||||
return res?.result;
|
||||
}
|
||||
|
||||
async addBooking(
|
||||
|
||||
@@ -114,12 +114,7 @@ export class CrmFeatureCustomerBonRedemptionComponent {
|
||||
}
|
||||
// Handle API errors
|
||||
else if (error) {
|
||||
let errorMsg = 'Bon-Validierung fehlgeschlagen';
|
||||
if (error instanceof ResponseArgsError) {
|
||||
errorMsg = error.message || errorMsg;
|
||||
} else if (error instanceof Error) {
|
||||
errorMsg = error.message;
|
||||
}
|
||||
const errorMsg = this.#extractErrorMessage(error);
|
||||
this.store.setError(errorMsg);
|
||||
}
|
||||
});
|
||||
@@ -224,4 +219,23 @@ export class CrmFeatureCustomerBonRedemptionComponent {
|
||||
this.store.reset();
|
||||
this.#bonCheckResource.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract error message from various error types.
|
||||
* ResponseArgsError already formats invalidProperties into a readable message.
|
||||
*/
|
||||
#extractErrorMessage(error: unknown): string {
|
||||
const defaultMsg = 'Bon-Validierung fehlgeschlagen';
|
||||
const actualError = (error as { cause?: unknown })?.cause ?? error;
|
||||
|
||||
if (actualError instanceof ResponseArgsError) {
|
||||
return actualError.message || defaultMsg;
|
||||
}
|
||||
|
||||
if (actualError instanceof Error) {
|
||||
return actualError.message || defaultMsg;
|
||||
}
|
||||
|
||||
return defaultMsg;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user