fix: bug preventing individual loan application, improved GLIM (#2329)

This fixes a recently introduced bug preventing individual loan
applications. It also simplifies dramatically the GLIM process,
improving GLIM user experience and functionality.

Partially addresses: WEB-9
This commit is contained in:
Felix van Hove
2025-03-17 18:37:24 -06:00
committed by GitHub
parent fbdafafd8c
commit 08e3dfbf6e
26 changed files with 286 additions and 2481 deletions
@@ -132,6 +132,60 @@
<tr mat-header-row *matHeaderRowDef="overdueChargesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: overdueChargesDisplayedColumns"></tr>
</table>
<div fxFlex="98%" *ngIf="activeClientMembers">
<table fxFlex="98%" mat-table [dataSource]="dataSource">
<!-- Check Column -->
<ng-container matColumnDef="check">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox (change)="toggleSelects()" [(ngModel)]="selectAllItems"></mat-checkbox>
</th>
<td mat-cell *matCellDef="let element">
<mat-checkbox (change)="toggleSelect()" [(ngModel)]="element.selected"></mat-checkbox>
</td>
</ng-container>
<!-- Position Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Client ID' | translate }}</th>
<td mat-cell *matCellDef="let element">{{ element.id }}</td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Client Name' | translate }}</th>
<td mat-cell *matCellDef="let element">{{ element.displayName }}</td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="purpose">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Loan Purpose' | translate }}</th>
<td mat-cell *matCellDef="let element">
<mat-form-field>
<mat-label>{{ 'labels.inputs.Select Purpose' | translate }}</mat-label>
<mat-select [(ngModel)]="element.loanPurposeId">
<mat-option *ngFor="let purpose of loanPurposeOptions" [value]="purpose.id">
{{ purpose.name }}
</mat-option>
</mat-select>
</mat-form-field>
</td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Original Loan' | translate }}</th>
<td mat-cell *matCellDef="let element">
<mat-form-field>
<input type="number" matInput [(ngModel)]="element.principal" />
</mat-form-field>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumn"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumn"></tr>
</table>
</div>
</div>
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
@@ -1,12 +1,13 @@
/** Angular Imports */
import { Component, OnInit, Input, OnChanges } from '@angular/core';
import { FormControl } from '@angular/forms';
// import { FormControl } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { MatTableDataSource } from '@angular/material/table';
/** Dialog Components */
import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
import { LoansAccountAddCollateralDialogComponent } from 'app/loans/custom-dialog/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component';
// import { LoansAccountAddCollateralDialogComponent } from 'app/loans/custom-dialog/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component';
/** Custom Services */
import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base';
@@ -31,6 +32,8 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
@Input() loansAccountTemplate: any;
// @Input() loansAccountFormValid: LoansAccountFormValid
@Input() loansAccountFormValid: boolean;
/** active Client Members in case of GSIM Account */
@Input() activeClientMembers?: any;
/** Charges Data */
chargeData: any;
@@ -56,6 +59,20 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
'amount',
'collectedon'
];
/** Table Data Source */
dataSource: any;
/** Check for select all the Clients List */
selectAllItems = false;
/** Loan Purpose Options */
loanPurposeOptions: string[] = [];
/** Table Displayed Columns */
displayedColumn: string[] = [
'check',
'id',
'name',
'purpose',
'amount'
];
/** Component is pristine if there has been no changes by user interaction */
pristine = true;
/** Check if value of collateral added is more than principal amount */
@@ -84,6 +101,7 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
this.chargesDataSource =
this.loansAccountTemplate.charges.map((charge: any) => ({ ...charge, id: charge.chargeId })) || [];
}
this.dataSource = new MatTableDataSource<any>(this.activeClientMembers);
}
/**
@@ -91,6 +109,7 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
*/
ngOnChanges() {
if (this.loansAccountProductTemplate) {
this.loanPurposeOptions = this.loansAccountProductTemplate.loanPurposeOptions;
this.chargeData = this.loansAccountProductTemplate.chargeOptions;
if (this.loansAccountProductTemplate.overdueCharges) {
this.overDueChargesDataSource = this.loansAccountProductTemplate.overdueCharges;
@@ -236,6 +255,13 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
});
}
get isValid() {
return (
!this.activeClientMembers ||
this.selectedClientMembers?.selectedMembers?.reduce((acc: any, cur: any) => acc + (cur.principal ?? 0), 0) > 0
);
}
/**
* Returns Loans Account Charges and Collateral Form
*/
@@ -244,4 +270,22 @@ export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
charges: this.chargesDataSource
};
}
get selectedClientMembers() {
return { selectedMembers: this.activeClientMembers.filter((item: any) => item.selected) };
}
/** Toggle all checks */
toggleSelects() {
for (const member of this.activeClientMembers) {
member.selected = this.selectAllItems;
}
}
/** Check if all the checks are selected */
toggleSelect() {
const len = this.activeClientMembers.length;
this.selectAllItems =
len === 0 ? false : this.activeClientMembers.filter((item: any) => item.selected).length === len;
}
}
@@ -42,6 +42,10 @@
</span>
</div>
<div fxFlex="98%" *ngIf="activeClientMembers">
<! -- TODO: Display activeClientMembers -->
</div>
<h3 class="mat-h3" fxFlexFill>{{ 'labels.heading.Terms' | translate }}</h3>
<mat-divider fxFlexFill></mat-divider>
@@ -1,5 +1,6 @@
/** Angular Imports */
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
/**
* Create Loans Account Preview Step
@@ -16,6 +17,9 @@ export class LoansAccountPreviewStepComponent implements OnChanges {
@Input() loansAccountProductTemplate: any;
/** Loans Account Data */
@Input() loansAccount: any;
/** active Client Members in case of GSIM Account */
@Input() activeClientMembers?: any;
/** Submit Loans Account */
@Output() submitEvent = new EventEmitter();
@@ -35,11 +39,20 @@ export class LoansAccountPreviewStepComponent implements OnChanges {
'collectedon'
];
/** Table Data Source */
dataSource: any;
productEnableDownPayment = false;
constructor() {}
ngOnChanges(changes: SimpleChanges): void {
this.productEnableDownPayment = this.loansAccountProductTemplate.product.enableDownPayment;
if (this.activeClientMembers) {
this.dataSource = new MatTableDataSource<any>(this.activeClientMembers);
this.loansAccount.principalAmount = this.activeClientMembers.reduce(
(acc: number, member: any) => acc + (member.principal ?? 0),
0
);
}
}
}
@@ -146,6 +146,7 @@ export class LoansAccountTermsStepComponent implements OnInit, OnChanges {
amortizationType: this.loansAccountTermsData.amortizationType.id,
isEqualAmortization: this.loansAccountTermsData.isEqualAmortization,
interestType: this.loansAccountTermsData.interestType.id,
// TODO: 2025-03-17: Is this correct?
isFloatingInterestRate: this.loansAccountTermsData.isLoanProductLinkedToFloatingRate ? false : '',
interestCalculationPeriodType: this.loansAccountTermsData.interestCalculationPeriodType.id,
allowPartialPeriodInterestCalculation: this.loansAccountTermsData.allowPartialPeriodInterestCalculation,