mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
feature(libs-feature-data-access): Using catchResponseArgsErrorPipe across all data-acesss services now and removed old patterns. Adjusted some tests and added Logging for every case wrapped in try catch patterns
Ref: #5340
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { AvailabilityService as GeneratedAvailabilityService } from '@generated/swagger/availability-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import { LogisticianService, Logistician } from '@isa/oms/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
// TODO: [Next Sprint - Architectural] Abstract cross-domain dependency
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { StoreCheckoutBranchService } from '@generated/swagger/checkout-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { Cache, CacheTimeToLive, InFlight } from '@isa/common/decorators';
|
||||
@@ -14,20 +17,20 @@ export class BranchService {
|
||||
@Cache({ ttl: CacheTimeToLive.fiveMinutes })
|
||||
@InFlight()
|
||||
async fetchBranches(abortSignal?: AbortSignal): Promise<Branch[]> {
|
||||
let req$ = this.#branchService.StoreCheckoutBranchGetBranches({});
|
||||
let req$ = this.#branchService
|
||||
.StoreCheckoutBranchGetBranches({})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as Branch[];
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch branches', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as Branch[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
PrintOrderConfirmation,
|
||||
PrintOrderConfirmationSchema,
|
||||
} from '../schemas';
|
||||
import { ResponseArgsError } from '@isa/common/data-access';
|
||||
import { catchResponseArgsErrorPipe } from '@isa/common/data-access';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { logger } from '@isa/core/logging';
|
||||
|
||||
@@ -18,16 +18,19 @@ export class CheckoutPrintService {
|
||||
): Promise<ResponseArgs> {
|
||||
const parsed = PrintOrderConfirmationSchema.parse(params);
|
||||
|
||||
const req$ = this.#omsPrintService.OMSPrintAbholscheinById(parsed);
|
||||
const req$ = this.#omsPrintService
|
||||
.OMSPrintAbholscheinById(parsed)
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to print order confirmation', err);
|
||||
throw err;
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to print order confirmation', error, () => ({
|
||||
printer: parsed.printer,
|
||||
orderIds: parsed.data,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ import {
|
||||
DestinationDTO,
|
||||
} from '@generated/swagger/checkout-api';
|
||||
|
||||
import { EntityContainer, ResponseArgsError } from '@isa/common/data-access';
|
||||
import {
|
||||
EntityContainer,
|
||||
catchResponseArgsErrorPipe,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { ShoppingCartService } from './shopping-cart.service';
|
||||
@@ -315,19 +318,21 @@ export class CheckoutService {
|
||||
shoppingCartId: number,
|
||||
customerFeatures: Record<string, string>,
|
||||
): Promise<void> {
|
||||
const req$ =
|
||||
this.#shoppingCartService.StoreCheckoutShoppingCartSetLogisticianOnDestinationsByBuyer(
|
||||
{
|
||||
shoppingCartId,
|
||||
payload: { customerFeatures },
|
||||
},
|
||||
const req$ = this.#shoppingCartService
|
||||
.StoreCheckoutShoppingCartSetLogisticianOnDestinationsByBuyer({
|
||||
shoppingCartId,
|
||||
payload: { customerFeatures },
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
try {
|
||||
await firstValueFrom(req$);
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to update destinations for customer',
|
||||
error,
|
||||
() => ({ shoppingCartId }),
|
||||
);
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to update destinations for customer', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -345,20 +350,24 @@ export class CheckoutService {
|
||||
items.map(async (item) => {
|
||||
if (!item.id) return;
|
||||
|
||||
const req$ =
|
||||
this.#shoppingCartService.StoreCheckoutShoppingCartUpdateShoppingCartItem(
|
||||
{
|
||||
const req$ = this.#shoppingCartService
|
||||
.StoreCheckoutShoppingCartUpdateShoppingCartItem({
|
||||
shoppingCartId,
|
||||
shoppingCartItemId: item.id,
|
||||
values: { specialComment: comment },
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
try {
|
||||
await firstValueFrom(req$);
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to set special comment on item',
|
||||
error,
|
||||
() => ({
|
||||
shoppingCartId,
|
||||
shoppingCartItemId: item.id,
|
||||
values: { specialComment: comment },
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to set special comment on item');
|
||||
throw error;
|
||||
}
|
||||
}),
|
||||
@@ -369,20 +378,21 @@ export class CheckoutService {
|
||||
* Refreshes checkout to get latest state.
|
||||
*/
|
||||
private async refreshCheckout(shoppingCartId: number): Promise<Checkout> {
|
||||
const req$ =
|
||||
this.#storeCheckoutService.StoreCheckoutCreateOrRefreshCheckout({
|
||||
const req$ = this.#storeCheckoutService
|
||||
.StoreCheckoutCreateOrRefreshCheckout({
|
||||
shoppingCartId,
|
||||
});
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to refresh checkout', error);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as Checkout;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to refresh checkout', error, () => ({
|
||||
shoppingCartId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as Checkout;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -579,20 +589,22 @@ export class CheckoutService {
|
||||
checkoutId: number,
|
||||
buyerDTO: Buyer,
|
||||
): Promise<Checkout> {
|
||||
const req$ = this.#buyerService.StoreCheckoutBuyerSetBuyerPOST({
|
||||
checkoutId,
|
||||
buyerDTO,
|
||||
});
|
||||
const req$ = this.#buyerService
|
||||
.StoreCheckoutBuyerSetBuyerPOST({
|
||||
checkoutId,
|
||||
buyerDTO,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to set buyer', error);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as Checkout;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to set buyer on checkout', error, () => ({
|
||||
checkoutId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as Checkout;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -602,20 +614,22 @@ export class CheckoutService {
|
||||
checkoutId: number,
|
||||
payer: Payer,
|
||||
): Promise<Checkout> {
|
||||
const req$ = this.#payerService.StoreCheckoutPayerSetPayerPOST({
|
||||
checkoutId,
|
||||
payerDTO: payer,
|
||||
});
|
||||
const req$ = this.#payerService
|
||||
.StoreCheckoutPayerSetPayerPOST({
|
||||
checkoutId,
|
||||
payerDTO: payer,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to set payer', error);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as Checkout;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to set payer on checkout', error, () => ({
|
||||
checkoutId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as Checkout;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -625,21 +639,24 @@ export class CheckoutService {
|
||||
checkoutId: number,
|
||||
channels: NotificationChannel,
|
||||
): Promise<Checkout> {
|
||||
const req$ =
|
||||
this.#storeCheckoutService.StoreCheckoutSetNotificationChannels({
|
||||
const req$ = this.#storeCheckoutService
|
||||
.StoreCheckoutSetNotificationChannels({
|
||||
checkoutId,
|
||||
notificationChannel: channels,
|
||||
});
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to set notification channels', error);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as Checkout;
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to set notification channels on checkout',
|
||||
error,
|
||||
() => ({ checkoutId }),
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as Checkout;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -649,20 +666,24 @@ export class CheckoutService {
|
||||
checkoutId: number,
|
||||
paymentType: PaymentType,
|
||||
): Promise<Checkout> {
|
||||
const req$ = this.#paymentService.StoreCheckoutPaymentSetPaymentType({
|
||||
checkoutId,
|
||||
paymentType: paymentType,
|
||||
});
|
||||
const req$ = this.#paymentService
|
||||
.StoreCheckoutPaymentSetPaymentType({
|
||||
checkoutId,
|
||||
paymentType: paymentType,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to set payment type', error);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as Checkout;
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to set payment type on checkout',
|
||||
error,
|
||||
() => ({ checkoutId, paymentType }),
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as Checkout;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -691,17 +712,21 @@ export class CheckoutService {
|
||||
shippingAddress: { ...shippingAddress },
|
||||
};
|
||||
|
||||
const req$ = this.#storeCheckoutService.StoreCheckoutUpdateDestination({
|
||||
checkoutId,
|
||||
destinationId: dest.id,
|
||||
destinationDTO: updatedDestination,
|
||||
});
|
||||
const req$ = this.#storeCheckoutService
|
||||
.StoreCheckoutUpdateDestination({
|
||||
checkoutId,
|
||||
destinationId: dest.id,
|
||||
destinationDTO: updatedDestination,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to update destination');
|
||||
try {
|
||||
await firstValueFrom(req$);
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to update destination', error, () => ({
|
||||
checkoutId,
|
||||
destinationId: dest.id,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
} from '../schemas';
|
||||
import { RewardSelectionItem, ShoppingCart, ShoppingCartItem } from '../models';
|
||||
import {
|
||||
ResponseArgsError,
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
ensureCurrencyDefaults,
|
||||
} from '@isa/common/data-access';
|
||||
@@ -36,107 +36,105 @@ export class ShoppingCartService {
|
||||
#checkoutMetadataService = inject(CheckoutMetadataService);
|
||||
|
||||
async createShoppingCart(): Promise<ShoppingCart> {
|
||||
const req$ =
|
||||
this.#storeCheckoutShoppingCartService.StoreCheckoutShoppingCartCreateShoppingCart();
|
||||
const req$ = this.#storeCheckoutShoppingCartService
|
||||
.StoreCheckoutShoppingCartCreateShoppingCart()
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to create shopping cart', err);
|
||||
throw err;
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.Created,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
return res.result as ShoppingCart;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to create shopping cart', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.Created,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
return res.result as ShoppingCart;
|
||||
}
|
||||
|
||||
async getShoppingCart(
|
||||
shoppingCartId: number,
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<ShoppingCart | undefined> {
|
||||
let req$ =
|
||||
this.#storeCheckoutShoppingCartService.StoreCheckoutShoppingCartGetShoppingCart(
|
||||
{
|
||||
shoppingCartId,
|
||||
},
|
||||
);
|
||||
let req$ = this.#storeCheckoutShoppingCartService
|
||||
.StoreCheckoutShoppingCartGetShoppingCart({
|
||||
shoppingCartId,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to fetch shopping cart', err);
|
||||
throw err;
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.ItemUpdated,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
return res.result as ShoppingCart;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to get shopping cart', error, () => ({
|
||||
shoppingCartId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.ItemUpdated,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
return res.result as ShoppingCart;
|
||||
}
|
||||
|
||||
async canAddItems(
|
||||
params: CanAddItemsToShoppingCartParams,
|
||||
): Promise<ItemsResult[]> {
|
||||
const parsed = CanAddItemsToShoppingCartParamsSchema.parse(params);
|
||||
const req$ =
|
||||
this.#storeCheckoutShoppingCartService.StoreCheckoutShoppingCartCanAddItems(
|
||||
{
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
payload: parsed.payload as ItemPayload[],
|
||||
},
|
||||
);
|
||||
const req$ = this.#storeCheckoutShoppingCartService
|
||||
.StoreCheckoutShoppingCartCanAddItems({
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
payload: parsed.payload as ItemPayload[],
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as unknown as ItemsResult[];
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to check if items can be added to shopping cart',
|
||||
err,
|
||||
'Failed to check if items can be added',
|
||||
error,
|
||||
() => ({ shoppingCartId: parsed.shoppingCartId }),
|
||||
);
|
||||
throw err;
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as unknown as ItemsResult[];
|
||||
}
|
||||
|
||||
async addItem(params: AddItemToShoppingCartParams): Promise<ShoppingCart> {
|
||||
const parsed = AddItemToShoppingCartParamsSchema.parse(params);
|
||||
|
||||
const req$ =
|
||||
this.#storeCheckoutShoppingCartService.StoreCheckoutShoppingCartAddItemToShoppingCart(
|
||||
{
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
items: parsed.items as AddToShoppingCartDTO[],
|
||||
},
|
||||
const req$ = this.#storeCheckoutShoppingCartService
|
||||
.StoreCheckoutShoppingCartAddItemToShoppingCart({
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
items: parsed.items as AddToShoppingCartDTO[],
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.ItemAdded,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to add item to shopping cart', err);
|
||||
throw err;
|
||||
return res.result as ShoppingCart;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to add item to shopping cart', error, () => ({
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.ItemAdded,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
return res.result as ShoppingCart;
|
||||
}
|
||||
|
||||
async updateItem(
|
||||
@@ -144,60 +142,62 @@ export class ShoppingCartService {
|
||||
): Promise<ShoppingCart> {
|
||||
const parsed = UpdateShoppingCartItemParamsSchema.parse(params);
|
||||
|
||||
const req$ =
|
||||
this.#storeCheckoutShoppingCartService.StoreCheckoutShoppingCartUpdateShoppingCartItem(
|
||||
{
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
shoppingCartItemId: parsed.shoppingCartItemId,
|
||||
values: parsed.values as UpdateShoppingCartItemDTO,
|
||||
},
|
||||
const req$ = this.#storeCheckoutShoppingCartService
|
||||
.StoreCheckoutShoppingCartUpdateShoppingCartItem({
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
shoppingCartItemId: parsed.shoppingCartItemId,
|
||||
values: parsed.values as UpdateShoppingCartItemDTO,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.ItemUpdated,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to update shopping cart item', err);
|
||||
throw err;
|
||||
return res.result as ShoppingCart;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to update shopping cart item', error, () => ({
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
shoppingCartItemId: parsed.shoppingCartItemId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.ItemUpdated,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
return res.result as ShoppingCart;
|
||||
}
|
||||
|
||||
async removeItem(
|
||||
params: RemoveShoppingCartItemParams,
|
||||
): Promise<ShoppingCart> {
|
||||
const parsed = RemoveShoppingCartItemParamsSchema.parse(params);
|
||||
const req$ =
|
||||
this.#storeCheckoutShoppingCartService.StoreCheckoutShoppingCartUpdateShoppingCartItem(
|
||||
{
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
shoppingCartItemId: parsed.shoppingCartItemId,
|
||||
values: {
|
||||
quantity: 0,
|
||||
},
|
||||
const req$ = this.#storeCheckoutShoppingCartService
|
||||
.StoreCheckoutShoppingCartUpdateShoppingCartItem({
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
shoppingCartItemId: parsed.shoppingCartItemId,
|
||||
values: {
|
||||
quantity: 0,
|
||||
},
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.ItemRemoved,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to remove item from shopping cart', err);
|
||||
throw err;
|
||||
return res.result as ShoppingCart;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to remove shopping cart item', error, () => ({
|
||||
shoppingCartId: parsed.shoppingCartId,
|
||||
shoppingCartItemId: parsed.shoppingCartItemId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#shoppingCartStream.pub(
|
||||
ShoppingCartEvent.ItemRemoved,
|
||||
res.result as ShoppingCart,
|
||||
'ShoppingCartService',
|
||||
);
|
||||
return res.result as ShoppingCart;
|
||||
}
|
||||
|
||||
// TODO: Code Kommentieren + Beschreiben
|
||||
|
||||
@@ -87,7 +87,8 @@ describe('SupplierService', () => {
|
||||
// Arrange
|
||||
const errorResponse = {
|
||||
result: null,
|
||||
error: { message: 'API Error', code: 500 },
|
||||
error: true,
|
||||
message: 'API Error',
|
||||
};
|
||||
|
||||
mockSupplierService.StoreCheckoutSupplierGetSuppliers.mockReturnValue(
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { StoreCheckoutSupplierService } from '@generated/swagger/checkout-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { Cache, CacheTimeToLive, InFlight } from '@isa/common/decorators';
|
||||
@@ -32,37 +35,42 @@ export class SupplierService {
|
||||
async getTakeAwaySupplier(abortSignal?: AbortSignal): Promise<Supplier> {
|
||||
this.#logger.debug('Fetching take away supplier');
|
||||
|
||||
let req$ = this.#supplierService.StoreCheckoutSupplierGetSuppliers({});
|
||||
let req$ = this.#supplierService
|
||||
.StoreCheckoutSupplierGetSuppliers({})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to fetch suppliers', error);
|
||||
const takeAwaySupplier = res.result?.find(
|
||||
(supplier) => supplier.supplierNumber === 'F',
|
||||
);
|
||||
|
||||
if (!takeAwaySupplier) {
|
||||
const notFoundError = new Error('Take away supplier (F) not found');
|
||||
this.#logger.error(
|
||||
'Take away supplier not found',
|
||||
notFoundError,
|
||||
() => ({
|
||||
availableSuppliers: res.result?.map((s) => s.supplierNumber),
|
||||
}),
|
||||
);
|
||||
throw notFoundError;
|
||||
}
|
||||
|
||||
this.#logger.debug('Take away supplier fetched', () => ({
|
||||
supplierId: takeAwaySupplier.id,
|
||||
supplierNumber: takeAwaySupplier.supplierNumber,
|
||||
}));
|
||||
|
||||
return takeAwaySupplier;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch take away supplier', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const takeAwaySupplier = res.result?.find(
|
||||
(supplier) => supplier.supplierNumber === 'F',
|
||||
);
|
||||
|
||||
if (!takeAwaySupplier) {
|
||||
const notFoundError = new Error('Take away supplier (F) not found');
|
||||
this.#logger.error('Take away supplier not found', notFoundError, () => ({
|
||||
availableSuppliers: res.result?.map((s) => s.supplierNumber),
|
||||
}));
|
||||
throw notFoundError;
|
||||
}
|
||||
|
||||
this.#logger.debug('Take away supplier fetched', () => ({
|
||||
supplierId: takeAwaySupplier.id,
|
||||
supplierNumber: takeAwaySupplier.supplierNumber,
|
||||
}));
|
||||
|
||||
return takeAwaySupplier;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { CountryService as ApiCountryService } from '@generated/swagger/crm-api';
|
||||
import { Cache, CacheTimeToLive } from '@isa/common/decorators';
|
||||
import { Cache } from '@isa/common/decorators';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { Country } from '../models';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
ResponseArgs,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { logger } from '@isa/core/logging';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CountryService {
|
||||
#apiCountryService = inject(ApiCountryService);
|
||||
#logger = logger(() => ({ service: 'CountryService' }));
|
||||
|
||||
@Cache()
|
||||
async getCountries(abortSignal?: AbortSignal): Promise<Country[]> {
|
||||
@@ -23,8 +24,12 @@ export class CountryService {
|
||||
|
||||
req$ = req$.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
return res.result as Country[];
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as Country[];
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to get countries', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
ResponseArgs,
|
||||
ResponseArgsError,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { Cache, CacheTimeToLive } from '@isa/common/decorators';
|
||||
@@ -161,8 +160,15 @@ export class CrmSearchService {
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
return res?.result;
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res?.result;
|
||||
} catch (error) {
|
||||
this.#logger.error('Error adding customer card', error, () => ({
|
||||
customerId: parsed.customerId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async lockCard(params: LockCardInput): Promise<boolean | undefined> {
|
||||
@@ -176,15 +182,15 @@ export class CrmSearchService {
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
this.#logger.error('Lock card Failed', err);
|
||||
throw err;
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res?.result;
|
||||
} catch (error) {
|
||||
this.#logger.error('Error locking customer card', error, () => ({
|
||||
cardCode: parsed.cardCode,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res?.result;
|
||||
}
|
||||
|
||||
async unlockCard(params: UnlockCardInput): Promise<boolean | undefined> {
|
||||
@@ -199,15 +205,16 @@ export class CrmSearchService {
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
this.#logger.error('Unlock card Failed', err);
|
||||
throw err;
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res?.result;
|
||||
} catch (error) {
|
||||
this.#logger.error('Error unlocking customer card', error, () => ({
|
||||
customerId: parsed.customerId,
|
||||
cardCode: parsed.cardCode,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res?.result;
|
||||
}
|
||||
|
||||
@Cache({ ttl: CacheTimeToLive.oneHour })
|
||||
@@ -224,10 +231,14 @@ export class CrmSearchService {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
this.#logger.debug('Successfully fetched current booking partner store');
|
||||
|
||||
return res?.result;
|
||||
try {
|
||||
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);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async addBooking(
|
||||
@@ -245,8 +256,16 @@ export class CrmSearchService {
|
||||
},
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
const res = await firstValueFrom(req$);
|
||||
return res?.result;
|
||||
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res?.result;
|
||||
} catch (error) {
|
||||
this.#logger.error('Error adding booking', error, () => ({
|
||||
cardCode: parsed.cardCode,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,16 +292,12 @@ export class CrmSearchService {
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
this.#logger.debug('Successfully checked Bon');
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
this.#logger.error('Bon check failed', err);
|
||||
throw err;
|
||||
}
|
||||
|
||||
return res as ResponseArgs<LoyaltyBonResponse>;
|
||||
} catch (error) {
|
||||
this.#logger.error('Error checking Bon', error);
|
||||
this.#logger.error('Error checking Bon', error, () => ({
|
||||
cardCode,
|
||||
bonNr,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -301,8 +316,16 @@ export class CrmSearchService {
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
this.#logger.debug('Successfully redeemed Bon');
|
||||
return res?.result ?? false;
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
this.#logger.debug('Successfully redeemed Bon');
|
||||
return res?.result ?? false;
|
||||
} catch (error) {
|
||||
this.#logger.error('Error redeeming Bon', error, () => ({
|
||||
cardCode,
|
||||
bonNr,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ import {
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { ReceiptService } from '@generated/swagger/oms-api';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { Receipt } from '../models';
|
||||
|
||||
@Injectable()
|
||||
@@ -74,29 +77,31 @@ export class HandleCommandService {
|
||||
parsed,
|
||||
}));
|
||||
|
||||
let req$ = this.#receiptService.ReceiptGetReceiptsByOrderItemSubset({
|
||||
payload: parsed, // Payload Default from old Implementation, eagerLoading: 1 and receiptType: (1 + 64 + 128) set as Schema default
|
||||
});
|
||||
let req$ = this.#receiptService
|
||||
.ReceiptGetReceiptsByOrderItemSubset({
|
||||
payload: parsed, // Payload Default from old Implementation, eagerLoading: 1 and receiptType: (1 + 64 + 128) set as Schema default
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const err = new ResponseArgsError(res);
|
||||
// Mapping Logic from old implementation
|
||||
const mappedReceipts =
|
||||
res?.result?.map((r) => r.item3?.data).filter((f) => !!f) ?? [];
|
||||
|
||||
return mappedReceipts as Receipt[];
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to fetch receipts by order item subset IDs',
|
||||
err,
|
||||
error,
|
||||
() => ({ ids: parsed.ids }),
|
||||
);
|
||||
throw err;
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Mapping Logic from old implementation
|
||||
const mappedReceipts =
|
||||
res?.result?.map((r) => r.item3?.data).filter((f) => !!f) ?? [];
|
||||
|
||||
return mappedReceipts as Receipt[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { LogisticianService as GeneratedLogisticianService } from '@generated/swagger/oms-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { Cache, CacheTimeToLive, InFlight } from '@isa/common/decorators';
|
||||
@@ -32,37 +35,38 @@ export class LogisticianService {
|
||||
async getLogistician2470(abortSignal?: AbortSignal): Promise<Logistician> {
|
||||
this.#logger.debug('Fetching logistician 2470');
|
||||
|
||||
let req$ = this.#logisticianService.LogisticianGetLogisticians({});
|
||||
let req$ = this.#logisticianService
|
||||
.LogisticianGetLogisticians({})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error || !res.result) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to fetch logisticians', error);
|
||||
const logistician = res.result?.find(
|
||||
(l) => l.logisticianNumber === '2470',
|
||||
);
|
||||
|
||||
if (!logistician) {
|
||||
const notFoundError = new Error('Logistician 2470 not found');
|
||||
this.#logger.error('Logistician 2470 not found', notFoundError, () => ({
|
||||
availableLogisticians: res.result?.map((l) => l.logisticianNumber),
|
||||
}));
|
||||
throw notFoundError;
|
||||
}
|
||||
|
||||
this.#logger.debug('Logistician 2470 fetched', () => ({
|
||||
logisticianId: logistician.id,
|
||||
logisticianNumber: logistician.logisticianNumber,
|
||||
}));
|
||||
|
||||
return logistician;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch logistician 2470', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const logistician = res.result.find(
|
||||
(l) => l.logisticianNumber === '2470',
|
||||
);
|
||||
|
||||
if (!logistician) {
|
||||
const notFoundError = new Error('Logistician 2470 not found');
|
||||
this.#logger.error('Logistician 2470 not found', notFoundError, () => ({
|
||||
availableLogisticians: res.result?.map((l) => l.logisticianNumber),
|
||||
}));
|
||||
throw notFoundError;
|
||||
}
|
||||
|
||||
this.#logger.debug('Logistician 2470 fetched', () => ({
|
||||
logisticianId: logistician.id,
|
||||
logisticianNumber: logistician.logisticianNumber,
|
||||
}));
|
||||
|
||||
return logistician;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ import {
|
||||
DBHOrderItemListItemDTO,
|
||||
QueryTokenDTO,
|
||||
} from '@generated/swagger/oms-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@@ -49,26 +52,26 @@ export class OpenRewardTasksService {
|
||||
orderBy: [],
|
||||
};
|
||||
|
||||
let req$ = this.#abholfachService.AbholfachWarenausgabe(payload);
|
||||
let req$ = this.#abholfachService
|
||||
.AbholfachWarenausgabe(payload)
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
const tasks = res.result ?? [];
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.debug('Open reward tasks fetched', () => ({
|
||||
taskCount: tasks.length,
|
||||
}));
|
||||
|
||||
return tasks;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch open reward tasks', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const tasks = res.result ?? [];
|
||||
|
||||
this.#logger.debug('Open reward tasks fetched', () => ({
|
||||
taskCount: tasks.length,
|
||||
}));
|
||||
|
||||
return tasks;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ import {
|
||||
LogisticianService,
|
||||
LogisticianDTO,
|
||||
} from '@generated/swagger/oms-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DisplayOrder } from '../models';
|
||||
@@ -36,19 +39,23 @@ export class OrderCreationService {
|
||||
throw new Error(`Invalid checkoutId: ${checkoutId}`);
|
||||
}
|
||||
|
||||
const req$ = this.#orderCheckoutService.OrderCheckoutCreateOrderPOST({
|
||||
checkoutId,
|
||||
});
|
||||
const req$ = this.#orderCheckoutService
|
||||
.OrderCheckoutCreateOrderPOST({
|
||||
checkoutId,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to create orders', error);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as DisplayOrder[];
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to create orders from checkout',
|
||||
error,
|
||||
() => ({ checkoutId }),
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as DisplayOrder[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,25 +70,29 @@ export class OrderCreationService {
|
||||
logisticianNumber = '2470',
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<LogisticianDTO> {
|
||||
let req$ = this.#logisticianService.LogisticianGetLogisticians({});
|
||||
let req$ = this.#logisticianService
|
||||
.LogisticianGetLogisticians({})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to get logistician', error);
|
||||
const logistician = res.result?.find(
|
||||
(l) => l.logisticianNumber === logisticianNumber,
|
||||
);
|
||||
|
||||
if (!logistician) {
|
||||
throw new Error(`Logistician ${logisticianNumber} not found`);
|
||||
}
|
||||
|
||||
return logistician;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to get logistician', error, () => ({
|
||||
logisticianNumber,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
const logistician = res.result?.find(
|
||||
(l) => l.logisticianNumber === logisticianNumber,
|
||||
);
|
||||
|
||||
if (!logistician) {
|
||||
throw new Error(`Logistician ${logisticianNumber} not found`);
|
||||
}
|
||||
|
||||
return logistician;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { OrderService } from '@generated/swagger/oms-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import {
|
||||
@@ -25,25 +28,28 @@ export class OrderRewardCollectService {
|
||||
throw error;
|
||||
}
|
||||
|
||||
const req$ = this.#orderService.OrderLoyaltyCollect({
|
||||
orderId: params.orderId,
|
||||
orderItemId: params.orderItemId,
|
||||
orderItemSubsetId: params.orderItemSubsetId,
|
||||
data: {
|
||||
collectType: params.collectType,
|
||||
quantity: params.quantity,
|
||||
},
|
||||
});
|
||||
const req$ = this.#orderService
|
||||
.OrderLoyaltyCollect({
|
||||
orderId: params.orderId,
|
||||
orderItemId: params.orderItemId,
|
||||
orderItemSubsetId: params.orderItemSubsetId,
|
||||
data: {
|
||||
collectType: params.collectType,
|
||||
quantity: params.quantity,
|
||||
},
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to collect reward item', error);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as DBHOrderItemListItem[];
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to collect order reward', error, () => ({
|
||||
orderId: params.orderId,
|
||||
orderItemSubsetId: params.orderItemSubsetId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as DBHOrderItemListItem[];
|
||||
}
|
||||
|
||||
async fetchOrderItemSubset(
|
||||
@@ -57,22 +63,22 @@ export class OrderRewardCollectService {
|
||||
throw error;
|
||||
}
|
||||
|
||||
let req$ = this.#orderService.OrderGetOrderItemSubset(
|
||||
params.orderItemSubsetId,
|
||||
);
|
||||
let req$ = this.#orderService
|
||||
.OrderGetOrderItemSubset(params.orderItemSubsetId)
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to fetch order item subset', error);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result as DisplayOrderItemSubset;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch order item subset', error, () => ({
|
||||
orderItemSubsetId: params.orderItemSubsetId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result as DisplayOrderItemSubset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ import {
|
||||
OrderDTO,
|
||||
DisplayOrderDTO,
|
||||
} from '@generated/swagger/oms-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@@ -20,21 +23,23 @@ export class OrdersService {
|
||||
orderId: number,
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<OrderDTO | null> {
|
||||
let req$ = this.#orderService.OrderGetOrder(orderId);
|
||||
let req$ = this.#orderService
|
||||
.OrderGetOrder(orderId)
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to fetch order', { orderId, error });
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result ?? null;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to get order', error, () => ({
|
||||
orderId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,21 +71,23 @@ export class OrdersService {
|
||||
orderId: number,
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<DisplayOrderDTO | null> {
|
||||
let req$ = this.#orderService.OrderGetDisplayOrder(orderId);
|
||||
let req$ = this.#orderService
|
||||
.OrderGetDisplayOrder(orderId)
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to fetch display order', { orderId, error });
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
return res.result ?? null;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to get display order', error, () => ({
|
||||
orderId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.result ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { StockService, BranchDTO } from '@generated/swagger/inventory-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@@ -27,41 +30,42 @@ export class BranchService {
|
||||
* @throws {Error} If branch retrieval fails
|
||||
*/
|
||||
async getDefaultBranch(abortSignal?: AbortSignal): Promise<BranchDTO> {
|
||||
let req$ = this.#stockService.StockCurrentBranch();
|
||||
let req$ = this.#stockService
|
||||
.StockCurrentBranch()
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
const branch = res.result;
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
if (!branch) {
|
||||
const error = new Error('No branch data returned');
|
||||
this.#logger.error('Failed to get default branch', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return {
|
||||
id: branch.id,
|
||||
name: branch.name,
|
||||
address: branch.address,
|
||||
branchType: branch.branchType,
|
||||
branchNumber: branch.branchNumber,
|
||||
changed: branch.changed,
|
||||
created: branch.created,
|
||||
isDefault: branch.isDefault,
|
||||
isOnline: branch.isOnline,
|
||||
key: branch.key,
|
||||
label: branch.label,
|
||||
pId: branch.pId,
|
||||
shortName: branch.shortName,
|
||||
status: branch.status,
|
||||
version: branch.version,
|
||||
};
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to get default branch', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const branch = res.result;
|
||||
|
||||
if (!branch) {
|
||||
const error = new Error('No branch data returned');
|
||||
this.#logger.error('Failed to get default branch', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return {
|
||||
id: branch.id,
|
||||
name: branch.name,
|
||||
address: branch.address,
|
||||
branchType: branch.branchType,
|
||||
branchNumber: branch.branchNumber,
|
||||
changed: branch.changed,
|
||||
created: branch.created,
|
||||
isDefault: branch.isDefault,
|
||||
isOnline: branch.isOnline,
|
||||
key: branch.key,
|
||||
label: branch.label,
|
||||
pId: branch.pId,
|
||||
shortName: branch.shortName,
|
||||
status: branch.status,
|
||||
version: branch.version,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ import { KeyValueStringAndString } from '../models';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { RemissionStockService } from './remission-stock.service';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { InFlight, Cache, CacheTimeToLive } from '@isa/common/decorators';
|
||||
|
||||
/**
|
||||
@@ -65,26 +68,29 @@ export class RemissionProductGroupService {
|
||||
stockId: assignedStock.id,
|
||||
}));
|
||||
|
||||
let req$ = this.#remiService.RemiProductgroups({
|
||||
stockId: assignedStock.id,
|
||||
});
|
||||
let req$ = this.#remiService
|
||||
.RemiProductgroups({
|
||||
stockId: assignedStock.id,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error || !res.result) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to fetch product groups', error);
|
||||
this.#logger.debug('Successfully fetched product groups', () => ({
|
||||
groupCount: res.result?.length || 0,
|
||||
}));
|
||||
|
||||
return res.result as KeyValueStringAndString[];
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch product groups', error, () => ({
|
||||
stockId: assignedStock.id,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#logger.debug('Successfully fetched product groups', () => ({
|
||||
groupCount: res.result?.length || 0,
|
||||
}));
|
||||
|
||||
return res.result as KeyValueStringAndString[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { ReturnService } from '@generated/swagger/inventory-api';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { KeyValueStringAndString } from '../models';
|
||||
import { logger } from '@isa/core/logging';
|
||||
@@ -74,29 +77,30 @@ export class RemissionReasonService {
|
||||
stockId: assignedStock?.id,
|
||||
}));
|
||||
|
||||
let req$ = this.#returnService.ReturnGetReturnReasons({
|
||||
stockId: assignedStock?.id,
|
||||
});
|
||||
let req$ = this.#returnService
|
||||
.ReturnGetReturnReasons({
|
||||
stockId: assignedStock?.id,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
this.#logger.debug('Request configured with abort signal');
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error) {
|
||||
this.#logger.error(
|
||||
'Failed to fetch return reasons',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
this.#logger.debug('Successfully fetched return reasons', () => ({
|
||||
reasonCount: res.result?.length || 0,
|
||||
}));
|
||||
|
||||
return res.result as KeyValueStringAndString[];
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch return reasons', error, () => ({
|
||||
stockId: assignedStock?.id,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#logger.debug('Successfully fetched return reasons', () => ({
|
||||
reasonCount: res.result?.length || 0,
|
||||
}));
|
||||
|
||||
return res.result as KeyValueStringAndString[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,15 +540,15 @@ describe('RemissionReturnReceiptService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle abort signal', async () => {
|
||||
it('should call API with correct parameters', async () => {
|
||||
mockReturnService.ReturnCreateAndAssignPackage.mockReturnValue(
|
||||
of({ result: mockReceipt, error: null }),
|
||||
);
|
||||
const abortController = new AbortController();
|
||||
await service.assignPackage(
|
||||
{ returnId: 123, receiptId: 456, packageNumber: 'PKG-789' },
|
||||
abortController.signal,
|
||||
);
|
||||
await service.assignPackage({
|
||||
returnId: 123,
|
||||
receiptId: 456,
|
||||
packageNumber: 'PKG-789',
|
||||
});
|
||||
expect(mockReturnService.ReturnCreateAndAssignPackage).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -1052,24 +1052,20 @@ describe('RemissionReturnReceiptService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle abort signal', async () => {
|
||||
it('should call API with correct parameters', async () => {
|
||||
// Arrange
|
||||
mockReturnService.ReturnAddReturnItem.mockReturnValue(
|
||||
of({ result: mockTuple, error: null }),
|
||||
);
|
||||
const abortController = new AbortController();
|
||||
|
||||
// Act
|
||||
await service.addReturnItem(
|
||||
{
|
||||
returnId: 1,
|
||||
receiptId: 2,
|
||||
returnItemId: 3,
|
||||
quantity: 4,
|
||||
inStock: 5,
|
||||
},
|
||||
abortController.signal,
|
||||
);
|
||||
await service.addReturnItem({
|
||||
returnId: 1,
|
||||
receiptId: 2,
|
||||
returnItemId: 3,
|
||||
quantity: 4,
|
||||
inStock: 5,
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(mockReturnService.ReturnAddReturnItem).toHaveBeenCalled();
|
||||
@@ -1163,24 +1159,20 @@ describe('RemissionReturnReceiptService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle abort signal', async () => {
|
||||
it('should call API with correct parameters', async () => {
|
||||
// Arrange
|
||||
mockReturnService.ReturnAddReturnSuggestion.mockReturnValue(
|
||||
of({ result: mockTuple, error: null }),
|
||||
);
|
||||
const abortController = new AbortController();
|
||||
|
||||
// Act
|
||||
await service.addReturnSuggestionItem(
|
||||
{
|
||||
returnId: 1,
|
||||
receiptId: 2,
|
||||
returnSuggestionId: 3,
|
||||
quantity: 4,
|
||||
inStock: 5,
|
||||
},
|
||||
abortController.signal,
|
||||
);
|
||||
await service.addReturnSuggestionItem({
|
||||
returnId: 1,
|
||||
receiptId: 2,
|
||||
returnSuggestionId: 3,
|
||||
quantity: 4,
|
||||
inStock: 5,
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(mockReturnService.ReturnAddReturnSuggestion).toHaveBeenCalled();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { ReturnService } from '@generated/swagger/inventory-api';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
ResponseArgs,
|
||||
ResponseArgsError,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
@@ -102,86 +102,21 @@ export class RemissionReturnReceiptService {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to fetch completed returns',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
const returns = (res?.result as Return[]) || [];
|
||||
this.#logger.debug('Successfully fetched completed returns', () => ({
|
||||
returnCount: returns.length,
|
||||
}));
|
||||
|
||||
return returns;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch completed returns', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const returns = (res?.result as Return[]) || [];
|
||||
this.#logger.debug('Successfully fetched completed returns', () => ({
|
||||
returnCount: returns.length,
|
||||
}));
|
||||
|
||||
return returns;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Fetches a specific remission return receipt by receipt and return IDs.
|
||||
// * Validates parameters using FetchRemissionReturnReceiptSchema before making the request.
|
||||
// *
|
||||
// * @async
|
||||
// * @param {FetchRemissionReturnParams} params - The receipt and return identifiers
|
||||
// * @param {FetchRemissionReturnParams} params.receiptId - ID of the receipt to fetch
|
||||
// * @param {FetchRemissionReturnParams} params.returnId - ID of the return containing the receipt
|
||||
// * @param {AbortSignal} [abortSignal] - Optional signal to abort the request
|
||||
// * @returns {Promise<Receipt | undefined>} The receipt object if found, undefined otherwise
|
||||
// * @throws {ResponseArgsError} When the API request fails
|
||||
// * @throws {z.ZodError} When parameter validation fails
|
||||
// *
|
||||
// * @example
|
||||
// * const receipt = await service.fetchRemissionReturnReceipt({
|
||||
// * receiptId: '123',
|
||||
// * returnId: '456'
|
||||
// * });
|
||||
// */
|
||||
// async fetchRemissionReturnReceipt(
|
||||
// params: FetchRemissionReturnParams,
|
||||
// abortSignal?: AbortSignal,
|
||||
// ): Promise<Receipt | undefined> {
|
||||
// this.#logger.debug('Fetching remission return receipt', () => ({ params }));
|
||||
|
||||
// const { receiptId, returnId } =
|
||||
// FetchRemissionReturnReceiptSchema.parse(params);
|
||||
|
||||
// this.#logger.info('Fetching return receipt from API', () => ({
|
||||
// receiptId,
|
||||
// returnId,
|
||||
// }));
|
||||
|
||||
// let req$ = this.#returnService.ReturnGetReturnReceipt({
|
||||
// receiptId,
|
||||
// returnId,
|
||||
// eagerLoading: 2,
|
||||
// });
|
||||
|
||||
// if (abortSignal) {
|
||||
// this.#logger.debug('Request configured with abort signal');
|
||||
// req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
// }
|
||||
|
||||
// const res = await firstValueFrom(req$);
|
||||
|
||||
// if (res?.error) {
|
||||
// this.#logger.error(
|
||||
// 'Failed to fetch return receipt',
|
||||
// new Error(res.message || 'Unknown error'),
|
||||
// );
|
||||
// throw new ResponseArgsError(res);
|
||||
// }
|
||||
|
||||
// const receipt = res?.result as Receipt | undefined;
|
||||
// this.#logger.debug('Successfully fetched return receipt', () => ({
|
||||
// found: !!receipt,
|
||||
// }));
|
||||
|
||||
// return receipt;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Fetches a remission return by its ID.
|
||||
* Validates parameters using FetchReturnSchema before making the request.
|
||||
@@ -218,22 +153,19 @@ export class RemissionReturnReceiptService {
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to fetch return',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
const returnData = res?.result as Return | undefined;
|
||||
this.#logger.debug('Successfully fetched return', () => ({
|
||||
found: !!returnData,
|
||||
}));
|
||||
|
||||
return returnData;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch return', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const returnData = res?.result as Return | undefined;
|
||||
this.#logger.debug('Successfully fetched return', () => ({
|
||||
found: !!returnData,
|
||||
}));
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,22 +218,19 @@ export class RemissionReturnReceiptService {
|
||||
},
|
||||
});
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to create return',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
const returnResponse = res as ResponseArgs<Return> | undefined;
|
||||
this.#logger.debug('Successfully created return', () => ({
|
||||
found: !!returnResponse,
|
||||
}));
|
||||
|
||||
return returnResponse;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to create return', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const returnResponse = res as ResponseArgs<Return> | undefined;
|
||||
this.#logger.debug('Successfully created return', () => ({
|
||||
found: !!returnResponse,
|
||||
}));
|
||||
|
||||
return returnResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,22 +283,19 @@ export class RemissionReturnReceiptService {
|
||||
},
|
||||
});
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to create return receipt',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
const receiptResponse = res as ResponseArgs<Receipt> | undefined;
|
||||
this.#logger.debug('Successfully created return receipt', () => ({
|
||||
found: !!receiptResponse,
|
||||
}));
|
||||
|
||||
return receiptResponse;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to create return receipt', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const receiptResponse = res as ResponseArgs<Receipt> | undefined;
|
||||
this.#logger.debug('Successfully created return receipt', () => ({
|
||||
found: !!receiptResponse,
|
||||
}));
|
||||
|
||||
return receiptResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -411,24 +337,21 @@ export class RemissionReturnReceiptService {
|
||||
},
|
||||
});
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to assign package',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
const receiptWithAssignedPackageResponse = res as
|
||||
| ResponseArgs<Receipt>
|
||||
| undefined;
|
||||
|
||||
this.#logger.debug('Successfully assigned package', () => ({
|
||||
found: !!receiptWithAssignedPackageResponse,
|
||||
}));
|
||||
return receiptWithAssignedPackageResponse;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to assign package', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const receiptWithAssignedPackageResponse = res as
|
||||
| ResponseArgs<Receipt>
|
||||
| undefined;
|
||||
|
||||
this.#logger.debug('Successfully assigned package', () => ({
|
||||
found: !!receiptWithAssignedPackageResponse,
|
||||
}));
|
||||
return receiptWithAssignedPackageResponse;
|
||||
}
|
||||
|
||||
async removeReturnItemFromReturnReceipt(params: {
|
||||
@@ -436,16 +359,15 @@ export class RemissionReturnReceiptService {
|
||||
receiptId: number;
|
||||
receiptItemId: number;
|
||||
}) {
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService.ReturnRemoveReturnItem(params),
|
||||
);
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to remove item from return receipt',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
try {
|
||||
await firstValueFrom(
|
||||
this.#returnService
|
||||
.ReturnRemoveReturnItem(params)
|
||||
.pipe(catchResponseArgsErrorPipe()),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to remove item from return receipt', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,16 +386,17 @@ export class RemissionReturnReceiptService {
|
||||
returnId: number;
|
||||
receiptId: number;
|
||||
}): Promise<void> {
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService.ReturnCancelReturnReceipt(params),
|
||||
);
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to cancel return receipt',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
try {
|
||||
await firstValueFrom(
|
||||
this.#returnService
|
||||
.ReturnCancelReturnReceipt(params)
|
||||
.pipe(catchResponseArgsErrorPipe()),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to cancel return receipt', error, () => ({
|
||||
params,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,34 +409,36 @@ export class RemissionReturnReceiptService {
|
||||
* @throws {ResponseArgsError} When the API request fails
|
||||
*/
|
||||
async cancelReturn(params: { returnId: number }): Promise<void> {
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService.ReturnCancelReturn(params),
|
||||
);
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to cancel return',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
try {
|
||||
await firstValueFrom(
|
||||
this.#returnService
|
||||
.ReturnCancelReturn(params)
|
||||
.pipe(catchResponseArgsErrorPipe()),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to cancel return', error, () => ({
|
||||
params,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async deleteReturnItem(params: { itemId: number }) {
|
||||
this.#logger.debug('Deleting return item', () => ({ params }));
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService.ReturnDeleteReturnItem(params),
|
||||
);
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to delete return item',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
try {
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService
|
||||
.ReturnDeleteReturnItem(params)
|
||||
.pipe(catchResponseArgsErrorPipe()),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
}
|
||||
|
||||
return res?.result as ReturnItem;
|
||||
return res?.result as ReturnItem;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to delete return item', error, () => ({
|
||||
params,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateReturnItemImpediment(params: UpdateItemImpediment) {
|
||||
@@ -521,24 +446,27 @@ export class RemissionReturnReceiptService {
|
||||
|
||||
const { itemId, comment } = UpdateItemImpedimentSchema.parse(params);
|
||||
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService.ReturnReturnItemImpediment({
|
||||
itemId,
|
||||
data: {
|
||||
comment,
|
||||
},
|
||||
}),
|
||||
);
|
||||
try {
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService
|
||||
.ReturnReturnItemImpediment({
|
||||
itemId,
|
||||
data: {
|
||||
comment,
|
||||
},
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe()),
|
||||
);
|
||||
|
||||
if (res?.error) {
|
||||
return res?.result as ReturnItem;
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to update return item impediment',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
error,
|
||||
() => ({ itemId, comment }),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res?.result as ReturnItem;
|
||||
}
|
||||
|
||||
async updateReturnSuggestionImpediment(params: UpdateItemImpediment) {
|
||||
@@ -546,22 +474,26 @@ export class RemissionReturnReceiptService {
|
||||
params,
|
||||
}));
|
||||
const { itemId, comment } = UpdateItemImpedimentSchema.parse(params);
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService.ReturnReturnSuggestionImpediment({
|
||||
itemId,
|
||||
data: {
|
||||
comment,
|
||||
},
|
||||
}),
|
||||
);
|
||||
if (res?.error) {
|
||||
try {
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService
|
||||
.ReturnReturnSuggestionImpediment({
|
||||
itemId,
|
||||
data: {
|
||||
comment,
|
||||
},
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe()),
|
||||
);
|
||||
return res?.result as ReturnSuggestion;
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to update return suggestion impediment',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
error,
|
||||
() => ({ itemId, comment }),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
throw error;
|
||||
}
|
||||
return res?.result as ReturnSuggestion;
|
||||
}
|
||||
|
||||
async completeReturnReceipt({
|
||||
@@ -572,23 +504,25 @@ export class RemissionReturnReceiptService {
|
||||
receiptId: number;
|
||||
}): Promise<Receipt> {
|
||||
this.#logger.debug('Completing return receipt', () => ({ returnId }));
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService.ReturnFinalizeReceipt({
|
||||
try {
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService
|
||||
.ReturnFinalizeReceipt({
|
||||
returnId,
|
||||
receiptId,
|
||||
data: {},
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe()),
|
||||
);
|
||||
|
||||
return res?.result as Receipt;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to complete return receipt', error, () => ({
|
||||
returnId,
|
||||
receiptId,
|
||||
data: {},
|
||||
}),
|
||||
);
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to complete return receipt',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res?.result as Receipt;
|
||||
}
|
||||
|
||||
async completeReturn(params: { returnId: number }): Promise<Return> {
|
||||
@@ -596,23 +530,24 @@ export class RemissionReturnReceiptService {
|
||||
returnId: params.returnId,
|
||||
}));
|
||||
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService.ReturnFinalizeReturn(params),
|
||||
);
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to complete return',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
try {
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService
|
||||
.ReturnFinalizeReturn(params)
|
||||
.pipe(catchResponseArgsErrorPipe()),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
|
||||
this.#logger.info('Successfully completed return', () => ({
|
||||
returnId: params.returnId,
|
||||
}));
|
||||
|
||||
return res?.result as Return;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to complete return', error, () => ({
|
||||
returnId: params.returnId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#logger.info('Successfully completed return', () => ({
|
||||
returnId: params.returnId,
|
||||
}));
|
||||
|
||||
return res?.result as Return;
|
||||
}
|
||||
|
||||
async completeReturnGroup(params: { returnGroup: string }) {
|
||||
@@ -620,23 +555,24 @@ export class RemissionReturnReceiptService {
|
||||
returnId: params.returnGroup,
|
||||
}));
|
||||
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService.ReturnFinalizeReturnGroup(params),
|
||||
);
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to complete return group',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
try {
|
||||
const res = await firstValueFrom(
|
||||
this.#returnService
|
||||
.ReturnFinalizeReturnGroup(params)
|
||||
.pipe(catchResponseArgsErrorPipe()),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
|
||||
this.#logger.info('Successfully completed return group', () => ({
|
||||
returnId: params.returnGroup,
|
||||
}));
|
||||
|
||||
return res?.result as Return[];
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to complete return group', error, () => ({
|
||||
returnGroup: params.returnGroup,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#logger.info('Successfully completed return group', () => ({
|
||||
returnId: params.returnGroup,
|
||||
}));
|
||||
|
||||
return res?.result as Return[];
|
||||
}
|
||||
|
||||
async completeReturnReceiptAndReturn(params: {
|
||||
@@ -711,22 +647,23 @@ export class RemissionReturnReceiptService {
|
||||
},
|
||||
});
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to add return item',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
const updatedReturn = res?.result as ReceiptReturnTuple | undefined;
|
||||
this.#logger.debug('Successfully added return item', () => ({
|
||||
found: !!updatedReturn,
|
||||
}));
|
||||
|
||||
return updatedReturn;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to add return item', error, () => ({
|
||||
returnId,
|
||||
receiptId,
|
||||
returnItemId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
const updatedReturn = res?.result as ReceiptReturnTuple | undefined;
|
||||
this.#logger.debug('Successfully added return item', () => ({
|
||||
found: !!updatedReturn,
|
||||
}));
|
||||
|
||||
return updatedReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -788,24 +725,25 @@ export class RemissionReturnReceiptService {
|
||||
},
|
||||
});
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to add return suggestion item',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
const updatedReturnSuggestion = res?.result as
|
||||
| ReceiptReturnSuggestionTuple
|
||||
| undefined;
|
||||
this.#logger.debug('Successfully added return suggestion item', () => ({
|
||||
found: !!updatedReturnSuggestion,
|
||||
}));
|
||||
|
||||
return updatedReturnSuggestion;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to add return suggestion item', error, () => ({
|
||||
returnId,
|
||||
receiptId,
|
||||
returnSuggestionId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
const updatedReturnSuggestion = res?.result as
|
||||
| ReceiptReturnSuggestionTuple
|
||||
| undefined;
|
||||
this.#logger.debug('Successfully added return suggestion item', () => ({
|
||||
found: !!updatedReturnSuggestion,
|
||||
}));
|
||||
|
||||
return updatedReturnSuggestion;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,8 +19,8 @@ import {
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import {
|
||||
BatchResponseArgs,
|
||||
catchResponseArgsErrorPipe,
|
||||
ListResponseArgs,
|
||||
ResponseArgsError,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
@@ -122,16 +122,18 @@ export class RemissionSearchService {
|
||||
},
|
||||
});
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to fetch required capacity', error);
|
||||
this.#logger.debug('Successfully fetched required capacity');
|
||||
return (res?.result ?? []) as ValueTupleOfStringAndInteger[];
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch required capacity', error, () => ({
|
||||
stockId: parsed.stockId,
|
||||
supplierId: parsed.supplierId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#logger.debug('Successfully fetched required capacity');
|
||||
return (res?.result ?? []) as ValueTupleOfStringAndInteger[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,14 +403,18 @@ export class RemissionSearchService {
|
||||
req = req.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req);
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to check item addition', error);
|
||||
try {
|
||||
const res = await firstValueFrom(req.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
return res as BatchResponseArgs<ReturnItem>;
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to check if items can be added to remission list',
|
||||
error,
|
||||
() => ({ stockId: stock.id, itemCount: items.length }),
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res as BatchResponseArgs<ReturnItem>;
|
||||
}
|
||||
|
||||
async addToList(
|
||||
@@ -437,14 +443,17 @@ export class RemissionSearchService {
|
||||
})),
|
||||
});
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$.pipe(catchResponseArgsErrorPipe()));
|
||||
|
||||
if (res.error) {
|
||||
const error = new ResponseArgsError(res);
|
||||
this.#logger.error('Failed to add item to remission list', error);
|
||||
return res.successful?.map((r) => r.value) as ReturnItem[];
|
||||
} catch (error) {
|
||||
this.#logger.error(
|
||||
'Failed to add items to remission list',
|
||||
error,
|
||||
() => ({ stockId: stock.id, itemCount: items.length }),
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
|
||||
return res.successful?.map((r) => r.value) as ReturnItem[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,13 +87,13 @@ describe('RemissionStockService', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw ResponseArgsError when API returns no result', async () => {
|
||||
it('should throw Error when API returns no result', async () => {
|
||||
mockStockService.StockCurrentStock.mockReturnValue(
|
||||
of({ error: false, result: undefined }),
|
||||
);
|
||||
|
||||
await expect(service.fetchAssignedStock()).rejects.toThrow(
|
||||
ResponseArgsError,
|
||||
'Assigned stock has no ID',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -196,16 +196,17 @@ describe('RemissionStockService', () => {
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should throw ResponseArgsError when API returns no result', async () => {
|
||||
it('should return empty array when API returns no result', async () => {
|
||||
// Arrange
|
||||
mockStockService.StockInStock.mockReturnValue(
|
||||
of({ error: false, result: undefined }),
|
||||
);
|
||||
|
||||
// Act & Assert
|
||||
await expect(service.fetchStockInfos(validParams)).rejects.toThrow(
|
||||
ResponseArgsError,
|
||||
);
|
||||
// Act
|
||||
const result = await service.fetchStockInfos(validParams);
|
||||
|
||||
// Assert
|
||||
expect(result).toBe(undefined);
|
||||
expect(mockStockService.StockInStock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,10 @@ import { StockService } from '@generated/swagger/inventory-api';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { Stock, StockInfo } from '../models';
|
||||
import { FetchStockInStock, FetchStockInStockSchema } from '../schemas';
|
||||
import { ResponseArgsError, takeUntilAborted } from '@isa/common/data-access';
|
||||
import {
|
||||
catchResponseArgsErrorPipe,
|
||||
takeUntilAborted,
|
||||
} from '@isa/common/data-access';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { InFlight, Cache, CacheTimeToLive } from '@isa/common/decorators';
|
||||
|
||||
@@ -56,73 +59,74 @@ export class RemissionStockService {
|
||||
@InFlight()
|
||||
async fetchAssignedStock(abortSignal?: AbortSignal): Promise<Stock> {
|
||||
this.#logger.info('Fetching assigned stock from API');
|
||||
let req$ = this.#stockService.StockCurrentStock();
|
||||
let req$ = this.#stockService
|
||||
.StockCurrentStock()
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
this.#logger.debug('Request configured with abort signal');
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
const result = res.result;
|
||||
if (result?.id === undefined) {
|
||||
const error = new Error('Assigned stock has no ID');
|
||||
this.#logger.error('Invalid stock response', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (res.error || !res.result) {
|
||||
this.#logger.error(
|
||||
'Failed to fetch assigned stock',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
}
|
||||
this.#logger.debug('Successfully fetched assigned stock', () => ({
|
||||
stockId: result.id,
|
||||
}));
|
||||
|
||||
const result = res.result;
|
||||
if (result.id === undefined) {
|
||||
const error = new Error('Assigned stock has no ID');
|
||||
this.#logger.error('Invalid stock response', error);
|
||||
// TypeScript cannot narrow StockDTO to Stock based on the id check above,
|
||||
// so we use a minimal type assertion after runtime validation
|
||||
return result as Stock;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch assigned stock', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#logger.debug('Successfully fetched assigned stock', () => ({
|
||||
stockId: result.id,
|
||||
}));
|
||||
|
||||
// TypeScript cannot narrow StockDTO to Stock based on the id check above,
|
||||
// so we use a minimal type assertion after runtime validation
|
||||
return result as Stock;
|
||||
}
|
||||
|
||||
async fetchStock(
|
||||
branchId: number,
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<Stock | undefined> {
|
||||
let req$ = this.#stockService.StockGetStocks();
|
||||
let req$ = this.#stockService
|
||||
.StockGetStocks()
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
this.#logger.debug('Request configured with abort signal');
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error || !res.result) {
|
||||
this.#logger.error(
|
||||
'Failed to fetch stocks',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
const stock = res.result?.find((s) => s.branch?.id === branchId);
|
||||
if (!stock) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (stock.id === undefined) {
|
||||
this.#logger.warn('Found stock without ID for branch', () => ({
|
||||
branchId,
|
||||
}));
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// TypeScript cannot narrow StockDTO to Stock based on the id check above,
|
||||
// so we use a minimal type assertion after runtime validation
|
||||
return stock as Stock;
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch stock', error, () => ({
|
||||
branchId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
const stock = res.result.find((s) => s.branch?.id === branchId);
|
||||
if (!stock) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (stock.id === undefined) {
|
||||
this.#logger.warn('Found stock without ID for branch', () => ({ branchId }));
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// TypeScript cannot narrow StockDTO to Stock based on the id check above,
|
||||
// so we use a minimal type assertion after runtime validation
|
||||
return stock as Stock;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,30 +183,31 @@ export class RemissionStockService {
|
||||
itemCount: parsed.itemIds.length,
|
||||
}));
|
||||
|
||||
let req$ = this.#stockService.StockInStock({
|
||||
stockId: assignedStockId,
|
||||
articleIds: parsed.itemIds,
|
||||
});
|
||||
let req$ = this.#stockService
|
||||
.StockInStock({
|
||||
stockId: assignedStockId,
|
||||
articleIds: parsed.itemIds,
|
||||
})
|
||||
.pipe(catchResponseArgsErrorPipe());
|
||||
|
||||
if (abortSignal) {
|
||||
this.#logger.debug('Request configured with abort signal');
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
try {
|
||||
const res = await firstValueFrom(req$);
|
||||
|
||||
if (res.error || !res.result) {
|
||||
this.#logger.error(
|
||||
'Failed to fetch stock info',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
this.#logger.debug('Successfully fetched stock info', () => ({
|
||||
itemCount: res.result?.length || 0,
|
||||
}));
|
||||
|
||||
return res.result as StockInfo[];
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch stock info', error, () => ({
|
||||
stockId: assignedStockId,
|
||||
}));
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.#logger.debug('Successfully fetched stock info', () => ({
|
||||
itemCount: res.result?.length || 0,
|
||||
}));
|
||||
|
||||
return res.result as StockInfo[];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user