mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merged PR 1888: fix: improve sorting of remission return receipts
fix: improve sorting of remission return receipts - Refactor data fetching to use a single API call for all returns - Apply sorting separately to completed and incomplete returns - Fix template tracking to use index instead of potentially undefined ID - Remove redundant API calls for incomplete returns This ensures proper sorting of remission return receipts while maintaining the separation between completed and incomplete items in the display order. Ref: #5224
This commit is contained in:
committed by
Nino Righi
parent
442670bdd0
commit
598df7d5ed
@@ -50,7 +50,7 @@ export class RemissionReturnReceiptService {
|
||||
* const completedReturns = await service
|
||||
* .fetchCompletedRemissionReturnReceipts(controller.signal);
|
||||
*/
|
||||
async fetchCompletedRemissionReturnReceipts(
|
||||
async fetchRemissionReturnReceipts(
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<Return[]> {
|
||||
this.#logger.debug('Fetching completed remission return receipts');
|
||||
@@ -108,50 +108,50 @@ export class RemissionReturnReceiptService {
|
||||
* const incompleteReturns = await service
|
||||
* .fetchIncompletedRemissionReturnReceipts();
|
||||
*/
|
||||
async fetchIncompletedRemissionReturnReceipts(
|
||||
abortSignal?: AbortSignal,
|
||||
): Promise<Return[]> {
|
||||
this.#logger.debug('Fetching incomplete remission return receipts');
|
||||
// async fetchIncompletedRemissionReturnReceipts(
|
||||
// abortSignal?: AbortSignal,
|
||||
// ): Promise<Return[]> {
|
||||
// this.#logger.debug('Fetching incomplete remission return receipts');
|
||||
|
||||
const assignedStock =
|
||||
await this.#remissionStockService.fetchAssignedStock(abortSignal);
|
||||
// const assignedStock =
|
||||
// await this.#remissionStockService.fetchAssignedStock(abortSignal);
|
||||
|
||||
this.#logger.info('Fetching incomplete returns from API', () => ({
|
||||
stockId: assignedStock.id,
|
||||
startDate: subDays(new Date(), 7).toISOString(),
|
||||
}));
|
||||
// this.#logger.info('Fetching incomplete returns from API', () => ({
|
||||
// stockId: assignedStock.id,
|
||||
// startDate: subDays(new Date(), 7).toISOString(),
|
||||
// }));
|
||||
|
||||
let req$ = this.#returnService.ReturnQueryReturns({
|
||||
stockId: assignedStock.id,
|
||||
queryToken: {
|
||||
input: { returncompleted: 'false' },
|
||||
start: subDays(new Date(), 7).toISOString(),
|
||||
eagerLoading: 3,
|
||||
},
|
||||
});
|
||||
// let req$ = this.#returnService.ReturnQueryReturns({
|
||||
// stockId: assignedStock.id,
|
||||
// queryToken: {
|
||||
// input: { returncompleted: 'false' },
|
||||
// start: subDays(new Date(), 7).toISOString(),
|
||||
// eagerLoading: 3,
|
||||
// },
|
||||
// });
|
||||
|
||||
if (abortSignal) {
|
||||
this.#logger.debug('Request configured with abort signal');
|
||||
req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
}
|
||||
// if (abortSignal) {
|
||||
// this.#logger.debug('Request configured with abort signal');
|
||||
// req$ = req$.pipe(takeUntilAborted(abortSignal));
|
||||
// }
|
||||
|
||||
const res = await firstValueFrom(req$);
|
||||
// const res = await firstValueFrom(req$);
|
||||
|
||||
if (res?.error) {
|
||||
this.#logger.error(
|
||||
'Failed to fetch incomplete returns',
|
||||
new Error(res.message || 'Unknown error'),
|
||||
);
|
||||
throw new ResponseArgsError(res);
|
||||
}
|
||||
// if (res?.error) {
|
||||
// this.#logger.error(
|
||||
// 'Failed to fetch incomplete returns',
|
||||
// new Error(res.message || 'Unknown error'),
|
||||
// );
|
||||
// throw new ResponseArgsError(res);
|
||||
// }
|
||||
|
||||
const returns = (res?.result as Return[]) || [];
|
||||
this.#logger.debug('Successfully fetched incomplete returns', () => ({
|
||||
returnCount: returns.length,
|
||||
}));
|
||||
// const returns = (res?.result as Return[]) || [];
|
||||
// this.#logger.debug('Successfully fetched incomplete returns', () => ({
|
||||
// returnCount: returns.length,
|
||||
// }));
|
||||
|
||||
return returns;
|
||||
}
|
||||
// return returns;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Fetches a specific remission return receipt by receipt and return IDs.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
</div>
|
||||
|
||||
<div class="grid grid-flow-rows grid-cols-1 gap-4">
|
||||
@for (remissionReturn of returns(); track remissionReturn[1].id) {
|
||||
@for (remissionReturn of returns(); track $index) {
|
||||
<a [routerLink]="[remissionReturn[0].id, remissionReturn[1].id]">
|
||||
<remi-return-receipt-list-item
|
||||
[remissionReturn]="remissionReturn[0]"
|
||||
|
||||
@@ -64,19 +64,19 @@ export class RemissionReturnReceiptListComponent {
|
||||
* Resource that fetches completed remission return receipts.
|
||||
* Automatically loads when the component is initialized.
|
||||
*/
|
||||
completedRemissionReturnsResource = resource({
|
||||
remissionReturnsResource = resource({
|
||||
loader: () =>
|
||||
this.#remissionReturnReceiptService.fetchCompletedRemissionReturnReceipts(),
|
||||
this.#remissionReturnReceiptService.fetchRemissionReturnReceipts(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Resource that fetches incomplete remission return receipts.
|
||||
* Automatically loads when the component is initialized.
|
||||
*/
|
||||
incompletedRemissionReturnsResource = resource({
|
||||
loader: () =>
|
||||
this.#remissionReturnReceiptService.fetchIncompletedRemissionReturnReceipts(),
|
||||
});
|
||||
// incompletedRemissionReturnsResource = resource({
|
||||
// loader: () =>
|
||||
// this.#remissionReturnReceiptService.fetchIncompletedRemissionReturnReceipts(),
|
||||
// });
|
||||
|
||||
/**
|
||||
* Computed signal that combines completed and incomplete returns.
|
||||
@@ -85,32 +85,35 @@ export class RemissionReturnReceiptListComponent {
|
||||
* @returns {Array<[Return, Receipt]>} Array of tuples containing return and receipt pairs
|
||||
*/
|
||||
returns = computed(() => {
|
||||
const completed = this.completedRemissionReturnsResource.value() || [];
|
||||
const incompleted = this.incompletedRemissionReturnsResource.value() || [];
|
||||
const returns = this.remissionReturnsResource.value() || [];
|
||||
let completed = returns.filter((ret) => ret.completed);
|
||||
let incompleted = returns.filter((ret) => !ret.completed);
|
||||
const orderBy = this.orderDateBy();
|
||||
|
||||
const allReturnReceiptTuples = [...incompleted, ...completed].flatMap(
|
||||
(ret) =>
|
||||
ret.receipts
|
||||
.filter((rec) => rec.data != null)
|
||||
.map((rec) => [ret, rec.data] as [Return, Receipt]),
|
||||
);
|
||||
if (orderBy) {
|
||||
const compareFn = (a: string | undefined, b: string | undefined) => {
|
||||
if (a === undefined) return 1;
|
||||
if (b === undefined) return -1;
|
||||
return (orderBy.dir === 'desc' ? compareDesc : compareAsc)(a, b);
|
||||
};
|
||||
|
||||
if (!orderBy) {
|
||||
return allReturnReceiptTuples;
|
||||
const orderByField = orderBy.by as 'created' | 'completed';
|
||||
completed = orderByKey(completed, orderByField, compareFn);
|
||||
incompleted = orderByKey(incompleted, orderByField, compareFn);
|
||||
}
|
||||
|
||||
const orderByField = orderBy.by as 'created' | 'completed';
|
||||
const compareFn = orderBy.dir === 'desc' ? compareDesc : compareAsc;
|
||||
|
||||
return allReturnReceiptTuples.sort((a, b) => {
|
||||
const dateA = a[1][orderByField];
|
||||
const dateB = b[1][orderByField];
|
||||
|
||||
if (!dateA) return -1;
|
||||
if (!dateB) return 1;
|
||||
|
||||
return compareFn(dateA, dateB);
|
||||
});
|
||||
return [...incompleted, ...completed].flatMap((ret) =>
|
||||
ret.receipts
|
||||
.filter((rec) => rec.data != null)
|
||||
.map((rec) => [ret, rec.data] as [Return, Receipt]),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function orderByKey<T, K extends keyof T>(
|
||||
items: T[],
|
||||
by: K,
|
||||
compareFn: T[K] extends infer U ? (a: U, b: U) => number : never,
|
||||
): T[] {
|
||||
return [...items].sort((a, b) => compareFn(a[by], b[by]) ?? 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user