Status Sortierung, Datepicker Styling, ROrderItem und OrderItemSubset Patch fix

Co-authored-by: s.neumair@paragon-data.de <s.neumair@paragon-data.de>
This commit is contained in:
Lorenz Hilpert
2020-09-01 17:30:34 +02:00
parent 1c1a6c05c2
commit a1c7167e50
24 changed files with 305 additions and 410 deletions

View File

@@ -1,37 +1,22 @@
<div class="filter-wrapper">
<div class="filter-nav">
<button
*ngFor="let filter of value; trackBy: trackByKeyOrName; let first = first"
type="button"
(click)="selected = filter"
class="isa-btn isa-btn-block isa-btn-default-bg isa-btn-l"
[class.customer]="module === 'Customer'"
[class.isa-mt-10]="!first"
[class.is-active]="filter === selected"
[class.isa-font-weight-emphasis]="filter !== selected"
[class.isa-font-weight-bold]="filter === selected"
>
<button *ngFor="let filter of value; trackBy: trackByKeyOrName; let first = first" type="button"
(click)="selected = filter" class="isa-btn isa-btn-block isa-btn-default-bg isa-btn-large"
[class.customer]="module === 'Customer'" [class.isa-mt-10]="!first" [class.is-active]="filter === selected"
[class.isa-font-weight-emphasis]="filter !== selected" [class.isa-font-weight-bold]="filter === selected">
<span>{{ filter.name }}</span>
<lib-icon
[name]="
<lib-icon [name]="
filter === selected
? 'Arrow_Next_Dark'
: module === 'Customer'
? 'Arrow_Next'
: 'Arrow_Next_Grey'
"
height="17px"
></lib-icon>
" height="17px"></lib-icon>
</button>
</div>
<div class="filter-content isa-ml-10" [ngSwitch]="selected?.type">
<app-select-filter
*ngSwitchCase="'select'"
[options]="selected.options"
[module]="module"
[max]="selected.max"
(optionsChanged)="emitOnChange($event)"
>
<app-select-filter *ngSwitchCase="'select'" [options]="selected.options" [module]="module" [max]="selected.max"
(optionsChanged)="emitOnChange($event)">
</app-select-filter>
</div>
</div>
</div>

View File

@@ -1,8 +1,8 @@
<div class="actions">
<button (click)="cancel.emit()"
class="isa-btn isa-btn-pill isa-btn-secondary isa-btn-shadow isa-btn-red-border isa-btn-medium">
Abbrechen</button><button (click)="save.emit()" [disabled]="disabled"
class="isa-btn isa-btn-pill isa-btn-primary isa-btn-shadow isa-btn-medium">
Abbrechen</button><button (click)="save.emit()"
class="isa-btn isa-btn-pill isa-btn-primary isa-btn-shadow isa-btn-medium" [disabled]="disabled">
Speichern
</button>
</div>

View File

@@ -29,6 +29,6 @@
</app-ui-select-input>
<hr class="isa-content-spacer" />
<app-ui-text-input formControlName="comment" label="Anmerkung"></app-ui-text-input>
<app-ui-text-input formControlName="comment" label="Anmerkung" [placeholder]="'-'"></app-ui-text-input>
</form>
</ng-container>

View File

@@ -1,9 +1,7 @@
<h2 class="isa-flex isa-justify-content-space-between">
<span>{{ orderDetails?.firstName }} {{ orderDetails?.lastName }}</span>
<span
>{{ orderDetails?.compartmentCode }}
{{ orderDetails?.compartmentInfo }}</span
>
<span>{{ orderDetails?.compartmentCode }}
{{ orderDetails?.compartmentInfo }}</span>
</h2>
<div class="isa-flex isa-justify-content-space-between">
<div class="isa-flex isa-flex-direction-column">
@@ -32,113 +30,63 @@
<div class="detail">
<div class="name">Status</div>
<div class="value">
<button
class="isa-btn isa-p-0 isa-btn-block isa-text-right"
(click)="statusDropdown.toggle()"
>
<lib-icon
class="isa-mr-8"
[ngClass]="icon"
*ngIf="
<button class="isa-btn isa-p-0 isa-btn-block isa-text-right" (click)="statusDropdown.toggle()">
<lib-icon class="isa-mr-8" [ngClass]="icon" *ngIf="
orderDetails?.processingStatus | processingStatus: 'icon';
let icon
"
[name]="icon"
>
" [name]="icon">
</lib-icon>
<strong>{{
orderDetails?.processingStatus | processingStatus
}}</strong>
<lib-icon
class="dp-button-icon"
[class.up]="statusDropdown.visible"
[class.down]="!statusDropdown.visible"
name="Arrow_right"
[height]="'16px'"
></lib-icon>
<lib-icon class="dp-button-icon" [class.up]="statusDropdown.visible" [class.down]="!statusDropdown.visible"
name="Arrow_right" [height]="'16px'"></lib-icon>
</button>
<app-ui-dropdown
#statusDropdown
[value]="orderDetails?.processingStatus"
(valueChange)="changeProcessingStatus.emit($event)"
>
<ng-container *ngFor="let status of processingKeys | keyvalue">
<button
appUiDropdownItem
class="isa-btn isa-text-left isa-p-16"
[value]="status.key"
*ngIf="status.key !== orderDetails?.processingStatus"
>
<app-ui-dropdown #statusDropdown [value]="orderDetails?.processingStatus"
(valueChange)="changeProcessingStatus.emit($event)">
<ng-container *ngFor="let status of processingKeys | keyvalue | processingStatusOptionsKeyValuePipe">
<button appUiDropdownItem class="isa-btn isa-text-left isa-p-16" [value]="status.key"
*ngIf="status.key !== orderDetails?.processingStatus">
{{ status?.value?.value }}
</button>
</ng-container>
</app-ui-dropdown>
</div>
</div>
<div
class="detail"
*ngIf="
<div class="detail" *ngIf="
orderDetails?.processingStatus === 16 ||
orderDetails?.processingStatus === 8192
"
>
">
<div class="name">vsl. Lieferdatum</div>
<div class="value">
<button
class="isa-btn isa-p-0 isa-btn-block isa-text-right"
(click)="uiDatepicker.toggle()"
>
<button class="isa-btn isa-p-0 isa-btn-block isa-text-right" (click)="uiDatepicker.toggle()">
<strong>
{{ orderDetails?.estimatedShippingDate | date: 'dd.MM.yy' }}
</strong>
<lib-icon
class="dp-button-icon"
[class.up]="uiDatepicker.opened"
[class.down]="!uiDatepicker.opened"
name="Arrow_right"
[height]="'16px'"
></lib-icon>
<lib-icon class="dp-button-icon" [class.up]="uiDatepicker.opened" [class.down]="!uiDatepicker.opened"
name="Arrow_right" [height]="'16px'"></lib-icon>
</button>
<app-ui-datepicker
#uiDatepicker
[right]="'-1rem'"
[selected]="orderDetails?.estimatedShippingDate"
(save)="
<app-ui-datepicker #uiDatepicker [right]="'-1rem'" [min]="minDate"
[selected]="orderDetails?.estimatedShippingDate" (save)="
changeEstimatedDeliveryDate.emit($event); uiDatepicker.close()
"
>
">
</app-ui-datepicker>
</div>
</div>
<div class="detail" *ngIf="orderDetails?.processingStatus === 128">
<div class="name">Abholfrist</div>
<div class="value">
<button
class="isa-btn isa-p-0 isa-btn-block isa-text-right"
(click)="deadlineDropdown.toggle()"
>
<button class="isa-btn isa-p-0 isa-btn-block isa-text-right" (click)="deadlineDropdown.toggle()">
<strong>
{{ orderDetails?.pickupDeadline | date: 'dd.MM.yy' }}
</strong>
<lib-icon
class="dp-button-icon"
[class.up]="deadlineDropdown.visible"
[class.down]="!deadlineDropdown.visible"
name="Arrow_right"
[height]="'16px'"
></lib-icon>
<lib-icon class="dp-button-icon" [class.up]="deadlineDropdown.visible"
[class.down]="!deadlineDropdown.visible" name="Arrow_right" [height]="'16px'"></lib-icon>
</button>
<app-ui-dropdown
#deadlineDropdown
[value]="orderDetails?.pickupDeadline"
(valueChange)="changePickUpDeadline.emit($event)"
>
<app-ui-dropdown #deadlineDropdown [value]="orderDetails?.pickupDeadline"
(valueChange)="changePickUpDeadline.emit($event)">
<ng-container *ngFor="let dl of pickupDeadlines | keyvalue">
<button
appUiDropdownItem
class="isa-btn isa-text-left isa-p-16"
[value]="dl.value"
>
<button appUiDropdownItem class="isa-btn isa-text-left isa-p-16" [value]="dl.value">
{{ dl.key }}
</button>
</ng-container>
@@ -146,4 +94,4 @@
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,14 +1,8 @@
import {
Component,
OnInit,
ChangeDetectionStrategy,
Input,
Output,
EventEmitter,
} from '@angular/core';
import { Component, OnInit, ChangeDetectionStrategy, Input, Output, EventEmitter } from '@angular/core';
import { OrderDetailsCardInput } from './order-details-card-input';
import { ProcessingStatusNameMap } from '../../constants';
import { OrderItemProcessingStatusValue } from '@swagger/oms';
import { DateAdapter } from '@isa-ui/core/date';
@Component({
selector: 'app-shelf-order-details-card',
@@ -17,16 +11,18 @@ import { OrderItemProcessingStatusValue } from '@swagger/oms';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ShelfOrderDetailsCardComponent implements OnInit {
minDate = this.dateAdapter.addCalendarDays(new Date(), -1);
get processingKeys() {
const copy = new Map(ProcessingStatusNameMap);
if (this.orderDetails) {
if (
this.orderDetails.processingStatus === 16 ||
this.orderDetails.processingStatus === 8192
) {
if (this.orderDetails.processingStatus === 16 || this.orderDetails.processingStatus === 8192) {
copy.delete(128);
}
if (this.orderDetails.processingStatus >= 0) {
copy.delete(this.orderDetails.processingStatus);
}
}
return copy;
@@ -64,7 +60,7 @@ export class ShelfOrderDetailsCardComponent implements OnInit {
@Output()
changePickUpDeadline = new EventEmitter<Date>();
constructor() {}
constructor(private dateAdapter: DateAdapter<Date>) {}
ngOnInit() {}
}

View File

@@ -1,7 +1,4 @@
export const ProcessingStatusNameMap = new Map<
number,
{ value: string; disabled: boolean }
>([
export const ProcessingStatusNameMap = new Map<number, { value: string; disabled: boolean }>([
[1, { value: 'neu', disabled: true }],
[2, { value: '', disabled: true }],
[4, { value: '', disabled: true }],

View File

@@ -1,28 +1,11 @@
import {
Component,
OnInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
} from '@angular/core';
import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable, from } from 'rxjs';
import {
filter,
map,
distinctUntilChanged,
shareReplay,
take,
withLatestFrom,
first,
} from 'rxjs/operators';
import { filter, map, distinctUntilChanged, shareReplay, take, withLatestFrom, first } from 'rxjs/operators';
import { isNullOrUndefined } from 'util';
import { ShelfEditFormService } from '../../services';
import { FormGroup, FormArray } from '@angular/forms';
import {
ProcessingStatusPipe,
PickUpDateOptionsToDisplayValuesPipe,
ProcessingStatusOptionsPipe,
} from '../../pipes';
import { ProcessingStatusPipe, PickUpDateOptionsToDisplayValuesPipe, ProcessingStatusOptionsPipe } from '../../pipes';
import { DatePipe } from '@angular/common';
import { ShelfNavigationService } from '../../shared/services';
import { OrderItemProcessingStatusValue } from '@swagger/oms/lib';
@@ -63,10 +46,7 @@ export class ShelfEditCompartmentComponent implements OnInit {
get processingStatus$() {
return this.activatedRoute.params.pipe(
map(
(params) =>
Number(params.processingStatus) as OrderItemProcessingStatusValue
),
map((params) => Number(params.processingStatus) as OrderItemProcessingStatusValue),
distinctUntilChanged(),
shareReplay()
);
@@ -77,57 +57,42 @@ export class ShelfEditCompartmentComponent implements OnInit {
}
async loadCompartmentAndInitForm() {
const compartmentCode = await this.compartmentCode$
.pipe(take(1))
.toPromise();
const processingStatus = await this.processingStatus$
.pipe(take(1))
.toPromise();
const compartmentCode = await this.compartmentCode$.pipe(take(1)).toPromise();
const processingStatus = await this.processingStatus$.pipe(take(1)).toPromise();
this.populateFormData(compartmentCode, processingStatus);
}
async onSubmit() {
const compartmentCode = await this.compartmentCode$
.pipe(first())
.toPromise();
const processingStatus = await this.processingStatus$
.pipe(first())
.toPromise();
const submitResult = await this.formService.submit(
this.form,
processingStatus
);
console.log(this.form.valid);
const compartmentCode = await this.compartmentCode$.pipe(first()).toPromise();
const processingStatus = await this.processingStatus$.pipe(first()).toPromise();
const submitResult = await this.formService.submit(this.form, processingStatus);
let newValues;
if (submitResult) {
// TODO Navigate back to Details Page with updated processingStatus
this.shelfNavigationService.navigateBackToDetails({
compartmentCode,
processingStatus:
this.form.get('processingStatus').value || processingStatus,
});
newValues = {
compartmentCode: this.form.get('compartmentCode').value || compartmentCode,
processingStatus: this.form.get('processingStatus').value || processingStatus,
};
this.shelfNavigationService.navigateBackToDetails(newValues, { compartmentCode, processingStatus });
}
}
onAbortEdit() {
return this.compartmentCode$
.pipe(take(1), withLatestFrom(this.processingStatus$))
.subscribe(([compartmentCode, processingStatus]) =>
this.shelfNavigationService.navigateToDetails({
compartmentCode,
processingStatus,
})
);
return this.compartmentCode$.pipe(take(1), withLatestFrom(this.processingStatus$)).subscribe(([compartmentCode, processingStatus]) =>
this.shelfNavigationService.navigateToDetails({
compartmentCode,
processingStatus,
})
);
}
private async populateFormData(
compartmentCode: string,
processingStatus: OrderItemProcessingStatusValue
) {
this.form = await this.formService.createFormByCompartmentCode(
compartmentCode,
processingStatus
);
private async populateFormData(compartmentCode: string, processingStatus: OrderItemProcessingStatusValue) {
this.form = await this.formService.createFormByCompartmentCode(compartmentCode, processingStatus);
this.items = this.formService.getItemsForm(compartmentCode);
this.customerName = this.formService.getCustomerName(compartmentCode);
this.cdr.detectChanges();

View File

@@ -2,6 +2,7 @@ import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
import { CustomerService } from '@swagger/crm';
import { ReplaySubject, of, NEVER } from 'rxjs';
import { switchMap, catchError, map, flatMap, filter, throttleTime, distinctUntilChanged } from 'rxjs/operators';
import { isNullOrUndefined } from 'util';
@Component({
selector: 'app-shelf-details-customer-features',
@@ -12,7 +13,9 @@ import { switchMap, catchError, map, flatMap, filter, throttleTime, distinctUnti
export class CustomerFeaturesComponent {
@Input()
set customerNumber(value: string) {
this.customernumber$.next(value);
if (!isNullOrUndefined(value)) {
this.customernumber$.next(value);
}
}
customernumber$ = new ReplaySubject<string>();

View File

@@ -48,6 +48,7 @@
<div class="cta-sticky isa-my-28 isa-text-center">
<button type="button" class="isa-btn isa-btn-primary isa-btn-pill isa-btn-medium"
[disabled]="shelfDetailsTag.selected === shelfDetailsTag.customValue.value && shelfDetailsTag.customValue.invalid"
(click)="changeProcessingStatus(128, { compartmentInfo: shelfDetailsTag.selected })">
eingetroffen und Drucken
</button>

View File

@@ -183,11 +183,18 @@ export class ShelfOrderDetailsComponent {
if (navigate) {
const firstItem = items[0];
const firstResult = results[0].result;
this.shelfNavigationService.updateDetailsNavigation({
compartmentCode: firstResult.item1.compartmentCode,
orderNumber: firstItem.orderNumber,
processingStatus: firstResult.item1.processingStatus,
});
this.shelfNavigationService.updateDetails(
{
compartmentCode: firstResult.item1.compartmentCode,
orderNumber: firstItem.orderNumber,
processingStatus: firstResult.item1.processingStatus,
},
{
compartmentCode: firstItem.compartmentCode,
orderNumber: firstItem.orderNumber,
processingStatus: firstItem.processingStatus,
}
);
}
}

View File

@@ -1,5 +1,5 @@
import { Component, ChangeDetectionStrategy, Input, EventEmitter, Output, ChangeDetectorRef, OnInit, OnDestroy } from '@angular/core';
import { FormControl } from '@angular/forms';
import { FormControl, Validators } from '@angular/forms';
import { Subscription } from 'rxjs';
@Component({
@@ -19,7 +19,7 @@ export class ShelfOrderDetailsShelfTagsComponent implements OnInit, OnDestroy {
@Input()
tags = ['Maxi', 'Mini', 'Kleinkram', 'Nonbook'];
customValue = new FormControl('');
customValue = new FormControl('', [Validators.required, Validators.maxLength(15)]);
subscription = new Subscription();

View File

@@ -1,19 +1,47 @@
import { Pipe, PipeTransform } from '@angular/core';
import { ProcessingStatusNameMap } from '../constants';
import { KeyValue } from '@angular/common';
@Pipe({
name: 'processingStatusOptionsPipe',
})
export class ProcessingStatusOptionsPipe implements PipeTransform {
transform(states: number[]): number[] {
return states.filter((state) => {
const result = ProcessingStatusNameMap.get(state);
return states
.filter((state) => {
const result = ProcessingStatusNameMap.get(state);
if (!result || result.disabled) {
return false;
}
if (!result || result.disabled) {
return false;
}
return true;
});
return true;
})
.sort((a, b) => {
const aValue = ProcessingStatusNameMap.get(a);
const bValue = ProcessingStatusNameMap.get(b);
return aValue.value.toUpperCase() === bValue.value.toUpperCase()
? 0
: aValue.value.toUpperCase() > bValue.value.toUpperCase()
? 1
: -1;
});
}
}
@Pipe({
name: 'processingStatusOptionsKeyValuePipe',
})
export class ProcessingStatusOptionsKeyValuePipe implements PipeTransform {
transform(states: KeyValue<number, { value: string; disabled: boolean }>[]): KeyValue<number, { value: string; disabled: boolean }>[] {
return states
.filter((state) => !state.value.disabled)
.sort((a, b) => {
return a.value.value.toUpperCase() === b.value.value.toUpperCase()
? 0
: a.value.value.toUpperCase() > b.value.value.toUpperCase()
? 1
: -1;
});
}
}

View File

@@ -10,7 +10,7 @@ import { VatDtoToVatValuePipe } from './vat-dto-to-vat-value.pipe';
import { VatTypeToDisplayNamePipe } from './vat-type-to-display-name.pipe';
import { VatDtoToVatTypePipe } from './vat-dto-to-vat-type.pipe';
import { VatTypePipe } from './vat-type.pipe';
import { ProcessingStatusOptionsPipe } from './processing-status-options.pipe';
import { ProcessingStatusOptionsPipe, ProcessingStatusOptionsKeyValuePipe } from './processing-status-options.pipe';
@NgModule({
imports: [CommonModule],
@@ -25,6 +25,7 @@ import { ProcessingStatusOptionsPipe } from './processing-status-options.pipe';
VatDtoToVatValuePipe,
VatDtoToVatTypePipe,
VatTypePipe,
ProcessingStatusOptionsKeyValuePipe,
],
declarations: [
VatTypeToDisplayNamePipe,
@@ -37,6 +38,7 @@ import { ProcessingStatusOptionsPipe } from './processing-status-options.pipe';
VatDtoToVatValuePipe,
VatDtoToVatTypePipe,
VatTypePipe,
ProcessingStatusOptionsKeyValuePipe,
],
})
export class ShelfPipesModule {}

View File

@@ -1,11 +1,5 @@
import { Injectable, ɵbypassSanitizationTrustResourceUrl } from '@angular/core';
import {
FormBuilder,
FormGroup,
Validators,
FormArray,
AbstractControl,
} from '@angular/forms';
import { FormBuilder, FormGroup, Validators, FormArray, AbstractControl } from '@angular/forms';
import { Observable, of, from } from 'rxjs';
import {
OrderItemListItemDTO,
@@ -49,10 +43,7 @@ export class ShelfEditFormService {
return this.vats$.pipe(filter((vats) => !!vats.length));
}
constructor(
private formBuilder: FormBuilder,
private detailsStoreFacade: DetailsFacade
) {}
constructor(private formBuilder: FormBuilder, private detailsStoreFacade: DetailsFacade) {}
public getItemsForm(compartmentCode: string): FormArray {
if (!this.forms.has(compartmentCode)) {
@@ -61,9 +52,7 @@ export class ShelfEditFormService {
return this.forms.get(compartmentCode).get('items') as FormArray;
}
public getCustomerName(
compartmentCode: string
): { firstName: string; lastName: string } {
public getCustomerName(compartmentCode: string): { firstName: string; lastName: string } {
if (!this.forms.has(compartmentCode)) {
return {
firstName: 'unbekannt',
@@ -78,14 +67,8 @@ export class ShelfEditFormService {
};
}
async createFormByOrderNumber(
orderNumber: string,
processingStatus: OrderItemProcessingStatusValue
): Promise<FormGroup> {
const controlsConfig = await this.getControlsConfigForOrder(
orderNumber,
processingStatus
);
async createFormByOrderNumber(orderNumber: string, processingStatus: OrderItemProcessingStatusValue): Promise<FormGroup> {
const controlsConfig = await this.getControlsConfigForOrder(orderNumber, processingStatus);
const form = this.formBuilder.group(controlsConfig);
this.forms.set(orderNumber, form);
@@ -93,14 +76,8 @@ export class ShelfEditFormService {
return this.forms.get(orderNumber);
}
async createFormByCompartmentCode(
compartmentCode: string,
processingStatus: OrderItemProcessingStatusValue
): Promise<FormGroup> {
const controlsConfig = await this.getControlsConfigForCompartment(
compartmentCode,
processingStatus
);
async createFormByCompartmentCode(compartmentCode: string, processingStatus: OrderItemProcessingStatusValue): Promise<FormGroup> {
const controlsConfig = await this.getControlsConfigForCompartment(compartmentCode, processingStatus);
const form = this.formBuilder.group(controlsConfig);
this.forms.set(compartmentCode, form);
@@ -108,13 +85,8 @@ export class ShelfEditFormService {
return this.forms.get(compartmentCode);
}
async getControlsConfigForOrder(
orderNumber: string,
processingStatus: OrderItemProcessingStatusValue
): Promise<{ [key: string]: any }> {
const orderItems$: Observable<
OrderItemListItemDTO[]
> = this.detailsStoreFacade.getOrderItemsByOrderNumberAndProcessingStatus$(
async getControlsConfigForOrder(orderNumber: string, processingStatus: OrderItemProcessingStatusValue): Promise<{ [key: string]: any }> {
const orderItems$: Observable<OrderItemListItemDTO[]> = this.detailsStoreFacade.getOrderItemsByOrderNumberAndProcessingStatus$(
orderNumber,
processingStatus
);
@@ -126,19 +98,14 @@ export class ShelfEditFormService {
compartmentCode: string,
processingStatus: OrderItemProcessingStatusValue
): Promise<{ [key: string]: any }> {
const orderItems$: Observable<
OrderItemListItemDTO[]
> = this.detailsStoreFacade.getOrderItemsByCompartmentCodeAndProcessingStatus$(
const orderItems$: Observable<OrderItemListItemDTO[]> = this.detailsStoreFacade.getOrderItemsByCompartmentCodeAndProcessingStatus$(
compartmentCode,
processingStatus
);
return this.createControlConfig(orderItems$);
}
private async createControlConfig(
orderItems$: Observable<OrderItemListItemDTO[]>
): Promise<{ [key: string]: any }> {
private async createControlConfig(orderItems$: Observable<OrderItemListItemDTO[]>): Promise<{ [key: string]: any }> {
const orderItems = await orderItems$
.pipe(
filter((items) => !isNullOrUndefined(items) && !!items.length),
@@ -150,9 +117,7 @@ export class ShelfEditFormService {
return {
...this.getGeneralForm(orderItems),
items: this.formBuilder.array(
orderItems.map((orderItem) => this.getItemForm(orderItem, vats))
),
items: this.formBuilder.array(orderItems.map((orderItem) => this.getItemForm(orderItem, vats))),
};
}
@@ -161,9 +126,7 @@ export class ShelfEditFormService {
return {
firstName: baseOrderItem.firstName,
lastName: baseOrderItem.lastName,
compartmentCode: [
{ value: baseOrderItem.compartmentCode, disabled: false },
],
compartmentCode: [{ value: baseOrderItem.compartmentCode, disabled: false }],
orderId: [{ value: baseOrderItem.orderId, disabled: true }],
orderNumber: [
{
@@ -179,19 +142,13 @@ export class ShelfEditFormService {
],
clientChannel: [
{
value: new EnvironmentChannelPipe().transform(
baseOrderItem.clientChannel
),
value: new EnvironmentChannelPipe().transform(baseOrderItem.clientChannel),
disabled: true,
},
],
buyerNumber: [{ value: baseOrderItem.buyerNumber, disabled: true }],
processingStatus: [
{ value: baseOrderItem.processingStatus, disabled: false },
],
estimatedShippingDate: [
{ value: baseOrderItem.estimatedShippingDate, disabled: false },
],
processingStatus: [{ value: baseOrderItem.processingStatus, disabled: false }],
estimatedShippingDate: [{ value: baseOrderItem.estimatedShippingDate, disabled: false }],
pickUpDeadline: [
{
value: baseOrderItem.pickUpDeadline,
@@ -209,17 +166,11 @@ export class ShelfEditFormService {
orderId: Number(form.get('orderId').value),
orderNumber: form.get('orderNumber').value,
orderDate: new Date(form.get('orderDate').value),
clientChannel: Number(
form.get('clientChannel').value
) as EnvironmentChannel,
clientChannel: Number(form.get('clientChannel').value) as EnvironmentChannel,
buyerNumber: form.get('buyerNumber').value,
processingStatus: Number(
form.get('processingStatus').value
) as OrderItemProcessingStatusValue,
processingStatus: Number(form.get('processingStatus').value) as OrderItemProcessingStatusValue,
pickUpDeadline: String(form.get('pickUpDeadline').value || ''),
estimatedShippingDate: String(
form.get('estimatedShippingDate').value || ''
),
estimatedShippingDate: String(form.get('estimatedShippingDate').value || ''),
};
}
@@ -227,13 +178,11 @@ export class ShelfEditFormService {
return this.formBuilder.group({
orderId: [{ value: orderItem.orderId, disabled: true }],
orderItemId: [{ value: orderItem.orderItemId, disabled: true }],
orderItemSubsetId: [
{ value: orderItem.orderItemSubsetId, disabled: true },
],
orderItemSubsetId: [{ value: orderItem.orderItemSubsetId, disabled: true }],
quantity: [{ value: orderItem.quantity, disabled: true }],
price: [
{ value: orderItem.price, disabled: false },
[Validators.required],
{ value: String(orderItem.price).replace('.', ','), disabled: false },
[Validators.required, Validators.pattern(/^\d+(,\d{1,2})?$/)],
],
ean: [
{
@@ -245,9 +194,7 @@ export class ShelfEditFormService {
title: [{ value: orderItem.product.name, disabled: true }],
ssc: [
{
value: orderItem.ssc
? orderItem.ssc + ' - ' + orderItem.sscText
: '-',
value: orderItem.ssc ? orderItem.ssc + ' - ' + orderItem.sscText : '-',
disabled: false,
},
],
@@ -259,41 +206,58 @@ export class ShelfEditFormService {
disabled: false,
},
],
comment: [{ value: orderItem.specialComment || '-', disabled: false }],
comment: [{ value: orderItem.specialComment, disabled: false }],
});
}
getDataFromItemForm(form: AbstractControl): OrderItemListItemDTO {
getOrderItemFromItemForm(form: AbstractControl): OrderItemDTO {
return {
orderId: Number(form.get('orderId').value),
orderItemId: Number(form.get('orderItemId').value),
orderItemSubsetId: Number(form.get('orderItemSubsetId').value),
id: Number(form.get('orderItemId').value),
quantity: Number(form.get('quantity').value),
price: Number(form.get('price').value),
vatType: Number(form.get('vat').value) as VATType,
specialComment: String(form.get('comment').value),
grossPrice: {
vat: { vatType: Number(form.get('vat').value) as VATType },
value: { value: Number(form.get('price').value.replace(',', '.')) },
},
product: { ean: String(form.get('ean').value) },
};
}
async submit(
form: FormGroup,
processingStatus: OrderItemProcessingStatusValue
): Promise<boolean> {
getOrderItemSubsetFromItemForm(ctrl: AbstractControl, form: FormGroup): OrderItemSubsetDTO & { orderItemId: number } {
const sscFull: string = ctrl.get('ssc').value;
let ssc = sscFull.split('-')[0];
let sscText = sscFull.substr(ssc.length + 1);
ssc = ssc.trim();
sscText = sscText.trim();
return {
id: Number(ctrl.get('orderItemSubsetId').value),
orderItemId: Number(ctrl.get('orderItemId').value),
processingStatus: form.get('processingStatus').value,
estimatedShippingDate: String(form.get('estimatedShippingDate').value),
compartmentCode: !!form.get('compartmentCode').value ? String(form.get('compartmentCode').value) : null,
specialComment: String(ctrl.get('comment').value),
ssc,
sscText,
};
}
async submit(form: FormGroup, processingStatus: OrderItemProcessingStatusValue): Promise<boolean> {
const formData = this.getDataFromGeneralForm(form);
console.log({ formData });
const patch = this.preparePatch(form, formData);
const newProcessingStatus = Number(
form.get('processingStatus').value
) as OrderItemProcessingStatusValue;
const orderItemsToPatch = this.prepareOrderItems(form);
const orderItemSubsetsToPatch = this.prepareOrderItemSubsets(form);
const newProcessingStatus = Number(form.get('processingStatus').value) as OrderItemProcessingStatusValue;
try {
await this.detailsStoreFacade.patchOrderItems(patch);
await this.detailsStoreFacade.patchOrderItemSubsets(patch);
await this.detailsStoreFacade.patchOrderItems(orderItemsToPatch);
await this.detailsStoreFacade.patchOrderItemSubsets(orderItemSubsetsToPatch);
if (newProcessingStatus !== processingStatus) {
const changeStatusData = this.prepareStatusChange(
form,
newProcessingStatus
);
const changeStatusData = this.prepareStatusChange(form, newProcessingStatus);
if (newProcessingStatus === 128) {
await this.detailsStoreFacade.arrived(changeStatusData, undefined);
} else {
@@ -308,49 +272,49 @@ export class ShelfEditFormService {
return true;
}
private preparePatch(
form: FormGroup,
{
estimatedShippingDate,
pickUpDeadline,
}: { estimatedShippingDate: string; pickUpDeadline: string }
private prepareOrderItems(form: FormGroup) {
const orderItems = (form.get('items') as FormArray).controls.map((control) => this.getOrderItemFromItemForm(control));
return orderItems.map((orderItem) => ({
orderId: Number(form.get('orderId').value),
orderItemId: orderItem.id,
orderItem,
}));
}
private prepareOrderItemSubsets(
form: FormGroup
): {
orderId: number;
orderItemId: number;
orderItemSubsetId: number;
orderItem: Partial<OrderItemDTO>;
orderItemSubset: Partial<OrderItemSubsetDTO>;
}[] {
const items = (form.get('items') as FormArray).controls.map((control) =>
this.getDataFromItemForm(control)
);
const subsetItems = (form.get('items') as FormArray).controls.map((control) => this.getOrderItemSubsetFromItemForm(control, form));
return items.map((item) => ({
orderId: item.orderId,
return subsetItems.map((item) => ({
orderId: form.get('orderId').value,
orderItemId: item.orderItemId,
orderItemSubsetId: item.orderItemSubsetId,
orderItem: {
...item,
estimatedShippingDate,
pickUpDeadline,
},
orderItemSubset: { estimatedShippingDate },
orderItemSubsetId: item.id,
orderItemSubset: { ...item },
}));
}
private prepareStatusChange(
form: FormGroup,
processingStatus: OrderItemProcessingStatusValue
) {
console.log({ form2: form });
const items = (form.get('items') as FormArray).controls.map((itemForm) =>
this.getDataFromItemForm(itemForm)
);
): {
orderItemSubsetId: number;
orderItemId: number;
orderId: number;
data: StatusValues;
}[] {
const items = (form.get('items') as FormArray).controls.map((itemForm) => this.getOrderItemSubsetFromItemForm(itemForm, form));
return items.map((item) => ({
orderId: item.orderId,
orderItemId: item.orderItemId,
orderItemSubsetId: item.orderItemSubsetId,
orderId: Number(form.get('orderId').value),
orderItemId: Number(form.get('orderItemId').value),
orderItemSubsetId: Number(form.get('orderItemSubsetId').value),
data: { processingStatus } as StatusValues,
}));
}

View File

@@ -1,15 +1,8 @@
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { Store } from '@ngxs/store';
import {
AddBreadcrumb,
UpdateCurrentBreadcrumbName,
PopLastBreadcrumbs,
} from 'apps/sales/src/app/core/store/actions/breadcrumb.actions';
import {
ChangeCurrentRoute,
AddProcess,
} from 'apps/sales/src/app/core/store/actions/process.actions';
import { AddBreadcrumb, UpdateCurrentBreadcrumbName, PopLastBreadcrumbs } from 'apps/sales/src/app/core/store/actions/breadcrumb.actions';
import { ChangeCurrentRoute, AddProcess } from 'apps/sales/src/app/core/store/actions/process.actions';
import { Breadcrumb } from 'apps/sales/src/app/core/models/breadcrumb.model';
import { OrderItemListItemDTO } from '@swagger/oms/lib';
import { ProcessSelectors } from 'apps/sales/src/app/core/store/selectors/process.selectors';
@@ -19,11 +12,7 @@ import { Process } from 'apps/sales/src/app/core/models/process.model';
export class ShelfNavigationService {
constructor(private store: Store, private router: Router) {}
navigateToDetails(order: {
orderNumber?: string;
compartmentCode?: string;
processingStatus?: number;
}) {
navigateToDetails(order: { orderNumber?: string; compartmentCode?: string; processingStatus?: number }) {
this.createTab();
const path = this.getDetailsPath(order);
const breadcrumb = this.getDetailsBreadcrumb(order);
@@ -31,11 +20,7 @@ export class ShelfNavigationService {
this.navigateToRoute(path, breadcrumb);
}
navigateToEdit(order: {
orderNumber?: string;
compartmentCode?: string;
processingStatus?: number;
}) {
navigateToEdit(order: { orderNumber?: string; compartmentCode?: string; processingStatus?: number }) {
this.createTab();
const path = this.getDetailsPath({ ...order, edit: true });
const breadcrumb = this.getEditBreadCrumb();
@@ -43,11 +28,7 @@ export class ShelfNavigationService {
this.navigateToRoute(path, breadcrumb);
}
updateDetailsNavigation(order: {
orderNumber?: string;
compartmentCode?: string;
processingStatus?: number;
}) {
updateDetailsNavigation(order: { orderNumber?: string; compartmentCode?: string; processingStatus?: number }) {
const path = this.getDetailsPath(order);
const breadcrumb = this.getDetailsBreadcrumb(order);
this.replaceRoute(path, breadcrumb);
@@ -59,13 +40,7 @@ export class ShelfNavigationService {
this.replaceRoute(path, breadcrumb);
}
navigateToResultList({
searchQuery,
numberOfHits,
}: {
searchQuery: string;
numberOfHits: number;
}) {
navigateToResultList({ searchQuery, numberOfHits }: { searchQuery: string; numberOfHits: number }) {
this.createTab();
const path = '/shelf/results';
const breadcrumb = this.getResultListBreadcrumb(searchQuery, numberOfHits);
@@ -73,17 +48,12 @@ export class ShelfNavigationService {
}
navigateToHistory(orderitem: OrderItemListItemDTO) {
this.navigateToRoute(
`shelf/history/${orderitem.orderItemSubsetId}`,
`Historie ${orderitem.orderItemSubsetId}`
);
this.navigateToRoute(`shelf/history/${orderitem.orderItemSubsetId}`, `Historie ${orderitem.orderItemSubsetId}`);
}
private replaceRoute(route: string, breadcrumbName: string) {
this.router.navigate([route]);
this.store.dispatch(
new UpdateCurrentBreadcrumbName(breadcrumbName, 'shelf')
);
this.store.dispatch(new UpdateCurrentBreadcrumbName(breadcrumbName, 'shelf'));
}
private navigateToRoute(route: string, breadcrumbName: string) {
@@ -100,27 +70,49 @@ export class ShelfNavigationService {
this.router.navigate([route]);
}
public navigateBackToDetails(data: {
orderNumber?: string;
compartmentCode?: string;
processingStatus?: number;
}) {
public navigateBackToDetails(
data: {
orderNumber?: string;
compartmentCode?: string;
processingStatus?: number;
},
previous?: {
orderNumber?: string;
compartmentCode?: string;
processingStatus?: number;
}
) {
this.store.dispatch(new PopLastBreadcrumbs(this.getEditBreadCrumb()));
if (previous) {
this.store.dispatch(new PopLastBreadcrumbs(this.getDetailsBreadcrumb(previous)));
}
this.navigateToDetails(data);
}
private getResultListBreadcrumb(
searchQuery: string,
numberOfHits: number
): string {
public updateDetails(
data: {
orderNumber?: string;
compartmentCode?: string;
processingStatus?: number;
},
previous?: {
orderNumber?: string;
compartmentCode?: string;
processingStatus?: number;
}
) {
if (previous) {
this.store.dispatch(new PopLastBreadcrumbs(this.getDetailsBreadcrumb(previous)));
}
this.navigateToDetails(data);
}
private getResultListBreadcrumb(searchQuery: string, numberOfHits: number): string {
return `${searchQuery} (${numberOfHits} Ergebnisse)`;
}
getDetailsBreadcrumb(data: {
orderNumber?: string;
compartmentCode?: string;
}): string {
getDetailsBreadcrumb(data: { orderNumber?: string; compartmentCode?: string }): string {
if (data.compartmentCode) {
return `${data.compartmentCode}`;
}
@@ -131,12 +123,7 @@ export class ShelfNavigationService {
return 'Bearbeiten';
}
private getDetailsPath(data: {
orderNumber?: string;
compartmentCode?: string;
processingStatus?: number;
edit?: boolean;
}): string {
private getDetailsPath(data: { orderNumber?: string; compartmentCode?: string; processingStatus?: number; edit?: boolean }): string {
let url = '';
if (data.compartmentCode) {
url = `/shelf/details/compartment/${data.compartmentCode}/${data.processingStatus}`;
@@ -152,8 +139,7 @@ export class ShelfNavigationService {
}
private createTab() {
const processExists =
this.store.selectSnapshot(ProcessSelectors.getProcessesCount) > 0;
const processExists = this.store.selectSnapshot(ProcessSelectors.getProcessesCount) > 0;
if (!processExists) {
this.createProcess();
}

View File

@@ -18,6 +18,12 @@ th {
height: 41px;
}
.is-today {
border: 1px dashed $datepicker-selected-cell-bg-color;
border-radius: 50%;
font-weight: 700;
}
.cell-not-in-range {
color: $datepicker-cell-not-in-range-color;
}
@@ -29,4 +35,5 @@ th {
.cell-selected {
background-color: $datepicker-selected-cell-bg-color;
border-radius: 22px;
font-weight: 700;
}

View File

@@ -30,6 +30,9 @@ export class UiDatepickerCellDirective<TDate> implements OnInit, OnDestroy {
@HostBinding('class.cell-not-in-range')
notInRange: boolean;
@HostBinding('class.is-today')
isToday: boolean;
private subscription = new Subscription();
constructor(private datepicker: Datepicker<TDate>, private dateAdapter: DateAdapter<TDate>) {}
@@ -38,6 +41,7 @@ export class UiDatepickerCellDirective<TDate> implements OnInit, OnDestroy {
this.initDisplayed$();
this.initSelected$();
this.initRange$();
this.initToday$();
}
initDisplayed$() {
@@ -69,6 +73,13 @@ export class UiDatepickerCellDirective<TDate> implements OnInit, OnDestroy {
this.subscription.add(sub);
}
initToday$() {
const sub = this.dateSubject.subscribe((date) => {
this.isToday = this.dateAdapter.compareDate(date, this.dateAdapter.today()) === 0;
});
this.subscription.add(sub);
}
ngOnDestroy(): void {
this.subscription.unsubscribe();
this.dateSubject.complete();

View File

@@ -4,7 +4,8 @@
{{ label }}
</label>
<span class="selected isa-font-weight-bold">{{ labelPipe ? labelPipe.transform(value) : value }}
<span
class="selected isa-font-weight-bold isa-white-space-nowrap">{{ labelPipe ? labelPipe.transform(value) : value }}
</span>
<lib-icon class="isa-accordion-arrow" [class.arrow-up]="dropdown.visible" [class.arrow-down]="!dropdown.visible"
name="Arrow_right" [height]="'16px'"></lib-icon>

View File

@@ -1,10 +1,4 @@
import {
Component,
ChangeDetectionStrategy,
forwardRef,
Input,
ChangeDetectorRef,
} from '@angular/core';
import { Component, ChangeDetectionStrategy, forwardRef, Input, ChangeDetectorRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { asyncScheduler } from 'rxjs';
@@ -24,6 +18,7 @@ import { asyncScheduler } from 'rxjs';
export class UiTextInputComponent implements ControlValueAccessor {
@Input() label = '';
@Input() suffix: string;
@Input() placeholder: string;
constructor(private cdr: ChangeDetectorRef) {}

View File

@@ -1,23 +1,13 @@
<div class="isa-form-field">
<label>
{{ label }}
<input
resize
type="text"
[(ngModel)]="value"
(input)="handleInput()"
(blur)="handleBlur()"
(focus)="handleFocus(true)"
[disabled]="!editable"
/>
<input resize type="text" [(ngModel)]="value" (input)="handleInput()" (blur)="handleBlur()"
(focus)="handleFocus(true)" [disabled]="!editable" [placeholder]="placeholder" />
<span class="isa-font-weight-bold suffix">{{ suffix }}</span>
</label>
<button
*ngIf="editable && value?.length && touched && focussed"
class="isa-input-reset-sm"
(click)="reset()"
></button>
<button *ngIf="editable && value?.length && touched && focussed" class="isa-input-reset-sm"
(click)="reset()"></button>
<span *ngIf="!editable" class="status">Nicht Änderbar</span>
</div>
</div>

View File

@@ -2,9 +2,9 @@ import { Injectable } from '@angular/core';
import { Actions, ofType, createEffect } from '@ngrx/effects';
import * as actions from './details.actions';
import { flatMap, catchError, map, concatMap } from 'rxjs/operators';
import { flatMap, catchError, map } from 'rxjs/operators';
import { OrderService, StrictHttpResponse, ListResponseArgsOfOrderItemListItemDTO, AbholfachService } from '@swagger/oms';
import { of, NEVER, zip, combineLatest } from 'rxjs';
import { of, NEVER } from 'rxjs';
import { SearchStateFacade } from '../search';
@Injectable()

View File

@@ -134,7 +134,7 @@ export class DetailsFacade {
orderId,
orderItemId,
orderItemSubsetId,
data: { processingStatus: 8192 } as StatusValues,
data: { processingStatus: 8192, compartmentNumber: '', compartmentInfo: '' } as StatusValues,
}));
return this.changeStatus(data);
}

View File

@@ -36,3 +36,7 @@
.isa-font-lightgrey {
color: $text-lightgrey;
}
.isa-white-space-nowrap {
white-space: nowrap;
}

View File

@@ -32,6 +32,11 @@
padding: 12px 25px;
}
.isa-btn-large {
font-size: 18px;
padding: 16px 20px;
}
.isa-btn-primary {
color: $text-light;
background-color: $isa-red;