mirror of
https://dev.azure.com/hugendubel/ISA/_git/ISA-Frontend
synced 2025-12-28 22:42:11 +01:00
181 lines
7.8 KiB
TypeScript
181 lines
7.8 KiB
TypeScript
import { Location } from '@angular/common';
|
|
import { HttpErrorResponse } from '@angular/common/http';
|
|
import { ChangeDetectorRef, Component, inject, OnInit } from '@angular/core';
|
|
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
|
import { ActivatedRoute } from '@angular/router';
|
|
import { CrmCustomerService } from '@domain/crm';
|
|
import { CountryDTO, CustomerDTO, KeyValueDTOOfStringAndString } from '@swagger/crm';
|
|
import { UiValidators } from '@ui/validators';
|
|
import { Observable, combineLatest } from 'rxjs';
|
|
import { first, map, switchMap } from 'rxjs/operators';
|
|
import { validateEmail } from '../../validators/email-validator';
|
|
import { genderLastNameValidator } from '../../validators/gender-b2b-validator';
|
|
import { camelCase } from 'lodash';
|
|
import { CustomerSearchStore } from '../store';
|
|
import { CustomerSearchNavigation, NavigationRoute } from '@shared/services/navigation';
|
|
import { zipCodeValidator } from '../../validators/zip-code-validator';
|
|
import { GenderSettingsService } from '@shared/services/gender';
|
|
|
|
@Component({ template: '' })
|
|
export abstract class CustomerDataEditComponent implements OnInit {
|
|
private customerService = inject(CrmCustomerService);
|
|
private activatedRoute = inject(ActivatedRoute);
|
|
private fb = inject(UntypedFormBuilder);
|
|
private cdr = inject(ChangeDetectorRef);
|
|
private location = inject(Location);
|
|
private _store = inject(CustomerSearchStore);
|
|
private _navigation = inject(CustomerSearchNavigation);
|
|
public genderSettings = inject(GenderSettingsService);
|
|
|
|
customer$: Observable<CustomerDTO>;
|
|
customerId$: Observable<number>;
|
|
countries$: Observable<CountryDTO[]>;
|
|
customerFeatures$: Observable<KeyValueDTOOfStringAndString[]>;
|
|
customerType$: Observable<string>;
|
|
isWebshopOrGuest$: Observable<boolean>;
|
|
customerFeatureB2bOrB2c$: Observable<string>;
|
|
isOnlineOrCustomerCardUser$: Observable<boolean>;
|
|
|
|
control: UntypedFormGroup;
|
|
|
|
detailsRoute$: Observable<NavigationRoute>;
|
|
|
|
get customerId() {
|
|
return Number(this.activatedRoute.snapshot.params['customerId']);
|
|
}
|
|
|
|
afterInitForm?: (control: AbstractControl) => void;
|
|
|
|
ngOnInit() {
|
|
this.customerId$ = this.activatedRoute.params.pipe(map((p) => Number(p['customerId'])));
|
|
this.customer$ = this.customerId$.pipe(
|
|
switchMap((id) => this.customerService.getCustomer(id, 2)),
|
|
map((cr) => cr.result),
|
|
);
|
|
this.customerFeatures$ = this.customer$.pipe(
|
|
map((customer: CustomerDTO) => {
|
|
// Bugfix - Logik muss aus folgendem Grund angepasst werden:
|
|
// -> Bei B2B Kunden ist meist 'd-account' mit enabled: true versehen
|
|
// -> Das feature mit dem key 'b2b' wird somit nicht zurückgegeben (da auf diesem Feature kein enabled vorhanden ist)
|
|
// -> Die View im nachfolgenden Code wird jedoch anhand des keys 'b2b' aufgebaut
|
|
const enabledFeatures = Object.values(customer.features).filter((f) => f.enabled);
|
|
const b2bFeature = customer?.features?.find((f) => f?.key === 'b2b');
|
|
const isB2B = enabledFeatures?.every(
|
|
(f) => f?.key === 'd-account' && f?.description?.toLowerCase()?.includes('business') && b2bFeature,
|
|
);
|
|
return isB2B ? [b2bFeature, ...enabledFeatures] : enabledFeatures;
|
|
}),
|
|
);
|
|
|
|
this.customerType$ = this.customerFeatures$.pipe(
|
|
map(
|
|
(features: KeyValueDTOOfStringAndString[]) =>
|
|
features.find((f) => f.key === 'store' || f.key === 'webshop' || f.key === 'b2b' || f.key === 'guest')?.key,
|
|
),
|
|
);
|
|
this.isOnlineOrCustomerCardUser$ = combineLatest([this.customerType$, this.customerFeatures$]).pipe(
|
|
map(
|
|
([type, features]) =>
|
|
type === 'webshop' || !!features?.find((feature) => feature?.key === 'p4muser' || feature?.key === 'd-account'),
|
|
),
|
|
);
|
|
this.isWebshopOrGuest$ = this.customerType$.pipe(map((type) => type === 'webshop' || type === 'guest'));
|
|
this.customerFeatureB2bOrB2c$ = this.customerType$.pipe(map((type) => (type === 'b2b' ? 'b2b' : 'b2c')));
|
|
this.countries$ = this.isWebshopOrGuest$.pipe(
|
|
switchMap((webshopOrGuest) => {
|
|
if (!webshopOrGuest) {
|
|
return this.customerService.getCountries().pipe(map((p) => p.result));
|
|
} else {
|
|
return this.customerService.getCountries().pipe(
|
|
map((p) => p.result),
|
|
map((countries) => countries.filter((country) => country.name === 'Deutschland')),
|
|
);
|
|
}
|
|
}),
|
|
);
|
|
this.initForm();
|
|
|
|
this.detailsRoute$ = combineLatest([this._store.processId$, this._store.customerId$]).pipe(
|
|
map(([processId, customerId]) => this._navigation.detailsRoute({ processId, customerId })),
|
|
);
|
|
}
|
|
|
|
async initForm() {
|
|
const { fb } = this;
|
|
const customerDTO = await this.customer$.pipe(first()).toPromise();
|
|
const customerType = await this.customerType$.pipe(first()).toPromise();
|
|
const customerFeatures = await this.customerFeatures$.pipe(first()).toPromise();
|
|
const isB2b = customerType === 'b2b';
|
|
const isBranch = customerType === 'store';
|
|
const isWebshop = customerType === 'webshop';
|
|
const isCard = customerFeatures.find((feature) => feature.key === 'p4muser');
|
|
const zipCodeValidators = (isWebshop && isCard) || isWebshop || isB2b ? [Validators.required, zipCodeValidator()] : []; // #2573 Validierung nur für Onlinekonto, Onlinekonto+Kundenkarte, Business Konto
|
|
this.control = fb.group(
|
|
{
|
|
gender: fb.control(customerDTO?.gender, [isBranch ? Validators.required : () => null]),
|
|
title: fb.control(customerDTO?.title),
|
|
lastName: fb.control(customerDTO?.lastName, [Validators.required]),
|
|
firstName: fb.control(customerDTO?.firstName, [Validators.required]),
|
|
dateOfBirth: fb.control(customerDTO?.dateOfBirth, [isWebshop && isCard ? Validators.required : () => null, UiValidators.date]),
|
|
communicationDetails: fb.group({
|
|
email: fb.control(customerDTO?.communicationDetails?.email, [validateEmail]),
|
|
phone: fb.control(customerDTO?.communicationDetails?.phone),
|
|
mobile: fb.control(customerDTO?.communicationDetails?.mobile),
|
|
}),
|
|
organisation: fb.group({
|
|
name: fb.control(customerDTO?.organisation?.name),
|
|
vatId: fb.control(customerDTO?.organisation?.vatId),
|
|
department: fb.control(customerDTO?.organisation?.department),
|
|
}),
|
|
address: fb.group({
|
|
street: fb.control(customerDTO?.address?.street),
|
|
streetNumber: fb.control(customerDTO?.address?.streetNumber),
|
|
zipCode: fb.control(customerDTO?.address?.zipCode, zipCodeValidators),
|
|
city: fb.control(customerDTO?.address?.city),
|
|
country: fb.control(customerDTO?.address?.country),
|
|
info: fb.control(customerDTO?.address?.info),
|
|
}),
|
|
},
|
|
{ validators: genderLastNameValidator(isB2b) },
|
|
);
|
|
|
|
if (typeof this.afterInitForm === 'function') {
|
|
this.afterInitForm.call(this, this.control);
|
|
}
|
|
|
|
this.control.markAllAsTouched();
|
|
this.cdr.markForCheck();
|
|
}
|
|
|
|
cancel() {
|
|
this.location.back();
|
|
}
|
|
|
|
async submit() {
|
|
if (!this.control.valid || !this.control.enabled) {
|
|
return;
|
|
}
|
|
|
|
this.control.disable();
|
|
|
|
try {
|
|
await this.customerService.patchCustomer(this.customerId, this.control.value).toPromise();
|
|
this._store.selectCustomer({ customerId: this._store.customerId, reload: true });
|
|
|
|
this.location.back();
|
|
} catch (error) {
|
|
this.control.enable();
|
|
if (error instanceof HttpErrorResponse) {
|
|
if (error.error.invalidProperties) {
|
|
const invProps = error.error.invalidProperties;
|
|
const keys = Object.keys(invProps);
|
|
for (const key of keys) {
|
|
this.control.get('address')?.get(camelCase(key))?.setErrors({ validateAddress: invProps[key] });
|
|
}
|
|
}
|
|
}
|
|
console.error(error);
|
|
}
|
|
}
|
|
}
|