Skip to content

Commit

Permalink
Add new interest pause and list existing interest pause periods of th…
Browse files Browse the repository at this point in the history
…e loan
  • Loading branch information
Jose Alberto Hernandez authored and alberto-art3ch committed Jan 6, 2025
1 parent a645521 commit d04890f
Show file tree
Hide file tree
Showing 37 changed files with 400 additions and 122 deletions.
2 changes: 1 addition & 1 deletion src/app/core/shell/breadcrumb/breadcrumb.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<nav class="breadcrumb-wrapper">
<ul class="breadcrumb">
<span #breadcrumb class="breadcrumb-title">{{ getTranslate(breadcrumbs[breadcrumbs.length - 1].label) }}</span>
<span #breadcrumb class="breadcrumb-title">{{ getTranslate(breadcrumbs[breadcrumbs?.length - 1].label) }}</span>
<span *ngIf="breadcrumbs.length - 1 !== 0" class="separator">
<li *ngFor="let breadcrumb of breadcrumbs; let last = last" class="breadcrumb-label">
<span *ngIf="!last" class="breadcrumb-link">
Expand Down
17 changes: 12 additions & 5 deletions src/app/core/shell/breadcrumb/breadcrumb.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,20 +117,20 @@ export class BreadcrumbComponent implements AfterViewInit {
breadcrumbLabel = route.snapshot.paramMap.get(route.snapshot.data[routeParamBreadcrumb]);
const routeData: Data = route.snapshot.data;
if (routeData.breadcrumb === 'Clients') {
breadcrumbLabel = routeData.clientViewData.displayName;
breadcrumbLabel = this.printableValue(routeData.clientViewData.displayName);
currentUrl += `/general`;
} else if (routeData.breadcrumb === 'Groups') {
breadcrumbLabel = routeData.groupViewData.name;
} else if (routeData.breadcrumb === 'Centers') {
breadcrumbLabel = routeData.centerViewData.name;
} else if (routeData.breadcrumb === 'Loans') {
breadcrumbLabel = routeData.loanDetailsData.loanProductName + ' (' + routeData.loanDetailsData.accountNo + ')';
breadcrumbLabel = this.printableValue(routeData.loanDetailsData.loanProductName) + ' (' + routeData.loanDetailsData.accountNo + ')';
} else if (routeData.breadcrumb === 'Savings') {
breadcrumbLabel = routeData.savingsAccountData.savingsProductName + ' (' + routeData.savingsAccountData.accountNo + ')';
breadcrumbLabel = this.printableValue(routeData.savingsAccountData.savingsProductName) + ' (' + routeData.savingsAccountData.accountNo + ')';
} else if (routeData.breadcrumb === 'Fixed Deposits') {
breadcrumbLabel = routeData.fixedDepositsAccountData.depositProductName + ' (' + routeData.fixedDepositsAccountData.accountNo + ')';
breadcrumbLabel = this.printableValue(routeData.fixedDepositsAccountData.depositProductName) + ' (' + routeData.fixedDepositsAccountData.accountNo + ')';
} else if (routeData.breadcrumb === 'Loan Products') {
breadcrumbLabel = routeData.loanProduct.name;
breadcrumbLabel = this.printableValue(routeData.loanProduct.name);
} else if (routeData.breadcrumb === 'Charges') {
breadcrumbLabel = routeData.loansAccountCharge.name;
} else if (routeData.breadcrumb === 'Saving Products') {
Expand Down Expand Up @@ -183,6 +183,13 @@ export class BreadcrumbComponent implements AfterViewInit {
});
}

printableValue(value: string): string {
if (value.length <= 30) {
return value;
}
return value.substring(0, 30) + '...';
}

/**
* Popover function
* @param template TemplateRef<any>.
Expand Down
33 changes: 33 additions & 0 deletions src/app/loans/common-resolvers/loan-term-variations.resolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';

/** rxjs Imports */
import { Observable } from 'rxjs';

/** Custom Services */
import { LoansService } from '../loans.service';

/**
* Clients data resolver.
*/
@Injectable()
export class LoanTermVariationsResolver implements Resolve<Object> {

/**
* @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');
if (!isNaN(+loanId)) {
return this.loansService.getInterestPausesOfLoan(loanId);
}
}

}
6 changes: 4 additions & 2 deletions src/app/loans/loans-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import { LoanCollateralsResolver } from './common-resolvers/loan-collaterals.res
import { LoanDelinquencyDataResolver } from './common-resolvers/loan-delinquency-data.resolver';
import { LoanDelinquencyActionsResolver } from './common-resolvers/loan-delinquency-actions.resolver';
import { LoanTermVariationsTabComponent } from './loans-view/loan-term-variations-tab/loan-term-variations-tab.component';
import { LoanTermVariationsResolver } from './common-resolvers/loan-term-variations.resolver';

/** Loans Route. */
const routes: Routes = [
Expand Down Expand Up @@ -171,7 +172,7 @@ const routes: Routes = [
component: LoanTermVariationsTabComponent,
data: { title: 'Loan Term Variations', breadcrumb: 'Loan Term Variations', routeParamBreadcrumb: false },
resolve: {
loanDetailsData: LoanDetailsResolver
loanTermVariationsData: LoanTermVariationsResolver
},
},
{
Expand Down Expand Up @@ -377,7 +378,8 @@ const routes: Routes = [
GSIMAccountsResolver,
GLIMLoanTemplateResolver,
ExternalAssetOwnerResolver,
LoanDelinquencyDataResolver
LoanDelinquencyDataResolver,
LoanTermVariationsResolver
]
})

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<div class="container mat-elevation-z8">
<mat-card>
<form [formGroup]="interestPauseLoanForm" (ngSubmit)="submit()">
<mat-card-content>
<div fxLayout="column">
<mat-form-field (click)="startDatePicker.open()">
<mat-label>{{ 'labels.inputs.Start Date' | translate }}</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="startDatePicker"
required formControlName="startDate" />
<mat-datepicker-toggle matSuffix [for]="startDatePicker"></mat-datepicker-toggle>
<mat-datepicker #startDatePicker></mat-datepicker>
<mat-error *ngIf="interestPauseLoanForm.controls.startDate.hasError('required')">
{{ 'labels.inputs.Start Date' | translate
}}<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>

<mat-form-field (click)="endDatePicker.open()">
<mat-label>{{ 'labels.inputs.End Date' | translate }}</mat-label>
<input matInput [min]="interestPauseLoanForm.value.startDate" [max]="maxDate" [matDatepicker]="endDatePicker"
required formControlName="endDate" />
<mat-datepicker-toggle matSuffix [for]="endDatePicker"></mat-datepicker-toggle>
<mat-datepicker #endDatePicker></mat-datepicker>
<mat-error *ngIf="interestPauseLoanForm.controls.endDate.hasError('required')">
{{ 'labels.inputs.End Date' | translate
}}<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
</mat-form-field>

</div>

<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../../general']">
{{ 'labels.buttons.Cancel' | translate }}
</button>
<button mat-raised-button color="primary" [disabled]="!interestPauseLoanForm.valid"
*mifosxHasPermission="'DISBURSE_LOAN'">
{{ 'labels.buttons.Submit' | translate }}
</button>
</mat-card-actions>
</mat-card-content>
</form>
</mat-card>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.expandcollapsebutton {
margin-top: -7px;
}

.container {
max-width: 37rem;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { AddInterestPauseComponent } from './add-interest-pause.component';

describe('AddInterestPauseComponent', () => {
let component: AddInterestPauseComponent;
let fixture: ComponentFixture<AddInterestPauseComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ AddInterestPauseComponent ]
})
.compileComponents();

fixture = TestBed.createComponent(AddInterestPauseComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { Component, Input, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Dates } from 'app/core/utils/dates';
import { LoansService } from 'app/loans/loans.service';
import { SettingsService } from 'app/settings/settings.service';

@Component({
selector: 'mifosx-add-interest-pause',
templateUrl: './add-interest-pause.component.html',
styleUrls: ['./add-interest-pause.component.scss']
})
export class AddInterestPauseComponent implements OnInit {

@Input() dataObject: any;
/** Loan Id */
loanId: string;
/** Payment Type Options */
paymentTypes: any;
/** Show payment details */
showPaymentDetails = false;
/** Minimum Date allowed. */
minDate = new Date(2000, 0, 1);
/** Maximum Date allowed. */
maxDate = new Date();
startDate = new Date();
/** Interest Pause Loan Form */
interestPauseLoanForm: UntypedFormGroup;

/**
* @param {FormBuilder} formBuilder Form Builder.
* @param {LoansService} loanService Loan Service.
* @param {ActivatedRoute} route Activated Route.
* @param {Router} router Router for navigation.
* @param {SettingsService} settingsService Settings Service
*/
constructor(private formBuilder: UntypedFormBuilder,
private loanService: LoansService,
private route: ActivatedRoute,
private router: Router,
private dateUtils: Dates,
private settingsService: SettingsService) {

this.loanId = this.route.snapshot.params['loanId'];
}

/**
* Creates the Interest Pause loan form
* and initialize with the required values
*/
ngOnInit() {
this.maxDate = new Date(this.dataObject.timeline.expectedMaturityDate);
this.startDate = new Date(this.settingsService.businessDate);
if (this.startDate < this.maxDate) {
this.maxDate = this.startDate;
} else {
this.startDate = this.maxDate;
}
this.createInterestPauseLoanForm();
}

/**
* Creates the Interest Pause loan form.
*/
createInterestPauseLoanForm() {
this.interestPauseLoanForm = this.formBuilder.group({
'startDate': [this.startDate, Validators.required],
'endDate': [this.startDate, Validators.required]
});
}

/** Submits the Interest Pause form */
submit() {
const interestPauseLoanFormData = this.interestPauseLoanForm.value;
const locale = this.settingsService.language.code;
const dateFormat = this.settingsService.dateFormat;
const startDate: Date = this.interestPauseLoanForm.value.startDate;
if (interestPauseLoanFormData.startDate instanceof Date) {
interestPauseLoanFormData.startDate = this.dateUtils.formatDate(startDate, dateFormat);
}
const endDate: Date = this.interestPauseLoanForm.value.endDate;
if (interestPauseLoanFormData.endDate instanceof Date) {
interestPauseLoanFormData.endDate = this.dateUtils.formatDate(endDate, dateFormat);
}
const data = {
...interestPauseLoanFormData,
dateFormat,
locale
};
this.loanService.addInterestPauseToLoan(this.loanId, data )
.subscribe((response: any) => {
this.router.navigate(['../../term-variations'], { relativeTo: this.route });
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@
<mifosx-asset-transfer-loan *ngIf="actions['Sell Loan'] || actions['Buy Back Loan']"></mifosx-asset-transfer-loan>
<mifosx-loan-reaging [dataObject]="actionButtonData" *ngIf="actions['Re-Age']"></mifosx-loan-reaging>
<mifosx-loan-reamortize [dataObject]="actionButtonData" *ngIf="actions['Re-Amortize']"></mifosx-loan-reamortize>
<mifosx-add-interest-pause [dataObject]="navigationData" *ngIf="actions['Add Interest Pause']"></mifosx-add-interest-pause>
Loading

0 comments on commit d04890f

Please sign in to comment.