blob: 68e876068b9c76240422f305bfe7cab05adcfb4c [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import {Component, Input, OnChanges, OnInit, SimpleChanges} from '@angular/core';
import {FormComponent} from '../../../../common/forms/form.component';
import {FormBuilder, FormControl, Validators} from '@angular/forms';
import {FimsValidators} from '../../../../common/validator/validators';
import {ChronoUnit} from '../../../../services/portfolio/domain/chrono-unit.model';
import {alignmentOptions} from '../../../../common/domain/alignment.model';
import {weekDayOptions} from '../../../../common/domain/week-days.model';
import {monthOptions} from '../../../../common/domain/months.model';
import {temporalOptionList} from '../../../../common/domain/temporal.domain';
import {Product} from '../../../../services/portfolio/domain/product.model';
import {ProductInstance} from '../../../../services/depositAccount/domain/instance/product-instance.model';
import {maxPayment, maxTerm} from './validator/max-term.validators';
export interface DetailFormData {
identifier: string;
productIdentifier: string;
interest: string;
principalAmount: string;
term: number;
termTemporalUnit: ChronoUnit;
paymentTemporalUnit: ChronoUnit;
paymentPeriod: number;
paymentAlignmentDay: number;
paymentAlignmentWeek: number;
paymentAlignmentMonth: number;
depositAccountIdentifier: string;
}
type MonthSetting = 'DAY' | 'WEEK_AND_DAY';
@Component({
selector: 'fims-case-detail-form',
templateUrl: './detail.component.html'
})
export class CaseDetailFormComponent extends FormComponent<DetailFormData> implements OnInit, OnChanges {
private _formData: DetailFormData;
numberFormat = '1.2-2';
@Input() editMode: boolean;
@Input() products: Product[];
@Input() productInstances: ProductInstance[];
@Input() set formData(formData: DetailFormData) {
this._formData = formData;
};
product: Product;
weekAlignments: any[] = alignmentOptions;
monthDays: any[] = [];
weekDays: any[] = weekDayOptions;
months: any[] = monthOptions;
temporalOptions = temporalOptionList;
displayDaysInWeek: boolean;
displayMonthSetting: boolean;
displayMonths: boolean;
constructor(private formBuilder: FormBuilder) {
super();
this.form = this.formBuilder.group({
identifier: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(32), FimsValidators.urlSafe]],
productIdentifier: ['', [Validators.required]],
interest: ['', [Validators.required]],
principalAmount: [''],
term: ['', [ Validators.required, FimsValidators.minValue(1), FimsValidators.maxScale(0)]],
termTemporalUnit: ['', Validators.required],
paymentTemporalUnit: ['', [ Validators.required ]],
paymentPeriod: ['', [ Validators.required, FimsValidators.minValue(1), FimsValidators.maxScale(0)]],
dayInWeek: ['', Validators.required],
monthSetting: ['', Validators.required],
monthSettingDay: ['', Validators.required],
monthSettingDayInWeek: ['', Validators.required],
monthSettingWeek: ['', Validators.required],
month: ['', Validators.required],
depositAccountIdentifier: ['', Validators.required]
});
this.form.get('productIdentifier').valueChanges
.filter(() => !!this.products)
.map(identifier => this.products.find(product => product.identifier === identifier))
.subscribe(product => this.toggleProduct(product));
this.form.get('paymentTemporalUnit').valueChanges
.subscribe(unit => this.toggleTemporalUnit(unit));
this.form.get('monthSetting').valueChanges
.subscribe(setting => this.toggleMonthSetting(setting));
}
ngOnInit(): void {
for (let i = 0; i < 30; i++) {
this.monthDays.push({
type: i, label: `${i + 1}.`
});
}
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.formData) {
this.form.reset({
identifier: this._formData.identifier,
productIdentifier: this._formData.productIdentifier,
interest: this._formData.interest,
principalAmount: this._formData.principalAmount,
term: this._formData.term,
termTemporalUnit: this._formData.termTemporalUnit,
paymentTemporalUnit: this._formData.paymentTemporalUnit,
paymentPeriod: this._formData.paymentPeriod,
dayInWeek: this._formData.paymentAlignmentDay,
monthSetting: this._formData.paymentAlignmentWeek != null ? 'WEEK_AND_DAY' : 'DAY',
monthSettingDay: this._formData.paymentAlignmentDay,
monthSettingDayInWeek: this._formData.paymentAlignmentDay,
monthSettingWeek: this._formData.paymentAlignmentWeek,
month: this._formData.paymentAlignmentMonth,
depositAccountIdentifier: this._formData.depositAccountIdentifier
});
}
if (changes.products && changes.products.currentValue && this._formData.productIdentifier) {
const foundProduct = this.products.find(product => product.identifier === this._formData.productIdentifier);
this.toggleProduct(foundProduct);
}
}
private toggleProduct(product: Product) {
this.product = product;
// Override validator with product constraints
const principalAmount = this.form.get('principalAmount') as FormControl;
this.toggleDisabledState(principalAmount, product.balanceRange.minimum, product.balanceRange.maximum, product.minorCurrencyUnitDigits);
const interest: FormControl = this.form.get('interest') as FormControl;
this.toggleDisabledState(interest, product.interestRange.minimum, product.interestRange.maximum, product.minorCurrencyUnitDigits);
this.form.setValidators([maxTerm(product.termRange), maxPayment()]);
}
private toggleDisabledState(formControl: FormControl, minimum: number, maximum: number, maxScale: number): void {
const hasRange: boolean = minimum !== maximum;
if (hasRange) {
formControl.enable();
formControl.setValidators([
Validators.required,
FimsValidators.minValue(minimum),
FimsValidators.maxValue(maximum)
]);
} else {
formControl.setValue(minimum.toFixed(maxScale));
formControl.disable();
}
formControl.updateValueAndValidity();
}
toggleTemporalUnit(chronoUnit: ChronoUnit): void {
const dayInWeek = this.form.get('dayInWeek');
const month = this.form.get('month');
if (chronoUnit === 'WEEKS') {
this.enableMonthSetting(false);
dayInWeek.enable();
month.disable();
this.displayDaysInWeek = true;
this.displayMonths = false;
} else if (chronoUnit === 'MONTHS') {
this.enableMonthSetting(true);
dayInWeek.disable();
month.disable();
this.displayDaysInWeek = false;
this.displayMonths = false;
} else {
this.enableMonthSetting(true);
dayInWeek.disable();
month.enable();
this.displayDaysInWeek = false;
this.displayMonths = true;
}
}
enableMonthSetting(enable: boolean): void {
const monthSetting = this.form.get('monthSetting');
const monthSettingDay = this.form.get('monthSettingDay');
const monthSettingDayInWeek = this.form.get('monthSettingDayInWeek');
const monthSettingWeek = this.form.get('monthSettingWeek');
if (enable) {
this.displayMonthSetting = true;
monthSetting.enable();
} else {
this.displayMonthSetting = false;
monthSetting.disable();
monthSettingDay.disable();
monthSettingDayInWeek.disable();
monthSettingWeek.disable();
}
}
toggleMonthSetting(setting: MonthSetting): void {
const monthSettingDay = this.form.get('monthSettingDay');
const monthSettingDayInWeek = this.form.get('monthSettingDayInWeek');
const monthSettingWeek = this.form.get('monthSettingWeek');
if (setting === 'DAY') {
monthSettingDay.enable();
monthSettingDayInWeek.disable();
monthSettingWeek.disable();
} else {
monthSettingDay.disable();
monthSettingDayInWeek.enable();
monthSettingWeek.enable();
}
}
get formData(): DetailFormData {
const paymentTemporalUnit = this.form.get('paymentTemporalUnit').value;
const dayInWeek = this.form.get('dayInWeek').value;
const monthSetting: MonthSetting = this.form.get('monthSetting').value;
const monthSettingDay = this.form.get('monthSettingDay').value;
const monthSettingDayInWeek = this.form.get('monthSettingDayInWeek').value;
const monthSettingWeek = this.form.get('monthSettingWeek').value;
const month = this.form.get('month').value;
let paymentAlignmentDay: number;
let paymentAlignmentWeek: number;
let paymentAlignmentMonth: number;
if (paymentTemporalUnit === 'WEEKS') {
paymentAlignmentDay = dayInWeek;
}
if (paymentTemporalUnit === 'MONTHS' || paymentTemporalUnit === 'YEARS') {
if (monthSetting === 'DAY') {
paymentAlignmentDay = monthSettingDay;
} else {
paymentAlignmentDay = monthSettingDayInWeek;
paymentAlignmentWeek = monthSettingWeek;
}
}
if (paymentTemporalUnit === 'YEARS') {
paymentAlignmentMonth = month;
}
const formData: DetailFormData = {
identifier: this.form.get('identifier').value,
productIdentifier: this.form.get('productIdentifier').value,
interest: this.form.get('interest').value,
principalAmount: this.form.get('principalAmount').value,
term: this.form.get('term').value,
termTemporalUnit: this.form.get('termTemporalUnit').value,
paymentTemporalUnit,
paymentPeriod: this.form.get('paymentPeriod').value,
paymentAlignmentDay,
paymentAlignmentWeek,
paymentAlignmentMonth,
depositAccountIdentifier: this.form.get('depositAccountIdentifier').value
};
return formData;
}
showIdentifierValidationError(): void {
this.setError('identifier', 'unique', true);
}
}