mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merge tag '4.0' into develop
Finish Release 4.0 4.0
This commit is contained in:
8
libs/oms/data-access/src/lib/index.ts
Normal file
8
libs/oms/data-access/src/lib/index.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export * from './errors';
|
||||
export * from './guards';
|
||||
export * from './models';
|
||||
export * from './operators';
|
||||
export * from './questions';
|
||||
export * from './schemas';
|
||||
export * from './services';
|
||||
export * from './stores';
|
||||
@@ -116,7 +116,7 @@ export class ReturnDetailsService {
|
||||
* Validates that the email parameter is a properly formatted email address.
|
||||
*/
|
||||
static FetchReceiptsEmailParamsSchema = z.object({
|
||||
email: z.string().email(),
|
||||
email: z.string(),
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
></oms-feature-return-details-static>
|
||||
@if (customerReceiptsResource.isLoading()) {
|
||||
<ui-progress-bar class="w-full" mode="indeterminate"></ui-progress-bar>
|
||||
} @else {
|
||||
} @else if (!customerReceiptsResource.error()) {
|
||||
@for (receipt of customerReceiptsResource.value(); track receipt.id) {
|
||||
@if (r.id !== receipt.id) {
|
||||
<oms-feature-return-details-lazy
|
||||
|
||||
@@ -1,151 +1,157 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
inject,
|
||||
resource,
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
||||
import { isaActionChevronLeft } from '@isa/icons';
|
||||
import { ButtonComponent } from '@isa/ui/buttons';
|
||||
import { injectActivatedTabId } from '@isa/core/tabs';
|
||||
import { Location } from '@angular/common';
|
||||
import { ExpandableDirectives } from '@isa/ui/expandable';
|
||||
import { ProgressBarComponent } from '@isa/ui/progress-bar';
|
||||
import {
|
||||
ReturnDetailsService,
|
||||
ReturnProcessStore,
|
||||
ReturnDetailsStore,
|
||||
} from '@isa/oms/data-access';
|
||||
import { ReturnDetailsStaticComponent } from './return-details-static/return-details-static.component';
|
||||
import { ReturnDetailsLazyComponent } from './return-details-lazy/return-details-lazy.component';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { groupBy } from 'lodash';
|
||||
|
||||
@Component({
|
||||
selector: 'oms-feature-return-details',
|
||||
templateUrl: './return-details.component.html',
|
||||
styleUrls: ['./return-details.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
ReturnDetailsStaticComponent,
|
||||
ReturnDetailsLazyComponent,
|
||||
NgIconComponent,
|
||||
ButtonComponent,
|
||||
ExpandableDirectives,
|
||||
ProgressBarComponent,
|
||||
],
|
||||
providers: [provideIcons({ isaActionChevronLeft }), ReturnDetailsStore],
|
||||
})
|
||||
export class ReturnDetailsComponent {
|
||||
#logger = logger(() => ({
|
||||
component: 'ReturnDetailsComponent',
|
||||
itemId: this.receiptId(),
|
||||
processId: this.processId(),
|
||||
params: this.params(),
|
||||
}));
|
||||
#store = inject(ReturnDetailsStore);
|
||||
#returnDetailsService = inject(ReturnDetailsService);
|
||||
#returnProcessStore = inject(ReturnProcessStore);
|
||||
|
||||
private processId = injectActivatedTabId();
|
||||
|
||||
private _router = inject(Router);
|
||||
|
||||
private _activatedRoute = inject(ActivatedRoute);
|
||||
|
||||
location = inject(Location);
|
||||
|
||||
params = toSignal(this._activatedRoute.params);
|
||||
|
||||
receiptId = computed<number>(() => {
|
||||
const params = this.params();
|
||||
if (params) {
|
||||
return z.coerce.number().parse(params['receiptId']);
|
||||
}
|
||||
throw new Error('No receiptId found in route params');
|
||||
});
|
||||
|
||||
receiptResource = this.#store.receiptResource(this.receiptId);
|
||||
|
||||
customerReceiptsResource = resource({
|
||||
params: this.receiptResource.value,
|
||||
loader: async ({ params, abortSignal }) => {
|
||||
const email = params.buyer?.communicationDetails?.email;
|
||||
if (!email) {
|
||||
return [];
|
||||
}
|
||||
return await this.#returnDetailsService.fetchReceiptsByEmail(
|
||||
{ email },
|
||||
abortSignal,
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
canStartProcess = computed(() => {
|
||||
return (
|
||||
this.#store.selectedItemIds().length > 0 && this.processId() !== undefined
|
||||
);
|
||||
});
|
||||
|
||||
startProcess() {
|
||||
if (!this.canStartProcess()) {
|
||||
this.#logger.warn(
|
||||
'Cannot start process: No items selected or no process ID',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const processId = this.processId();
|
||||
const selectedItems = this.#store.selectedItems();
|
||||
const selectedQuantites = this.#store.selectedQuantityMap();
|
||||
const selectedProductCategories = this.#store.itemCategoryMap();
|
||||
|
||||
this.#logger.info('Starting return process', () => ({
|
||||
processId: processId,
|
||||
selectedItems: selectedItems.map((item) => item.id),
|
||||
}));
|
||||
|
||||
if (!selectedItems.length || !processId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const itemsGrouptByReceiptId = groupBy(
|
||||
selectedItems,
|
||||
(item) => item.receipt?.id,
|
||||
);
|
||||
const receipts = this.#store.receiptsEntityMap();
|
||||
|
||||
const returns = Object.entries(itemsGrouptByReceiptId).map(
|
||||
([receiptId, items]) => ({
|
||||
receipt: receipts[Number(receiptId)],
|
||||
items: items.map((item) => {
|
||||
const receiptItem = item;
|
||||
return {
|
||||
receiptItem,
|
||||
quantity: selectedQuantites[receiptItem.id],
|
||||
category: selectedProductCategories[receiptItem.id],
|
||||
};
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
this.#logger.info('Starting return process with returns', () => ({
|
||||
processId,
|
||||
returns,
|
||||
}));
|
||||
|
||||
this.#returnProcessStore.startProcess({
|
||||
processId,
|
||||
returns,
|
||||
});
|
||||
|
||||
this._router.navigate(['../../', 'process'], {
|
||||
relativeTo: this._activatedRoute,
|
||||
});
|
||||
}
|
||||
}
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
computed,
|
||||
inject,
|
||||
resource,
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
||||
import { isaActionChevronLeft } from '@isa/icons';
|
||||
import { ButtonComponent } from '@isa/ui/buttons';
|
||||
import { injectActivatedTabId } from '@isa/core/tabs';
|
||||
import { Location } from '@angular/common';
|
||||
import { ExpandableDirectives } from '@isa/ui/expandable';
|
||||
import { ProgressBarComponent } from '@isa/ui/progress-bar';
|
||||
import {
|
||||
ReturnDetailsService,
|
||||
ReturnProcessStore,
|
||||
ReturnDetailsStore,
|
||||
} from '@isa/oms/data-access';
|
||||
import { ReturnDetailsStaticComponent } from './return-details-static/return-details-static.component';
|
||||
import { ReturnDetailsLazyComponent } from './return-details-lazy/return-details-lazy.component';
|
||||
import { logger } from '@isa/core/logging';
|
||||
import { groupBy } from 'lodash';
|
||||
|
||||
@Component({
|
||||
selector: 'oms-feature-return-details',
|
||||
templateUrl: './return-details.component.html',
|
||||
styleUrls: ['./return-details.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
imports: [
|
||||
ReturnDetailsStaticComponent,
|
||||
ReturnDetailsLazyComponent,
|
||||
NgIconComponent,
|
||||
ButtonComponent,
|
||||
ExpandableDirectives,
|
||||
ProgressBarComponent,
|
||||
],
|
||||
providers: [provideIcons({ isaActionChevronLeft }), ReturnDetailsStore],
|
||||
})
|
||||
export class ReturnDetailsComponent {
|
||||
#logger = logger(() => ({
|
||||
component: 'ReturnDetailsComponent',
|
||||
itemId: this.receiptId(),
|
||||
processId: this.processId(),
|
||||
params: this.params(),
|
||||
}));
|
||||
#store = inject(ReturnDetailsStore);
|
||||
#returnDetailsService = inject(ReturnDetailsService);
|
||||
#returnProcessStore = inject(ReturnProcessStore);
|
||||
|
||||
private processId = injectActivatedTabId();
|
||||
|
||||
private _router = inject(Router);
|
||||
|
||||
private _activatedRoute = inject(ActivatedRoute);
|
||||
|
||||
location = inject(Location);
|
||||
|
||||
params = toSignal(this._activatedRoute.params);
|
||||
|
||||
receiptId = computed<number>(() => {
|
||||
const params = this.params();
|
||||
if (params) {
|
||||
return z.coerce.number().parse(params['receiptId']);
|
||||
}
|
||||
throw new Error('No receiptId found in route params');
|
||||
});
|
||||
|
||||
receiptResource = this.#store.receiptResource(this.receiptId);
|
||||
|
||||
customerReceiptsResource = resource({
|
||||
params: this.receiptResource.value,
|
||||
loader: async ({ params, abortSignal }) => {
|
||||
const email = params.buyer?.communicationDetails?.email;
|
||||
if (!email) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
return await this.#returnDetailsService.fetchReceiptsByEmail(
|
||||
{ email },
|
||||
abortSignal,
|
||||
);
|
||||
} catch (error) {
|
||||
this.#logger.error('Failed to fetch customer receipts', error);
|
||||
return [];
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
canStartProcess = computed(() => {
|
||||
return (
|
||||
this.#store.selectedItemIds().length > 0 && this.processId() !== undefined
|
||||
);
|
||||
});
|
||||
|
||||
startProcess() {
|
||||
if (!this.canStartProcess()) {
|
||||
this.#logger.warn(
|
||||
'Cannot start process: No items selected or no process ID',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const processId = this.processId();
|
||||
const selectedItems = this.#store.selectedItems();
|
||||
const selectedQuantites = this.#store.selectedQuantityMap();
|
||||
const selectedProductCategories = this.#store.itemCategoryMap();
|
||||
|
||||
this.#logger.info('Starting return process', () => ({
|
||||
processId: processId,
|
||||
selectedItems: selectedItems.map((item) => item.id),
|
||||
}));
|
||||
|
||||
if (!selectedItems.length || !processId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const itemsGrouptByReceiptId = groupBy(
|
||||
selectedItems,
|
||||
(item) => item.receipt?.id,
|
||||
);
|
||||
const receipts = this.#store.receiptsEntityMap();
|
||||
|
||||
const returns = Object.entries(itemsGrouptByReceiptId).map(
|
||||
([receiptId, items]) => ({
|
||||
receipt: receipts[Number(receiptId)],
|
||||
items: items.map((item) => {
|
||||
const receiptItem = item;
|
||||
return {
|
||||
receiptItem,
|
||||
quantity: selectedQuantites[receiptItem.id],
|
||||
category: selectedProductCategories[receiptItem.id],
|
||||
};
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
this.#logger.info('Starting return process with returns', () => ({
|
||||
processId,
|
||||
returns,
|
||||
}));
|
||||
|
||||
this.#returnProcessStore.startProcess({
|
||||
processId,
|
||||
returns,
|
||||
});
|
||||
|
||||
this._router.navigate(['../../', 'process'], {
|
||||
relativeTo: this._activatedRoute,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user