mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 2057: feat(checkout): add branch selection to reward catalog
feat(checkout): add branch selection to reward catalog - Add new select-branch-dropdown library with BranchDropdownComponent and SelectedBranchDropdownComponent for branch selection - Extend DropdownButtonComponent with filter and option subcomponents - Integrate branch selection into reward catalog page - Add BranchesResource for fetching available branches - Update CheckoutMetadataService with branch selection persistence - Add comprehensive tests for dropdown components Related work items: #5464
This commit is contained in:
committed by
Nino Righi
parent
4589146e31
commit
7950994d66
@@ -4,6 +4,11 @@ import { RemissionStockService } from '../services';
|
||||
import { FetchStockInStock } from '../schemas';
|
||||
import { StockInfo } from '../models';
|
||||
|
||||
export type StockInfoResourceParams = { itemId: number } & (
|
||||
| { stockId?: number }
|
||||
| { branchId: number }
|
||||
);
|
||||
|
||||
/**
|
||||
* Smart batching resource for stock information.
|
||||
* Collects item params from multiple components, waits for a batching window,
|
||||
@@ -19,11 +24,12 @@ import { StockInfo } from '../models';
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class StockInfoResource extends BatchingResource<
|
||||
{ itemId: number; stockId?: number },
|
||||
StockInfoResourceParams,
|
||||
FetchStockInStock,
|
||||
StockInfo
|
||||
> {
|
||||
#stockService = inject(RemissionStockService);
|
||||
#currentBatchBranchId?: number;
|
||||
|
||||
constructor() {
|
||||
super(250); // batchWindowMs
|
||||
@@ -43,27 +49,51 @@ export class StockInfoResource extends BatchingResource<
|
||||
* Build API request params from list of item params.
|
||||
*/
|
||||
protected buildParams(
|
||||
paramsList: { itemId: number; stockId?: number }[],
|
||||
paramsList: { itemId: number; stockId?: number; branchId?: number }[],
|
||||
): FetchStockInStock {
|
||||
const first = paramsList[0];
|
||||
// Track branchId for result matching (StockInfo doesn't contain branchId)
|
||||
this.#currentBatchBranchId = first?.branchId;
|
||||
|
||||
if (first?.branchId !== undefined) {
|
||||
return {
|
||||
itemIds: paramsList.map((p) => p.itemId),
|
||||
branchId: first.branchId,
|
||||
};
|
||||
}
|
||||
return {
|
||||
itemIds: paramsList.map((p) => p.itemId),
|
||||
stockId: paramsList[0]?.stockId,
|
||||
stockId: first?.stockId,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract params from result for cache matching.
|
||||
* Uses tracked branchId since StockInfo doesn't contain it.
|
||||
*/
|
||||
protected getKeyFromResult(
|
||||
stock: StockInfo,
|
||||
): { itemId: number; stockId?: number } | undefined {
|
||||
return stock.itemId !== undefined ? { itemId: stock.itemId } : undefined;
|
||||
): { itemId: number; stockId?: number; branchId?: number } | undefined {
|
||||
if (stock.itemId === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
itemId: stock.itemId,
|
||||
branchId: this.#currentBatchBranchId,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate cache key from params.
|
||||
*/
|
||||
protected getCacheKey(params: { itemId: number; stockId?: number }): string {
|
||||
protected getCacheKey(params: {
|
||||
itemId: number;
|
||||
stockId?: number;
|
||||
branchId?: number;
|
||||
}): string {
|
||||
if (params.branchId !== undefined) {
|
||||
return `branch-${params.branchId}-${params.itemId}`;
|
||||
}
|
||||
return `${params.stockId ?? 'default'}-${params.itemId}`;
|
||||
}
|
||||
|
||||
@@ -76,7 +106,8 @@ export class StockInfoResource extends BatchingResource<
|
||||
): { itemId: number; stockId?: number }[] {
|
||||
return params.itemIds.map((itemId) => ({
|
||||
itemId,
|
||||
stockId: params.stockId,
|
||||
stockId: 'stockId' in params ? params.stockId : undefined,
|
||||
branchId: 'branchId' in params ? params.branchId : undefined,
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const FetchStockInStockSchema = z.object({
|
||||
export const FetchStockInStockWithStockIdSchema = z.object({
|
||||
stockId: z.number().describe('Stock identifier').optional(),
|
||||
itemIds: z.array(z.number()).describe('Item ids'),
|
||||
});
|
||||
|
||||
export const FetchStockInStockWithBranchIdSchema = z.object({
|
||||
branchId: z.number().describe('Branch identifier'),
|
||||
});
|
||||
|
||||
export const FetchStockInStockSchema = z
|
||||
.object({
|
||||
itemIds: z.array(z.number()).describe('Item ids'),
|
||||
})
|
||||
.and(
|
||||
z.union([
|
||||
FetchStockInStockWithBranchIdSchema,
|
||||
FetchStockInStockWithStockIdSchema,
|
||||
]),
|
||||
);
|
||||
|
||||
export type FetchStockInStock = z.infer<typeof FetchStockInStockSchema>;
|
||||
|
||||
@@ -157,8 +157,17 @@ export class RemissionStockService {
|
||||
|
||||
let assignedStockId: number;
|
||||
|
||||
if (parsed.stockId) {
|
||||
if ('stockId' in parsed && parsed.stockId) {
|
||||
assignedStockId = parsed.stockId;
|
||||
} else if ('branchId' in parsed) {
|
||||
const stock = await this.fetchStock(parsed.branchId, abortSignal);
|
||||
if (!stock) {
|
||||
this.#logger.warn('No stock found for branch', () => ({
|
||||
branchId: parsed.branchId,
|
||||
}));
|
||||
return [];
|
||||
}
|
||||
assignedStockId = stock.id;
|
||||
} else {
|
||||
assignedStockId = await this.fetchAssignedStock(abortSignal).then(
|
||||
(s) => s.id,
|
||||
@@ -166,7 +175,7 @@ export class RemissionStockService {
|
||||
}
|
||||
|
||||
this.#logger.info('Fetching stock info from API', () => ({
|
||||
stockId: parsed.stockId,
|
||||
stockId: assignedStockId,
|
||||
itemCount: parsed.itemIds.length,
|
||||
}));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user