Merged PR 858: #2204 WE Reorder Modal Breadcrumb Fix and Display Correct Item after Action C...

#2204 WE Reorder Modal Breadcrumb Fix and Display Correct Item after Action Click
This commit is contained in:
Nino Righi
2021-09-22 09:34:22 +00:00
committed by Lorenz Hilpert
parent 647f5a06be
commit 15f5aa7d10
9 changed files with 144 additions and 101 deletions

View File

@@ -1,23 +1,73 @@
import { Injectable } from '@angular/core';
import { ActionHandler } from '@core/command';
import { ActionHandler, CommandService } from '@core/command';
import { OrderItemsContext } from './order-items.context';
import { UiModalService } from '@ui/modal';
import { ReorderModalComponent } from '@modal/reorder';
import { ReorderModalComponent, ReorderResult } from '@modal/reorder';
import { DomainCheckoutService } from '@domain/checkout';
import { AvailabilityDTO2, OrderItemListItemDTO } from '@swagger/oms';
@Injectable()
export class ReOrderActionHandler extends ActionHandler<OrderItemsContext> {
constructor(private _uiModal: UiModalService) {
constructor(private _command: CommandService, private _domainCheckoutService: DomainCheckoutService, private _uiModal: UiModalService) {
super('REORDER');
}
async handler(data: OrderItemsContext): Promise<OrderItemsContext> {
await this._uiModal
.open({
content: ReorderModalComponent,
data: data.items[0],
})
.afterClosed$.toPromise();
const updatedItems: OrderItemListItemDTO[] = [];
for (const orderItem of data.items) {
const result = await this._uiModal
.open<ReorderResult, OrderItemListItemDTO>({
content: ReorderModalComponent,
data: orderItem,
})
.afterClosed$.toPromise();
if (result.data) {
if (result.data.action === 'REORDER') {
const reorderResult = await this.reorder(result.data.item, result.data.availability);
const resItem = reorderResult.item1;
return data;
updatedItems.push({
...result.data.item,
orderItemSubsetId: resItem.id,
compartmentCode: resItem.compartmentCode,
compartmentInfo: resItem.compartmentInfo,
estimatedShippingDate: resItem.estimatedShippingDate,
isPrebooked: resItem.isPrebooked,
processingStatus: 8192,
processingStatusDate: resItem.processingStatusDate,
quantity: resItem.quantity,
specialComment: resItem.specialComment,
ssc: resItem.ssc,
sscText: resItem.sscText,
});
} else if (result.data.action === 'NOTAVAILABLE') {
let context = { ...data, items: [orderItem] };
context = await this._command.handleCommand('NOTAVAILABLE', context);
updatedItems.push(...context.items);
}
}
}
return { ...data, items: updatedItems };
}
async reorder(orderItem: OrderItemListItemDTO, availability: AvailabilityDTO2) {
return await this._domainCheckoutService
.reorder(orderItem.orderId, orderItem.orderItemId, orderItem.orderItemSubsetId, {
quantity: orderItem.quantity,
availability: {
availabilityType: availability.status,
ssc: availability.ssc,
sscText: availability.sscText,
supplier: {
id: availability.supplierId,
},
isPrebooked: availability.isPrebooked,
estimatedShippingDate: availability.at,
price: availability.price,
inStock: availability.qty,
},
})
.toPromise();
}
}

View File

@@ -1,12 +1,11 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { DomainAvailabilityService } from '@domain/availability';
import { DomainCheckoutService } from '@domain/checkout';
import { DomainOmsService } from '@domain/oms';
import { ComponentStore } from '@ngrx/component-store';
import { AvailabilityDTO2, OrderItemListItemDTO } from '@swagger/oms';
import { UiModalRef } from '@ui/modal';
import { combineLatest } from 'rxjs';
import { catchError, map, switchMap, tap } from 'rxjs/operators';
import { ReorderResult } from './reorder.result';
interface GoodsInListReorderModalState {
orderItem: OrderItemListItemDTO;
@@ -109,10 +108,8 @@ export class ReorderModalComponent extends ComponentStore<GoodsInListReorderModa
takeAwayAvailabilityError: boolean;
constructor(
public modalRef: UiModalRef<any, OrderItemListItemDTO>,
private domainCheckoutService: DomainCheckoutService,
private domainAvailabilityService: DomainAvailabilityService,
private domainOmsService: DomainOmsService
public modalRef: UiModalRef<ReorderResult, OrderItemListItemDTO>,
private domainAvailabilityService: DomainAvailabilityService
) {
super({
orderItem: modalRef.data,
@@ -127,41 +124,22 @@ export class ReorderModalComponent extends ComponentStore<GoodsInListReorderModa
this.checkedAvailability = event ? availability : undefined;
}
async reorder() {
reorder() {
if (this.checkedAvailability) {
this.ctaDisabled = true;
await this.domainCheckoutService
.reorder(this.orderItem.orderId, this.orderItem.orderItemId, this.orderItem.orderItemSubsetId, {
quantity: this.orderItem.quantity,
availability: {
availabilityType: this.checkedAvailability.status,
ssc: this.checkedAvailability.ssc,
sscText: this.checkedAvailability.sscText,
supplier: {
id: this.checkedAvailability.supplierId,
},
isPrebooked: this.checkedAvailability.isPrebooked,
estimatedShippingDate: this.checkedAvailability.at,
price: this.checkedAvailability.price,
inStock: this.checkedAvailability.qty,
},
})
.toPromise();
this.ctaDisabled = false;
this.modalRef.close({ refresh: true });
this.modalRef.close({
item: this.orderItem,
availability: this.checkedAvailability,
action: 'REORDER',
});
}
}
async notAvailable() {
notAvailable() {
this.ctaDisabled = true;
await this.domainOmsService
.changeOrderStatus(this.orderItem.orderId, this.orderItem.orderItemId, this.orderItem.orderItemSubsetId, {
processingStatus: 4096,
})
.toPromise();
this.ctaDisabled = false;
this.modalRef.close({ refresh: true });
this.modalRef.close({
item: this.orderItem,
action: 'NOTAVAILABLE',
});
}
}

View File

@@ -0,0 +1,7 @@
import { AvailabilityDTO2, OrderItemListItemDTO } from '@swagger/oms';
export interface ReorderResult {
item: OrderItemListItemDTO;
availability?: AvailabilityDTO2;
action: 'REORDER' | 'NOTAVAILABLE';
}

View File

@@ -2,6 +2,7 @@
* Public API Surface of reorder
*/
export * from './lib/reorder.result';
export * from './lib/supplier-name.pipe';
export * from './lib/reorder.component';
export * from './lib/reorder.module';

View File

@@ -4,8 +4,8 @@ import { BreadcrumbService } from '@core/breadcrumb';
import { DomainGoodsService, OrderItemsContext } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { OrderItemListItemDTO, OrderItemProcessingStatusValue } from '@swagger/oms';
import { combineLatest, Subject, Subscription } from 'rxjs';
import { debounceTime, first, map, switchMap, takeUntil, tap, withLatestFrom } from 'rxjs/operators';
import { combineLatest, Subject } from 'rxjs';
import { debounceTime, first, map, switchMap, takeUntil, tap, throttleTime, withLatestFrom } from 'rxjs/operators';
export interface GoodsInDetailsComponentState {
fetching: boolean;
@@ -56,21 +56,15 @@ export class GoodsInDetailsComponent extends ComponentStore<GoodsInDetailsCompon
}
ngOnInit() {
this._activatedRoute.params.pipe(takeUntil(this._onDestroy$)).subscribe((params) => {
this._activatedRoute.params.pipe(takeUntil(this._onDestroy$)).subscribe(async (params) => {
const orderNumber: string = params?.orderNumber;
const selectedOrderItemId: number = +params?.orderItemId || undefined;
const processingStatus = +params?.processingStatus as OrderItemProcessingStatusValue;
this.patchState({ orderNumber, selectedOrderItemId, processingStatus });
await this.removeDetailsCrumbs();
this.loadItems();
});
this.itemsWithProcessingStatus$.pipe(takeUntil(this._onDestroy$)).subscribe((items) => {
if (items.length === 0 && this.items?.length > 0) {
this.navigateToDetailsPage(this.items[0]);
}
});
this.removeBreadcrumbs();
}
@@ -87,16 +81,27 @@ export class GoodsInDetailsComponent extends ComponentStore<GoodsInDetailsCompon
});
}
async updateBreadcrumb(item: OrderItemListItemDTO) {
await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
key: 'goods-in',
name: item?.orderNumber,
path: `/goods/in/details/order/${encodeURIComponent(item?.orderNumber)}/item/${item?.orderItemId}/${item?.processingStatus}`,
section: 'branch',
tags: ['goods-in', 'details', item?.orderNumber],
async removeDetailsCrumbs() {
const detailsCrumbs = await this._breadcrumb.getBreadcrumbsByKeyAndTags$('goods-in', ['goods-in', 'details']).pipe(first()).toPromise();
detailsCrumbs.forEach((crumb) => {
this._breadcrumb.removeBreadcrumb(crumb.id, true);
});
}
async updateBreadcrumb(item: OrderItemListItemDTO) {
if (item) {
await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
key: 'goods-in',
name: item?.orderNumber,
path: `/goods/in/details/order/${encodeURIComponent(item?.orderNumber)}/item/${item?.orderItemId}/${item?.processingStatus}`,
section: 'branch',
tags: ['goods-in', 'details', item?.orderNumber],
});
}
}
// tslint:disable-next-line: member-ordering
loadItems = this.effect(($) =>
$.pipe(
tap(() => this.patchState({ fetching: false })),
@@ -117,7 +122,7 @@ export class GoodsInDetailsComponent extends ComponentStore<GoodsInDetailsCompon
res.result.find((item) => item.orderItemId === selectedOrderItemId && item.processingStatus === processingStatus)
);
},
(err) => {},
() => {},
() => {
this.patchState({ fetching: false });
}
@@ -161,10 +166,11 @@ export class GoodsInDetailsComponent extends ComponentStore<GoodsInDetailsCompon
}
}
actionHandled(handler: { orderItemsContext: OrderItemsContext; navigation: 'details' | 'main' | 'reservation' }) {
async actionHandled(handler: { orderItemsContext: OrderItemsContext; command: string; navigation: 'details' | 'main' | 'reservation' }) {
switch (handler.navigation) {
case 'details':
this.navigateToDetailsPage(handler.orderItemsContext.items.find((_) => true));
await this.removeDetailsCrumbs();
this.loadItems();
break;
case 'main':

View File

@@ -1,9 +1,8 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, Output } from '@angular/core';
import { CommandService } from '@core/command';
import { DomainOmsService } from '@domain/oms';
import { ReorderModalComponent } from '@modal/reorder';
import { ComponentStore } from '@ngrx/component-store';
import { OrderItemListItemDTO } from '@swagger/oms';
import { UiModalService } from '@ui/modal';
import { isEqual } from 'lodash';
import { Subject } from 'rxjs';
import { catchError, first, shareReplay, switchMap, takeUntil } from 'rxjs/operators';
@@ -115,7 +114,7 @@ export class GoodsInListItemComponent extends ComponentStore<GoodsInListItemComp
private _onDestroy$ = new Subject();
constructor(private _omsService: DomainOmsService, private _uiModal: UiModalService) {
constructor(private _omsService: DomainOmsService, private _command: CommandService) {
super({
item: undefined,
editSsc: false,
@@ -153,15 +152,8 @@ export class GoodsInListItemComponent extends ComponentStore<GoodsInListItemComp
this.sscChanged = false;
}
showReorderModal() {
const modal = this._uiModal.open({
content: ReorderModalComponent,
data: this.item,
});
modal.afterClosed$.pipe(takeUntil(this._onDestroy$)).subscribe((modal) => {
if (modal?.data?.refresh) {
this.refresh.emit();
}
});
async showReorderModal() {
await this._command.handleCommand('REORDER', { items: [this.item] });
this.refresh.emit();
}
}

View File

@@ -1,5 +1,8 @@
<shared-goods-in-out-order-details (actionHandled)="actionHandled($event)" [itemsSelectable]="true">
<shared-goods-in-out-order-details-header (editClick)="navigateToEditPage($event)"></shared-goods-in-out-order-details-header>
<shared-goods-in-out-order-details-item *ngFor="let item of items$ | async" [orderItem]="item"></shared-goods-in-out-order-details-item>
<shared-goods-in-out-order-details-item
*ngFor="let item of itemsWithProcessingStatus$ | async"
[orderItem]="item"
></shared-goods-in-out-order-details-item>
<shared-goods-in-out-order-details-tags></shared-goods-in-out-order-details-tags>
</shared-goods-in-out-order-details>

View File

@@ -4,6 +4,7 @@ import { BreadcrumbService } from '@core/breadcrumb';
import { DomainGoodsService, OrderItemsContext } from '@domain/oms';
import { ComponentStore, tapResponse } from '@ngrx/component-store';
import { ListResponseArgsOfOrderItemListItemDTO, OrderItemListItemDTO, OrderItemProcessingStatusValue } from '@swagger/oms';
import { Command } from 'protractor';
import { combineLatest, Observable, Subject, Subscription } from 'rxjs';
import { debounceTime, first, map, switchMap, takeUntil, tap, withLatestFrom } from 'rxjs/operators';
@@ -52,21 +53,16 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
}
ngOnInit() {
this._activatedRoute.params.pipe(takeUntil(this._onDestroy$)).subscribe((params) => {
this._activatedRoute.params.pipe(takeUntil(this._onDestroy$)).subscribe(async (params) => {
const orderNumber: string = params?.orderNumber;
const compartmentCode = params?.compartmentCode;
const processingStatus = +params?.processingStatus as OrderItemProcessingStatusValue;
this.patchState({ orderNumber, compartmentCode, processingStatus });
await this.removeDetailsCrumbs();
this.loadItems();
});
this.itemsWithProcessingStatus$.pipe(takeUntil(this._onDestroy$)).subscribe((items) => {
if (items.length === 0 && this.items?.length > 0) {
this.navigateToDetailsPage(this.items[0]);
}
});
this.removeBreadcrumbs();
}
@@ -76,32 +72,37 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
}
async updateBreadcrumb(item: OrderItemListItemDTO) {
await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
key: 'goods-out',
name: item?.compartmentCode || item?.orderNumber,
path: this.getDetailsPath(item),
section: 'customer',
tags: ['goods-out', 'details', item?.compartmentCode || item?.orderNumber],
});
if (item) {
await this._breadcrumb.addOrUpdateBreadcrumbIfNotExists({
key: 'goods-out',
name: item?.compartmentCode || item?.orderNumber,
path: this.getDetailsPath(item),
section: 'customer',
tags: ['goods-out', 'details', item?.compartmentCode || item?.orderNumber],
});
}
}
async removeBreadcrumbs() {
const detailsCrumbs = await this._breadcrumb
.getBreadcrumbsByKeyAndTags$('goods-out', ['goods-out', 'details'])
.pipe(first())
.toPromise();
const editCrumbs = await this._breadcrumb.getBreadcrumbsByKeyAndTags$('goods-out', ['goods-out', 'edit']).pipe(first()).toPromise();
editCrumbs.forEach((crumb) => {
this._breadcrumb.removeBreadcrumb(crumb.id, true);
});
}
async removeDetailsCrumbs() {
const detailsCrumbs = await this._breadcrumb
.getBreadcrumbsByKeyAndTags$('goods-out', ['goods-out', 'details'])
.pipe(first())
.toPromise();
detailsCrumbs.forEach((crumb) => {
this._breadcrumb.removeBreadcrumb(crumb.id, true);
});
}
// tslint:disable-next-line: member-ordering
loadItems = this.effect(($) =>
$.pipe(
tap(() => this.patchState({ fetching: false })),
@@ -141,8 +142,9 @@ export class GoodsOutDetailsComponent extends ComponentStore<GoodsOutDetailsComp
this._router.navigate([this.getDetailsPath(item)]);
}
actionHandled(handler: { orderItemsContext: OrderItemsContext; navigation: 'details' | 'main' | 'reservation' }) {
async actionHandled(handler: { orderItemsContext: OrderItemsContext; command: string; navigation: 'details' | 'main' | 'reservation' }) {
this.navigateToDetailsPage(handler.orderItemsContext.items.find((_) => true));
await this.removeDetailsCrumbs();
this.loadItems();
}

View File

@@ -49,7 +49,11 @@ export class SharedGoodsInOutOrderDetailsComponent extends SharedGoodsInOutOrder
changeActionDisabled$ = new BehaviorSubject<boolean>(false);
@Output()
actionHandled = new EventEmitter<{ orderItemsContext: OrderItemsContext; navigation: 'details' | 'main' | 'reservation' }>();
actionHandled = new EventEmitter<{
orderItemsContext: OrderItemsContext;
command: string;
navigation: 'details' | 'main' | 'reservation';
}>();
private _orderDetailsItemComponentsChangeSubscription: Subscription;
@@ -127,7 +131,7 @@ export class SharedGoodsInOutOrderDetailsComponent extends SharedGoodsInOutOrder
if (action.command.includes('ARRIVED')) {
navigateTo = await this.arrivedActionNavigation();
}
this.actionHandled.emit({ orderItemsContext: commandData, navigation: navigateTo });
this.actionHandled.emit({ orderItemsContext: commandData, command: action.command, navigation: navigateTo });
this.updateOrderItems(commandData.items);
} catch (error) {
console.error(error);