Support to pause and resume Loan Delinquency Classification (#1918)
Co-authored-by: Jose Alberto Hernandez <alberto@blue-daemon.local>
This commit is contained in:
co-authored by
Jose Alberto Hernandez
parent
3f4e9870b6
commit
a26c906d2c
@@ -1,16 +1,8 @@
|
||||
/** Angular Imports */
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MatTableDataSource, MatTable } from '@angular/material/table';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { FormControl } from '@angular/forms';
|
||||
|
||||
/** Custom Services */
|
||||
import { AccountTransfersService } from '../account-transfers.service';
|
||||
|
||||
/** Dialog Components */
|
||||
import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
|
||||
|
||||
/**
|
||||
* Recurring Deposits Standing Instructions Tab
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { LoansService } from '../loans.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class LoanDelinquencyActionsResolver implements Resolve<boolean> {
|
||||
|
||||
/**
|
||||
* @param {LoansService} LoansService Loans service.
|
||||
*/
|
||||
constructor(private loansService: LoansService) { }
|
||||
|
||||
/**
|
||||
* Returns the Loans with Association data.
|
||||
* @returns {Observable<any>}
|
||||
*/
|
||||
resolve(route: ActivatedRouteSnapshot): Observable<any> {
|
||||
const loanId = route.paramMap.get('loanId') || route.parent.paramMap.get('loanId');
|
||||
return this.loansService.getDelinquencyActions(loanId);
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
|
||||
<h2 mat-dialog-title>{{"labels.heading.Loan Delinquency Actions" | translate}}</h2>
|
||||
|
||||
<div mat-dialog-content [formGroup]="delinquencyActionForm" fxLayout="column">
|
||||
|
||||
<mat-form-field fxFlex="48%" (click)="validFromDatePicker.open()">
|
||||
<mat-label>{{"labels.inputs.Start Date" | translate}}</mat-label>
|
||||
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="validFromDatePicker" required
|
||||
formControlName="startDate">
|
||||
<mat-datepicker-toggle matSuffix [for]="validFromDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #validFromDatePicker></mat-datepicker>
|
||||
<mat-error *ngIf="delinquencyActionForm.controls.startDate.hasError('required')">
|
||||
{{"labels.inputs.Start Date" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field fxFlex="48%" (click)="validTillDatePicker.open()">
|
||||
<mat-label>{{"labels.inputs.End Date" | translate}}</mat-label>
|
||||
<input matInput [min]="delinquencyActionForm.value.startDate" [max]="maxDate" [matDatepicker]="validTillDatePicker" required
|
||||
formControlName="endDate">
|
||||
<mat-datepicker-toggle matSuffix [for]="validTillDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #validTillDatePicker></mat-datepicker>
|
||||
<mat-error *ngIf="delinquencyActionForm.controls.endDate.hasError('required')">
|
||||
{{"labels.inputs.End Date" | translate}} {{"labels.commons.is" | translate}} <strong>{{"labels.commons.required" | translate}}</strong>
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
</div>
|
||||
|
||||
<mat-dialog-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||
<button mat-raised-button mat-dialog-close> {{"labels.buttons.Cancel" | translate}} </button>
|
||||
<button mat-raised-button color="primary" [mat-dialog-close]="{ data: delinquencyActionForm }"
|
||||
[disabled]="!delinquencyActionForm.valid || delinquencyActionForm.pristine">{{"labels.buttons.Submit" | translate}}</button>
|
||||
</mat-dialog-actions>
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoanDelinquencyActionDialogComponent } from './loan-delinquency-action-dialog.component';
|
||||
|
||||
describe('LoanDelinquencyActionDialogComponent', () => {
|
||||
let component: LoanDelinquencyActionDialogComponent;
|
||||
let fixture: ComponentFixture<LoanDelinquencyActionDialogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LoanDelinquencyActionDialogComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(LoanDelinquencyActionDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-loan-delinquency-action-dialog',
|
||||
templateUrl: './loan-delinquency-action-dialog.component.html',
|
||||
styleUrls: ['./loan-delinquency-action-dialog.component.scss']
|
||||
})
|
||||
export class LoanDelinquencyActionDialogComponent implements OnInit {
|
||||
|
||||
delinquencyActionForm: UntypedFormGroup;
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date(2100, 0, 1);
|
||||
|
||||
constructor(public dialogRef: MatDialogRef<LoanDelinquencyActionDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private formBuilder: UntypedFormBuilder,
|
||||
private settingsService: SettingsService) {
|
||||
this.createDelinquencyActionForm();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.minDate = this.settingsService.businessDate;
|
||||
}
|
||||
|
||||
createDelinquencyActionForm() {
|
||||
this.delinquencyActionForm = this.formBuilder.group({
|
||||
'startDate': [new Date(), Validators.required],
|
||||
'endDate': ['', Validators.required],
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -59,6 +59,7 @@ import { ExternalAssetOwnerResolver } from './common-resolvers/external-asset-ow
|
||||
import { ExternalAssetOwnerActiveTransferResolver } from './common-resolvers/external-asset-owner-active-transfer.resolver';
|
||||
import { LoanCollateralsResolver } from './common-resolvers/loan-collaterals.resolver';
|
||||
import { LoanDelinquencyDataResolver } from './common-resolvers/loan-delinquency-data.resolver';
|
||||
import { LoanDelinquencyActionsResolver } from './common-resolvers/loan-delinquency-actions.resolver';
|
||||
|
||||
/** Loans Route. */
|
||||
const routes: Routes = [
|
||||
@@ -133,7 +134,8 @@ const routes: Routes = [
|
||||
data: { title: 'Loans Delinquency Tags', breadcrumb: 'Delinquency Tags', routeParamBreadcrumb: false },
|
||||
resolve: {
|
||||
loanDelinquencyTagsData: LoanDelinquencyTagsResolver,
|
||||
loanDelinquencyData: LoanDelinquencyDataResolver
|
||||
loanDelinquencyData: LoanDelinquencyDataResolver,
|
||||
loanDelinquencyActions: LoanDelinquencyActionsResolver
|
||||
},
|
||||
children: [
|
||||
{
|
||||
|
||||
+50
@@ -60,4 +60,54 @@
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<div fxLayout="row" fxLayoutAlign="flex-end" class="m-t-20 m-b-10" *ngIf="allowPause">
|
||||
<button mat-raised-button color="primary" (click)="createDelinquencyAction()" *mifosxHasPermission="'CREATE_DELINQUENCY_ACTION'">
|
||||
<fa-icon icon="pause" class="m-r-10"></fa-icon>{{ 'labels.buttons.Pause Delinquency Classification' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="loanDelinquencyActions.length > 0" class="m-t-10">
|
||||
<h3>{{"labels.heading.Loan Delinquency Actions" | translate}}</h3>
|
||||
|
||||
<table mat-table [dataSource]="loanDelinquencyActions">
|
||||
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Action" | translate}} </th>
|
||||
<td mat-cell *matCellDef="let item" ngClass="{{actionClass(item.action)}}"> {{ item.action }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="startDate">
|
||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Start Date" | translate}} </th>
|
||||
<td mat-cell *matCellDef="let item"> {{ item.startDate | dateFormat }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="endDate">
|
||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.End Date" | translate}} </th>
|
||||
<td mat-cell *matCellDef="let item"> {{ item.endDate | dateFormat }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="createdOn">
|
||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Created On" | translate}} </th>
|
||||
<td mat-cell *matCellDef="let item"> {{ item.createdOn | datetimeFormat }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="actions">
|
||||
<th mat-header-cell *matHeaderCellDef> {{"labels.inputs.Actions" | translate}} </th>
|
||||
<td mat-cell *matCellDef="let item">
|
||||
<span *ngIf="isCurrentAndPauseAction(item)">
|
||||
<button mat-button color="primary" (click)="resumeDelinquencyClassification(item)"
|
||||
*mifosxHasPermission="'CREATE_DELINQUENCY_ACTION'" matTooltip="{{'tooltips.Resume Delinquency Classification' | translate}}" >
|
||||
<fa-icon icon="play" class="m-r-10"></fa-icon>
|
||||
</button>
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="loanDelinquencyActionsColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: loanDelinquencyActionsColumns;"></tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
+109
-4
@@ -1,6 +1,12 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { DelinquentData, InstallmentLevelDelinquency } from 'app/loans/models/loan-account.model';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { LoanDelinquencyActionDialogComponent } from 'app/loans/custom-dialog/loan-delinquency-action-dialog/loan-delinquency-action-dialog.component';
|
||||
import { LoansService } from 'app/loans/loans.service';
|
||||
import { DelinquentData, InstallmentLevelDelinquency, LoanDelinquencyAction, LoanDelinquencyTags } from 'app/loans/models/loan-account.model';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { ConfirmationDialogComponent } from 'app/shared/confirmation-dialog/confirmation-dialog.component';
|
||||
import { Currency } from 'app/shared/models/general.model';
|
||||
|
||||
@Component({
|
||||
@@ -10,15 +16,34 @@ import { Currency } from 'app/shared/models/general.model';
|
||||
})
|
||||
export class LoanDelinquencyTagsTabComponent implements OnInit {
|
||||
|
||||
loanDelinquencyTags: any;
|
||||
loanDelinquencyTags: LoanDelinquencyTags[] = [];
|
||||
loanDelinquencyActions: LoanDelinquencyAction[] = [];
|
||||
currentLoanDelinquencyAction: LoanDelinquencyAction | null;
|
||||
currency: Currency;
|
||||
installmentLevelDelinquency: InstallmentLevelDelinquency[] = [];
|
||||
loanDelinquencyTagsColumns: string[] = ['classification', 'addedOn', 'liftedOn'];
|
||||
loanDelinquencyActionsColumns: string[] = ['action', 'startDate', 'endDate', 'createdOn', 'actions'];
|
||||
installmentDelinquencyTagsColumns: string[] = ['classification', 'minimumAgeDays', 'amount'];
|
||||
|
||||
constructor(private route: ActivatedRoute) {
|
||||
this.route.parent.data.subscribe((data: { loanDelinquencyTagsData: any, loanDelinquencyData: any }) => {
|
||||
allowPause = true;
|
||||
loanId: any;
|
||||
|
||||
locale: string;
|
||||
dateFormat: string;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private loansServices: LoansService,
|
||||
private dateUtils: Dates,
|
||||
private settingsService: SettingsService,
|
||||
public dialog: MatDialog) {
|
||||
this.loanId = this.route.parent.parent.snapshot.params['loanId'];
|
||||
|
||||
this.route.parent.data.subscribe((data: { loanDelinquencyTagsData: LoanDelinquencyTags[],
|
||||
loanDelinquencyData: any,
|
||||
loanDelinquencyActions: LoanDelinquencyAction[] }) => {
|
||||
this.loanDelinquencyTags = data.loanDelinquencyTagsData;
|
||||
this.loanDelinquencyActions = data.loanDelinquencyActions || [];
|
||||
this.validateDelinquencyActions();
|
||||
const loanDelinquencyData: DelinquentData | null = data.loanDelinquencyData.delinquent || null;
|
||||
this.currency = data.loanDelinquencyData.currency;
|
||||
this.installmentLevelDelinquency = [];
|
||||
@@ -29,6 +54,86 @@ export class LoanDelinquencyTagsTabComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.locale = this.settingsService.language.code;
|
||||
this.dateFormat = this.settingsService.dateFormat;
|
||||
this.currentLoanDelinquencyAction = null;
|
||||
this.validateDelinquencyActions();
|
||||
}
|
||||
|
||||
validateDelinquencyActions(): void {
|
||||
if (this.loanDelinquencyActions.length > 0) {
|
||||
const businessDate: Date = this.settingsService.businessDate;
|
||||
this.currentLoanDelinquencyAction = this.loanDelinquencyActions[this.loanDelinquencyActions.length - 1];
|
||||
this.allowPause = (this.currentLoanDelinquencyAction.action === 'RESUME');
|
||||
}
|
||||
}
|
||||
|
||||
createDelinquencyAction(): void {
|
||||
const action = 'pause';
|
||||
const loanDelinquencyActionDialogRef = this.dialog.open(LoanDelinquencyActionDialogComponent, {
|
||||
data: {
|
||||
action: action
|
||||
},
|
||||
});
|
||||
loanDelinquencyActionDialogRef.afterClosed().subscribe((response: { data: any }) => {
|
||||
const startDate: Date = response.data.value.startDate;
|
||||
const endDate: Date = response.data.value.endDate;
|
||||
|
||||
this.sendDelinquencyAction(action, startDate, endDate);
|
||||
});
|
||||
}
|
||||
|
||||
resumeDelinquencyClassification(item: LoanDelinquencyAction): void {
|
||||
const removePauseDialogRef = this.dialog.open(ConfirmationDialogComponent, {
|
||||
data: { heading: 'Loan Delinquency Classification',
|
||||
dialogContext: 'Are you sure you want resume the Delinquency Classification for Loan ' + this.loanId,
|
||||
type: 'Mild'
|
||||
}
|
||||
});
|
||||
removePauseDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.confirm) {
|
||||
this.sendDelinquencyAction('resume', new Date(), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sendDelinquencyAction(action: string, startDate: Date, endDate: Date): void {
|
||||
let payload: any = {
|
||||
action,
|
||||
locale: this.locale,
|
||||
dateFormat: this.dateFormat,
|
||||
startDate: this.dateUtils.formatDate(startDate, this.dateFormat)
|
||||
};
|
||||
if (action === 'pause') {
|
||||
payload = {
|
||||
action,
|
||||
locale: this.locale,
|
||||
dateFormat: this.dateFormat,
|
||||
startDate: this.dateUtils.formatDate(startDate, this.dateFormat),
|
||||
endDate: this.dateUtils.formatDate(endDate, this.dateFormat)
|
||||
};
|
||||
}
|
||||
|
||||
this.loansServices.createDelinquencyActions(this.loanId, payload).subscribe((result: any) => {
|
||||
this.loansServices.getDelinquencyActions(this.loanId).subscribe((loanDelinquencyActions: LoanDelinquencyAction[]) => {
|
||||
this.loanDelinquencyActions = loanDelinquencyActions;
|
||||
this.validateDelinquencyActions();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
isCurrentAndPauseAction(item: LoanDelinquencyAction): boolean {
|
||||
if (this.currentLoanDelinquencyAction != null) {
|
||||
return (this.currentLoanDelinquencyAction.id === item.id && item.action === 'PAUSE');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
actionClass(action: string): string {
|
||||
if (action === 'PAUSE') {
|
||||
return 'status-pending';
|
||||
}
|
||||
return 'status-active';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,28 +20,34 @@
|
||||
<h3>
|
||||
<i class="fa fa-stop" matTooltip="{{'labels.status.' + loanDetailsData.status.value | translate}}"
|
||||
[ngClass]="loanDetailsData.inArrears?'status-active-overdue':( iconLoanStatusColor() | statusLookup)"></i>
|
||||
{{'labels.heading.Loan Product' | translate}}: {{loanDetailsData.loanProductName}}
|
||||
<span class="m-r-10">{{'labels.heading.Loan Product' | translate}}:</span> {{loanDetailsData.loanProductName}}
|
||||
<mifosx-account-number accountNo="{{loanDetailsData.accountNo}}"></mifosx-account-number>
|
||||
</h3>
|
||||
<span class="loans-overview">
|
||||
{{'labels.text.' + entityType | translate}} {{"labels.inputs.name" | translate}}: {{loanDetailsData.clientName ||
|
||||
loanDetailsData.groupName}}<span class="m-l-10">({{loanDetailsData.clientAccountNo}})</span><br />
|
||||
<span class="m-r-10">{{'labels.text.' + entityType | translate}} {{"labels.inputs.name" | translate}} :</span> {{loanDetailsData.clientName ||
|
||||
loanDetailsData.groupName}}<span class="m-l-5">({{loanDetailsData.clientAccountNo}})</span><br />
|
||||
</span>
|
||||
<div *ngIf="loanDisplayArrearsDelinquency != 1">
|
||||
<span class="loans-overview" *ngIf="loanDetailsData.delinquencyRange">
|
||||
{{"labels.inputs.Loan Account Classification" | translate}} :
|
||||
{{loanDetailsData?.delinquencyRange.classification}}<br />
|
||||
</span>
|
||||
<span class="loans-overview"
|
||||
*ngIf="loanDetailsData.delinquent && loanDetailsData.delinquent.pastDueDays > 0">
|
||||
{{"labels.inputs.Past Due Days" | translate}} : {{loanDetailsData?.delinquent.pastDueDays |
|
||||
formatNumber }}<br />
|
||||
</span>
|
||||
<span class="loans-overview" *ngIf="loanDetailsData.delinquent && loanDetailsData.delinquent.delinquentDays > 0
|
||||
&& loanDetailsData.delinquent.pastDueDays != loanDetailsData.delinquent.delinquentDays">
|
||||
{{"labels.inputs.Delinquent Days" | translate}} : {{loanDetailsData?.delinquent.delinquentDays |
|
||||
formatNumber }}
|
||||
</span>
|
||||
<table class="account-overview">
|
||||
<tbody>
|
||||
<tr *ngIf="loanDetailsData.delinquencyRange">
|
||||
<td>{{"labels.inputs.Delinquency Classification" | translate}} :</td>
|
||||
<td>
|
||||
<span class="m-r-3"><i [ngClass]="loanDelinquencyClassificationStyle"></i></span>
|
||||
{{loanDetailsData?.delinquencyRange.classification}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr *ngIf="loanDetailsData.delinquent && loanDetailsData.delinquent.pastDueDays > 0">
|
||||
<td>{{"labels.inputs.Past Due Days" | translate}} :</td>
|
||||
<td>{{loanDetailsData?.delinquent.pastDueDays | formatNumber }}</td>
|
||||
</tr>
|
||||
<tr *ngIf="loanDetailsData.delinquent && loanDetailsData.delinquent.delinquentDays > 0
|
||||
&& loanDetailsData.delinquent.pastDueDays != loanDetailsData.delinquent.delinquentDays">
|
||||
<td>{{"labels.inputs.Delinquent Days" | translate}} :</td>
|
||||
<td>{{loanDetailsData?.delinquent.delinquentDays | formatNumber }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,40 +1,8 @@
|
||||
.loan-card {
|
||||
margin: 0 auto;
|
||||
max-width: 80rem;
|
||||
width: 90%;
|
||||
padding: 0;
|
||||
.header {
|
||||
padding: 1%;
|
||||
.header-title-group {
|
||||
.loan-card-title {
|
||||
color: white;
|
||||
width: 90%;
|
||||
p {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.profile-image-container {
|
||||
margin: 1%;
|
||||
.profile-image {
|
||||
object-fit: cover;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
.loan-actions {
|
||||
align-self: flex-end;
|
||||
margin: 0 1%;
|
||||
// min-width: 72%;
|
||||
}
|
||||
.loan-span {
|
||||
margin: 0 0.5%;
|
||||
}
|
||||
}
|
||||
.navigation-tabs {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.loans-overview {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.account-overview {
|
||||
min-width: 60%;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { ConfirmationDialogComponent } from '../../shared/confirmation-dialog/co
|
||||
import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
|
||||
import { LoanStatus } from '../models/loan-status.model';
|
||||
import { Currency } from 'app/shared/models/general.model';
|
||||
import { DelinquencyPausePeriod } from '../models/loan-account.model';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-loans-view',
|
||||
@@ -42,6 +43,7 @@ export class LoansViewComponent implements OnInit {
|
||||
/** Disburse Transaction number */
|
||||
disburseTransactionNo = 0;
|
||||
|
||||
loanDelinquencyClassificationStyle = '';
|
||||
loanStatus: LoanStatus;
|
||||
currency: Currency;
|
||||
|
||||
@@ -80,6 +82,7 @@ export class LoansViewComponent implements OnInit {
|
||||
} else if (this.router.url.includes('centers')) {
|
||||
this.entityType = 'Center';
|
||||
}
|
||||
this.loanDelinquencyClassification();
|
||||
}
|
||||
|
||||
// Defines the buttons based on the status of the loan account
|
||||
@@ -199,6 +202,17 @@ export class LoansViewComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
loanDelinquencyClassification(): void {
|
||||
this.loanDelinquencyClassificationStyle = '';
|
||||
if (this.loanDetailsData.delinquent && this.loanDetailsData.delinquent.delinquencyPausePeriods) {
|
||||
this.loanDetailsData.delinquent.delinquencyPausePeriods.some((period: DelinquencyPausePeriod) => {
|
||||
if (period.active) {
|
||||
this.loanDelinquencyClassificationStyle = 'fa fa-stop status-pending';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
iconLoanStatusColor() {
|
||||
if (this.loanDetailsData.chargedOff) {
|
||||
return 'loanStatusType.chargeoff';
|
||||
|
||||
@@ -79,6 +79,7 @@ import { AssetTransferLoanComponent } from './loans-view/loan-account-actions/as
|
||||
import { ExternalAssetOwnerTabComponent } from './loans-view/external-asset-owner-tab/external-asset-owner-tab.component';
|
||||
import { ExternalAssetTransferComponent } from './loans-view/external-asset-owner-tab/external-asset-transfer/external-asset-transfer.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { LoanDelinquencyActionDialogComponent } from './custom-dialog/loan-delinquency-action-dialog/loan-delinquency-action-dialog.component';
|
||||
|
||||
/**
|
||||
* Loans Module
|
||||
@@ -161,7 +162,8 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
ChargeOffComponent,
|
||||
AssetTransferLoanComponent,
|
||||
ExternalAssetOwnerTabComponent,
|
||||
ExternalAssetTransferComponent
|
||||
ExternalAssetTransferComponent,
|
||||
LoanDelinquencyActionDialogComponent
|
||||
],
|
||||
providers: [ ],
|
||||
})
|
||||
|
||||
@@ -82,6 +82,14 @@ export class LoansService {
|
||||
return this.http.get(`/loans/${loanId}`, { params: httpParams });
|
||||
}
|
||||
|
||||
getDelinquencyActions(loanId: string) {
|
||||
return this.http.get(`/loans/${loanId}/delinquency-actions`);
|
||||
}
|
||||
|
||||
createDelinquencyActions(loanId: string, delinquencyActions: any) {
|
||||
return this.http.post(`/loans/${loanId}/delinquency-actions`, delinquencyActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the loan template data with specific condition
|
||||
* @param loanId Loan Id
|
||||
|
||||
@@ -24,3 +24,28 @@ export interface InstallmentLevelDelinquency {
|
||||
minimumAgeDays: number;
|
||||
delinquentAmount: number;
|
||||
}
|
||||
|
||||
export interface LoanDelinquencyTags {
|
||||
id: number;
|
||||
loanId: number;
|
||||
delinquencyRange: DelinquencyRange;
|
||||
addedOnDate: number[];
|
||||
liftedOnDate: number[];
|
||||
}
|
||||
|
||||
export interface LoanDelinquencyAction {
|
||||
id: number;
|
||||
action: string;
|
||||
startDate: number[];
|
||||
endDate: number[];
|
||||
createdById: number;
|
||||
createdOn: Date;
|
||||
updatedById: number;
|
||||
lastModifiedOn: Date;
|
||||
}
|
||||
|
||||
export interface DelinquencyPausePeriod {
|
||||
active: boolean;
|
||||
pausePeriodStart: number[];
|
||||
pausePeriodEnd: number[];
|
||||
}
|
||||
|
||||
@@ -107,7 +107,8 @@ import {
|
||||
faFileExcel,
|
||||
faFileExport,
|
||||
faCalculator,
|
||||
faCalendarCheck
|
||||
faCalendarCheck,
|
||||
faPause
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
/**
|
||||
@@ -177,6 +178,7 @@ export class IconsModule {
|
||||
faMinusCircle,
|
||||
faMoneyBillAlt,
|
||||
faMoneyCheck,
|
||||
faPause,
|
||||
faPencilAlt,
|
||||
faPlay,
|
||||
faPlus,
|
||||
|
||||
Reference in New Issue
Block a user