Merged PR 814: #2148 Wareneingangsliste Anpassungen

Related work items: #2148
This commit is contained in:
Andreas Schickinger
2021-09-08 15:27:17 +00:00
committed by Nino Righi
parent 236d81de15
commit 590407d04a
8 changed files with 86 additions and 31 deletions

View File

@@ -1,6 +1,6 @@
<ng-container *ngIf="item$ | async; let orderItem">
<div class="header">
<h3>
<h3 class="customer-name">
<span *ngIf="orderItem.organisation != null">{{ orderItem.organisation }}</span>
<span *ngIf="orderItem.organisation != null && orderItem.firstName != null && orderItem.lastName != null"> - </span>
<span *ngIf="orderItem.firstName != null && orderItem.lastName != null">{{ orderItem.firstName }} {{ orderItem.lastName }}</span>
@@ -8,12 +8,18 @@
<h3 class="ssc" *ngIf="!(editSsc$ | async) && orderItem.ssc && orderItem.sscText">{{ orderItem.ssc }} - {{ orderItem.sscText }}</h3>
<div *ngIf="editSsc$ | async" class="ssc-wrapper">
<label>Meldenummer</label>
<input class="ssc-input" [class.err-border]="sscInvalid$ | async" type="text" [ngModel]="ssc" (ngModelChange)="sscChange($event)" />
<ng-container *ngIf="editSsc$ | async">
<div *ngIf="!(supplierIdError$ | async)" class="ssc-wrapper">
<label>Meldenummer</label>
<input class="ssc-input" [class.err-border]="sscInvalid$ | async" type="text" [ngModel]="ssc" (ngModelChange)="sscChange($event)" />
<span class="ssc-text" [class.err]="sscInvalid$ | async">{{ sscText$ | async }}</span>
</div>
<span class="ssc-text" [class.err]="sscInvalid$ | async">{{ sscText$ | async }}</span>
</div>
<div class="err" *ngIf="supplierIdError$ | async">
Kein Lieferant vorhanden
</div>
</ng-container>
</div>
<div class="grid-container">
@@ -48,7 +54,7 @@
</div>
<div class="item-id spec">
<span>Vorgangs-ID</span>
<strong>{{ orderItem.orderId }}</strong>
<strong>{{ orderItem.orderNumber }}</strong>
</div>
<div class="price">

View File

@@ -4,6 +4,16 @@
.header {
@apply w-full flex flex-row justify-between;
min-height: 60px;
.customer-name {
@apply mr-6;
max-width: 550px;
}
.ssc {
min-width: 155px;
}
}
.grid-container {
@@ -128,21 +138,29 @@
.ssc-input:focus {
@apply border-active-branch;
}
}
.err-border {
@apply border-brand;
}
.err-border {
@apply border-brand;
}
.err-border:focus {
@apply border-brand;
}
.err-border:focus {
@apply border-brand;
}
.ssc-text {
@apply mt-3;
font-size: 13px;
}
.ssc-text {
@apply mt-3;
font-size: 13px;
}
.err {
@apply text-brand;
.err {
@apply text-brand;
}
@media (min-width: 1025px) {
.header {
.customer-name {
max-width: 745px;
}
}
}

View File

@@ -14,7 +14,7 @@ describe('GoodsInListItemComponent', () => {
let spectator: Spectator<GoodsInListItemComponent>;
let uiModalServiceMock: jasmine.SpyObj<UiModalService>;
let domainOmsServiceMock: jasmine.SpyObj<DomainOmsService>;
let orderItemMock = { product: {} };
let orderItemMock = { product: {}, supplierId: 1 };
const createComponent = createComponentFactory({
component: GoodsInListItemComponent,
@@ -148,10 +148,10 @@ describe('GoodsInListItemComponent', () => {
});
it('should render ean', () => {
const item = { ...orderItemMock, orderId: 1 };
const item = { ...orderItemMock, orderNumber: 'abc' };
spectator.setInput({ item });
expect(spectator.query('div .details .item-id span')).toHaveText('Vorgangs-ID');
expect(spectator.query('div .details .item-id strong')).toHaveText(`${item.orderId}`);
expect(spectator.query('div .details .item-id strong')).toHaveText(`${item.orderNumber}`);
});
it('should render price', () => {

View File

@@ -5,7 +5,7 @@ import { OrderItemListItemDTO } from '@swagger/oms';
import { UiModalService } from '@ui/modal';
import { isEqual } from 'lodash';
import { Subject } from 'rxjs';
import { first, shareReplay, switchMap, takeUntil } from 'rxjs/operators';
import { catchError, first, shareReplay, switchMap, takeUntil } from 'rxjs/operators';
import { GoodsInListReorderModalComponent } from '../goods-in-list-reorder-modal/goods-in-list-reorder-modal.component';
interface GoodsInListItemComponentState {
@@ -15,6 +15,7 @@ interface GoodsInListItemComponentState {
sscChanged: boolean;
ssc: string;
sscText: string;
supplierIdError: boolean;
}
@Component({
@@ -32,6 +33,10 @@ export class GoodsInListItemComponent extends ComponentStore<GoodsInListItemComp
}
set item(item: OrderItemListItemDTO) {
if (!isEqual(this.item, item)) {
if (!item.supplierId) {
this.patchState({ supplierIdError: true });
}
this.patchState({ item });
this.ssc = item.ssc;
this.sscText = item.sscText;
@@ -90,7 +95,20 @@ export class GoodsInListItemComponent extends ComponentStore<GoodsInListItemComp
}
readonly sscText$ = this.select((s) => s.sscText);
readonly statusCodes$ = this.item$.pipe(switchMap((item) => this._omsService.getStockStatusCodes(item.supplierId)));
readonly supplierIdError$ = this.select((s) => s.supplierIdError);
readonly statusCodes$ = this.item$.pipe(
switchMap((item) => {
if (item.supplierId) {
return this._omsService.getStockStatusCodes(item.supplierId);
}
this.patchState({ supplierIdError: true });
}),
catchError(() => {
this.patchState({ supplierIdError: true });
return [undefined];
})
);
private _onDestroy$ = new Subject();
@@ -102,6 +120,7 @@ export class GoodsInListItemComponent extends ComponentStore<GoodsInListItemComp
sscChanged: false,
ssc: undefined,
sscText: undefined,
supplierIdError: false,
});
}
@@ -114,7 +133,7 @@ export class GoodsInListItemComponent extends ComponentStore<GoodsInListItemComp
this.ssc = value;
this.sscChanged = true;
const code = (await this.statusCodes$.pipe(first()).toPromise()).find((statusCode) => statusCode.code === value);
const code = (await this.statusCodes$.pipe(first()).toPromise())?.find((statusCode) => statusCode.code === value);
if (!!code) {
this.sscText = code.supplierDescription;
this.sscInvalid = false;

View File

@@ -29,7 +29,9 @@
Abbrechen
</button>
<button class="cta-save-ssc cta-action-primary" (click)="saveSsc()" [disabled]="editSscDisabled$ | async">
Meldenummern speichern
<ui-spinner [show]="showSaveSscSpinner$ | async">
Meldenummern speichern
</ui-spinner>
</button>
</ng-container>
</div>

View File

@@ -5,6 +5,7 @@ import { DomainOmsService } from '@domain/oms';
import { createComponentFactory, mockProvider, Spectator } from '@ngneat/spectator';
import { UiCommonModule } from '@ui/common';
import { UiModalService } from '@ui/modal';
import { UiSpinnerModule } from 'apps/ui/spinner/src/lib/ui-spinner.module';
import { BehaviorSubject, of } from 'rxjs';
import { first } from 'rxjs/operators';
import { GoodsInListItemModule } from './goods-in-list-item/goods-in-list-item.module';
@@ -18,7 +19,7 @@ describe('GoodsInListComponent', () => {
const createComponent = createComponentFactory({
component: GoodsInListComponent,
imports: [GoodsInListItemModule, RouterTestingModule, UiCommonModule],
imports: [GoodsInListItemModule, RouterTestingModule, UiCommonModule, UiSpinnerModule],
componentProviders: [
mockProvider(GoodsInListService, {
searchResponse$: new BehaviorSubject({}),

View File

@@ -1,7 +1,7 @@
import { AfterViewInit, ChangeDetectionStrategy, Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core';
import { BreadcrumbService } from '@core/breadcrumb';
import { DomainOmsService } from '@domain/oms';
import { combineLatest, Observable, Subject } from 'rxjs';
import { BehaviorSubject, combineLatest, Observable, Subject } from 'rxjs';
import { first, map, shareReplay, takeUntil } from 'rxjs/operators';
import { GoodsInListItemComponent } from './goods-in-list-item/goods-in-list-item.component';
import { GoodsInListService } from './goods-in-list-service';
@@ -26,6 +26,8 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
editSscDisabled$: Observable<boolean>;
showSaveSscSpinner$ = new BehaviorSubject<boolean>(false);
protected readonly viewportEnterOptions: IntersectionObserverInit = {
threshold: 0.75,
};
@@ -79,7 +81,7 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
}
async saveSsc() {
this.editSsc = false;
this.showSaveSscSpinner$.next(true);
const payload = this.listItems
.filter((item) => item.sscChanged)
@@ -87,9 +89,15 @@ export class GoodsInListComponent implements OnInit, AfterViewInit, OnDestroy {
return { id: listItem.item.orderItemSubsetId, ssc: listItem.ssc, quantity: listItem.item.quantity };
});
if (payload?.length > 0) {
await this._domainOmsService.changeStockStatusCode(payload).toPromise();
try {
await this._domainOmsService.changeStockStatusCode(payload).toPromise();
} catch (error) {
console.error(error);
}
}
this.refreshList();
this.showSaveSscSpinner$.next(false);
this.editSsc = false;
}
cancelSsc() {

View File

@@ -2,13 +2,14 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { UiCommonModule } from '@ui/common';
import { UiIconModule } from '@ui/icon';
import { UiSpinnerModule } from 'apps/ui/spinner/src/lib/ui-spinner.module';
import { GoodsInListItemModule } from './goods-in-list-item/goods-in-list-item.module';
import { GoodsInListReorderModalModule } from './goods-in-list-reorder-modal/goods-in-list-reorder-modal.module';
import { GoodsInListComponent } from './goods-in-list.component';
@NgModule({
imports: [CommonModule, UiCommonModule, UiIconModule, GoodsInListItemModule, GoodsInListReorderModalModule],
imports: [CommonModule, UiCommonModule, UiIconModule, GoodsInListItemModule, GoodsInListReorderModalModule, UiSpinnerModule],
exports: [],
declarations: [GoodsInListComponent],
providers: [],