Fixed Length configuration in Loan Accounts

This commit is contained in:
Jose Alberto Hernandez
2024-03-19 07:56:04 -06:00
committed by Jose Alberto Hernandez
parent e4274c55bb
commit 466efacbd8
24 changed files with 163 additions and 79 deletions
@@ -43,11 +43,13 @@ export class TransactionsTabComponent implements OnInit {
ngOnInit() {
this.hideAccrualsParam = new UntypedFormControl(false);
this.dataSource = new MatTableDataSource(this.transactionsData);
this.tempTransaction.forEach((element: any) => {
if (this.isAccrual(element.transactionType)) {
this.tempTransaction = this.removeItem(this.tempTransaction, element);
}
});
if (this.tempTransaction) {
this.tempTransaction.forEach((element: any) => {
if (this.isAccrual(element.transactionType)) {
this.tempTransaction = this.removeItem(this.tempTransaction, element);
}
});
}
}
private removeItem(arr: any, item: any) {
@@ -43,11 +43,13 @@ export class TransactionsTabComponent implements OnInit {
ngOnInit() {
this.dataSource = new MatTableDataSource(this.transactionsData);
this.hideAccrualsParam = new UntypedFormControl(false);
this.tempTransaction.forEach((element: any) => {
if (this.isAccrual(element.transactionType)) {
this.tempTransaction = this.removeItem(this.tempTransaction, element);
}
});
if (this.tempTransaction) {
this.tempTransaction.forEach((element: any) => {
if (this.isAccrual(element.transactionType)) {
this.tempTransaction = this.removeItem(this.tempTransaction, element);
}
});
}
}
private removeItem(arr: any, item: any) {
@@ -1,6 +1,6 @@
<div fxLayout="row wrap" fxLayout.lt-md="column">
<button mat-stroked-button color="primary" (click)="showRepaymentInfo()">
<button mat-flat-button color="primary" (click)="showRepaymentInfo()">
<fa-icon icon="calendar" class="m-r-10"></fa-icon>{{"labels.inputs.Generate Repayment Schedule" | translate}}
</button>
@@ -13,7 +13,7 @@
<h4 fxFlex="98%" class="mat-h4">{{"labels.heading.Term Options" | translate}} <i class="fas fa-question" matTooltip="The loan term parameter in loan accounts
is the default-calculated field based on the number of repayments and repaid every value entered by the user"></i></h4>
<mat-form-field fxFlex="48%">
<mat-form-field fxFlex="23%">
<mat-label>{{"labels.inputs.Loan Term" | translate}}</mat-label>
<input type="number" matInput required disabled formControlName="loanTermFrequency">
<mat-error *ngIf="loansAccountTermsForm.controls.loanTermFrequency.hasError('required')">
@@ -21,7 +21,7 @@
</mat-error>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-form-field fxFlex="23%">
<mat-label>{{"labels.inputs.Frequency" | translate}}</mat-label>
<mat-select required formControlName="loanTermFrequencyType">
<mat-option *ngFor="let type of termFrequencyTypeData" [value]="type.id">
@@ -33,6 +33,12 @@
</mat-error>
</mat-form-field>
<mat-form-field fxFlex="20%" *ngIf="hasFixedLength()">
<mat-label>{{"labels.inputs.Fixed Length" | translate}}</mat-label>
<input type="number" matInput formControlName="fixedLength">
</mat-form-field>
<span fxFlex="20%" *ngIf="hasFixedLength()" class="label-field">{{ loansAccountTermsForm.value.loanTermFrequencyType | find:termFrequencyTypeData:'id':'value' }}</span>
<h4 fxFlex="98%" class="mat-h4">Repayments </h4>
<mat-form-field fxFlex="48%">
@@ -44,7 +50,7 @@
</mat-error>
</mat-form-field>
<mat-form-field fxFlex="48%" (click)="repaymentsPicker.open()">
<mat-form-field fxFlex="23%" (click)="repaymentsPicker.open()">
<mat-label>{{"labels.inputs.First repayment on" | translate}}</mat-label>
<input matInput [min]="minDate" [max]="maxDate" matTooltip="{{ 'tooltips.May be entered to override' | translate}}" [matDatepicker]="repaymentsPicker"
formControlName="repaymentsStartingFromDate">
@@ -52,9 +58,17 @@
<mat-datepicker #repaymentsPicker></mat-datepicker>
</mat-form-field>
<mat-form-field fxFlex="23%" (click)="interestPicker.open()">
<mat-label>{{"labels.inputs.Interest charged from" | translate}}</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="interestPicker" matTooltip="{{ 'tooltips.May be entered to override the date' | translate}}"
formControlName="interestChargedFromDate">
<mat-datepicker-toggle matSuffix [for]="interestPicker"></mat-datepicker-toggle>
<mat-datepicker #interestPicker></mat-datepicker>
</mat-form-field>
<h4 fxFlex="98%" class="mat-h4">{{"labels.heading.Repaid Every" | translate}} <i class="fas fa-question" matTooltip="{{ 'tooltips.Fields are input to calculating the repayment schedule' | translate}}"></i></h4>
<mat-form-field fxFlex="48%">
<mat-form-field fxFlex="23%">
<mat-label>{{"labels.inputs.Repaid every" | translate}}</mat-label>
<input type="number" matInput required formControlName="repaymentEvery"
matTooltip="These fields are input to calculating the repayment schedule for a loan account and are used to determine when payments are due.">
@@ -63,7 +77,7 @@
</mat-error>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-form-field fxFlex="23%">
<mat-label>{{"labels.inputs.Frequency" | translate}}</mat-label>
<mat-select formControlName="repaymentFrequencyType" disabled required>
<mat-option *ngFor="let repaymentFrequencyType of termFrequencyTypeData" [value]="repaymentFrequencyType.id">
@@ -72,7 +86,7 @@
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="48%" *ngIf="loansAccountTermsForm.controls.repaymentFrequencyType.value == 2">
<mat-form-field fxFlex="20%" *ngIf="loansAccountTermsForm.controls.repaymentFrequencyType.value == 2">
<mat-label>{{"labels.inputs.Select On" | translate}}</mat-label>
<mat-select formControlName="repaymentFrequencyNthDayType">
<mat-option *ngFor="let repaymentFrequencyNthDayType of repaymentFrequencyNthDayTypeData"
@@ -82,7 +96,7 @@
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="48%" *ngIf="loansAccountTermsForm.controls.repaymentFrequencyType.value == 2">
<mat-form-field fxFlex="20%" *ngIf="loansAccountTermsForm.controls.repaymentFrequencyType.value == 2">
<mat-label>{{"labels.inputs.Select Day" | translate}}</mat-label>
<mat-select formControlName="repaymentFrequencyDayOfWeekType">
<mat-option *ngFor="let repaymentFrequencyDayOfWeekType of repaymentFrequencyDaysOfWeekTypeData"
@@ -92,22 +106,16 @@
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="48%" (click)="interestPicker.open()">
<mat-label>{{"labels.inputs.Interest charged from" | translate}}</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="interestPicker" matTooltip="{{ 'tooltips.May be entered to override the date' | translate}}"
formControlName="interestChargedFromDate">
<mat-datepicker-toggle matSuffix [for]="interestPicker"></mat-datepicker-toggle>
<mat-datepicker #interestPicker></mat-datepicker>
</mat-form-field>
<h4 fxFlex="98%" class="mat-h4">{{"labels.inputs.Nominal interest rate" | translate}}</h4>
<ng-container *ngIf="!loansAccountTermsData?.isLoanProductLinkedToFloatingRate">
<mat-form-field fxFlex="48%">
<mat-form-field fxFlex="23%">
<mat-label>{{"labels.inputs.Nominal interest rate" | translate}}</mat-label>
<input type="number" matInput formControlName="interestRatePerPeriod">
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-form-field fxFlex="23%">
<mat-label>{{"labels.inputs.Interest method" | translate}}</mat-label>
<mat-select formControlName="interestType" matTooltip="{{ 'tooltips.The Interest method value' | translate}}">
<mat-option *ngFor="let interestType of interestTypeData" [value]="interestType.id">
@@ -115,29 +123,24 @@
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="23%">
<mat-label>{{"labels.inputs.Amortization" | translate}}</mat-label>
<mat-select required matTooltip="{{ 'tooltips.The Amortization value' | translate}}" formControlName="amortizationType">
<mat-option *ngFor="let amortizationType of amortizationTypeData" [value]="amortizationType.id">
{{ amortizationType.value }}
</mat-option>
</mat-select>
<mat-error *ngIf="loansAccountTermsForm.controls.amortizationType.hasError('required')">
{{"labels.inputs.Amortization Type" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
</mat-error>
</mat-form-field>
<mat-checkbox fxFlex="48%" formControlName="isEqualAmortization"
<mat-checkbox fxFlex="23%" formControlName="isEqualAmortization"
[checked]="loansAccountTermsData?.isEqualAmortization">
<p>{{"labels.inputs.Is Equal Amortization" | translate}}</p>
</mat-checkbox>
<div fxFlex="48%" *ngIf="loanScheduleType">
<span fxFlex="40%"><p>{{"labels.inputs.Loan Schedule Type" | translate}}</p></span>
<span fxFlex="60%"><p>{{ loanScheduleType.value }}</p></span>
</div>
<mat-form-field fxFlex="48%">
<mat-label>{{"labels.inputs.Repayment Strategy" | translate}}</mat-label>
<mat-select formControlName="transactionProcessingStrategyCode" matTooltip="{{ 'tooltips.The repayment strategy' | translate}}" [disabled]="repaymentStrategyDisabled">
<mat-option *ngFor="let transactionProcessingStrategy of transactionProcessingStrategyOptions" [value]="transactionProcessingStrategy.code">
{{ transactionProcessingStrategy.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="loansAccountTermsForm.controls.transactionProcessingStrategyCode.hasError('required')">
{{"labels.inputs.Repayment Strategy" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
</mat-error>
</mat-form-field>
</ng-container>
<ng-container *ngIf="loansAccountTermsData?.isLoanProductLinkedToFloatingRate">
@@ -153,6 +156,18 @@
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>{{"labels.inputs.Amortization" | translate}}</mat-label>
<mat-select required matTooltip="{{ 'tooltips.The Amortization value' | translate}}" formControlName="amortizationType">
<mat-option *ngFor="let amortizationType of amortizationTypeData" [value]="amortizationType.id">
{{ amortizationType.value }}
</mat-option>
</mat-select>
<mat-error *ngIf="loansAccountTermsForm.controls.amortizationType.hasError('required')">
{{"labels.inputs.Amortization Type" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
</mat-error>
</mat-form-field>
<mat-checkbox fxFlex="48%" formControlName="isFloatingInterestRate">
<p>{{"labels.inputs.Is Floating Rate" | translate}}?</p>
</mat-checkbox>
@@ -161,15 +176,20 @@
</ng-container>
<div fxFlex="48%" *ngIf="loanScheduleType">
<span fxFlex="40%"><p>{{"labels.inputs.Loan Schedule Type" | translate}}</p></span>
<span fxFlex="60%"><p>{{ loanScheduleType.value }}</p></span>
</div>
<mat-form-field fxFlex="48%">
<mat-label>{{"labels.inputs.Amortization" | translate}}</mat-label>
<mat-select required matTooltip="{{ 'tooltips.The Amortization value' | translate}}" formControlName="amortizationType">
<mat-option *ngFor="let amortizationType of amortizationTypeData" [value]="amortizationType.id">
{{ amortizationType.value }}
<mat-label>{{"labels.inputs.Repayment Strategy" | translate}}</mat-label>
<mat-select formControlName="transactionProcessingStrategyCode" matTooltip="{{ 'tooltips.The repayment strategy' | translate}}" [disabled]="repaymentStrategyDisabled">
<mat-option *ngFor="let transactionProcessingStrategy of transactionProcessingStrategyOptions" [value]="transactionProcessingStrategy.code">
{{ transactionProcessingStrategy.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="loansAccountTermsForm.controls.amortizationType.hasError('required')">
{{"labels.inputs.Amortization Type" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
<mat-error *ngIf="loansAccountTermsForm.controls.transactionProcessingStrategyCode.hasError('required')">
{{"labels.inputs.Repayment Strategy" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
</mat-error>
</mat-form-field>
@@ -1,6 +1,6 @@
/** Angular Imports */
import { Component, OnInit, Input, OnChanges } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators, FormArray } from '@angular/forms';
import { UntypedFormGroup, UntypedFormBuilder, Validators, FormArray, UntypedFormControl } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute } from '@angular/router';
import { LoansAccountAddCollateralDialogComponent } from 'app/loans/custom-dialog/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component';
@@ -117,7 +117,6 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
'numberOfRepayments': this.loansAccountTermsData.numberOfRepayments,
'repaymentEvery': this.loansAccountTermsData.repaymentEvery,
'repaymentFrequencyType': this.loansAccountTermsData.repaymentFrequencyType.id,
'interestRatePerPeriod': this.loansAccountTermsData.interestRatePerPeriod,
'amortizationType': this.loansAccountTermsData.amortizationType.id,
'isEqualAmortization': this.loansAccountTermsData.isEqualAmortization,
'interestType': this.loansAccountTermsData.interestType.id,
@@ -136,6 +135,8 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
'multiDisburseLoan': this.loansAccountTermsData.multiDisburseLoan
});
this.setAdvancedPaymentStrategyControls();
if (this.loansAccountTermsData.isLoanProductLinkedToFloatingRate) {
this.loansAccountTermsForm.removeControl('interestRatePerPeriod');
}
@@ -205,7 +206,6 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
'numberOfRepayments': this.loansAccountTermsData.numberOfRepayments,
'repaymentEvery': this.loansAccountTermsData.repaymentEvery,
'repaymentFrequencyType': this.loansAccountTermsData.repaymentFrequencyType.id,
'interestRatePerPeriod': this.loansAccountTermsData.interestRatePerPeriod,
'amortizationType': this.loansAccountTermsData.amortizationType.id,
'isEqualAmortization': this.loansAccountTermsData.isEqualAmortization,
'interestType': this.loansAccountTermsData.interestType.id,
@@ -225,6 +225,7 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
});
}
this.createloansAccountTermsForm();
this.setAdvancedPaymentStrategyControls();
// this.setCustomValidators();
this.setLoanTermListener();
}
@@ -272,7 +273,27 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
.subscribe(loanTermFrequencyType => {
this.loansAccountTermsForm.patchValue({'repaymentFrequencyType': loanTermFrequencyType});
});
}
setAdvancedPaymentStrategyControls(): void {
// Fixed Length validation
if (this.loansAccountTermsData) {
this.loansAccountTermsForm.removeControl('interestRatePerPeriod');
this.loansAccountTermsForm.removeControl('fixedLength');
if (this.loansAccountTermsData.product.fixedLength) {
this.loansAccountTermsForm.addControl('interestRatePerPeriod', new UntypedFormControl({value: 0, disabled: true}, Validators.required));
this.loansAccountTermsForm.addControl('fixedLength', new UntypedFormControl({value: this.loansAccountTermsData.product.fixedLength, disabled: true}));
} else {
this.loansAccountTermsForm.addControl('interestRatePerPeriod', new UntypedFormControl(this.loansAccountTermsData.interestRatePerPeriod, Validators.required));
}
}
}
hasFixedLength(): boolean {
if (this.loansAccountTermsData) {
return this.loansAccountTermsData.product.fixedLength ? true : false;
}
return false;
}
/** Create Loans Account Terms Form */
@@ -472,7 +493,9 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
* Returns loans account terms form value.
*/
get loansAccountTerms() {
return this.loansAccountTermsForm.getRawValue();
const terms = this.loansAccountTermsForm.getRawValue();
delete terms['fixedLength'];
return terms;
}
get loanCollateral() {
@@ -64,11 +64,13 @@ export class TransactionsTabComponent implements OnInit {
this.dataSource = new MatTableDataSource(this.transactions);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.tempTransaction.forEach((element: any) => {
if (this.isAccrual(element.type)) {
this.tempTransaction = this.removeItem(this.tempTransaction, element);
}
});
if (this.tempTransaction) {
this.tempTransaction.forEach((element: any) => {
if (this.isAccrual(element.transactionType)) {
this.tempTransaction = this.removeItem(this.tempTransaction, element);
}
});
}
}
/**
@@ -17,7 +17,7 @@ import { DeleteDialogComponent } from '../../../shared/delete-dialog/delete-dial
templateUrl: './view-collateral.component.html',
styleUrls: ['./view-collateral.component.scss']
})
export class ViewCollateralComponent implements OnInit {
export class ViewCollateralComponent {
/** Collateral Data */
collateralData: any;
@@ -34,21 +34,18 @@ export class ViewCollateralComponent implements OnInit {
private route: ActivatedRoute,
private router: Router,
private dialog: MatDialog,
private translateService:TranslateService) {
private translateService: TranslateService) {
this.route.data.subscribe((data: { collateral: any }) => {
this.collateralData = data.collateral;
});
}
ngOnInit(): void {
}
}
/**
* Deletes the collateral and redirects to collaterals
*/
deleteCollateral() {
const deleteCollateralDialogRef = this.dialog.open(DeleteDialogComponent, {
data: { deleteContext: this.translateService.instant('labels.text.Collateral') + " " + this.collateralData.id}
data: { deleteContext: this.translateService.instant('labels.text.Collateral') + ' ' + this.collateralData.id}
});
deleteCollateralDialogRef.afterClosed().subscribe((response: any) => {
if (response.delete) {
@@ -21,7 +21,3 @@ mat-divider {
.margin-t {
margin-top: 1em;
}
.label-field {
margin-top: 32px;
}
@@ -177,7 +177,7 @@
</tr>
<tr *ngIf="savingsAccountData.enforceMinRequiredBalance">
<td>{{'labels.inputs.Enforce Minimum Required Balance' | translate}}</td>
<td>{{savingsAccountData.enforceMinRequiredBalance | formatNumber}}</td>
<td>{{savingsAccountData.enforceMinRequiredBalance | yesNo}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.lastInterestCalculationDate">
<td>{{'labels.inputs.Interest Recalculation Date' | translate}}</td>
@@ -59,11 +59,13 @@ export class TransactionsTabComponent implements OnInit {
this.accountWithTransactions = (this.transactionsData && this.transactionsData.length > 0);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.tempTransaction.forEach((element: any) => {
if (this.isAccrual(element.transactionType)) {
this.tempTransaction = this.removeItem(this.tempTransaction, element);
}
});
if (this.tempTransaction) {
this.tempTransaction.forEach((element: any) => {
if (this.isAccrual(element.transactionType)) {
this.tempTransaction = this.removeItem(this.tempTransaction, element);
}
});
}
}
private removeItem(arr: any, item: any) {
@@ -65,7 +65,7 @@ export class SavingsTransactionGeneralTabComponent implements OnInit {
locale
};
this.savingsService.executeSavingsAccountTransactionsCommand(this.accountId, 'undo', data, this.transactionData.id).subscribe(() => {
this.router.navigate(['../'], { relativeTo: this.route });
this.router.navigate(['../..'], { relativeTo: this.route });
});
}
});