feat: add loan button (reschedule loan) (#875)

Fixes: #245
This commit is contained in:
Muskan Khedia
2020-06-27 15:15:24 +05:30
committed by GitHub
parent 30dafba546
commit 8e86ccab8f
9 changed files with 232 additions and 2 deletions
@@ -38,6 +38,8 @@ export class LoanActionButtonResolver implements Resolve<Object> {
return this.loansService.getLoanActionTemplate(loanId, 'close');
} else if (loanActionButton === 'close-as-rescheduled') {
return this.loansService.getLoanActionTemplate(loanId, 'close-rescheduled');
} else if (loanActionButton === 'reschedule') {
return this.loansService.rescheduleLoanTemplate();
} else {
return this.loansService.getLoanActionTemplate(loanId, 'prepayLoan');
}
@@ -9,5 +9,6 @@
<mifosx-waive-interest [dataObject]="actionButtonData" *ngIf="actions.waive_interest"></mifosx-waive-interest>
<mifosx-write-off-page [dataObject]="actionButtonData" *ngIf="actions.write_off"></mifosx-write-off-page>
<mifosx-close-as-rescheduled [dataObject]="actionButtonData" *ngIf="actions.close_as_rescheduled"></mifosx-close-as-rescheduled>
<mifosx-loan-reschedule [dataObject]="actionButtonData" *ngIf="actions.reschedule"></mifosx-loan-reschedule>
</mat-card>
</div>
@@ -21,7 +21,8 @@ export class LoanAccountActionsComponent {
prepay_loan: boolean,
make_repayment: boolean,
waive_interest: boolean,
close_as_rescheduled: boolean } = {
close_as_rescheduled: boolean,
reschedule: boolean } = {
close: false,
undo_approval: false,
write_off: false,
@@ -30,7 +31,9 @@ export class LoanAccountActionsComponent {
prepay_loan: false,
make_repayment: false,
waive_interest: false,
close_as_rescheduled: false };
close_as_rescheduled: false,
reschedule: false };
actionButtonData: any;
actionName: any;
@@ -0,0 +1,99 @@
<div class="container">
<form [formGroup]="rescheduleLoanForm" (ngSubmit)="submit()">
<mat-card-content>
<div fxLayout="column">
<mat-form-field>
<mat-label>Reschedule from Installment On</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="rescheduleDatePicker" required formControlName="rescheduleFromDate">
<mat-datepicker-toggle matSuffix [for]="rescheduleDatePicker"></mat-datepicker-toggle>
<mat-datepicker #rescheduleDatePicker></mat-datepicker>
<mat-error *ngIf="rescheduleLoanForm.controls.rescheduleFromDate.hasError('required')">
Reschedule Date <strong>is required</strong>
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Reason for Rescheduling</mat-label>
<mat-select formControlName="rescheduleReasonId">
<mat-option *ngFor="let rescheduleReasonCode of codes" [value]="rescheduleReasonCode.id">
{{ rescheduleReasonCode.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="rescheduleLoanForm.controls.rescheduleReasonId.hasError('required')">
Reason for Rescheduling <strong>is required</strong>
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Submitted On</mat-label>
<input matInput [min]="minDate" [matDatepicker]="submittedDatePicker" required formControlName="submittedOnDate">
<mat-datepicker-toggle matSuffix [for]="submittedDatePicker"></mat-datepicker-toggle>
<mat-datepicker #submittedDatePicker></mat-datepicker>
<mat-error *ngIf="rescheduleLoanForm.controls.submittedOnDate.hasError('required')">
Submitted On Date <strong>is required</strong>
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Comments</mat-label>
<textarea matInput formControlName="rescheduleReasonComment"></textarea>
</mat-form-field>
<mat-checkbox [formControl]="changeRepaymentDate"> Change Repayment Date </mat-checkbox>
<ng-container *ngIf="changeRepaymentDate.value">
<mat-form-field>
<mat-label>Installment Rescheduled to</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="installmentrescheduledDatePicker" formControlName="adjustedDueDate">
<mat-datepicker-toggle matSuffix [for]="installmentrescheduledDatePicker"></mat-datepicker-toggle>
<mat-datepicker #installmentrescheduledDatePicker></mat-datepicker>
</mat-form-field>
</ng-container>
<mat-checkbox [formControl]="introduceGracePeriods"> Introduce Mid-term grace periods </mat-checkbox>
<ng-container *ngIf="introduceGracePeriods.value">
<mat-form-field>
<mat-label>Principal Grace Periods </mat-label>
<input matInput formControlName="graceOnPrincipal">
</mat-form-field>
<mat-form-field>
<mat-label>Interest Grace Periods </mat-label>
<input matInput formControlName="graceOnInterest">
</mat-form-field>
</ng-container>
<mat-checkbox [formControl]="extendRepaymentPeriod"> Extend Repayment Period </mat-checkbox>
<ng-container *ngIf="extendRepaymentPeriod.value">
<mat-form-field>
<mat-label>Number Of new Repayments</mat-label>
<input matInput formControlName="extraTerms">
</mat-form-field>
</ng-container>
<mat-checkbox [formControl]="adjustinterestrates"> Adjust interest rates for remainder of loan </mat-checkbox>
<ng-container *ngIf="adjustinterestrates.value">
<mat-form-field>
<mat-label>New Interest Rate</mat-label>
<input matInput formControlName="newInterestRate">
</mat-form-field>
</ng-container>
</div>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../general']">Cancel</button>
<button mat-raised-button color="primary" [disabled]="!rescheduleLoanForm.valid" *mifosxHasPermission="'APPROVE_RESCHEDULELOAN'">Submit</button>
</mat-card-actions>
</mat-card-content>
</form>
</div>
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LoanRescheduleComponent } from './loan-reschedule.component';
describe('LoanRescheduleComponent', () => {
let component: LoanRescheduleComponent;
let fixture: ComponentFixture<LoanRescheduleComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoanRescheduleComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoanRescheduleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,88 @@
import { Component, OnInit, Input } from '@angular/core';
import { LoansService } from 'app/loans/loans.service';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { DatePipe } from '@angular/common';
import { subscribeOn } from 'rxjs/operators';
@Component({
selector: 'mifosx-loan-reschedule',
templateUrl: './loan-reschedule.component.html',
styleUrls: ['./loan-reschedule.component.scss']
})
export class LoanRescheduleComponent implements OnInit {
@Input() dataObject: any;
loanId: any;
rescheduleLoanForm: FormGroup;
/** Minimum Date allowed. */
minDate = new Date(2000, 0, 1);
/** Maximum Date allowed. */
maxDate = new Date();
codes: any;
changeRepaymentDate = new FormControl(false);
introduceGracePeriods = new FormControl(false);
extendRepaymentPeriod = new FormControl(false);
adjustinterestrates = new FormControl(false);
/**
* @param {FormBuilder} formBuilder Form Builder.
* @param {LoansService} systemService Loan Service.
* @param {ActivatedRoute} route Activated Route.
* @param {Router} router Router for navigation.
*/
constructor(private formBuilder: FormBuilder,
private loanService: LoansService,
private route: ActivatedRoute,
private router: Router,
private datePipe: DatePipe) {
this.loanId = this.route.parent.snapshot.params['loanId'];
}
ngOnInit() {
this.codes = this.dataObject.rescheduleReasons;
this.setRescheduleLoanForm();
}
setRescheduleLoanForm() {
this.rescheduleLoanForm = this.formBuilder.group({
'rescheduleFromDate': [new Date(), Validators.required],
'rescheduleReasonId': ['', Validators.required],
'submittedOnDate': [new Date(), Validators.required],
'rescheduleReasonComment': [''],
'adjustedDueDate': [''],
'graceOnPrincipal': [''],
'graceOnInterest': [''],
'extraTerms': [''],
'newInterestRate': ['']
});
}
submit() {
const rescheduleFromDate = this.rescheduleLoanForm.value.rescheduleFromDate;
const adjustedDueDate = this.rescheduleLoanForm.value.adjustedDueDate;
const submittedOnDate = this.rescheduleLoanForm.value.submittedOnDate;
const dateFormat = 'dd MMMM yyyy';
this.rescheduleLoanForm.patchValue({
rescheduleFromDate: this.datePipe.transform(rescheduleFromDate, dateFormat),
adjustedDueDate: this.datePipe.transform(adjustedDueDate, dateFormat),
submittedOnDate: this.datePipe.transform(submittedOnDate, dateFormat)
});
const rescheduleForm = this.rescheduleLoanForm.value;
rescheduleForm.locale = 'en';
rescheduleForm.dateFormat = dateFormat;
rescheduleForm.loanId = this.loanId;
this.loanService.submitRescheduleData(rescheduleForm).subscribe((response: any) => {
// TODO: needs to be updated
// mentioned in Community App:
// location.path('/loans/' + scope.loanId + '/viewreschedulerequest/'+ data.resourceId);
this.router.navigate(['../general'], { relativeTo: this.route });
});
}
}
+2
View File
@@ -34,6 +34,7 @@ import { FloatingInterestRatesComponent } from './loans-view/floating-interest-r
import { WriteOffPageComponent } from './loans-view/loan-account-actions/write-off-page/write-off-page.component';
import { LoanTrancheDetailsComponent } from './loans-view/loan-tranche-details/loan-tranche-details.component';
import { CloseAsRescheduledComponent } from './loans-view/loan-account-actions/close-as-rescheduled/close-as-rescheduled.component';
import { LoanRescheduleComponent } from './loans-view/loan-account-actions/loan-reschedule/loan-reschedule.component';
/**
* Loans Module
@@ -68,6 +69,7 @@ import { CloseAsRescheduledComponent } from './loans-view/loan-account-actions/c
WriteOffPageComponent,
LoanTrancheDetailsComponent,
CloseAsRescheduledComponent,
LoanRescheduleComponent,
],
providers: [DatePipe],
})
+10
View File
@@ -188,4 +188,14 @@ export class LoansService {
return this.http.post(`/loans/${loanId}/transactions`, data, {params: httpParams});
}
rescheduleLoanTemplate() {
return this.http.get('/rescheduleloans/template');
}
submitRescheduleData(data: any) {
// https://staging.mifos.io/fineract-provider/api/v1/rescheduleloans?command=reschedule
const httpParams = new HttpParams().set('command', 'reschedule');
return this.http.post('/rescheduleloans', data, {params: httpParams});
}
}