mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
Merge branch 'release/2.0' into develop
This commit is contained in:
@@ -318,9 +318,22 @@ export class CheckoutReviewComponent extends ComponentStore<CheckoutReviewCompon
|
||||
const fb = this._fb;
|
||||
const notificationChannel = await this.notificationChannel$.pipe(first()).toPromise();
|
||||
const communicationDetails = await this.communicationDetails$.pipe(first()).toPromise();
|
||||
|
||||
let selectedNotificationChannel = 0;
|
||||
if ((notificationChannel & 1) === 1 && communicationDetails.email) {
|
||||
selectedNotificationChannel += 1;
|
||||
}
|
||||
if ((notificationChannel & 2) === 2 && communicationDetails.mobile) {
|
||||
selectedNotificationChannel += 2;
|
||||
}
|
||||
// #1967 Wenn E-Mail und SMS als NotificationChannel gesetzt sind, nur E-Mail anhaken
|
||||
if ((selectedNotificationChannel & 3) === 3) {
|
||||
selectedNotificationChannel = 1;
|
||||
}
|
||||
|
||||
this.control = fb.group({
|
||||
notificationChannel: new FormGroup({
|
||||
selected: new FormControl((notificationChannel & 3) === 3 || communicationDetails.email ? 1 : notificationChannel),
|
||||
selected: new FormControl(selectedNotificationChannel),
|
||||
email: new FormControl(communicationDetails ? communicationDetails.email : '', emailNotificationValidator),
|
||||
mobile: new FormControl(communicationDetails ? communicationDetails.mobile : '', mobileNotificationValidator),
|
||||
}),
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<shared-goods-in-out-order-details (actionHandled)="actionHandled($event)" [itemsSelectable]="true">
|
||||
<shared-goods-in-out-order-details-header
|
||||
[order]="order$ | async"
|
||||
(editClick)="navigateToEditPage($event)"
|
||||
></shared-goods-in-out-order-details-header>
|
||||
<shared-goods-in-out-order-details-header [order]="order$ | async" (editClick)="navigateToEditPage($event)">
|
||||
</shared-goods-in-out-order-details-header>
|
||||
<shared-goods-in-out-order-details-item
|
||||
*ngFor="let item of itemsWithProcessingStatus$ | async"
|
||||
*ngFor="let item of items$ | async"
|
||||
[orderItem]="item"
|
||||
[order]="order$ | async"
|
||||
></shared-goods-in-out-order-details-item>
|
||||
|
||||
@@ -4,12 +4,14 @@ import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { DomainGoodsService, DomainOmsService, OrderItemsContext } from '@domain/oms';
|
||||
import { ComponentStore, tapResponse } from '@ngrx/component-store';
|
||||
import { ListResponseArgsOfOrderItemListItemDTO, OrderItemListItemDTO, OrderItemProcessingStatusValue } from '@swagger/oms';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { combineLatest, Observable, Subject } from 'rxjs';
|
||||
import { debounceTime, filter, first, map, shareReplay, switchMap, takeUntil, tap, withLatestFrom } from 'rxjs/operators';
|
||||
|
||||
export interface GoodsOutDetailsComponentState {
|
||||
fetching: boolean;
|
||||
orderNumber?: string;
|
||||
buyerNumber?: string;
|
||||
processingStatus?: OrderItemProcessingStatusValue;
|
||||
compartmentCode?: string;
|
||||
items?: OrderItemListItemDTO[];
|
||||
@@ -25,6 +27,8 @@ export interface GoodsOutDetailsComponentState {
|
||||
export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComponentState> implements OnInit, OnDestroy {
|
||||
orderNumber$ = this.select((s) => decodeURIComponent(s.orderNumber ?? '') || undefined);
|
||||
|
||||
buyerNumber$ = this.select((s) => s.buyerNumber);
|
||||
|
||||
compartmentCode$ = this.select((s) => decodeURIComponent(s.compartmentCode ?? '') || undefined);
|
||||
|
||||
processingStatus$ = this.select((s) => s.processingStatus);
|
||||
@@ -37,10 +41,6 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
return this.get((s) => s.items);
|
||||
}
|
||||
|
||||
itemsWithProcessingStatus$ = combineLatest([this.items$, this.processingStatus$]).pipe(
|
||||
map(([items, processingStatus]) => items.filter((item) => item.processingStatus === processingStatus))
|
||||
);
|
||||
|
||||
order$ = this.orderId$.pipe(
|
||||
filter((orderId) => !!orderId),
|
||||
switchMap((orderId) => this._omsService.getOrder(orderId)),
|
||||
@@ -60,7 +60,8 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
private _domainGoodsInService: DomainGoodsService,
|
||||
private _omsService: DomainOmsService,
|
||||
private _breadcrumb: BreadcrumbService,
|
||||
private _router: Router
|
||||
private _router: Router,
|
||||
private _uiModal: UiModalService
|
||||
) {
|
||||
super({
|
||||
fetching: false,
|
||||
@@ -68,6 +69,11 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this._activatedRoute.queryParams.pipe(takeUntil(this._onDestroy$)).subscribe((params) => {
|
||||
const buyerNumber: string = decodeURIComponent(params.buyerNumber ?? '');
|
||||
this.patchState({ buyerNumber });
|
||||
});
|
||||
|
||||
this._activatedRoute.params.pipe(takeUntil(this._onDestroy$)).subscribe(async (params) => {
|
||||
const orderNumber: string = params?.orderNumber;
|
||||
const compartmentCode = params?.compartmentCode;
|
||||
@@ -92,6 +98,9 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
key: this.processId,
|
||||
name: item?.compartmentCode || item?.orderNumber,
|
||||
path: this.getDetailsPath(item),
|
||||
params: {
|
||||
buyerNumber: item.buyerNumber,
|
||||
},
|
||||
section: 'customer',
|
||||
tags: ['goods-out', 'details', item?.compartmentCode || item?.orderNumber],
|
||||
});
|
||||
@@ -122,8 +131,8 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
$.pipe(
|
||||
tap(() => this.patchState({ fetching: false })),
|
||||
debounceTime(500),
|
||||
withLatestFrom(this.orderNumber$, this.compartmentCode$, this.processingStatus$),
|
||||
switchMap(([_, orderNumber, compartmentCode, processingStatus]) => {
|
||||
withLatestFrom(this.orderNumber$, this.compartmentCode$),
|
||||
switchMap(([_, orderNumber, compartmentCode]) => {
|
||||
let request$: Observable<ListResponseArgsOfOrderItemListItemDTO>;
|
||||
if (compartmentCode) {
|
||||
request$ = this._domainGoodsInService.getWarenausgabeItemByCompartment(compartmentCode);
|
||||
@@ -131,14 +140,20 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
request$ = this._domainGoodsInService.getWarenausgabeItemByOrderNumber(orderNumber);
|
||||
}
|
||||
|
||||
return request$.pipe(
|
||||
return combineLatest([request$, this.processingStatus$, this.buyerNumber$]).pipe(
|
||||
tapResponse(
|
||||
(res) => {
|
||||
this.patchState({
|
||||
items: res.result,
|
||||
orderId: res.result[0].orderId,
|
||||
([res, processingStatus, buyerNumber]) => {
|
||||
const items = res.result.filter((item) => {
|
||||
return item.processingStatus === processingStatus && (!!buyerNumber ? item.buyerNumber === buyerNumber : true);
|
||||
});
|
||||
this.updateBreadcrumb(res.result.find((item) => item.processingStatus === processingStatus));
|
||||
|
||||
this.openModalIfItemsHaveDifferentCustomers(items);
|
||||
|
||||
this.patchState({
|
||||
items,
|
||||
orderId: items[0].orderId,
|
||||
});
|
||||
this.updateBreadcrumb(items[0]);
|
||||
},
|
||||
(err) => {},
|
||||
() => {
|
||||
@@ -150,12 +165,25 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
|
||||
)
|
||||
);
|
||||
|
||||
openModalIfItemsHaveDifferentCustomers(items: OrderItemListItemDTO[]) {
|
||||
const buyerNumbers = new Set(items.map((item) => item.buyerNumber));
|
||||
if (buyerNumbers.size > 1) {
|
||||
this._uiModal.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Achtung',
|
||||
data: {
|
||||
message: 'Anzeige ist fehlerhaft.\nEs wurden mehrere Positionen gefunden, die mehreren Kunden unterschiedlichen sind.',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
navigateToEditPage(orderItem: OrderItemListItemDTO) {
|
||||
this._router.navigate([this.getEditPath(orderItem)]);
|
||||
this._router.navigate([this.getEditPath(orderItem)], { queryParams: { buyerNumber: orderItem.buyerNumber } });
|
||||
}
|
||||
|
||||
navigateToDetailsPage(item: OrderItemListItemDTO) {
|
||||
this._router.navigate([this.getDetailsPath(item)]);
|
||||
this._router.navigate([this.getDetailsPath(item)], { queryParams: { buyerNumber: item.buyerNumber } });
|
||||
}
|
||||
|
||||
navigateToLandingPage() {
|
||||
|
||||
@@ -2,8 +2,10 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { BreadcrumbService } from '@core/breadcrumb';
|
||||
import { DomainGoodsService } from '@domain/oms';
|
||||
import { OrderItemListItemDTO } from '@swagger/oms';
|
||||
import { UiMessageModalComponent, UiModalService } from '@ui/modal';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { map, shareReplay, switchMap, withLatestFrom } from 'rxjs/operators';
|
||||
import { map, shareReplay, switchMap, tap, withLatestFrom } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'page-goods-out-edit',
|
||||
@@ -28,14 +30,22 @@ export class GoodsOutEditComponent implements OnInit {
|
||||
map((params) => decodeURIComponent(params?.compartmentCode ?? '') || undefined)
|
||||
);
|
||||
|
||||
buyerNumber$ = this._activatedRoute.queryParams.pipe(map((params) => params.buyerNumber));
|
||||
|
||||
items$ = combineLatest([this.orderNumber$, this.compartmentCode$]).pipe(
|
||||
switchMap(([orderNumber, compartmentCode]) =>
|
||||
compartmentCode
|
||||
? this._domainGoodsInService.getWarenausgabeItemByCompartment(compartmentCode)
|
||||
: this._domainGoodsInService.getWarenausgabeItemByOrderNumber(orderNumber)
|
||||
),
|
||||
withLatestFrom(this.processingStatus$),
|
||||
map(([response, processingStatus]) => response.result.filter((item) => item.processingStatus === +processingStatus)),
|
||||
withLatestFrom(this.processingStatus$, this.buyerNumber$),
|
||||
map(([response, processingStatus, buyerNumber]) => {
|
||||
console.log(response, processingStatus, buyerNumber);
|
||||
return response.result.filter(
|
||||
(item) => item.processingStatus === +processingStatus && (!!buyerNumber ? item.buyerNumber === buyerNumber : true)
|
||||
);
|
||||
}),
|
||||
tap((items) => this.openModalIfItemsHaveDifferentCustomers(items)),
|
||||
shareReplay()
|
||||
);
|
||||
|
||||
@@ -43,7 +53,8 @@ export class GoodsOutEditComponent implements OnInit {
|
||||
private _activatedRoute: ActivatedRoute,
|
||||
private _breadcrumb: BreadcrumbService,
|
||||
private _domainGoodsInService: DomainGoodsService,
|
||||
private _router: Router
|
||||
private _router: Router,
|
||||
private _uiModal: UiModalService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -54,6 +65,7 @@ export class GoodsOutEditComponent implements OnInit {
|
||||
const orderNumber = this._activatedRoute.snapshot.params.orderNumber;
|
||||
const compartmentCode = this._activatedRoute.snapshot.params.compartmentCode;
|
||||
const processingStatus = this._activatedRoute.snapshot.params.processingStatus;
|
||||
const buyerNumber = this._activatedRoute.snapshot.queryParams.buyerNumber;
|
||||
await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
|
||||
key: this.processId,
|
||||
name: 'Bearbeiten',
|
||||
@@ -61,6 +73,7 @@ export class GoodsOutEditComponent implements OnInit {
|
||||
? `/kunde/${this.processId}/goods/out/details/compartment/${encodeURIComponent(compartmentCode)}/${processingStatus}/edit`
|
||||
: `/kunde/${this.processId}/goods/out/details/order/${encodeURIComponent(orderNumber)}/${processingStatus}/edit`,
|
||||
section: 'customer',
|
||||
params: { buyerNumber },
|
||||
tags: ['goods-out', 'edit', compartmentCode || orderNumber],
|
||||
});
|
||||
}
|
||||
@@ -69,10 +82,27 @@ export class GoodsOutEditComponent implements OnInit {
|
||||
const orderNumber = this._activatedRoute.snapshot.params.orderNumber;
|
||||
const compartmentCode = this._activatedRoute.snapshot.params.compartmentCode;
|
||||
const processingStatus = options?.processingStatus ? options.processingStatus : this._activatedRoute.snapshot.params.processingStatus;
|
||||
const buyerNumber = this._activatedRoute.snapshot.queryParams.buyerNumber;
|
||||
compartmentCode
|
||||
? this._router.navigate([
|
||||
`/kunde/${this.processId}/goods/out/details/compartment/${encodeURIComponent(compartmentCode)}/${processingStatus}`,
|
||||
])
|
||||
: this._router.navigate([`/kunde/${this.processId}/goods/out/details/order/${encodeURIComponent(orderNumber)}/${processingStatus}`]);
|
||||
? this._router.navigate(
|
||||
[`/kunde/${this.processId}/goods/out/details/compartment/${encodeURIComponent(compartmentCode)}/${processingStatus}`],
|
||||
{ queryParams: { buyerNumber } }
|
||||
)
|
||||
: this._router.navigate([`/kunde/${this.processId}/goods/out/details/order/${encodeURIComponent(orderNumber)}/${processingStatus}`], {
|
||||
queryParams: { buyerNumber },
|
||||
});
|
||||
}
|
||||
|
||||
openModalIfItemsHaveDifferentCustomers(items: OrderItemListItemDTO[]) {
|
||||
const buyerNumbers = new Set(items.map((item) => item.buyerNumber));
|
||||
if (buyerNumbers.size > 1) {
|
||||
this._uiModal.open({
|
||||
content: UiMessageModalComponent,
|
||||
title: 'Achtung',
|
||||
data: {
|
||||
message: 'Anzeige ist fehlerhaft.\nEs wurden mehrere Positionen gefunden, die unterschiedlichen Kunden zugeordnet sind.',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,9 +258,14 @@ export class GoodsOutSearchResultsComponent extends ComponentStore<GoodsOutSearc
|
||||
const compartmentCode = orderItem.compartmentCode;
|
||||
|
||||
if (compartmentCode) {
|
||||
this._router.navigate([
|
||||
`/kunde/${processId}/goods/out/details/compartment/${encodeURIComponent(compartmentCode)}/${processingStatus}`,
|
||||
]);
|
||||
this._router.navigate(
|
||||
[`/kunde/${processId}/goods/out/details/compartment/${encodeURIComponent(compartmentCode)}/${processingStatus}`],
|
||||
{
|
||||
queryParams: {
|
||||
buyerNumber: orderItem.buyerNumber,
|
||||
},
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this._router.navigate([`/kunde/${processId}/goods/out/details/order/${encodeURIComponent(orderNumber)}/${processingStatus}`]);
|
||||
}
|
||||
|
||||
@@ -107,9 +107,18 @@ export class AddProductModalComponent implements OnInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
|
||||
const item = { ...this.item };
|
||||
|
||||
if (!item.retailPrice) {
|
||||
item.retailPrice = {
|
||||
value: { value: 0, currency: 'EUR' },
|
||||
vat: item.retailPrice?.vat,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await this._remiService
|
||||
.addProductToRemit(this.item, this.selectedReason, this.form.value.quantity)
|
||||
.addProductToRemit(item, this.selectedReason, this.form.value.quantity)
|
||||
.pipe(first())
|
||||
.toPromise();
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<ng-container *ngIf="requiredCapacities?.length > 1">
|
||||
<div class="progress-outer">
|
||||
<div class="progress-inner" [style.width]="capacityPercentage + '%'"></div>
|
||||
<div class="progress-inner" [style.width]="leistungPercentage + '%'"></div>
|
||||
</div>
|
||||
<div class="mt-px-2 text-active-branch">Leistungsplätze: {{ capacity }} von {{ maxCapacity }} Exemplaren</div>
|
||||
<div class="mt-px-2 text-active-branch">Leistungsplätze: {{ leistung }} von {{ maxLeistung }} Exemplaren</div>
|
||||
|
||||
<div class="progress-outer">
|
||||
<div class="progress-inner" [style.width]="staplePercentage + '%'"></div>
|
||||
<div class="progress-inner" [style.width]="stapelPercentage + '%'"></div>
|
||||
</div>
|
||||
<div class="mt-px-2 text-active-branch">Stapelplätze: {{ staple }} von {{ maxStaple }} Titel</div>
|
||||
<div class="mt-px-2 text-active-branch">Stapelplätze: {{ stapel }} von {{ maxStapel }} Titel</div>
|
||||
</ng-container>
|
||||
|
||||
@@ -11,38 +11,75 @@ export class RequiredCapacitiesComponent {
|
||||
@Input()
|
||||
requiredCapacities: ValueTupleOfStringAndIntegerAndIntegerAndNullableIntegerAndString[];
|
||||
|
||||
get capacity() {
|
||||
return this.requiredCapacities?.find((_) => true)?.item3 || 0;
|
||||
get leistungCapacity() {
|
||||
return this.requiredCapacities?.find((cap) => cap.item1 === 'Leistung') || undefined;
|
||||
}
|
||||
|
||||
get maxCapacity() {
|
||||
return Math.max(this.capacity, this.requiredCapacities?.find((_) => true)?.item2);
|
||||
get leistung() {
|
||||
const capacity = this.leistungCapacity;
|
||||
if (!capacity) {
|
||||
return 0;
|
||||
}
|
||||
return capacity.item3 > capacity.item2 ? capacity.item2 : capacity.item3;
|
||||
}
|
||||
|
||||
get capacityPercentage() {
|
||||
if (this.maxCapacity > 0) {
|
||||
return (this.capacity / this.maxCapacity) * 100;
|
||||
get maxLeistung() {
|
||||
const capacity = this.leistungCapacity;
|
||||
if (!capacity) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const maxLeistung =
|
||||
(capacity.item4 || 0) < capacity.item2
|
||||
? capacity.item4 || (capacity.item3 > capacity.item2 ? capacity.item2 : capacity.item3) || 0
|
||||
: capacity.item2;
|
||||
|
||||
return Math.max(this.leistung, maxLeistung);
|
||||
}
|
||||
|
||||
get leistungPercentage() {
|
||||
if (this.leistung === this.maxLeistung) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (this.maxLeistung > 0) {
|
||||
return Math.min(Math.max((this.leistung / this.maxLeistung) * 100, 0), 100);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
get staple() {
|
||||
if (this.requiredCapacities?.length > 0) {
|
||||
return this.requiredCapacities[1].item3;
|
||||
}
|
||||
return 0;
|
||||
get stapelCapacity() {
|
||||
return this.requiredCapacities?.find((cap) => cap.item1 === 'Stapel') || undefined;
|
||||
}
|
||||
|
||||
get maxStaple() {
|
||||
if (this.requiredCapacities?.length > 0) {
|
||||
return Math.max(this.staple, this.requiredCapacities[1].item2);
|
||||
get stapel() {
|
||||
const capacity = this.stapelCapacity;
|
||||
if (!capacity) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
return capacity.item3 > capacity.item2 ? capacity.item2 : capacity.item3;
|
||||
}
|
||||
|
||||
get staplePercentage() {
|
||||
if (this.maxStaple > 0) {
|
||||
return (this.staple / this.maxStaple) * 100;
|
||||
get maxStapel() {
|
||||
const capacity = this.stapelCapacity;
|
||||
if (!capacity) {
|
||||
return 0;
|
||||
}
|
||||
const maxStapel =
|
||||
(capacity.item4 || 0) < capacity.item2
|
||||
? capacity.item4 || (capacity.item3 > capacity.item2 ? capacity.item2 : capacity.item3) || 0
|
||||
: capacity.item2;
|
||||
|
||||
return Math.max(this.stapel, maxStapel);
|
||||
}
|
||||
|
||||
get stapelPercentage() {
|
||||
if (this.stapel === this.maxStapel) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (this.maxStapel > 0) {
|
||||
return Math.min(Math.max((this.stapel / this.maxStapel) * 100, 0), 100);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user