chore: prettier write

This commit is contained in:
Lorenz Hilpert
2025-02-24 15:29:32 +01:00
parent eb6149a6e3
commit 3f77646f8a
425 changed files with 4021 additions and 1617 deletions

View File

@@ -1,4 +1,12 @@
import { Component, ChangeDetectionStrategy, ElementRef, ViewChild, NgZone, AfterViewInit, OnDestroy } from '@angular/core';
import {
Component,
ChangeDetectionStrategy,
ElementRef,
ViewChild,
NgZone,
AfterViewInit,
OnDestroy,
} from '@angular/core';
import { BarcodeCapture, BarcodeCaptureSettings, Symbology } from 'scandit-web-datacapture-barcode';
import { Camera, DataCaptureContext, DataCaptureView, FrameSourceState } from 'scandit-web-datacapture-core';

View File

@@ -1,5 +1,16 @@
import { DOCUMENT } from '@angular/common';
import { Component, effect, HostListener, inject, Inject, Injector, OnInit, Renderer2, signal, untracked } from '@angular/core';
import {
Component,
effect,
HostListener,
inject,
Inject,
Injector,
OnInit,
Renderer2,
signal,
untracked,
} from '@angular/core';
import { Title } from '@angular/platform-browser';
import { SwUpdate } from '@angular/service-worker';
import { ApplicationService } from '@core/application';
@@ -121,7 +132,10 @@ export class AppComponent implements OnInit {
}
logVersion() {
console.log(`%c${this._config.get('title')}\r\nVersion: ${packageInfo.version}`, 'font-weight: bold; font-size: 20px;');
console.log(
`%c${this._config.get('title')}\r\nVersion: ${packageInfo.version}`,
'font-weight: bold; font-size: 20px;',
);
}
determinePlatform() {

View File

@@ -40,9 +40,12 @@ export class CreateKubiCustomerCommand extends ActionHandler<Result<CustomerInfo
customerType = 'store';
}
await this._router.navigate(['/kunde', this._application.activatedProcessId, 'customer', 'create', `${customerType}-p4m`], {
queryParams: { formData },
});
await this._router.navigate(
['/kunde', this._application.activatedProcessId, 'customer', 'create', `${customerType}-p4m`],
{
queryParams: { formData },
},
);
return data;
}
}

View File

@@ -4,7 +4,10 @@ import { ApplicationService } from '@core/application';
import { Config } from '@core/config';
import { take } from 'rxjs/operators';
export const ActivateProcessIdGuard: CanActivateFn = async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
export const ActivateProcessIdGuard: CanActivateFn = async (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
) => {
const application = inject(ApplicationService);
const processIdStr = route.params.processId;
@@ -27,20 +30,18 @@ export const ActivateProcessIdGuard: CanActivateFn = async (route: ActivatedRout
return true;
};
export const ActivateProcessIdWithConfigKeyGuard: (key: string) => CanActivateFn = (key) => async (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
) => {
const application = inject(ApplicationService);
const config = inject(Config);
export const ActivateProcessIdWithConfigKeyGuard: (key: string) => CanActivateFn =
(key) => async (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => {
const application = inject(ApplicationService);
const config = inject(Config);
const processId = config.get(`process.ids.${key}`);
const processId = config.get(`process.ids.${key}`);
if (isNaN(processId)) {
return false;
}
if (isNaN(processId)) {
return false;
}
application.activateProcess(processId);
application.activateProcess(processId);
return true;
};
return true;
};

View File

@@ -6,10 +6,16 @@ import { first } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class CanActivateAssortmentGuard {
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
constructor(
private readonly _applicationService: ApplicationService,
private readonly _config: Config,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.assortment')).pipe(first()).toPromise();
const process = await this._applicationService
.getProcessById$(this._config.get('process.ids.assortment'))
.pipe(first())
.toPromise();
if (!process) {
await this._applicationService.createProcess({
id: this._config.get('process.ids.assortment'),

View File

@@ -8,10 +8,7 @@ export class CanActivateCartWithProcessIdGuard {
constructor(private readonly _applicationService: ApplicationService) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService
.getProcessById$(+route.params.processId)
.pipe(first())
.toPromise();
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
// if (!(process?.type === 'cart')) {
// // TODO:

View File

@@ -14,7 +14,10 @@ export class CanActivateCartGuard {
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
let lastActivatedProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
.pipe(first())
.toPromise()
)?.id;
if (!lastActivatedProcessId) {
lastActivatedProcessId = Date.now();

View File

@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class CanActivateCustomerOrdersWithProcessIdGuard {
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
constructor(
private readonly _applicationService: ApplicationService,
private readonly _breadcrumbService: BreadcrumbService,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService
.getProcessById$(+route.params.processId)
.pipe(first())
.toPromise();
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
if (!process) {
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
@@ -31,10 +31,7 @@ export class CanActivateCustomerOrdersWithProcessIdGuard {
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
const crumbs = await this._breadcrumbService
.getBreadcrumbByKey$(+route.params.processId)
.pipe(first())
.toPromise();
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
// Entferne alle Crumbs die nichts mit den Kundenbestellungen zu tun haben
if (crumbs.length > 1) {

View File

@@ -17,11 +17,17 @@ export class CanActivateCustomerOrdersGuard {
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
let lastActivatedProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
.pipe(first())
.toPromise()
)?.id;
const lastActivatedCartCheckoutProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
.pipe(first())
.toPromise()
)?.id;
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();

View File

@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class CanActivateCustomerWithProcessIdGuard {
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
constructor(
private readonly _applicationService: ApplicationService,
private readonly _breadcrumbService: BreadcrumbService,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService
.getProcessById$(+route.params.processId)
.pipe(first())
.toPromise();
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
// if (!(process?.type === 'cart')) {
// // TODO:
@@ -37,10 +37,7 @@ export class CanActivateCustomerWithProcessIdGuard {
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
const crumbs = await this._breadcrumbService
.getBreadcrumbByKey$(+route.params.processId)
.pipe(first())
.toPromise();
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
// Entferne alle Crumbs die nichts mit der Kundensuche zu tun haben
if (crumbs.length > 1) {

View File

@@ -17,15 +17,24 @@ export class CanActivateCustomerGuard {
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
let lastActivatedProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
.pipe(first())
.toPromise()
)?.id;
const lastActivatedCartCheckoutProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
.pipe(first())
.toPromise()
)?.id;
const lastActivatedGoodsOutProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out')
.pipe(first())
.toPromise()
)?.id;
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();

View File

@@ -6,10 +6,16 @@ import { first } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class CanActivateGoodsInGuard {
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
constructor(
private readonly _applicationService: ApplicationService,
private readonly _config: Config,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.goodsIn')).pipe(first()).toPromise();
const process = await this._applicationService
.getProcessById$(this._config.get('process.ids.goodsIn'))
.pipe(first())
.toPromise();
if (!process) {
await this._applicationService.createProcess({
id: this._config.get('process.ids.goodsIn'),

View File

@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class CanActivateGoodsOutWithProcessIdGuard {
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
constructor(
private readonly _applicationService: ApplicationService,
private readonly _breadcrumbService: BreadcrumbService,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService
.getProcessById$(+route.params.processId)
.pipe(first())
.toPromise();
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
if (!process) {
// const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
@@ -31,10 +31,7 @@ export class CanActivateGoodsOutWithProcessIdGuard {
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
const crumbs = await this._breadcrumbService
.getBreadcrumbByKey$(+route.params.processId)
.pipe(first())
.toPromise();
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
// Entferne alle Crumbs die nichts mit der Warenausgabe zu tun haben
if (crumbs.length > 1) {

View File

@@ -9,7 +9,7 @@ export class CanActivateGoodsOutGuard {
constructor(
private readonly _applicationService: ApplicationService,
private readonly _checkoutService: DomainCheckoutService,
private readonly _router: Router
private readonly _router: Router,
) {}
// !!! Ticket #3272 Code soll vorerst bestehen bleiben. Prozess Warenausgabe soll wieder Vorgang heißen (wie aktuell im Produktiv), bis zum neuen Navigationskonzept
@@ -103,11 +103,17 @@ export class CanActivateGoodsOutGuard {
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
let lastActivatedProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
.pipe(first())
.toPromise()
)?.id;
const lastActivatedCartCheckoutProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
.pipe(first())
.toPromise()
)?.id;
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();

View File

@@ -6,7 +6,10 @@ import { first } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class CanActivatePackageInspectionGuard {
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
constructor(
private readonly _applicationService: ApplicationService,
private readonly _config: Config,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService

View File

@@ -6,13 +6,13 @@ import { first } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class CanActivateProductWithProcessIdGuard {
constructor(private readonly _applicationService: ApplicationService, private readonly _breadcrumbService: BreadcrumbService) {}
constructor(
private readonly _applicationService: ApplicationService,
private readonly _breadcrumbService: BreadcrumbService,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService
.getProcessById$(+route.params.processId)
.pipe(first())
.toPromise();
const process = await this._applicationService.getProcessById$(+route.params.processId).pipe(first()).toPromise();
// if (!(process?.type === 'cart')) {
// // TODO:
@@ -37,10 +37,7 @@ export class CanActivateProductWithProcessIdGuard {
// Fix #3292: Alle Breadcrumbs die nichts mit dem aktuellen Prozess zu tun haben, müssen removed werden
async removeBreadcrumbWithSameProcessId(route: ActivatedRouteSnapshot) {
const crumbs = await this._breadcrumbService
.getBreadcrumbByKey$(+route.params.processId)
.pipe(first())
.toPromise();
const crumbs = await this._breadcrumbService.getBreadcrumbByKey$(+route.params.processId).pipe(first()).toPromise();
// Entferne alle Crumbs die nichts mit der Artikelsuche zu tun haben
if (crumbs.length > 1) {

View File

@@ -16,15 +16,24 @@ export class CanActivateProductGuard {
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const processes = await this._applicationService.getProcesses$('customer').pipe(first()).toPromise();
let lastActivatedProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart')
.pipe(first())
.toPromise()
)?.id;
const lastActivatedCartCheckoutProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'cart-checkout')
.pipe(first())
.toPromise()
)?.id;
const lastActivatedGoodsOutProcessId = (
await this._applicationService.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out').pipe(first()).toPromise()
await this._applicationService
.getLastActivatedProcessWithSectionAndType$('customer', 'goods-out')
.pipe(first())
.toPromise()
)?.id;
const activatedProcessId = await this._applicationService.getActivatedProcessId$().pipe(first()).toPromise();

View File

@@ -9,11 +9,14 @@ export class CanActivateRemissionGuard {
constructor(
private readonly _applicationService: ApplicationService,
private readonly _config: Config,
private readonly _router: Router
private readonly _router: Router,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.remission')).pipe(first()).toPromise();
const process = await this._applicationService
.getProcessById$(this._config.get('process.ids.remission'))
.pipe(first())
.toPromise();
if (!process) {
await this._applicationService.createProcess({
id: this._config.get('process.ids.remission'),

View File

@@ -6,10 +6,16 @@ import { first } from 'rxjs/operators';
@Injectable({ providedIn: 'root' })
export class CanActivateTaskCalendarGuard {
constructor(private readonly _applicationService: ApplicationService, private readonly _config: Config) {}
constructor(
private readonly _applicationService: ApplicationService,
private readonly _config: Config,
) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
const process = await this._applicationService.getProcessById$(this._config.get('process.ids.taskCalendar')).pipe(first()).toPromise();
const process = await this._applicationService
.getProcessById$(this._config.get('process.ids.taskCalendar'))
.pipe(first())
.toPromise();
if (!process) {
await this._applicationService.createProcess({
id: this._config.get('process.ids.taskCalendar'),

View File

@@ -5,7 +5,7 @@ import { take } from 'rxjs/operators';
export const ProcessIdGuard: CanActivateFn = async (
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
state: RouterStateSnapshot,
): Promise<boolean | UrlTree> => {
const application = inject(ApplicationService);
const router = inject(Router);

View File

@@ -4,7 +4,10 @@ import { ApplicationService } from '@core/application';
import { Observable } from 'rxjs';
export abstract class SectionResolver {
constructor(protected section: 'customer' | 'branch', protected applicationService: ApplicationService) {}
constructor(
protected section: 'customer' | 'branch',
protected applicationService: ApplicationService,
) {}
resolve(route: ActivatedRouteSnapshot): Observable<string> | Promise<string> | string {
this.applicationService.setSection(this.section);

View File

@@ -43,7 +43,11 @@ export class RootStateService {
takeUntil(this._cancelSave),
debounceTime(1000),
switchMap((state) => {
const raw = JSON.stringify({ ...state, version: packageInfo.version, sub: this._authService.getClaimByKey('sub') });
const raw = JSON.stringify({
...state,
version: packageInfo.version,
sub: this._authService.getClaimByKey('sub'),
});
RootStateService.SaveToLocalStorageRaw(raw);
return this._userStateService.UserStateSetUserState({ content: raw });
}),

View File

@@ -1,219 +1,222 @@
/* cyrillic-ext */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 400;
font-stretch: normal;
src: url('./Open_Sans-400-cyrillic-ext1.woff2') format('woff2');
src: url("./Open_Sans-400-cyrillic-ext1.woff2") format("woff2");
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 400;
font-stretch: normal;
src: url('./Open_Sans-400-cyrillic2.woff2') format('woff2');
src: url("./Open_Sans-400-cyrillic2.woff2") format("woff2");
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 400;
font-stretch: normal;
src: url('./Open_Sans-400-greek-ext3.woff2') format('woff2');
src: url("./Open_Sans-400-greek-ext3.woff2") format("woff2");
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 400;
font-stretch: normal;
src: url('./Open_Sans-400-greek4.woff2') format('woff2');
src: url("./Open_Sans-400-greek4.woff2") format("woff2");
unicode-range: U+0370-03FF;
}
/* hebrew */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 400;
font-stretch: normal;
src: url('./Open_Sans-400-hebrew5.woff2') format('woff2');
src: url("./Open_Sans-400-hebrew5.woff2") format("woff2");
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}
/* vietnamese */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 400;
font-stretch: normal;
src: url('./Open_Sans-400-vietnamese6.woff2') format('woff2');
src: url("./Open_Sans-400-vietnamese6.woff2") format("woff2");
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 400;
font-stretch: normal;
src: url('./Open_Sans-400-latin-ext7.woff2') format('woff2');
src: url("./Open_Sans-400-latin-ext7.woff2") format("woff2");
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 400;
font-stretch: normal;
src: url('./Open_Sans-400-latin8.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
src: url("./Open_Sans-400-latin8.woff2") format("woff2");
unicode-range:
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 600;
font-stretch: normal;
src: url('./Open_Sans-600-cyrillic-ext9.woff2') format('woff2');
src: url("./Open_Sans-600-cyrillic-ext9.woff2") format("woff2");
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 600;
font-stretch: normal;
src: url('./Open_Sans-600-cyrillic10.woff2') format('woff2');
src: url("./Open_Sans-600-cyrillic10.woff2") format("woff2");
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 600;
font-stretch: normal;
src: url('./Open_Sans-600-greek-ext11.woff2') format('woff2');
src: url("./Open_Sans-600-greek-ext11.woff2") format("woff2");
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 600;
font-stretch: normal;
src: url('./Open_Sans-600-greek12.woff2') format('woff2');
src: url("./Open_Sans-600-greek12.woff2") format("woff2");
unicode-range: U+0370-03FF;
}
/* hebrew */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 600;
font-stretch: normal;
src: url('./Open_Sans-600-hebrew13.woff2') format('woff2');
src: url("./Open_Sans-600-hebrew13.woff2") format("woff2");
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}
/* vietnamese */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 600;
font-stretch: normal;
src: url('./Open_Sans-600-vietnamese14.woff2') format('woff2');
src: url("./Open_Sans-600-vietnamese14.woff2") format("woff2");
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 600;
font-stretch: normal;
src: url('./Open_Sans-600-latin-ext15.woff2') format('woff2');
src: url("./Open_Sans-600-latin-ext15.woff2") format("woff2");
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 600;
font-stretch: normal;
src: url('./Open_Sans-600-latin16.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
src: url("./Open_Sans-600-latin16.woff2") format("woff2");
unicode-range:
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 700;
font-stretch: normal;
src: url('./Open_Sans-700-cyrillic-ext17.woff2') format('woff2');
src: url("./Open_Sans-700-cyrillic-ext17.woff2") format("woff2");
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 700;
font-stretch: normal;
src: url('./Open_Sans-700-cyrillic18.woff2') format('woff2');
src: url("./Open_Sans-700-cyrillic18.woff2") format("woff2");
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 700;
font-stretch: normal;
src: url('./Open_Sans-700-greek-ext19.woff2') format('woff2');
src: url("./Open_Sans-700-greek-ext19.woff2") format("woff2");
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 700;
font-stretch: normal;
src: url('./Open_Sans-700-greek20.woff2') format('woff2');
src: url("./Open_Sans-700-greek20.woff2") format("woff2");
unicode-range: U+0370-03FF;
}
/* hebrew */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 700;
font-stretch: normal;
src: url('./Open_Sans-700-hebrew21.woff2') format('woff2');
src: url("./Open_Sans-700-hebrew21.woff2") format("woff2");
unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
}
/* vietnamese */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 700;
font-stretch: normal;
src: url('./Open_Sans-700-vietnamese22.woff2') format('woff2');
src: url("./Open_Sans-700-vietnamese22.woff2") format("woff2");
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 700;
font-stretch: normal;
src: url('./Open_Sans-700-latin-ext23.woff2') format('woff2');
src: url("./Open_Sans-700-latin-ext23.woff2") format("woff2");
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Open Sans';
font-family: "Open Sans";
font-style: normal;
font-weight: 700;
font-stretch: normal;
src: url('./Open_Sans-700-latin24.woff2') format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
U+2212, U+2215, U+FEFF, U+FFFD;
src: url("./Open_Sans-700-latin24.woff2") format("woff2");
unicode-range:
U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

View File

@@ -35,7 +35,9 @@ export class ApplicationService {
getProcesses$(section?: 'customer' | 'branch') {
const processes$ = this.store.select(selectProcesses);
return processes$.pipe(map((processes) => processes.filter((process) => (section ? process.section === section : true))));
return processes$.pipe(
map((processes) => processes.filter((process) => (section ? process.section === section : true))),
);
}
getProcessById$(processId: number): Observable<ApplicationProcess> {
@@ -135,7 +137,10 @@ export class ApplicationService {
this.store.dispatch(setSection({ section }));
}
getLastActivatedProcessWithSectionAndType$(section: 'customer' | 'branch', type: string): Observable<ApplicationProcess> {
getLastActivatedProcessWithSectionAndType$(
section: 'customer' | 'branch',
type: string,
): Observable<ApplicationProcess> {
return this.getProcesses$(section).pipe(
map((processes) =>
processes

View File

@@ -11,8 +11,17 @@ export const addProcess = createAction(`${prefix} Add Process`, props<{ process:
export const removeProcess = createAction(`${prefix} Remove Process`, props<{ processId: number }>());
export const setActivatedProcess = createAction(`${prefix} Set Activated Process`, props<{ activatedProcessId: number }>());
export const setActivatedProcess = createAction(
`${prefix} Set Activated Process`,
props<{ activatedProcessId: number }>(),
);
export const patchProcess = createAction(`${prefix} Patch Process`, props<{ processId: number; changes: Partial<ApplicationProcess> }>());
export const patchProcess = createAction(
`${prefix} Patch Process`,
props<{ processId: number; changes: Partial<ApplicationProcess> }>(),
);
export const patchProcessData = createAction(`${prefix} Patch Process Data`, props<{ processId: number; data: Record<string, any> }>());
export const patchProcessData = createAction(
`${prefix} Patch Process Data`,
props<{ processId: number; data: Record<string, any> }>(),
);

View File

@@ -120,7 +120,10 @@ export class BreadcrumbService {
if (recursive) {
const breadcrumbs = await this.getBreadcrumbByKey$(breadcrumb.key).pipe(take(1)).toPromise();
breadcrumbsToRemove = [...breadcrumbsToRemove, ...breadcrumbs.filter((crumb) => crumb.timestamp > breadcrumb.timestamp)];
breadcrumbsToRemove = [
...breadcrumbsToRemove,
...breadcrumbs.filter((crumb) => crumb.timestamp > breadcrumb.timestamp),
];
}
if (!breadcrumbsToRemove.length) {
@@ -135,7 +138,10 @@ export class BreadcrumbService {
crumbs.forEach((crumb) => this.removeBreadcrumb(crumb.id));
}
getLatestBreadcrumbForSection(section: 'customer' | 'branch', predicate: (crumb: Breadcrumb) => boolean = (_) => true) {
getLatestBreadcrumbForSection(
section: 'customer' | 'branch',
predicate: (crumb: Breadcrumb) => boolean = (_) => true,
) {
return this.store
.select(selectors.selectBreadcrumbsBySection, { section })
.pipe(map((crumbs) => crumbs.sort((a, b) => b.timestamp - a.timestamp).find((f) => predicate(f))));

View File

@@ -11,7 +11,10 @@ export const addBreadcrumb = createAction(`${prefix} Add Breadcrumb`, props<{ br
/**
* Action um Breadcrumb im State zu ändern
*/
export const updateBreadcrumb = createAction(`${prefix} Update Breadcrumb`, props<{ id: number; changes: Partial<Breadcrumb> }>());
export const updateBreadcrumb = createAction(
`${prefix} Update Breadcrumb`,
props<{ id: number; changes: Partial<Breadcrumb> }>(),
);
/**
* Action um Breadcrumb im State zu entfernen

View File

@@ -43,7 +43,10 @@ describe('Breadcrumb Reducer', () => {
const state = breadcrumbReducer(INIT, action.addBreadcrumb({ breadcrumb }));
const fixture = breadcrumbReducer(state, action.updateBreadcrumb({ id: breadcrumb.id, changes: { name: 'Test Name 2' } }));
const fixture = breadcrumbReducer(
state,
action.updateBreadcrumb({ id: breadcrumb.id, changes: { name: 'Test Name 2' } }),
);
expect(fixture.entities[breadcrumb.id]).toEqual(expected);
});

View File

@@ -10,26 +10,46 @@ describe('Breadcrumb Selectors', () => {
beforeEach(() => {
state = breadcrumbReducer(
INIT,
action.addBreadcrumb({ breadcrumb: { id: 1, key: 'unit-test-1', path: '', name: 'Unit Test 1', section: 'customer' } }),
);
state = breadcrumbReducer(
state,
action.addBreadcrumb({
breadcrumb: { id: 2, key: 'unit-test-1', path: '', name: 'Unit Test 1', tags: ['details'], section: 'customer' },
breadcrumb: { id: 1, key: 'unit-test-1', path: '', name: 'Unit Test 1', section: 'customer' },
}),
);
state = breadcrumbReducer(
state,
action.addBreadcrumb({ breadcrumb: { id: 3, key: 'unit-test-2', path: '', name: 'Unit Test 1', section: 'customer' } }),
);
state = breadcrumbReducer(
state,
action.addBreadcrumb({ breadcrumb: { id: 4, key: 'unit-test-3', path: '', name: 'Unit Test 1', section: 'customer' } }),
action.addBreadcrumb({
breadcrumb: {
id: 2,
key: 'unit-test-1',
path: '',
name: 'Unit Test 1',
tags: ['details'],
section: 'customer',
},
}),
);
state = breadcrumbReducer(
state,
action.addBreadcrumb({
breadcrumb: { id: 5, key: 'unit-test-3', path: '', name: 'Unit Test 1', tags: ['details'], section: 'customer' },
breadcrumb: { id: 3, key: 'unit-test-2', path: '', name: 'Unit Test 1', section: 'customer' },
}),
);
state = breadcrumbReducer(
state,
action.addBreadcrumb({
breadcrumb: { id: 4, key: 'unit-test-3', path: '', name: 'Unit Test 1', section: 'customer' },
}),
);
state = breadcrumbReducer(
state,
action.addBreadcrumb({
breadcrumb: {
id: 5,
key: 'unit-test-3',
path: '',
name: 'Unit Test 1',
tags: ['details'],
section: 'customer',
},
}),
);
});

View File

@@ -20,7 +20,9 @@ export const selectBreadcrumbById = createSelector(selectEntities, (entities, id
/**
* Gibt alle Breadcrumb Entities als Array zurück die den key enthalten
*/
export const selectBreadcrumbsByKey = createSelector(selectAll, (entities, key: string) => entities.filter((crumb) => crumb.key == key));
export const selectBreadcrumbsByKey = createSelector(selectAll, (entities, key: string) =>
entities.filter((crumb) => crumb.key == key),
);
/**
* Gibt alle Breadcrumb Entities als Array zurück die den key und tag enthalten
@@ -37,12 +39,15 @@ export const selectBreadcrumbsByKeyAndTag = createSelector(
export const selectBreadcrumbsByKeyAndTags = createSelector(
selectAll,
(entities: Breadcrumb[], { key, tags }: { key: string; tags: string[] }) =>
entities.filter((crumb) => crumb.key == key && isArray(crumb.tags) && tags.every((tag) => crumb.tags.includes(tag))),
entities.filter(
(crumb) => crumb.key == key && isArray(crumb.tags) && tags.every((tag) => crumb.tags.includes(tag)),
),
);
/**
* Gibt alle Breadcrumb Entities als Array zurück die die tags enthalten
*/
export const selectBreadcrumbsBySection = createSelector(selectAll, (entities: Breadcrumb[], { section }: { section: string }) =>
entities.filter((crumb) => crumb.section === section),
export const selectBreadcrumbsBySection = createSelector(
selectAll,
(entities: Breadcrumb[], { section }: { section: string }) => entities.filter((crumb) => crumb.section === section),
);

View File

@@ -4,7 +4,10 @@ import { CommandService } from './command.service';
import { FEATURE_ACTION_HANDLERS, ROOT_ACTION_HANDLERS } from './tokens';
export function provideActionHandlers(actionHandlers: Type<ActionHandler>[]): Provider[] {
return [CommandService, actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true }))];
return [
CommandService,
actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true })),
];
}
@NgModule({})
@@ -12,14 +15,20 @@ export class CoreCommandModule {
static forRoot(actionHandlers: Type<ActionHandler>[]): ModuleWithProviders<CoreCommandModule> {
return {
ngModule: CoreCommandModule,
providers: [CommandService, actionHandlers.map((handler) => ({ provide: ROOT_ACTION_HANDLERS, useClass: handler, multi: true }))],
providers: [
CommandService,
actionHandlers.map((handler) => ({ provide: ROOT_ACTION_HANDLERS, useClass: handler, multi: true })),
],
};
}
static forChild(actionHandlers: Type<ActionHandler>[]): ModuleWithProviders<CoreCommandModule> {
return {
ngModule: CoreCommandModule,
providers: [CommandService, actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true }))],
providers: [
CommandService,
actionHandlers.map((handler) => ({ provide: FEATURE_ACTION_HANDLERS, useClass: handler, multi: true })),
],
};
}
}

View File

@@ -21,7 +21,9 @@ export class ConfigModule {
providers: [
Config,
configLoaderProvider,
options.jsonConfigLoaderUrl ? { provide: CORE_JSON_CONFIG_LOADER_URL, useValue: options.jsonConfigLoaderUrl } : null,
options.jsonConfigLoaderUrl
? { provide: CORE_JSON_CONFIG_LOADER_URL, useValue: options.jsonConfigLoaderUrl }
: null,
],
};
}

View File

@@ -19,7 +19,12 @@ import { AvailabilityDTO as CatAvailabilityDTO } from '@generated/swagger/cat-se
import { map, shareReplay, switchMap, withLatestFrom, mergeMap, timeout, first } from 'rxjs/operators';
import { isArray, memorize } from '@utils/common';
import { LogisticianDTO, LogisticianService } from '@generated/swagger/oms-api';
import { ResponseArgsOfIEnumerableOfStockInfoDTO, StockDTO, StockInfoDTO, StockService } from '@generated/swagger/inventory-api';
import {
ResponseArgsOfIEnumerableOfStockInfoDTO,
StockDTO,
StockInfoDTO,
StockService,
} from '@generated/swagger/inventory-api';
import { PriceDTO } from '@generated/swagger/availability-api';
import { AvailabilityByBranchDTO, ItemData, Ssc } from './defs';
import { Availability } from './defs/availability';
@@ -171,7 +176,13 @@ export class DomainAvailabilityService {
),
map(([response, supplier, defaultBranch]) => {
const price = item?.price;
return this._mapToTakeAwayAvailability({ response, supplier, branchId: branch?.id ?? defaultBranch?.id, quantity, price });
return this._mapToTakeAwayAvailability({
response,
supplier,
branchId: branch?.id ?? defaultBranch?.id,
quantity,
price,
});
}),
shareReplay(1),
);
@@ -216,7 +227,13 @@ export class DomainAvailabilityService {
switchMap((s) => this._stockService.StockInStockByEAN({ eans, stockId: s.id })),
withLatestFrom(this.getTakeAwaySupplier(), this.getDefaultBranch()),
map(([response, supplier, defaultBranch]) => {
return this._mapToTakeAwayAvailability({ response, supplier, branchId: branchId ?? defaultBranch.id, quantity, price });
return this._mapToTakeAwayAvailability({
response,
supplier,
branchId: branchId ?? defaultBranch.id,
quantity,
price,
});
}),
shareReplay(1),
);
@@ -329,7 +346,10 @@ export class DomainAvailabilityService {
this.getPickUpAvailability({ item, quantity, branch: branch ?? defaultBranch }).pipe(
mergeMap((availability) =>
logistician$.pipe(
map((logistician) => ({ ...(availability?.length > 0 ? availability[0] : []), logistician: { id: logistician.id } })),
map((logistician) => ({
...(availability?.length > 0 ? availability[0] : []),
logistician: { id: logistician.id },
})),
),
),
shareReplay(1),
@@ -427,7 +447,9 @@ export class DomainAvailabilityService {
return this.getPickUpAvailabilities(payload, true).pipe(
timeout(20000),
switchMap((availability) =>
logistician$.pipe(map((logistician) => ({ availability: [...availability], logistician: { id: logistician.id } }))),
logistician$.pipe(
map((logistician) => ({ availability: [...availability], logistician: { id: logistician.id } })),
),
),
shareReplay(1),
);
@@ -512,7 +534,9 @@ export class DomainAvailabilityService {
return availability;
}
private _mapToPickUpAvailability(availabilities: SwaggerAvailabilityDTO[]): Availability<AvailabilityDTO, SwaggerAvailabilityDTO>[] {
private _mapToPickUpAvailability(
availabilities: SwaggerAvailabilityDTO[],
): Availability<AvailabilityDTO, SwaggerAvailabilityDTO>[] {
if (isArray(availabilities)) {
const preferred = availabilities.filter((f) => f.preferred === 1);
const totalAvailable = availabilities.reduce((sum, av) => sum + (av?.qty || 0), 0);
@@ -572,7 +596,9 @@ export class DomainAvailabilityService {
}
const stock$ = branchId$.pipe(
mergeMap((branchId) => this._stockService.StockGetStocksByBranch({ branchId }).pipe(map((response) => response.result?.[0]))),
mergeMap((branchId) =>
this._stockService.StockGetStocksByBranch({ branchId }).pipe(map((response) => response.result?.[0])),
),
);
return stock$.pipe(
@@ -598,7 +624,9 @@ export class DomainAvailabilityService {
getInStock({ itemIds, branchId }: { itemIds: number[]; branchId: number }): Observable<StockInfoDTO[]> {
return this.getStockByBranch(branchId).pipe(
mergeMap((stock) =>
this._stockService.StockInStock({ articleIds: itemIds, stockId: stock.id }).pipe(map((response) => response.result)),
this._stockService
.StockInStock({ articleIds: itemIds, stockId: stock.id })
.pipe(map((response) => response.result)),
),
);
}

View File

@@ -90,10 +90,15 @@ export class DomainInStockService {
const grouped = groupBy(itemBranchData, 'branchId');
Object.keys(grouped).forEach((key) => {
const branchId = Number(key);
const itemIds = itemBranchData.filter((itemBranch) => itemBranch.branchId === branchId).map((item) => item.itemId);
const itemIds = itemBranchData
.filter((itemBranch) => itemBranch.branchId === branchId)
.map((item) => item.itemId);
this._availability
.getInStock({ itemIds, branchId })
.subscribe(this._fetchStockDataResponse({ itemIds, branchId }), this._fetchStockDataError({ itemIds, branchId }));
.subscribe(
this._fetchStockDataResponse({ itemIds, branchId }),
this._fetchStockDataError({ itemIds, branchId }),
);
});
}
@@ -101,7 +106,9 @@ export class DomainInStockService {
({ itemIds, branchId }: { itemIds: number[]; branchId: number }) =>
(stockInfos: StockInfoDTO[]) => {
itemIds.forEach((itemId) => {
const stockInfo = stockInfos.find((stockInfo) => stockInfo.itemId === itemId && stockInfo.branchId === branchId);
const stockInfo = stockInfos.find(
(stockInfo) => stockInfo.itemId === itemId && stockInfo.branchId === branchId,
);
let inStock = 0;
if (stockInfo?.inStock) {

View File

@@ -1,6 +1,11 @@
import { Injectable } from '@angular/core';
import { ApplicationService } from '@core/application';
import { AutocompleteTokenDTO, PromotionService, QueryTokenDTO, SearchService } from '@generated/swagger/cat-search-api';
import {
AutocompleteTokenDTO,
PromotionService,
QueryTokenDTO,
SearchService,
} from '@generated/swagger/cat-search-api';
import { memorize } from '@utils/common';
import { map, share, shareReplay } from 'rxjs/operators';

View File

@@ -21,6 +21,9 @@ export class DomainCheckoutModule {
}
@NgModule({
imports: [StoreModule.forFeature(storeFeatureName, domainCheckoutReducer), EffectsModule.forFeature([DomainCheckoutEffects])],
imports: [
StoreModule.forFeature(storeFeatureName, domainCheckoutReducer),
EffectsModule.forFeature([DomainCheckoutEffects]),
],
})
export class RootDomainCheckoutModule {}

View File

@@ -135,7 +135,13 @@ export class DomainCheckoutService {
);
}
addItemToShoppingCart({ processId, items }: { processId: number; items: AddToShoppingCartDTO[] }): Observable<ShoppingCartDTO> {
addItemToShoppingCart({
processId,
items,
}: {
processId: number;
items: AddToShoppingCartDTO[];
}): Observable<ShoppingCartDTO> {
return this.getShoppingCart({ processId }).pipe(
first(),
mergeMap((cart) =>
@@ -488,7 +494,11 @@ export class DomainCheckoutService {
checkAvailabilities({ processId }: { processId: number }): Observable<any> {
const shoppingCart$ = this.getShoppingCart({ processId }).pipe(first());
const itemsToCheck$ = shoppingCart$.pipe(
map((cart) => cart?.items?.filter((item) => item?.data?.features?.orderType === 'Download' && !item.data.availability.lastRequest)),
map((cart) =>
cart?.items?.filter(
(item) => item?.data?.features?.orderType === 'Download' && !item.data.availability.lastRequest,
),
),
);
return itemsToCheck$.pipe(
@@ -537,7 +547,8 @@ export class DomainCheckoutService {
const itemsToUpdate$ = shoppingCart$.pipe(
map((cart) =>
cart?.items?.filter(
(item) => item?.data?.features?.orderType === 'DIG-Versand' || item?.data?.features?.orderType === 'B2B-Versand',
(item) =>
item?.data?.features?.orderType === 'DIG-Versand' || item?.data?.features?.orderType === 'B2B-Versand',
),
),
);
@@ -770,7 +781,9 @@ export class DomainCheckoutService {
const availabilities$ = this.validateAvailabilities({ processId });
return combineLatest([olaStatus$, availabilities$]).pipe(map(([olaStatus, availabilities]) => olaStatus && availabilities));
return combineLatest([olaStatus$, availabilities$]).pipe(
map(([olaStatus, availabilities]) => olaStatus && availabilities),
);
}
completeCheckout({ processId }: { processId: number }): Observable<DisplayOrderDTO[]> {
@@ -871,7 +884,8 @@ export class DomainCheckoutService {
const setPaymentType$ = itemOrderOptions$.pipe(
mergeMap(({ hasDownload, hasDelivery, hasDigDelivery, hasB2BDelivery }) => {
const paymentType = hasDownload || hasDelivery || hasDigDelivery || hasB2BDelivery ? 128 /* Rechnung */ : 4; /* Bar */
const paymentType =
hasDownload || hasDelivery || hasDigDelivery || hasB2BDelivery ? 128 /* Rechnung */ : 4; /* Bar */
return this.setPayment({ processId, paymentType });
}),
shareReplay(),
@@ -1057,7 +1071,13 @@ export class DomainCheckoutService {
.pipe(shareReplay(1));
}
setNotificationChannels({ processId, notificationChannels }: { processId: number; notificationChannels: NotificationChannel }): void {
setNotificationChannels({
processId,
notificationChannels,
}: {
processId: number;
notificationChannels: NotificationChannel;
}): void {
this.store.dispatch(DomainCheckoutActions.setNotificationChannels({ processId, notificationChannels }));
}
@@ -1065,7 +1085,15 @@ export class DomainCheckoutService {
return this.store.select(DomainCheckoutSelectors.selectNotificationChannels, { processId });
}
setBuyerCommunicationDetails({ processId, mobile, email }: { processId: number; mobile?: string; email?: string }): void {
setBuyerCommunicationDetails({
processId,
mobile,
email,
}: {
processId: number;
mobile?: string;
email?: string;
}): void {
this.store.dispatch(DomainCheckoutActions.setBuyerCommunicationDetails({ processId, mobile, email }));
}
@@ -1125,7 +1153,11 @@ export class DomainCheckoutService {
.pipe(
map((r) => {
return r.result.filter(
(branch) => branch.status === 1 && branch.branchType === 1 && branch.isOnline === true && branch.isShippingEnabled === true,
(branch) =>
branch.status === 1 &&
branch.branchType === 1 &&
branch.isOnline === true &&
branch.isShippingEnabled === true,
);
}),
shareReplay(),

View File

@@ -14,9 +14,15 @@ import { DisplayOrderDTO, DisplayOrderItemDTO } from '@generated/swagger/oms-api
const prefix = '[DOMAIN-CHECKOUT]';
export const setShoppingCart = createAction(`${prefix} Set Shopping Cart`, props<{ processId: number; shoppingCart: ShoppingCartDTO }>());
export const setShoppingCart = createAction(
`${prefix} Set Shopping Cart`,
props<{ processId: number; shoppingCart: ShoppingCartDTO }>(),
);
export const setCheckout = createAction(`${prefix} Set Checkout`, props<{ processId: number; checkout: CheckoutDTO }>());
export const setCheckout = createAction(
`${prefix} Set Checkout`,
props<{ processId: number; checkout: CheckoutDTO }>(),
);
export const setNotificationChannels = createAction(
`${prefix} Set Notification Channel`,
@@ -45,7 +51,10 @@ export const setShippingAddress = createAction(
props<{ processId: number; shippingAddress: ShippingAddressDTO }>(),
);
export const removeCheckoutWithProcessId = createAction(`${prefix} Remove Checkout With Process Id`, props<{ processId: number }>());
export const removeCheckoutWithProcessId = createAction(
`${prefix} Remove Checkout With Process Id`,
props<{ processId: number }>(),
);
export const setOrders = createAction(`${prefix} Add Orders`, props<{ orders: DisplayOrderDTO[] }>());
@@ -57,11 +66,20 @@ export const setBuyer = createAction(`${prefix} Set Buyer`, props<{ processId: n
export const setPayer = createAction(`${prefix} Set Payer`, props<{ processId: number; payer: PayerDTO }>());
export const setSpecialComment = createAction(`${prefix} Set Agent Comment`, props<{ processId: number; agentComment: string }>());
export const setSpecialComment = createAction(
`${prefix} Set Agent Comment`,
props<{ processId: number; agentComment: string }>(),
);
export const setOlaError = createAction(`${prefix} Set Ola Error`, props<{ processId: number; olaErrorIds: number[] }>());
export const setOlaError = createAction(
`${prefix} Set Ola Error`,
props<{ processId: number; olaErrorIds: number[] }>(),
);
export const setCustomer = createAction(`${prefix} Set Customer`, props<{ processId: number; customer: CustomerDTO }>());
export const setCustomer = createAction(
`${prefix} Set Customer`,
props<{ processId: number; customer: CustomerDTO }>(),
);
export const addShoppingCartItemAvailabilityToHistory = createAction(
`${prefix} Add Shopping Cart Item Availability To History`,

View File

@@ -12,7 +12,9 @@ const _domainCheckoutReducer = createReducer(
const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
const addedShoppingCartItems =
shoppingCart?.items?.filter((item) => !entity.shoppingCart?.items?.find((i) => i.id === item.id))?.map((item) => item.data) ?? [];
shoppingCart?.items
?.filter((item) => !entity.shoppingCart?.items?.find((i) => i.id === item.id))
?.map((item) => item.data) ?? [];
entity.shoppingCart = shoppingCart;
@@ -118,27 +120,34 @@ const _domainCheckoutReducer = createReducer(
entity.customer = customer;
return storeCheckoutAdapter.setOne(entity, s);
}),
on(DomainCheckoutActions.addShoppingCartItemAvailabilityToHistory, (s, { processId, shoppingCartItemId, availability }) => {
const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
on(
DomainCheckoutActions.addShoppingCartItemAvailabilityToHistory,
(s, { processId, shoppingCartItemId, availability }) => {
const entity = getOrCreateCheckoutEntity({ processId, entities: s.entities });
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp ? { ...entity?.itemAvailabilityTimestamp } : {};
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp
? { ...entity?.itemAvailabilityTimestamp }
: {};
const item = entity?.shoppingCart?.items?.find((i) => i.id === shoppingCartItemId)?.data;
const item = entity?.shoppingCart?.items?.find((i) => i.id === shoppingCartItemId)?.data;
if (!item?.features?.orderType) return s;
if (!item?.features?.orderType) return s;
itemAvailabilityTimestamp[`${item.id}_${item?.features?.orderType}`] = Date.now();
itemAvailabilityTimestamp[`${item.id}_${item?.features?.orderType}`] = Date.now();
entity.itemAvailabilityTimestamp = itemAvailabilityTimestamp;
entity.itemAvailabilityTimestamp = itemAvailabilityTimestamp;
return storeCheckoutAdapter.setOne(entity, s);
}),
return storeCheckoutAdapter.setOne(entity, s);
},
),
on(
DomainCheckoutActions.addShoppingCartItemAvailabilityToHistoryByShoppingCartId,
(s, { shoppingCartId, shoppingCartItemId, availability }) => {
const entity = getCheckoutEntityByShoppingCartId({ shoppingCartId, entities: s.entities });
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp ? { ...entity?.itemAvailabilityTimestamp } : {};
const itemAvailabilityTimestamp = entity?.itemAvailabilityTimestamp
? { ...entity?.itemAvailabilityTimestamp }
: {};
const item = entity?.shoppingCart?.items?.find((i) => i.id === shoppingCartItemId)?.data;
@@ -157,7 +166,13 @@ export function domainCheckoutReducer(state, action) {
return _domainCheckoutReducer(state, action);
}
function getOrCreateCheckoutEntity({ entities, processId }: { entities: Dictionary<CheckoutEntity>; processId: number }): CheckoutEntity {
function getOrCreateCheckoutEntity({
entities,
processId,
}: {
entities: Dictionary<CheckoutEntity>;
processId: number;
}): CheckoutEntity {
let entity = entities[processId];
if (isNullOrUndefined(entity)) {

View File

@@ -23,7 +23,8 @@ export const selectCheckoutByProcessId = createSelector(
export const selectCustomerFeaturesByProcessId = createSelector(
selectEntities,
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) => getCusomterFeatures(entities[processId]?.customer),
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) =>
getCusomterFeatures(entities[processId]?.customer),
);
export const selectShippingAddressByProcessId = createSelector(
@@ -48,12 +49,14 @@ export const selectSpecialComment = createSelector(
export const selectNotificationChannels = createSelector(
selectEntities,
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) => entities[processId]?.notificationChannels,
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) =>
entities[processId]?.notificationChannels,
);
export const selectBuyerCommunicationDetails = createSelector(
selectEntities,
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) => entities[processId]?.buyer?.communicationDetails,
(entities: Dictionary<CheckoutEntity>, { processId }: { processId: number }) =>
entities[processId]?.buyer?.communicationDetails,
);
export const selectOrders = createSelector(storeFeatureSelector, (s) => s.orders);

View File

@@ -226,7 +226,13 @@ export class CrmCustomerService {
}
async updateToOnlineCustomer(customer: CustomerDTO): Promise<Result<CustomerDTO>> {
const payload: CustomerDTO = { shippingAddresses: [], payers: [], ...customer, customerType: 8, hasOnlineAccount: true };
const payload: CustomerDTO = {
shippingAddresses: [],
payers: [],
...customer,
customerType: 8,
hasOnlineAccount: true,
};
const notificationChannels = this.getNotificationChannelForCommunicationDetails({
communicationDetails: payload?.communicationDetails,
@@ -466,21 +472,30 @@ export class CrmCustomerService {
return this.loyaltyCardService.LoyaltyCardCheckLoyaltyCard({ loyaltyCardNumber, customerId });
}
createPayer(customerId: number, payer: PayerDTO, isDefault?: boolean): Promise<[Result<PayerDTO>, Result<AssignedPayerDTO>]> {
createPayer(
customerId: number,
payer: PayerDTO,
isDefault?: boolean,
): Promise<[Result<PayerDTO>, Result<AssignedPayerDTO>]> {
return this.getCustomer(customerId)
.pipe(
mergeMap((customerResponse) =>
this.payerService
.PayerCreatePayer({ ...payer, payerType: customerResponse.result.customerType })
.pipe(
mergeMap((payerResponse) =>
this.customerService
.CustomerAddPayerReference({ customerId: customerId, payerId: payerResponse.result.id, isDefault: isDefault })
.pipe(
map((assigendPayerResponse) => [payerResponse, assigendPayerResponse] as [Result<PayerDTO>, Result<AssignedPayerDTO>]),
this.payerService.PayerCreatePayer({ ...payer, payerType: customerResponse.result.customerType }).pipe(
mergeMap((payerResponse) =>
this.customerService
.CustomerAddPayerReference({
customerId: customerId,
payerId: payerResponse.result.id,
isDefault: isDefault,
})
.pipe(
map(
(assigendPayerResponse) =>
[payerResponse, assigendPayerResponse] as [Result<PayerDTO>, Result<AssignedPayerDTO>],
),
),
),
),
),
),
)
.toPromise();
@@ -496,7 +511,11 @@ export class CrmCustomerService {
return this.customerService.CustomerModifyPayerReference({ payerId, customerId, isDefault });
}
createShippingAddress(customerId: number, shippingAddress: ShippingAddressDTO, isDefault?: boolean): Promise<Result<ShippingAddressDTO>> {
createShippingAddress(
customerId: number,
shippingAddress: ShippingAddressDTO,
isDefault?: boolean,
): Promise<Result<ShippingAddressDTO>> {
const data: ShippingAddressDTO = { ...shippingAddress };
if (isDefault) {
data.isDefault = new Date().toJSON();
@@ -504,7 +523,9 @@ export class CrmCustomerService {
delete data.isDefault;
}
return this.shippingAddressService.ShippingAddressCreateShippingAddress({ customerId, shippingAddress: data }).toPromise();
return this.shippingAddressService
.ShippingAddressCreateShippingAddress({ customerId, shippingAddress: data })
.toPromise();
}
updateShippingAddress(
@@ -530,7 +551,9 @@ export class CrmCustomerService {
return this.shippingAddressService.ShippingAddressGetShippingaddress(shippingAddressId);
}
getShippingAddresses(params: ShippingAddressService.ShippingAddressGetShippingAddressesParams): Observable<Result<ShippingAddressDTO[]>> {
getShippingAddresses(
params: ShippingAddressService.ShippingAddressGetShippingAddressesParams,
): Observable<Result<ShippingAddressDTO[]>> {
return this.shippingAddressService.ShippingAddressGetShippingAddresses(params);
}

View File

@@ -3,7 +3,12 @@ import { AddressHelper } from './address.helper';
describe('AddressHelper', () => {
describe('hasRequiredProperties', () => {
it('should return true', () => {
const result = AddressHelper.hasRequiredProperties({ city: 'Teststadt', street: 'Teststr.', zipCode: '12345', country: 'DEU' });
const result = AddressHelper.hasRequiredProperties({
city: 'Teststadt',
street: 'Teststr.',
zipCode: '12345',
country: 'DEU',
});
expect(result).toBeTruthy();
});

View File

@@ -9,7 +9,11 @@ describe('ShippingAddressHelper', () => {
});
it('should return the latest default shippingAdress', () => {
const shippingAdress: ShippingAddressDTO[] = [{ isDefault: new Date().toJSON() }, { isDefault: new Date(2020, 5, 15).toJSON() }, {}];
const shippingAdress: ShippingAddressDTO[] = [
{ isDefault: new Date().toJSON() },
{ isDefault: new Date(2020, 5, 15).toJSON() },
{},
];
expect(ShippingAddressHelper.getDefaultShippingAddress(shippingAdress)).toEqual(shippingAdress[0]);
});
});

View File

@@ -21,7 +21,9 @@ export class PrintShippingNoteActionHandler extends ActionHandler<OrderItemsCont
async printShippingNoteHelper(printer: string, receipts: ReceiptDTO[]) {
try {
for (const group of groupBy(receipts, (receipt) => receipt?.buyer?.buyerNumber)) {
await this.domainPrinterService.printShippingNote({ printer, receipts: group?.items?.map((r) => r?.id) }).toPromise();
await this.domainPrinterService
.printShippingNote({ printer, receipts: group?.items?.map((r) => r?.id) })
.toPromise();
}
return {
error: false,

View File

@@ -21,7 +21,10 @@ export class PrintSmallamountinvoiceActionHandler extends ActionHandler<OrderIte
super('PRINT_SMALLAMOUNTINVOICE');
}
private _printKleinbetragsrechnungHelper(printer: string, receiptGroup: Group<string, ReceiptDTO>): Promise<ResponseArgs> {
private _printKleinbetragsrechnungHelper(
printer: string,
receiptGroup: Group<string, ReceiptDTO>,
): Promise<ResponseArgs> {
return firstValueFrom(
this.omsPrintService.OMSPrintKleinbetragsrechnung({
data: receiptGroup?.items?.map((r) => r?.id),

View File

@@ -33,7 +33,10 @@ export class ShopWithKulturpassActionHandler extends ActionHandler<OrderItemsCon
command = result.data[1];
if (displayOrder) {
const subsetItems = displayOrder.items.reduce((acc, item) => [...acc, ...item.subsetItems], [] as DisplayOrderItemSubsetDTO[]);
const subsetItems = displayOrder.items.reduce(
(acc, item) => [...acc, ...item.subsetItems],
[] as DisplayOrderItemSubsetDTO[],
);
const orderItems = await this.getItems(displayOrder.orderNumber);

View File

@@ -48,10 +48,14 @@ export class DomainOmsService {
}
getHistory(orderItemSubsetId: number): Observable<HistoryDTO[]> {
return this.orderService.OrderGetOrderItemStatusHistory({ orderItemSubsetId }).pipe(map((response) => response.result));
return this.orderService
.OrderGetOrderItemStatusHistory({ orderItemSubsetId })
.pipe(map((response) => response.result));
}
getReceipts(orderItemSubsetIds: number[]): Observable<ValueTupleOfLongAndReceiptTypeAndEntityDTOContainerOfReceiptDTO[]> {
getReceipts(
orderItemSubsetIds: number[],
): Observable<ValueTupleOfLongAndReceiptTypeAndEntityDTOContainerOfReceiptDTO[]> {
return this.receiptService
.ReceiptGetReceiptsByOrderItemSubset({
payload: {
@@ -133,14 +137,20 @@ export class DomainOmsService {
.pipe(map((o) => o.result));
}
setEstimatedShippingDate(orderId: number, orderItemId: number, orderItemSubsetId: number, estimatedShippingDate: Date | string) {
setEstimatedShippingDate(
orderId: number,
orderItemId: number,
orderItemSubsetId: number,
estimatedShippingDate: Date | string,
) {
return this.orderService
.OrderPatchOrderItemSubset({
orderId,
orderItemId,
orderItemSubsetId,
orderItemSubset: {
estimatedShippingDate: estimatedShippingDate instanceof Date ? estimatedShippingDate.toJSON() : estimatedShippingDate,
estimatedShippingDate:
estimatedShippingDate instanceof Date ? estimatedShippingDate.toJSON() : estimatedShippingDate,
},
})
.pipe(map((response) => response.result));
@@ -171,7 +181,15 @@ export class DomainOmsService {
return this.orderService.OrderChangeStockStatusCode(payload).pipe(map((response) => response.result));
}
orderAtSupplier({ orderId, orderItemId, orderItemSubsetId }: { orderId: number; orderItemId: number; orderItemSubsetId: number }) {
orderAtSupplier({
orderId,
orderItemId,
orderItemSubsetId,
}: {
orderId: number;
orderItemId: number;
orderItemSubsetId: number;
}) {
return this._orderCheckoutService.OrderCheckoutOrderSubsetItemAtSupplier({
orderId,
orderItemId,
@@ -273,7 +291,14 @@ export class DomainOmsService {
skip?: number;
}): Observable<Record<string, Date[]>> {
return this.orderService
.OrderGetOrderItemSubsetTasks({ orderId, orderItemId, orderItemSubsetId, completed: new Date(0).toISOString(), take, skip })
.OrderGetOrderItemSubsetTasks({
orderId,
orderItemId,
orderItemSubsetId,
completed: new Date(0).toISOString(),
take,
skip,
})
.pipe(
map((res) =>
res.result

View File

@@ -54,7 +54,9 @@ export class PickupShelfInService extends PickupShelfIOService {
});
}
getOrderItemsByCustomerNumber(args: { customerNumber: string }): Observable<ListResponseArgsOfDBHOrderItemListItemDTO> {
getOrderItemsByCustomerNumber(args: {
customerNumber: string;
}): Observable<ListResponseArgsOfDBHOrderItemListItemDTO> {
return this._abholfachService.AbholfachWareneingang({
filter: { orderitemprocessingstatus: '16;128;8192;1048576' },
input: {

View File

@@ -25,5 +25,7 @@ export abstract class PickupShelfIOService {
filter?: Filter;
}): Observable<ListResponseArgsOfDBHOrderItemListItemDTO>;
abstract getOrderItemsByCustomerNumber(args: { customerNumber: string }): Observable<ListResponseArgsOfDBHOrderItemListItemDTO>;
abstract getOrderItemsByCustomerNumber(args: {
customerNumber: string;
}): Observable<ListResponseArgsOfDBHOrderItemListItemDTO>;
}

View File

@@ -55,7 +55,9 @@ export class PickupShelfOutService extends PickupShelfIOService {
});
}
getOrderItemsByCustomerNumber(args: { customerNumber: string }): Observable<ListResponseArgsOfDBHOrderItemListItemDTO> {
getOrderItemsByCustomerNumber(args: {
customerNumber: string;
}): Observable<ListResponseArgsOfDBHOrderItemListItemDTO> {
throw new Error('Method not implemented.');
}
}

View File

@@ -50,7 +50,11 @@ export class DomainPrinterService {
}
if (response.error) {
return {
error: response.message ? response.message : response.error.message ? response.error.message : 'Ein Fehler ist aufgetreten',
error: response.message
? response.message
: response.error.message
? response.error.message
: 'Ein Fehler ist aufgetreten',
};
}
@@ -81,7 +85,11 @@ export class DomainPrinterService {
}
if (response.error) {
return {
error: response.message ? response.message : response.error.message ? response.error.message : 'Ein Fehler ist aufgetreten',
error: response.message
? response.message
: response.error.message
? response.error.message
: 'Ein Fehler ist aufgetreten',
};
}
@@ -112,7 +120,11 @@ export class DomainPrinterService {
}
if (response.error) {
return {
error: response.message ? response.message : response.error.message ? response.error.message : 'Ein Fehler ist aufgetreten',
error: response.message
? response.message
: response.error.message
? response.error.message
: 'Ein Fehler ist aufgetreten',
};
}
@@ -208,7 +220,9 @@ export class DomainPrinterService {
});
}
printProductListItemsResponse(payload: DocumentPayloadOfIEnumerableOfProductListItemDTO): Observable<ResponseArgsOfString> {
printProductListItemsResponse(
payload: DocumentPayloadOfIEnumerableOfProductListItemDTO,
): Observable<ResponseArgsOfString> {
return this._productListService.ProductListProductListItemPdfAsBase64(payload);
}
@@ -254,7 +268,15 @@ export class DomainPrinterService {
);
}
printDisplayInfoDTOList({ displayInfos, printer, title }: { displayInfos: DisplayInfoDTO[]; printer: string; title?: string }) {
printDisplayInfoDTOList({
displayInfos,
printer,
title,
}: {
displayInfos: DisplayInfoDTO[];
printer: string;
title?: string;
}) {
return this.eisPublicDocumentService
.EISPublicDocumentGetInfosPdfAsBase64({
payload: { data: displayInfos, title },

View File

@@ -1,7 +1,13 @@
import { Logger } from '@core/logger';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator';
import { SearchService } from '@generated/swagger/cat-search-api';
import { PackageService, RemiService, ReturnService, StockService, SupplierService } from '@generated/swagger/inventory-api';
import {
PackageService,
RemiService,
ReturnService,
StockService,
SupplierService,
} from '@generated/swagger/inventory-api';
import { DomainRemissionService } from './remission.service';
import { DateAdapter } from '@ui/common';
@@ -9,7 +15,16 @@ describe('DomainRemissionService', () => {
let service: SpectatorService<DomainRemissionService>;
const createService = createServiceFactory({
service: DomainRemissionService,
mocks: [RemiService, StockService, SupplierService, PackageService, ReturnService, SearchService, Logger, DateAdapter],
mocks: [
RemiService,
StockService,
SupplierService,
PackageService,
ReturnService,
SearchService,
Logger,
DateAdapter,
],
});
beforeEach(() => {

View File

@@ -174,7 +174,9 @@ export class DomainRemissionService {
);
}
getItemsForPflichtremission(arg: { queryToken: RemiQueryTokenDTO }): Observable<{ hits: number; result: RemissionListItem[] }> {
getItemsForPflichtremission(arg: {
queryToken: RemiQueryTokenDTO;
}): Observable<{ hits: number; result: RemissionListItem[] }> {
return this._remiService
.RemiPflichtremissionsartikel({
queryToken: arg.queryToken,
@@ -187,7 +189,9 @@ export class DomainRemissionService {
);
}
getItemsForAbteilungsremission(arg: { queryToken: RemiQueryTokenDTO }): Observable<{ hits: number; result: RemissionListItem[] }> {
getItemsForAbteilungsremission(arg: {
queryToken: RemiQueryTokenDTO;
}): Observable<{ hits: number; result: RemissionListItem[] }> {
return this._remiService
.RemiUeberlauf({
queryToken: arg.queryToken,
@@ -213,7 +217,9 @@ export class DomainRemissionService {
.pipe(
map((res) => {
const o = items.map((item) => {
const stockInfo = res?.result?.find((stockInfo) => stockInfo.itemId === +item.dto.product.catalogProductNumber);
const stockInfo = res?.result?.find(
(stockInfo) => stockInfo.itemId === +item.dto.product.catalogProductNumber,
);
if (!stockInfo) {
const defaultStockData = {
@@ -423,7 +429,15 @@ export class DomainRemissionService {
return this._returnService.ReturnDeleteReturnItem({ itemId });
}
removeReturnItemFromReceipt({ returnId, receiptId, receiptItemId }: { returnId: number; receiptId: number; receiptItemId: number }) {
removeReturnItemFromReceipt({
returnId,
receiptId,
receiptItemId,
}: {
returnId: number;
receiptId: number;
receiptItemId: number;
}) {
return this._returnService.ReturnRemoveReturnItem({ returnId, receiptItemId, receiptId });
}

View File

@@ -1,3 +1,10 @@
export type ProcessingStatusType = 'Approved' | 'InProcess' | 'Completed' | 'Overdue' | 'Archived' | 'Uncompleted' | 'Removed';
export type ProcessingStatusType =
| 'Approved'
| 'InProcess'
| 'Completed'
| 'Overdue'
| 'Archived'
| 'Uncompleted'
| 'Removed';
export type ProcessingStatusList = ProcessingStatusType[];

View File

@@ -75,7 +75,8 @@ export class NativeContainerService {
}
if (this.windowRef.nativeWindow['isRunningNative'] === undefined) {
this.windowRef.nativeWindow['isRunningNative'] = (_) => window.postMessage({ status: 'INIT', data: 'Is a WebView' }, '*');
this.windowRef.nativeWindow['isRunningNative'] = (_) =>
window.postMessage({ status: 'INIT', data: 'Is a WebView' }, '*');
}
// Try sending ping request, to invoke the containers isRunningNative event

View File

@@ -27,7 +27,9 @@ export class AddressSelectionModalService {
.toPromise();
if (addresses?.length > 0) {
const modalResult = await this.modal.open({ content: AddressSelectionModalComponent, data: addresses }).afterClosed$.toPromise();
const modalResult = await this.modal
.open({ content: AddressSelectionModalComponent, data: addresses })
.afterClosed$.toPromise();
if (modalResult?.data) {
if (modalResult.data === 'continue') {
return address;

View File

@@ -16,7 +16,10 @@
</ui-searchbox>
<p class="subtitle">
<span class="bold">{{ item.product?.name }}</span> ist in den <span class="bold">Umkreisfilialen</span> folgendermaßen verfügbar:
<span class="bold">{{ item.product?.name }}</span>
ist in den
<span class="bold">Umkreisfilialen</span>
folgendermaßen verfügbar:
</p>
<hr />

View File

@@ -46,7 +46,9 @@ export class ModalAvailabilitiesComponent {
branch?.id !== userbranch?.id &&
branch?.branchType === 1,
)
.filter((b) => b.name?.toLowerCase()?.indexOf(search?.toLowerCase()) > -1 || b.address?.zipCode.indexOf(search) > -1)
.filter(
(b) => b.name?.toLowerCase()?.indexOf(search?.toLowerCase()) > -1 || b.address?.zipCode.indexOf(search) > -1,
)
.sort((a, b) =>
this.branchSorterFn(
a,

View File

@@ -9,5 +9,5 @@
<strong>{{ customerNumber }}</strong>
</div>
</div>
<shared-history-list [history]="history"> </shared-history-list>
<shared-history-list [history]="history"></shared-history-list>
</div>

View File

@@ -36,7 +36,9 @@ export class KulturpassOrderItemStore extends ComponentStore<KulturpassOrderItem
readonly itemQuantity$ = this.select((state) => state.item?.quantity ?? 0);
readonly availability$ = this.item$.pipe(switchMap((item) => this._parentStore.getAvailability$(getCatalogProductNumber(item))));
readonly availability$ = this.item$.pipe(
switchMap((item) => this._parentStore.getAvailability$(getCatalogProductNumber(item))),
);
readonly availableQuantity$ = this.availability$.pipe(map((availability) => availability?.inStock ?? 0));

View File

@@ -22,7 +22,8 @@
<div class="overflow-y-auto -mx-4 scroll-bar">
<div *ngIf="emptyShoppingCart$ | async" class="h-full grid items-center justify-center">
<h3 class="text-xl font-bold text-center text-gray-500">
Warenkorb ist leer, bitte suchen oder scannen <br />
Warenkorb ist leer, bitte suchen oder scannen
<br />
Sie Artikel um den Warenkob zu füllen.
</h3>
</div>
@@ -30,8 +31,7 @@
class="border-b border-solid border-[#EFF1F5]"
*ngFor="let item of items$ | async; trackBy: trackItemById"
[item]="item"
>
</shared-kulturpass-order-item>
></shared-kulturpass-order-item>
</div>
<div class="flex flex-row justify-evenly items-stretch border-t border-solid border-[#EFF1F5] py-3 px-4 -mx-4">
<div class="grid grid-flow-row text-xl">
@@ -56,7 +56,7 @@
[disabled]="orderButtonDisabled$ | async"
(click)="order()"
>
<shared-loader [loading]="ordering$ | async" hideContent="true"> Kauf abschließen und Rechnung drucken </shared-loader>
<shared-loader [loading]="ordering$ | async" hideContent="true">Kauf abschließen und Rechnung drucken</shared-loader>
</button>
</div>
</div>

View File

@@ -19,7 +19,13 @@ import { getCatalogProductNumber } from './catalog-product-number';
styleUrls: ['kulturpass-order-modal.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'shared-kulturpass-order-modal' },
imports: [KulturpassOrderSearchboxComponent, CommonModule, BranchNamePipe, KulturpassOrderItemComponent, LoaderComponent],
imports: [
KulturpassOrderSearchboxComponent,
CommonModule,
BranchNamePipe,
KulturpassOrderItemComponent,
LoaderComponent,
],
providers: [provideComponentStore(KulturpassOrderModalStore)],
})
export class KulturpassOrderModalComponent implements OnInit {
@@ -33,7 +39,9 @@ export class KulturpassOrderModalComponent implements OnInit {
kulturpassCode$ = this._store.orderItemListItem$.pipe(map((orderItemListItem) => orderItemListItem.buyerNumber));
credit$ = this._store.orderItemListItem$.pipe(map((orderItemListItem) => orderItemListItem?.retailPrice?.value?.value ?? 0));
credit$ = this._store.orderItemListItem$.pipe(
map((orderItemListItem) => orderItemListItem?.retailPrice?.value?.value ?? 0),
);
total$ = this._store.shoppingCart$.pipe(map((shoppingCart) => shoppingCart?.total?.value ?? 0));

View File

@@ -93,12 +93,19 @@ export class KulturpassOrderModalStore extends ComponentStore<KulturpassOrderMod
readonly fetchShoppingCart$ = this.select((state) => state.fetchShoppingCart);
readonly updateFetchShoppingCart = this.updater((state, fetchShoppingCart: boolean) => ({ ...state, fetchShoppingCart }));
readonly updateFetchShoppingCart = this.updater((state, fetchShoppingCart: boolean) => ({
...state,
fetchShoppingCart,
}));
readonly ordering$ = this.select((state) => state.ordering);
loadBranch = this.effect(($) =>
$.pipe(switchMap(() => this._branchService.BranchGetBranches({}).pipe(tapResponse(this.handleBranchResponse, this.handleBranchError)))),
$.pipe(
switchMap(() =>
this._branchService.BranchGetBranches({}).pipe(tapResponse(this.handleBranchResponse, this.handleBranchError)),
),
),
);
handleBranchResponse = (res: ResponseArgsOfIEnumerableOfBranchDTO) => {
@@ -193,7 +200,9 @@ export class KulturpassOrderModalStore extends ComponentStore<KulturpassOrderMod
),
);
handleOrderResponse = (res: ResponseArgsOfValueTupleOfIEnumerableOfDisplayOrderDTOAndIEnumerableOfKeyValueDTOOfStringAndString) => {
handleOrderResponse = (
res: ResponseArgsOfValueTupleOfIEnumerableOfDisplayOrderDTOAndIEnumerableOfKeyValueDTOOfStringAndString,
) => {
this.onOrderSuccess(res.result.item1[0], res.result.item2);
};
@@ -205,7 +214,10 @@ export class KulturpassOrderModalStore extends ComponentStore<KulturpassOrderMod
};
itemQuantityByCatalogProductNumber(catalogProductNumber: string) {
return this.shoppingCart?.items?.find((i) => getCatalogProductNumber(i?.data) === catalogProductNumber)?.data?.quantity ?? 0;
return (
this.shoppingCart?.items?.find((i) => getCatalogProductNumber(i?.data) === catalogProductNumber)?.data
?.quantity ?? 0
);
}
canAddItem = this.effect((item$: Observable<ItemDTO>) =>
@@ -285,7 +297,8 @@ export class KulturpassOrderModalStore extends ComponentStore<KulturpassOrderMod
}
// Preis und priceMaintained werden immer erst vom Katalog genommen. Bei nicht Verfügbarkeit greifen die anderen Availabilities
const offlinePrice = item?.catalogAvailability?.price?.value?.value ?? takeAwayAvailability?.price?.value?.value ?? -1;
const offlinePrice =
item?.catalogAvailability?.price?.value?.value ?? takeAwayAvailability?.price?.value?.value ?? -1;
const availability = takeAwayAvailability;
availability.price = item?.catalogAvailability?.price ?? takeAwayAvailability?.price;

View File

@@ -8,5 +8,4 @@
(search)="search($event)"
(scan)="search($event)"
[hint]="hint$ | async"
>
</ui-searchbox>
></ui-searchbox>

View File

@@ -19,7 +19,10 @@ export interface KulturpassOrderSearchboxState {
}
@Injectable()
export class KulturpassOrderSearchboxStore extends ComponentStore<KulturpassOrderSearchboxState> implements OnStoreInit {
export class KulturpassOrderSearchboxStore
extends ComponentStore<KulturpassOrderSearchboxState>
implements OnStoreInit
{
private _parentStore = inject(KulturpassOrderModalStore);
private _catalogService = inject(DomainCatalogService);
private _availabilityService = inject(DomainAvailabilityService);
@@ -63,7 +66,11 @@ export class KulturpassOrderSearchboxStore extends ComponentStore<KulturpassOrde
loadBranch = this.effect(($) =>
$.pipe(
switchMap(() => this._availabilityService.getDefaultBranch().pipe(tapResponse(this.handleBranchResponse, this.handleBranchError))),
switchMap(() =>
this._availabilityService
.getDefaultBranch()
.pipe(tapResponse(this.handleBranchResponse, this.handleBranchError)),
),
),
);
@@ -80,7 +87,9 @@ export class KulturpassOrderSearchboxStore extends ComponentStore<KulturpassOrde
tap(() => this.patchState({ fetching: true })),
withLatestFrom(this.query$),
switchMap(([_, query]) =>
this._catalogService.getDetailsByEan({ ean: query?.trim() }).pipe(tapResponse(this.handleSearchResponse, this.handleSearchError)),
this._catalogService
.getDetailsByEan({ ean: query?.trim() })
.pipe(tapResponse(this.handleSearchResponse, this.handleSearchError)),
),
),
);

View File

@@ -6,5 +6,5 @@
</div>
<div class="actions">
<a class="cta-primary" [routerLink]="['/filiale/remission/create']" (click)="navigated.emit()"> Zur Remission </a>
<a class="cta-primary" [routerLink]="['/filiale/remission/create']" (click)="navigated.emit()">Zur Remission</a>
</div>

View File

@@ -6,5 +6,5 @@
</div>
<div class="actions">
<a class="cta-primary" [routerLink]="['/filiale/goods/in', 'reservation']" (click)="navigated.emit()"> Zu den Reservierungen </a>
<a class="cta-primary" [routerLink]="['/filiale/goods/in', 'reservation']" (click)="navigated.emit()">Zu den Reservierungen</a>
</div>

View File

@@ -6,5 +6,5 @@
</div>
<div class="actions">
<a class="cta-primary" [routerLink]="['/filiale/task-calendar/calendar']" (click)="navigated.emit()"> Zum Tätigkeitskalender </a>
<a class="cta-primary" [routerLink]="['/filiale/task-calendar/calendar']" (click)="navigated.emit()">Zum Tätigkeitskalender</a>
</div>

View File

@@ -33,7 +33,6 @@
*ngSwitchCase="'Wareneingang Lagerware'"
[notifications]="notifications[selectedArea]"
(navigated)="close()"
>
</modal-notifications-package-inspection-group>
></modal-notifications-package-inspection-group>
</ng-container>
</ng-container>

View File

@@ -1,7 +1,14 @@
import { ItemType, PriceDTO, PriceValueDTO, VATValueDTO } from '@generated/swagger/checkout-api';
import { OrderType, PurchaseOption } from './store';
export const PURCHASE_OPTIONS: PurchaseOption[] = ['in-store', 'pickup', 'delivery', 'dig-delivery', 'b2b-delivery', 'download'];
export const PURCHASE_OPTIONS: PurchaseOption[] = [
'in-store',
'pickup',
'delivery',
'dig-delivery',
'b2b-delivery',
'download',
];
export const DELIVERY_PURCHASE_OPTIONS: PurchaseOption[] = ['delivery', 'dig-delivery', 'b2b-delivery'];

View File

@@ -15,7 +15,7 @@
@apply transition-all;
@apply duration-200;
@apply ease-in-out;
content: '';
content: "";
top: 0;
left: 0;
right: 0;
@@ -31,7 +31,7 @@
}
.fancy-checkbox::after {
content: '';
content: "";
background-image: url("data:image/svg+xml,%3Csvg width='100%25' height='100%25' viewBox='0 0 24 24' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xml:space='preserve' xmlns:serif='http://www.serif.com/'%3E%3Cpath fill='white' d='M21.432,3.715C21.432,3.715 21.432,3.715 21.432,3.715C21.115,3.76 20.823,3.911 20.604,4.143C16.03,8.727 12.603,12.511 8.244,16.932C8.244,16.932 3.297,12.754 3.297,12.754C2.909,12.424 2.374,12.327 1.895,12.499C1.895,12.499 1.895,12.499 1.895,12.499C1.415,12.672 1.065,13.088 0.975,13.589C0.885,14.091 1.072,14.602 1.463,14.929L7.415,19.966C7.981,20.441 8.818,20.403 9.338,19.877C14.251,14.954 17.761,11.007 22.616,6.141C23.057,5.714 23.172,5.051 22.903,4.499C22.903,4.499 22.903,4.499 22.903,4.499C22.633,3.948 22.04,3.631 21.432,3.715Z'/%3E%3C/svg%3E%0A");
@apply absolute;
top: 0.4rem;

View File

@@ -72,8 +72,8 @@
<ng-container *ngSwitchCase="'in-store'">
<shared-icon icon="isa-shopping-bag" [size]="18"></shared-icon>
{{ availability.data.inStock }}x
<ng-container *ngIf="isEVT; else noEVT"> ab {{ isEVT | date: 'dd. MMMM yyyy' }}</ng-container>
<ng-template #noEVT> ab sofort</ng-template>
<ng-container *ngIf="isEVT; else noEVT">ab {{ isEVT | date: 'dd. MMMM yyyy' }}</ng-container>
<ng-template #noEVT>ab sofort</ng-template>
</ng-container>
<ng-container *ngSwitchCase="'download'">
<shared-icon icon="isa-download" [size]="22"></shared-icon>
@@ -123,7 +123,8 @@
</shared-input-control>
<ui-tooltip [warning]="true" xPosition="after" yPosition="below" [xOffset]="-55" [yOffset]="18" [closeable]="true" #giftCardTooltip>
Tragen Sie hier den <br />
Tragen Sie hier den
<br />
Gutscheinbetrag ein.
</ui-tooltip>
</div>
@@ -131,7 +132,7 @@
{{ priceValue$ | async | currency: 'EUR' : 'code' }}
</ng-template>
</div>
<ui-quantity-dropdown class="mt-2" [formControl]="quantityFormControl" [range]="maxSelectableQuantity$ | async"> </ui-quantity-dropdown>
<ui-quantity-dropdown class="mt-2" [formControl]="quantityFormControl" [range]="maxSelectableQuantity$ | async"></ui-quantity-dropdown>
<div class="pt-7">
<input
*ngIf="(canAddResult$ | async)?.canAdd"
@@ -151,7 +152,7 @@
<span *ngIf="showMaxAvailableQuantity$ | async" class="font-bold text-[#BE8100] mt-[14px]">
{{ (availability$ | async)?.inStock }} Exemplare sofort lieferbar
</span>
<span *ngIf="showNotAvailable$ | async" class="font-bold text-[#BE8100] mt-[14px]"> Derzeit nicht bestellbar </span>
<span *ngIf="showNotAvailable$ | async" class="font-bold text-[#BE8100] mt-[14px]">Derzeit nicht bestellbar</span>
</div>
</div>
<div class="flex flex-row">

View File

@@ -3,14 +3,14 @@
<div class="rounded p-4 shadow-card mt-4 grid grid-flow-col gap-4 justify-center items-center relative">
<ng-container *ngIf="!(isDownloadOnly$ | async)">
<ng-container *ngIf="!(isGiftCardOnly$ | async)">
<app-in-store-purchase-options-tile *ngIf="showOption('in-store')"> </app-in-store-purchase-options-tile>
<app-in-store-purchase-options-tile *ngIf="showOption('in-store')"></app-in-store-purchase-options-tile>
<app-pickup-purchase-options-tile *ngIf="showOption('pickup')"></app-pickup-purchase-options-tile>
</ng-container>
<app-delivery-purchase-options-tile *ngIf="showOption('delivery')"></app-delivery-purchase-options-tile>
</ng-container>
<ng-container *ngIf="hasDownload$ | async">
<app-download-purchase-options-tile *ngIf="showOption('download')"> </app-download-purchase-options-tile>
<app-download-purchase-options-tile *ngIf="showOption('download')"></app-download-purchase-options-tile>
</ng-container>
</div>
<shared-purchase-options-list-header></shared-purchase-options-list-header>

View File

@@ -48,8 +48,14 @@
@apply rounded;
}
::ng-deep app-pickup-purchase-options-tile shared-branch-selector.shared-branch-selector-opend .shared-branch-selector-input-container,
::ng-deep app-in-store-purchase-options-tile shared-branch-selector.shared-branch-selector-opend .shared-branch-selector-input-container {
::ng-deep
app-pickup-purchase-options-tile
shared-branch-selector.shared-branch-selector-opend
.shared-branch-selector-input-container,
::ng-deep
app-in-store-purchase-options-tile
shared-branch-selector.shared-branch-selector-opend
.shared-branch-selector-input-container {
@apply shadow-card;
}

View File

@@ -2,7 +2,14 @@ import { PriceDTO } from '@generated/swagger/availability-api';
import { ItemDTO } from '@generated/swagger/cat-search-api';
import { AvailabilityDTO, OLAAvailabilityDTO, ShoppingCartItemDTO } from '@generated/swagger/checkout-api';
import { GIFT_CARD_TYPE } from '../constants';
import { ActionType, Item, ItemData, ItemPayloadWithSourceId, OrderType, PurchaseOption } from './purchase-options.types';
import {
ActionType,
Item,
ItemData,
ItemPayloadWithSourceId,
OrderType,
PurchaseOption,
} from './purchase-options.types';
export function isItemDTO(item: any, type: ActionType): item is ItemDTO {
return type === 'add';

View File

@@ -1,8 +1,22 @@
import { PriceDTO, PriceValueDTO } from '@generated/swagger/checkout-api';
import { DEFAULT_PRICE_DTO, DEFAULT_PRICE_VALUE, GIFT_CARD_MAX_PRICE, GIFT_CARD_TYPE, PURCHASE_OPTIONS } from '../constants';
import {
DEFAULT_PRICE_DTO,
DEFAULT_PRICE_VALUE,
GIFT_CARD_MAX_PRICE,
GIFT_CARD_TYPE,
PURCHASE_OPTIONS,
} from '../constants';
import { isArchive, isGiftCard, isItemDTO } from './purchase-options.helpers';
import { PurchaseOptionsState } from './purchase-options.state';
import { ActionType, Availability, Branch, CanAdd, FetchingAvailability, Item, PurchaseOption } from './purchase-options.types';
import {
ActionType,
Availability,
Branch,
CanAdd,
FetchingAvailability,
Item,
PurchaseOption,
} from './purchase-options.types';
export function getType(state: PurchaseOptionsState): ActionType {
return state.type;
@@ -108,13 +122,17 @@ export function getPurchaseOptionsInAvailabilities(state: PurchaseOptionsState):
purchaseOptions = Array.from(new Set(purchaseOptions));
// if 'delivery' is not present but 'dig-delivery' or 'b2b-delivery' is present, add 'delivery' to the list
if (!purchaseOptions.includes('delivery') && (purchaseOptions.includes('dig-delivery') || purchaseOptions.includes('b2b-delivery'))) {
if (
!purchaseOptions.includes('delivery') &&
(purchaseOptions.includes('dig-delivery') || purchaseOptions.includes('b2b-delivery'))
) {
purchaseOptions.push('delivery');
}
// if remove 'dig-delivery' and 'b2b-delivery' and 'catalog' as 'catalog' is not a purchase option but is needed for other data (Needed for #4813 and Bugfix for #4710)
purchaseOptions = purchaseOptions.filter(
(purchaseOption) => purchaseOption !== 'dig-delivery' && purchaseOption !== 'b2b-delivery' && purchaseOption !== 'catalog',
(purchaseOption) =>
purchaseOption !== 'dig-delivery' && purchaseOption !== 'b2b-delivery' && purchaseOption !== 'catalog',
);
return purchaseOptions.sort((a, b) => PURCHASE_OPTIONS.indexOf(a) - PURCHASE_OPTIONS.indexOf(b));
@@ -124,14 +142,18 @@ export function getFetchingAvailabilities(state: PurchaseOptionsState): Array<Fe
return state.fetchingAvailabilities;
}
export function getFetchingAvailabilitiesForItem(itemId: number): (state: PurchaseOptionsState) => Array<FetchingAvailability> {
export function getFetchingAvailabilitiesForItem(
itemId: number,
): (state: PurchaseOptionsState) => Array<FetchingAvailability> {
return (state: PurchaseOptionsState) => {
const fetchingAvailabilities = getFetchingAvailabilities(state);
return fetchingAvailabilities.filter((fa) => fa.itemId === itemId);
};
}
export function getItemsThatHaveAnAvailabilityForPurchaseOption(purchaseOption: PurchaseOption): (state: PurchaseOptionsState) => Item[] {
export function getItemsThatHaveAnAvailabilityForPurchaseOption(
purchaseOption: PurchaseOption,
): (state: PurchaseOptionsState) => Item[] {
return (state) => {
const availabilities = getAvailabilities(state);
const items = getItems(state);
@@ -159,7 +181,9 @@ export function getItemsThatHaveAnAvailabilityAndCanAddForPurchaseOption(purchas
const canAddResults = getCanAddResults(state);
return items.filter((item) =>
canAddResults.some((canAdd) => canAdd.itemId === item.id && canAdd.purchaseOption === purchaseOption && canAdd.canAdd),
canAddResults.some(
(canAdd) => canAdd.itemId === item.id && canAdd.purchaseOption === purchaseOption && canAdd.canAdd,
),
);
};
}
@@ -198,14 +222,20 @@ export function getAvailabilitiesForItem(
availabilities = availabilities.filter((availability) => availability.itemId === itemId);
// if 'delivery', 'dig-delivery' and 'b2b-delivery' are present remove 'dig-delivery' and 'b2b-delivery'
if (!allDeliveryAvailabilities && availabilities.some((availability) => availability.purchaseOption === 'delivery')) {
if (
!allDeliveryAvailabilities &&
availabilities.some((availability) => availability.purchaseOption === 'delivery')
) {
availabilities = availabilities.filter(
(availability) => availability.purchaseOption !== 'dig-delivery' && availability.purchaseOption !== 'b2b-delivery',
(availability) =>
availability.purchaseOption !== 'dig-delivery' && availability.purchaseOption !== 'b2b-delivery',
);
}
const optionsOrder = PURCHASE_OPTIONS;
return availabilities.sort((a, b) => optionsOrder.indexOf(a.purchaseOption) - optionsOrder.indexOf(b.purchaseOption));
return availabilities.sort(
(a, b) => optionsOrder.indexOf(a.purchaseOption) - optionsOrder.indexOf(b.purchaseOption),
);
};
}
@@ -346,7 +376,10 @@ export function getAvailabilityPriceForPurchaseOption(
};
}
export function getPriceForPurchaseOption(itemId: number, purchaseOption: PurchaseOption): (state: PurchaseOptionsState) => PriceDTO {
export function getPriceForPurchaseOption(
itemId: number,
purchaseOption: PurchaseOption,
): (state: PurchaseOptionsState) => PriceDTO {
return (state) => {
if (getCanEditPrice(itemId)(state)) {
const price = getPrices(state)[itemId];
@@ -367,7 +400,9 @@ export function getQuantityForItem(itemId: number): (state: PurchaseOptionsState
};
}
export function getCanAddResultForItemAndCurrentPurchaseOption(itemId: number): (state: PurchaseOptionsState) => CanAdd {
export function getCanAddResultForItemAndCurrentPurchaseOption(
itemId: number,
): (state: PurchaseOptionsState) => CanAdd {
return (state) => {
const fetchingAvailabilities = getFetchingAvailabilitiesForItem(itemId)(state);
const purchaseOption = getPurchaseOption(state);
@@ -386,7 +421,9 @@ export function getCanAddResultForItemAndCurrentPurchaseOption(itemId: number):
const canAddResults = getCanAddResults(state);
return canAddResults.find((canAddResult) => canAddResult.itemId === itemId && canAddResult.purchaseOption === purchaseOption);
return canAddResults.find(
(canAddResult) => canAddResult.itemId === itemId && canAddResult.purchaseOption === purchaseOption,
);
};
}
@@ -410,10 +447,15 @@ export function getAvailabilityWithPurchaseOption(
};
}
export function getCanAddResultWithPurchaseOption(itemId: number, purchaseOption: PurchaseOption): (state: PurchaseOptionsState) => CanAdd {
export function getCanAddResultWithPurchaseOption(
itemId: number,
purchaseOption: PurchaseOption,
): (state: PurchaseOptionsState) => CanAdd {
return (state) => {
const canAddResults = getCanAddResults(state);
return canAddResults.find((canAddResult) => canAddResult.itemId === itemId && canAddResult.purchaseOption === purchaseOption);
return canAddResults.find(
(canAddResult) => canAddResult.itemId === itemId && canAddResult.purchaseOption === purchaseOption,
);
};
}

View File

@@ -1,5 +1,13 @@
import { PriceDTO } from '@generated/swagger/checkout-api';
import { ActionType, Availability, Branch, CanAdd, FetchingAvailability, Item, PurchaseOption } from './purchase-options.types';
import {
ActionType,
Availability,
Branch,
CanAdd,
FetchingAvailability,
Item,
PurchaseOption,
} from './purchase-options.types';
export interface PurchaseOptionsState {
type: ActionType;

View File

@@ -27,7 +27,11 @@ import {
import { Observable } from 'rxjs';
import { first, switchMap } from 'rxjs/operators';
import { DEFAULT_PRICE_DTO, DEFAULT_PRICE_VALUE, DEFAULT_VAT_VALUE } from '../constants';
import { AddToShoppingCartDTO, EntityDTOContainerOfDestinationDTO, UpdateShoppingCartItemDTO } from '@generated/swagger/checkout-api';
import {
AddToShoppingCartDTO,
EntityDTOContainerOfDestinationDTO,
UpdateShoppingCartItemDTO,
} from '@generated/swagger/checkout-api';
import { uniqueId } from 'lodash';
import { VATDTO } from '@generated/swagger/oms-api';
import { DomainCatalogService } from '@domain/catalog';
@@ -248,7 +252,9 @@ export class PurchaseOptionsStore extends ComponentStore<PurchaseOptionsState> {
private async _loadCatalogueAvailability() {
const items = this.items;
if (this.type === 'update') {
const items = await this._catalogService.searchByEans({ eans: this.items.map((item) => item.product.ean) }).toPromise();
const items = await this._catalogService
.searchByEans({ eans: this.items.map((item) => item.product.ean) })
.toPromise();
if (items.result.length > 0) await this._addCatalogueAvailabilities(items.result);
} else {
await this._addCatalogueAvailabilities(items as ItemDTO[]);
@@ -404,7 +410,9 @@ export class PurchaseOptionsStore extends ComponentStore<PurchaseOptionsState> {
if (this._service.isAvailable(availability.data)) {
const availabilities = this.availabilities;
const index = availabilities.findIndex((a) => a.itemId === availability.itemId && a.purchaseOption === availability.purchaseOption);
const index = availabilities.findIndex(
(a) => a.itemId === availability.itemId && a.purchaseOption === availability.purchaseOption,
);
if (index > -1) {
availabilities[index] = availability;
@@ -423,7 +431,9 @@ export class PurchaseOptionsStore extends ComponentStore<PurchaseOptionsState> {
private _addCanAddResult(canAdd: CanAdd) {
let canAddResults = this.canAddResults;
canAddResults = canAddResults.filter((c) => !(c.itemId === canAdd.itemId && c.purchaseOption === canAdd.purchaseOption));
canAddResults = canAddResults.filter(
(c) => !(c.itemId === canAdd.itemId && c.purchaseOption === canAdd.purchaseOption),
);
canAddResults.push(canAdd);
this.patchState({ canAddResults });
}
@@ -440,7 +450,9 @@ export class PurchaseOptionsStore extends ComponentStore<PurchaseOptionsState> {
this.items.forEach((item) => {
// Get Rücklage availability
const inStoreAvailability = this.availabilities.find((a) => a.itemId === item.id && a.purchaseOption === 'in-store');
const inStoreAvailability = this.availabilities.find(
(a) => a.itemId === item.id && a.purchaseOption === 'in-store',
);
if (inStoreAvailability) {
payloads['Rücklage'].push(
mapToItemPayload({
@@ -453,9 +465,15 @@ export class PurchaseOptionsStore extends ComponentStore<PurchaseOptionsState> {
}
// Get Versand availability
let deliveryAvailability = this.availabilities.find((a) => a.itemId === item.id && a.purchaseOption === 'delivery');
const digDeliveryAvailability = this.availabilities.find((a) => a.itemId === item.id && a.purchaseOption === 'dig-delivery');
const b2bDeliveryAvailability = this.availabilities.find((a) => a.itemId === item.id && a.purchaseOption === 'b2b-delivery');
let deliveryAvailability = this.availabilities.find(
(a) => a.itemId === item.id && a.purchaseOption === 'delivery',
);
const digDeliveryAvailability = this.availabilities.find(
(a) => a.itemId === item.id && a.purchaseOption === 'dig-delivery',
);
const b2bDeliveryAvailability = this.availabilities.find(
(a) => a.itemId === item.id && a.purchaseOption === 'b2b-delivery',
);
deliveryAvailability = deliveryAvailability || digDeliveryAvailability || b2bDeliveryAvailability;
if (deliveryAvailability) {
payloads['Versand'].push(
@@ -482,7 +500,9 @@ export class PurchaseOptionsStore extends ComponentStore<PurchaseOptionsState> {
}
// Get Download availability
const downloadAvailability = this.availabilities.find((a) => a.itemId === item.id && a.purchaseOption === 'download');
const downloadAvailability = this.availabilities.find(
(a) => a.itemId === item.id && a.purchaseOption === 'download',
);
if (downloadAvailability) {
payloads['Download'].push(
mapToItemPayload({
@@ -714,7 +734,11 @@ export class PurchaseOptionsStore extends ComponentStore<PurchaseOptionsState> {
let price = prices[itemId];
if (price?.vat?.vatType !== vat?.vatType) {
if (!price) {
price = { ...DEFAULT_PRICE_DTO, value: { ...DEFAULT_PRICE_VALUE, ...price?.value }, vat: { ...DEFAULT_VAT_VALUE, ...vat } };
price = {
...DEFAULT_PRICE_DTO,
value: { ...DEFAULT_PRICE_VALUE, ...price?.value },
vat: { ...DEFAULT_VAT_VALUE, ...vat },
};
} else {
price = { ...price, value: price.value, vat: { ...price.vat, ...vat } };
}
@@ -829,10 +853,14 @@ export class PurchaseOptionsStore extends ComponentStore<PurchaseOptionsState> {
const purchaseOption = this.purchaseOption;
if (type === 'add') {
const payloads = this.selectedItemIds.map((itemId) => this.getAddToShoppingCartDTOForItem(itemId, purchaseOption));
const payloads = this.selectedItemIds.map((itemId) =>
this.getAddToShoppingCartDTOForItem(itemId, purchaseOption),
);
await this._service.addItemToShoppingCart(this.processId, payloads).toPromise();
} else if (type === 'update') {
const payloads = this.selectedItemIds.map((itemId) => this.getUpdateShoppingCartItemDTOForItem(itemId, purchaseOption));
const payloads = this.selectedItemIds.map((itemId) =>
this.getUpdateShoppingCartItemDTOForItem(itemId, purchaseOption),
);
for (const itemId of this.selectedItemIds) {
const item = this.items.find((i) => i.id === itemId);

View File

@@ -4,7 +4,14 @@ import { AvailabilityDTO, BranchDTO, ItemPayload, ShoppingCartItemDTO } from '@g
export type ActionType = 'add' | 'update';
export type PurchaseOption = 'delivery' | 'dig-delivery' | 'b2b-delivery' | 'pickup' | 'in-store' | 'download' | 'catalog';
export type PurchaseOption =
| 'delivery'
| 'dig-delivery'
| 'b2b-delivery'
| 'pickup'
| 'in-store'
| 'download'
| 'catalog';
export type OrderType = 'Rücklage' | 'Abholung' | 'Versand' | 'Download';

View File

@@ -41,7 +41,7 @@
<span class="number">{{ availability.qty || 0 }}</span>
<span>{{ availability.ssc }}</span>
<span>
<ui-checkbox *ngIf="availability.supplier !== 'F'" [(ngModel)]="availability.isPrebooked"> </ui-checkbox>
<ui-checkbox *ngIf="availability.supplier !== 'F'" [(ngModel)]="availability.isPrebooked"></ui-checkbox>
</span>
<span>{{ availability.at | date: 'dd.MM.yy' }}</span>
<span class="number">{{ availability.price?.value?.value | currency: 'EUR' : 'code' }}</span>
@@ -83,10 +83,10 @@
<div class="actions">
<button class="cta-not-available cta-action-secondary" [disabled]="ctaDisabled$ | async" (click)="notAvailable()">
<ui-spinner [show]="ctaDisabled$ | async"> Nicht lieferbar </ui-spinner>
<ui-spinner [show]="ctaDisabled$ | async">Nicht lieferbar</ui-spinner>
</button>
<button class="cta-reorder cta-action-primary" [disabled]="ctaReorderDisabled$ | async" (click)="reorder()">
<ui-spinner [show]="ctaDisabled$ | async"> Bestellen </ui-spinner>
<ui-spinner [show]="ctaDisabled$ | async">Bestellen</ui-spinner>
</button>
</div>
</ng-container>

View File

@@ -12,7 +12,7 @@
<span class="title">{{ review.title }}</span>
</div>
<div class="row">
<span class="author"> {{ review.author }} | {{ review.created | date: 'dd.MM.yy' }} </span>
<span class="author">{{ review.author }} | {{ review.created | date: 'dd.MM.yy' }}</span>
</div>
<div class="row">
<span>

View File

@@ -11,7 +11,8 @@ import { UiModalRef } from '@ui/modal';
})
export class ModalReviewsComponent {
reviews = this.modalRef.data;
rating = Math.floor((this.reviews.map((r) => r.rating).reduce((total, num) => total + num) / this.reviews.length) * 2) / 2;
rating =
Math.floor((this.reviews.map((r) => r.rating).reduce((total, num) => total + num) / this.reviews.length) * 2) / 2;
expandIds: string[] = [];
constructor(private modalRef: UiModalRef<void, ReviewDTO[]>) {}

View File

@@ -49,7 +49,10 @@ export class SendOrderConfirmationModalComponent implements OnInit {
try {
await this.orderService
.OrderPatchOrder({ orderId: order.id, order: { notificationChannels, buyer: { communicationDetails: { email } } } })
.OrderPatchOrder({
orderId: order.id,
order: { notificationChannels, buyer: { communicationDetails: { email } } },
})
.toPromise();
const response = await this.orderService.OrderOrderConfirmationTask(order.id).toPromise();
this.toaster.open({

View File

@@ -1,6 +1,7 @@
<h2 class="text-center font-bold text-xl mt-10">Sie haben {{ packageCount }} Irrläufer</h2>
<p class="text-center text-xl mt-4">
Stellen Sie diese Packstücke für die anderen Filialen bereit. <br />
Stellen Sie diese Packstücke für die anderen Filialen bereit.
<br />
Der Spediteur holt Sie zum nächstmöglichsten Zeitpunkt ab.
</p>
<page-package-list [packages]="packages" [showHeader]="false" navigationEnabled="false"></page-package-list>

View File

@@ -3,7 +3,8 @@
>
<p class="page-price-update-item__item-instruction font-bold text-lg">{{ item?.task?.instruction }}</p>
<p class="page-price-update-item__item-due-date text-p2">
gültig ab <span class="font-bold ml-2">{{ item?.task?.dueDate | date }}</span>
gültig ab
<span class="font-bold ml-2">{{ item?.task?.dueDate | date }}</span>
</p>
</div>
@@ -50,7 +51,8 @@
<div class="page-price-update-item__item-misc">
{{ environment.isTablet() ? (item?.product?.manufacturer | substr: 18) : item?.product?.manufacturer }} | {{ item?.product?.ean }}
<br />
{{ item?.product?.volume }} <span *ngIf="item?.product?.volume && item?.product?.publicationDate">|</span>
{{ item?.product?.volume }}
<span *ngIf="item?.product?.volume && item?.product?.publicationDate">|</span>
{{ publicationDate }}
</div>
</div>
@@ -76,8 +78,9 @@
*ngIf="inStock$ | async; let stock"
[class.skeleton]="stock?.inStock === undefined"
class="min-w-[1rem] text-right inline-block"
>{{ stock?.inStock }}</span
>
{{ stock?.inStock }}
</span>
x
</div>
</div>

View File

@@ -26,7 +26,7 @@
</div>
<div class="page-price-update-list__order-by h-[53px] flex flex-row items-center justify-center bg-white rounded-t mb-px-2">
<ui-order-by-filter [orderBy]="orderBy$ | async" (selectedOrderByChange)="search()"> </ui-order-by-filter>
<ui-order-by-filter [orderBy]="orderBy$ | async" (selectedOrderByChange)="search()"></ui-order-by-filter>
</div>
<div class="items scroll-bar">
@@ -34,11 +34,11 @@
@defer (on viewport) {
<page-price-update-item [item]="item" [selected]="isSelected(item)" [class.mt-px-10]="!first"></page-price-update-item>
} @placeholder {
<page-price-update-item-loader> </page-price-update-item-loader>
<page-price-update-item-loader></page-price-update-item-loader>
}
}
<page-price-update-item-loader *ngIf="fetching"> </page-price-update-item-loader>
<page-price-update-item-loader *ngIf="fetching"></page-price-update-item-loader>
<div class="h-28"></div>
</div>

View File

@@ -16,7 +16,9 @@ import { trigger, transition, style, animate } from '@angular/animations';
style({ transform: 'scale(1.2)', opacity: 0 }),
animate('250ms cubic-bezier(0.35, 0, 0.25, 1)', style({ transform: 'scale(1)', opacity: 1 })),
]),
transition(':leave', [animate('250ms cubic-bezier(0.35, 0, 0.25, 1)', style({ transform: 'scale(0.8)', opacity: 0 }))]),
transition(':leave', [
animate('250ms cubic-bezier(0.35, 0, 0.25, 1)', style({ transform: 'scale(0.8)', opacity: 0 })),
]),
]),
],
standalone: false,

View File

@@ -11,7 +11,15 @@ import { PriceUpdateItemComponent } from './price-update-item.component';
import { PriceUpdateListComponent } from './price-update-list.component';
@NgModule({
imports: [FormsModule, CommonModule, UiCommonModule, UiIconModule, ProductImageModule, UiSpinnerModule, UiOrderByFilterModule],
imports: [
FormsModule,
CommonModule,
UiCommonModule,
UiIconModule,
ProductImageModule,
UiSpinnerModule,
UiOrderByFilterModule,
],
exports: [PriceUpdateListComponent, PriceUpdateItemComponent, PriceUpdateItemLoaderComponent],
declarations: [PriceUpdateListComponent, PriceUpdateItemComponent, PriceUpdateItemLoaderComponent],
providers: [],

View File

@@ -11,8 +11,11 @@
</button>
</div>
<page-price-update-list *ngIf="showList$ | async; else noResults" [items]="store.items$ | async" [fetching]="store.fetching$ | async">
</page-price-update-list>
<page-price-update-list
*ngIf="showList$ | async; else noResults"
[items]="store.items$ | async"
[fetching]="store.fetching$ | async"
></page-price-update-list>
<shell-filter-overlay #filterOverlay class="relative">
<div class="relative">
@@ -47,7 +50,7 @@
(click)="applyFilter()"
[disabled]="store.fetching$ | async"
>
<ui-spinner [show]="store.fetching$ | async"> Filter anwenden </ui-spinner>
<ui-spinner [show]="store.fetching$ | async">Filter anwenden</ui-spinner>
</button>
</div>
</shell-filter-overlay>

View File

@@ -94,7 +94,9 @@ export class PriceUpdateComponentStore extends ComponentStore<PriceUpdateCompone
fetchSettings = this.effect(($) =>
$.pipe(
switchMap((_) => this._productListService.getQuerySettings().pipe(tapResponse(this.onFetchSettingsResponse, this.onFetchError))),
switchMap((_) =>
this._productListService.getQuerySettings().pipe(tapResponse(this.onFetchSettingsResponse, this.onFetchError)),
),
),
);
@@ -137,7 +139,9 @@ export class PriceUpdateComponentStore extends ComponentStore<PriceUpdateCompone
data: {
printerType: 'Office',
print: (printer) =>
this._domainPrinterService.printProductListItems({ data: selectableItems, printer, title: 'Preisänderungen' }).toPromise(),
this._domainPrinterService
.printProductListItems({ data: selectableItems, printer, title: 'Preisänderungen' })
.toPromise(),
} as PrintModalData,
config: {
panelClass: [],
@@ -161,7 +165,10 @@ export class PriceUpdateComponentStore extends ComponentStore<PriceUpdateCompone
let items = this.items;
if (response.error) {
this._uiModal.error('Setzen der Produkte auf Erledigt enthält fehlerhafte Einträge.', new Error(response.message));
this._uiModal.error(
'Setzen der Produkte auf Erledigt enthält fehlerhafte Einträge.',
new Error(response.message),
);
} else if (response.successful) {
items = items.filter((item) => !response.successful.some((s) => s.key === item.uId));
} else {

View File

@@ -35,7 +35,9 @@ export class PriceUpdateComponent implements OnInit {
* Zeigt die liste an, wenn entweder keine items geladen werden oder wenn items geladen wurden
* und mindestens ein item vorhanden ist.
*/
showList$ = combineLatest([this.store.fetching$, this.store.items$]).pipe(map(([fetching, items]) => fetching || items.length > 0));
showList$ = combineLatest([this.store.fetching$, this.store.items$]).pipe(
map(([fetching, items]) => fetching || items.length > 0),
);
constructor(
public store: PriceUpdateComponentStore,
@@ -132,7 +134,10 @@ export class PriceUpdateComponent implements OnInit {
}
async removeBreadcrumbs(): Promise<void> {
const filterCrumbs = await this._breadcrumb.getBreadcrumbsByKeyAndTag$(this.breadcrumbKey, 'filter').pipe(first()).toPromise();
const filterCrumbs = await this._breadcrumb
.getBreadcrumbsByKeyAndTag$(this.breadcrumbKey, 'filter')
.pipe(first())
.toPromise();
const crumbs = [...filterCrumbs];
for (let crumb of crumbs) {
await this._breadcrumb.removeBreadcrumb(crumb.id);

View File

@@ -8,7 +8,14 @@ import { PriceUpdateComponent } from './price-update.component';
import { IconComponent } from '@shared/components/icon';
@NgModule({
imports: [CommonModule, PriceUpdateListModule, UiFilterNextModule, SharedFilterOverlayModule, UiSpinnerModule, IconComponent],
imports: [
CommonModule,
PriceUpdateListModule,
UiFilterNextModule,
SharedFilterOverlayModule,
UiSpinnerModule,
IconComponent,
],
exports: [PriceUpdateComponent],
declarations: [PriceUpdateComponent],
providers: [],

View File

@@ -6,6 +6,9 @@
</page-article-details-text-link>
<br />
</ng-container>
<ng-container *ngSwitchDefault> {{ line }} <br /> </ng-container>
<ng-container *ngSwitchDefault>
{{ line }}
<br />
</ng-container>
</ng-container>
</ng-container>

View File

@@ -11,7 +11,15 @@ import { ReiheRoutePipe } from './reihe-route.pipe';
styleUrls: ['article-details-text.component.css'],
changeDetection: ChangeDetectionStrategy.OnPush,
host: { class: 'page-article-details-text' },
imports: [ArticleDetailsTextLinkComponent, NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault, LineTypePipe, ReiheRoutePipe],
imports: [
ArticleDetailsTextLinkComponent,
NgFor,
NgSwitch,
NgSwitchCase,
NgSwitchDefault,
LineTypePipe,
ReiheRoutePipe,
],
})
export class ArticleDetailsTextComponent {
@Input()

View File

@@ -15,18 +15,18 @@
grid-template-columns: max-content auto;
grid-template-rows: 2.1875rem repeat(11, minmax(auto, max-content));
grid-template-areas:
'. . . bookmark'
'image contributors contributors contributors'
'image title title print'
'image title title .'
'image misc price price'
'image misc price price'
'image origin origin stock'
'image origin origin stock'
'image specs availabilities availabilities'
'image specs ssc ssc'
'image . ssc ssc'
'image . ssc ssc';
". . . bookmark"
"image contributors contributors contributors"
"image title title print"
"image title title ."
"image misc price price"
"image misc price price"
"image origin origin stock"
"image origin origin stock"
"image specs availabilities availabilities"
"image specs ssc ssc"
"image . ssc ssc"
"image . ssc ssc";
}
.page-article-details__product-bookmark {

View File

@@ -20,7 +20,11 @@ import { DateAdapter } from '@ui/common';
import { DatePipe } from '@angular/common';
import { PurchaseOptionsModalService } from '@modal/purchase-options';
import { EnvironmentService } from '@core/environment';
import { CheckoutNavigationService, ProductCatalogNavigationService, CustomerSearchNavigation } from '@shared/services/navigation';
import {
CheckoutNavigationService,
ProductCatalogNavigationService,
CustomerSearchNavigation,
} from '@shared/services/navigation';
import { DomainCheckoutService } from '@domain/checkout';
import { Store } from '@ngrx/store';
import moment, { Moment } from 'moment';
@@ -63,9 +67,10 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
shareReplay(),
);
showDeliveryTruck$ = combineLatest([this.store.isDeliveryAvailabilityAvailable$, this.store.isDeliveryDigAvailabilityAvailable$]).pipe(
map(([delivery, digDelivery]) => delivery || digDelivery),
);
showDeliveryTruck$ = combineLatest([
this.store.isDeliveryAvailabilityAvailable$,
this.store.isDeliveryDigAvailabilityAvailable$,
]).pipe(map(([delivery, digDelivery]) => delivery || digDelivery));
showDeliveryB2BTruck$ = combineLatest([
this.store.isDeliveryDigAvailabilityAvailable$,
@@ -88,7 +93,10 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
showArchivBadge$ = this.store.item$.pipe(map((item) => item?.features?.find((i) => i.key === 'ARC')));
isBadgeVisible$ = combineLatest([this.showSubscriptionBadge$, this.showPromotionBadge$, this.showArchivBadge$]).pipe(
map(([showSubscriptionBadge, showPromotionBadge, showArchivBadge]) => showSubscriptionBadge || showPromotionBadge || showArchivBadge),
map(
([showSubscriptionBadge, showPromotionBadge, showArchivBadge]) =>
showSubscriptionBadge || showPromotionBadge || showArchivBadge,
),
);
contributors$ = this.store.item$.pipe(map((item) => item?.product?.contributors?.split(';').map((m) => m.trim())));
@@ -115,7 +123,9 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
publicationDate$ = this.store.item$.pipe(
filter((item) => !!item?.product?.publicationDate),
map((item) => {
const firstDayOfSale = item.catalogAvailability?.firstDayOfSale ? moment(item.catalogAvailability.firstDayOfSale) : null;
const firstDayOfSale = item.catalogAvailability?.firstDayOfSale
? moment(item.catalogAvailability.firstDayOfSale)
: null;
const publicationDate = item.product?.publicationDate ? moment(item.product.publicationDate) : null;
if (!firstDayOfSale && !publicationDate) {
@@ -236,7 +246,9 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
.pipe(
debounceTime(0),
switchMap((params) =>
this.applicationService.getSelectedBranch$(Number(params.processId)).pipe(map((selectedBranch) => ({ params, selectedBranch }))),
this.applicationService
.getSelectedBranch$(Number(params.processId))
.pipe(map((selectedBranch) => ({ params, selectedBranch }))),
),
)
.subscribe(({ params, selectedBranch }) => {
@@ -287,7 +299,10 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
}
getDetailsPath(ean?: string) {
return this._navigationService.getArticleDetailsPathByEan({ processId: this.applicationService.activatedProcessId, ean }).path;
return this._navigationService.getArticleDetailsPathByEan({
processId: this.applicationService.activatedProcessId,
ean,
}).path;
}
async updateBreadcrumb(item: ItemDTO) {
@@ -303,7 +318,10 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
this.breadcrumb.addBreadcrumbIfNotExists({
key: this.applicationService.activatedProcessId,
name: item.product?.name,
path: this._navigationService.getArticleDetailsPath({ processId: this.applicationService.activatedProcessId, itemId: item.id }).path,
path: this._navigationService.getArticleDetailsPath({
processId: this.applicationService.activatedProcessId,
itemId: item.id,
}).path,
params: this.activatedRoute.snapshot.queryParams,
tags: ['catalog', 'details', `${item.id}`],
section: 'customer',
@@ -328,8 +346,10 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
this.breadcrumb.addBreadcrumbIfNotExists({
key: this.applicationService.activatedProcessId,
name: item.product?.name,
path: this._navigationService.getArticleDetailsPath({ processId: this.applicationService.activatedProcessId, itemId: item.id })
.path,
path: this._navigationService.getArticleDetailsPath({
processId: this.applicationService.activatedProcessId,
itemId: item.id,
}).path,
params: this.activatedRoute.snapshot.queryParams,
tags: ['catalog', 'details', `${item.id}`],
section: 'customer',
@@ -339,8 +359,10 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
this.breadcrumb.patchBreadcrumb(crumb.id, {
key: this.applicationService.activatedProcessId,
name: item.product?.name,
path: this._navigationService.getArticleDetailsPath({ processId: this.applicationService.activatedProcessId, itemId: item.id })
.path,
path: this._navigationService.getArticleDetailsPath({
processId: this.applicationService.activatedProcessId,
itemId: item.id,
}).path,
params: this.activatedRoute.snapshot.queryParams,
tags: ['catalog', 'details', `${item.id}`],
section: 'customer',
@@ -355,7 +377,8 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
data: {
printerType: 'Label',
// TODO: remove item: item as PrinterItemDTO when the backend is fixed
print: (printer) => this.domainPrinterService.printProduct({ item: item as PrinterItemDTO, printer }).toPromise(),
print: (printer) =>
this.domainPrinterService.printProduct({ item: item as PrinterItemDTO, printer }).toPromise(),
} as PrintModalData,
config: {
panelClass: [],
@@ -459,7 +482,10 @@ export class ArticleDetailsComponent implements OnInit, OnDestroy {
.pipe(
first(),
switchMap((customerFeatures) => {
return this._domainCheckoutService.canSetCustomer({ processId: this.applicationService.activatedProcessId, customerFeatures });
return this._domainCheckoutService.canSetCustomer({
processId: this.applicationService.activatedProcessId,
customerFeatures,
});
}),
)
.toPromise();

View File

@@ -47,11 +47,16 @@ export class ArticleDetailsStore extends ComponentStore<ArticleDetailsState> {
readonly fetchingItem$ = this.select((s) => s.fetchingItem);
readonly item$ = this.select((s) => s.item);
readonly itemData$ = this.select(this.item$, (item) =>
!!item ? ({ ean: item?.product?.ean, itemId: item?.id, price: item?.catalogAvailability?.price } as ItemData) : undefined,
!!item
? ({ ean: item?.product?.ean, itemId: item?.id, price: item?.catalogAvailability?.price } as ItemData)
: undefined,
);
//#endregion
readonly isDownload$ = this.select(this.item$, (item) => !!(item?.product?.format === 'EB' || item?.product?.format === 'DL'));
readonly isDownload$ = this.select(
this.item$,
(item) => !!(item?.product?.format === 'EB' || item?.product?.format === 'DL'),
);
get processId() {
return this.get((s) => s.processId);
@@ -74,13 +79,17 @@ export class ArticleDetailsStore extends ComponentStore<ArticleDetailsState> {
readonly reviewRating$ = this.item$.pipe(
filter((i) => !!i),
map((i) => (i.reviews?.length > 0 ? i.reviews.map((r) => r.rating).reduce((total, num) => total + num) / i.reviews.length : 0)),
map((i) =>
i.reviews?.length > 0 ? i.reviews.map((r) => r.rating).reduce((total, num) => total + num) / i.reviews.length : 0,
),
);
readonly recommendations$ = this.item$.pipe(
filter((item) => !!item),
switchMap((item) =>
item.ids?.dig ? this.domainCatalogService.getRecommendations({ digId: item.ids['dig'] }).pipe(map((res) => res.result)) : of([]),
item.ids?.dig
? this.domainCatalogService.getRecommendations({ digId: item.ids['dig'] }).pipe(map((res) => res.result))
: of([]),
),
);
@@ -222,7 +231,9 @@ export class ArticleDetailsStore extends ComponentStore<ArticleDetailsState> {
//#region DIG Versandverfügbarkeit
readonly fetchingDeliveryDigAvailability$ = this.select((s) => s.fetchingDeliveryDigAvailability);
readonly deliveryDigAvailability$ = combineLatest([this.itemData$, this.isDownload$]).pipe(
tap(() => this.patchState({ fetchingDeliveryDigAvailability: true, fetchingDeliveryDigAvailabilityError: undefined })),
tap(() =>
this.patchState({ fetchingDeliveryDigAvailability: true, fetchingDeliveryDigAvailabilityError: undefined }),
),
switchMap(([item, isDownload]) =>
!!item && !isDownload
? this.domainAvailabilityService.getDigDeliveryAvailability({ item, quantity: 1 }).pipe(
@@ -245,7 +256,9 @@ export class ArticleDetailsStore extends ComponentStore<ArticleDetailsState> {
//#region B2B Versandverfügbarkeit
readonly fetchingDeliveryB2BAvailability$ = this.select((s) => s.fetchingDeliveryB2BAvailability);
readonly deliveryB2BAvailability$ = combineLatest([this.itemData$, this.isDownload$, this.branch$]).pipe(
tap(() => this.patchState({ fetchingDeliveryB2BAvailability: true, fetchingDeliveryB2BAvailabilityError: undefined })),
tap(() =>
this.patchState({ fetchingDeliveryB2BAvailability: true, fetchingDeliveryB2BAvailabilityError: undefined }),
),
switchMap(([item, isDownload, branch]) =>
!!item && !isDownload
? this.domainAvailabilityService.getB2bDeliveryAvailability({ item, quantity: 1, branch }).pipe(
@@ -274,46 +287,52 @@ export class ArticleDetailsStore extends ComponentStore<ArticleDetailsState> {
this.downloadAvailability$,
]).pipe(
withLatestFrom(this.domainAvailabilityService.sscs$),
map(([[item, isDownload, pickupAvailability, deliveryDigAvailability, deliveryB2BAvailability, downloadAvailability], sscs]) => {
let availability: AvailabilityDTO;
map(
([
[item, isDownload, pickupAvailability, deliveryDigAvailability, deliveryB2BAvailability, downloadAvailability],
sscs,
]) => {
let availability: AvailabilityDTO;
if (isDownload) {
availability = downloadAvailability;
} else {
if (pickupAvailability?.sscText) {
availability = pickupAvailability;
} else if (deliveryDigAvailability?.sscText) {
availability = deliveryDigAvailability;
} else if (deliveryB2BAvailability?.sscText) {
availability = deliveryB2BAvailability;
if (isDownload) {
availability = downloadAvailability;
} else {
if (pickupAvailability?.sscText) {
availability = pickupAvailability;
} else if (deliveryDigAvailability?.sscText) {
availability = deliveryDigAvailability;
} else if (deliveryB2BAvailability?.sscText) {
availability = deliveryB2BAvailability;
}
}
}
let ssc = '';
let sscText = 'Keine Lieferanten vorhanden';
let ssc = '';
let sscText = 'Keine Lieferanten vorhanden';
if (item?.catalogAvailability?.supplier === 'S' && !isDownload) {
ssc = item?.catalogAvailability?.ssc;
sscText = item?.catalogAvailability?.sscText;
if (item?.catalogAvailability?.supplier === 'S' && !isDownload) {
ssc = item?.catalogAvailability?.ssc;
sscText = item?.catalogAvailability?.sscText;
return [ssc, sscText].filter((f) => !!f).join(' - ');
}
if (availability?.ssc || availability?.sscText) {
ssc = availability?.ssc;
sscText = availability?.sscText;
const sscExists = !!sscs?.find((ssc) => !!item?.id && ssc?.itemId === item.id);
const sscEqualsCatalogSsc =
ssc === item.catalogAvailability.ssc && sscText === item.catalogAvailability.sscText;
// To keep result list in sync with details page
if (!sscExists && !sscEqualsCatalogSsc) {
this.domainAvailabilityService.sscs$.next([...sscs, { itemId: item?.id, ssc, sscText }]);
}
}
return [ssc, sscText].filter((f) => !!f).join(' - ');
}
if (availability?.ssc || availability?.sscText) {
ssc = availability?.ssc;
sscText = availability?.sscText;
const sscExists = !!sscs?.find((ssc) => !!item?.id && ssc?.itemId === item.id);
const sscEqualsCatalogSsc = ssc === item.catalogAvailability.ssc && sscText === item.catalogAvailability.sscText;
// To keep result list in sync with details page
if (!sscExists && !sscEqualsCatalogSsc) {
this.domainAvailabilityService.sscs$.next([...sscs, { itemId: item?.id, ssc, sscText }]);
}
}
return [ssc, sscText].filter((f) => !!f).join(' - ');
}),
},
),
);
constructor(
@@ -402,7 +421,10 @@ export class ArticleDetailsStore extends ComponentStore<ArticleDetailsState> {
});
async navigateBack() {
const crumb = await this._breadcrumb.getLastActivatedBreadcrumbByKey$(this._appService.activatedProcessId).pipe(first()).toPromise();
const crumb = await this._breadcrumb
.getLastActivatedBreadcrumbByKey$(this._appService.activatedProcessId)
.pipe(first())
.toPromise();
if (crumb) {
await this._router.navigate([crumb.path]);
} else {

View File

@@ -15,7 +15,7 @@
</span>
<ng-container *ngIf="store.recommendations$ | async; let recommendations">
<span *ngIf="recommendations.length === 0" class="empty-message"> Keine Empfehlungen verfügbar </span>
<span *ngIf="recommendations.length === 0" class="empty-message">Keine Empfehlungen verfügbar</span>
<ui-slider *ngIf="recommendations.length > 0" [scrollDistance]="210">
<a

View File

@@ -20,6 +20,9 @@ export class ArticleRecommendationsComponent {
) {}
getDetailsPath(ean?: string) {
return this._navigationService.getArticleDetailsPathByEan({ processId: this._applicationService.activatedProcessId, ean }).path;
return this._navigationService.getArticleDetailsPathByEan({
processId: this._applicationService.activatedProcessId,
ean,
}).path;
}
}

View File

@@ -76,7 +76,9 @@ export function mapFilterArrayToStringDictionary(source: Filter[]): { [key: stri
const selected = options.filter((o) => o.selected);
const selectedSubOptions: FilterOption[] = [];
const optionsWithSuboptions: FilterOption[] = options.filter((o) => (isSelectFilterOption(o) ? o?.options?.length > 0 : null));
const optionsWithSuboptions: FilterOption[] = options.filter((o) =>
isSelectFilterOption(o) ? o?.options?.length > 0 : null,
);
for (const o of optionsWithSuboptions) {
if (isSelectFilterOption(o)) {
const subOptions = o.options.filter((sO) => sO.selected);
@@ -117,7 +119,9 @@ export function mapSelectedFilterToParams(source: Filter[]): string {
const selected = options.filter((o) => o.type === 'select' && o.selected);
const selectedSubOptions: FilterOption[] = [];
const optionsWithSuboptions: FilterOption[] = options.filter((o) => (isSelectFilterOption(o) ? o?.options?.length > 0 : null));
const optionsWithSuboptions: FilterOption[] = options.filter((o) =>
isSelectFilterOption(o) ? o?.options?.length > 0 : null,
);
for (const o of optionsWithSuboptions) {
if (isSelectFilterOption(o)) {
const subOptions = o.options.filter((sO) => sO.type === 'select' && sO.selected);

Some files were not shown because too many files have changed in this diff Show More