diff --git a/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.html b/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.html index 23b0a1f5c..191a799f2 100644 --- a/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.html +++ b/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.html @@ -7,29 +7,29 @@

Loan Tranche Details

-
- - - - +
+ +
- +
- + @@ -41,12 +41,19 @@ - @@ -63,7 +70,7 @@ - + @@ -75,6 +82,4 @@
Expected Disbursement On {{ ele.expectedDisbursementDate | dateFormat}} {{ ele.expectedDisbursementDate | dateFormat}} Disbursed On - {{ ele.actualDisbursementDate | dateFormat }} + {{ ele.actualDisbursementDate | dateFormat }} Actions + - + Applicable From Date {{ ele.termVariationApplicableFrom | dateFormat}} {{ ele.termVariationApplicableFrom | dateFormat}}
- - diff --git a/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.ts b/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.ts index 5b29619b8..e553ccec6 100644 --- a/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.ts +++ b/src/app/loans/loans-view/loan-tranche-details/loan-tranche-details.component.ts @@ -1,5 +1,14 @@ import { Component, OnInit } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; import { ActivatedRoute } from '@angular/router'; +import { Dates } from 'app/core/utils/dates'; +import { LoansService } from 'app/loans/loans.service'; +import { SettingsService } from 'app/settings/settings.service'; +import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; +import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component'; +import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base'; +import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base'; +import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; @Component({ selector: 'mifosx-loan-tranche-details', @@ -10,63 +19,196 @@ export class LoanTrancheDetailsComponent implements OnInit { loanDetails: any; return: any; status: any; - totalDisbursedAmount: any; count: number; expectedDisbursementColumns: string[] = ['expected disbursement on', 'disbursed on', 'principal', 'action']; emivariationColumns: string[] = ['emi amount variation from', 'fixed emi amount']; + loanId: number; + currentPrincipalAmount: number; + minDate = new Date(2000, 0, 1); + maxDate = new Date(2100, 0, 1); + disbursementDataSource: {}[] = []; + totalMultiDisbursed: number = null; + disallowExpectedDisbursements = false; + pristine = true; + /** * Retrieves the loans data from `resolve`. * @param {ActivatedRoute} route Activated Route. */ - constructor(private route: ActivatedRoute) { + constructor(private route: ActivatedRoute, + public dialog: MatDialog, + private loanServices: LoansService, + private settingsService: SettingsService, + private dateUtils: Dates) { this.route.parent.data.subscribe((data: { loanDetailsData: any }) => { + this.loanId = data.loanDetailsData.id; this.loanDetails = data.loanDetailsData; + this.disallowExpectedDisbursements = this.loanDetails.disallowExpectedDisbursements || false; + this.disbursementDataSource = data.loanDetailsData.disbursementDetails; + this.currentPrincipalAmount = this.loanDetails.approvedPrincipal; }); } ngOnInit() { + this.maxDate = this.settingsService.maxFutureDate; this.status = this.loanDetails.status.value; } - showAddDeleteTrancheButtons(action: string) { + showAddTrancheButtons() { this.return = true; if ( this.status === 'Closed (obligations met)' || this.status === 'Overpaid' || this.status === 'Closed (rescheduled)' || this.status === 'Closed (written off)' || - this.status === 'Submitted and pending approval' + this.status === 'Submitted and pending approval' || + this.disallowExpectedDisbursements ) { this.return = false; } - this.totalDisbursedAmount = 0; - this.count = 0; - this.loanDetails.disbursementDetails.forEach((element: any) => { - if (element.actualDisbursementDate) { - this.totalDisbursedAmount += element.principal; - } else { - this.count += 1; - } - }); - if (this.totalDisbursedAmount === this.loanDetails.approvedPrincipal || this.return === false) { - return false; - } - if (this.count === 0 && action === 'deletedisbursedetails') { + this.calculateTotalDisbursedAmount(); + + if (this.totalMultiDisbursed === this.currentPrincipalAmount || this.return === false) { return false; } return true; } - showEdit(disbursementDetail: any) { + showActionsTrancheButtons() { if ( - (!disbursementDetail.actualDisbursementDate || disbursementDetail.actualDisbursementDate === null) && - this.status === 'Approved' + this.status === 'Closed (obligations met)' || + this.status === 'Overpaid' || + this.status === 'Closed (rescheduled)' || + this.status === 'Closed (written off)' || + this.status === 'Submitted and pending approval' || + this.disallowExpectedDisbursements ) { - return true; + return false; } - return false; + + return true; } + + /** + * Adds the Principal Disbursed. + */ + calculateTotalDisbursedAmount() { + this.totalMultiDisbursed = 0; + this.count = 0; + this.disbursementDataSource.forEach((item: any) => { + this.totalMultiDisbursed += (item.principal * 1); + this.count += 1; + }); + } + + buildForm(expectedDisbursementDate: Date, principal: number): FormfieldBase[] { + const formBase: FormfieldBase[] = [ + new DatepickerBase({ + controlName: 'expectedDisbursementDate', + label: 'Expected Disbursement Date', + value: expectedDisbursementDate || '', + type: 'datetime-local', + minDate: this.minDate, + maxDate: this.maxDate, + required: true, + order: 1 + }), + new InputBase({ + controlName: 'principal', + label: 'Principal', + value: principal, + type: 'number', + required: true, + order: 2 + }) + ]; + return formBase; + } + + /** + * Adds the Disbursement Data entry form to given Disbursement Data entry. + */ + addDisbursementDataEntry() { + this.calculateTotalDisbursedAmount(); + + const data = { + title: 'Add Disbursement Details', + layout: { addButtonText: 'Add' }, + formfields: this.buildForm(new Date(), (this.currentPrincipalAmount - this.totalMultiDisbursed)) + }; + const disbursementDialogRef = this.dialog.open(FormDialogComponent, { data }); + disbursementDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + const principal = response.data.value.principal * 1; + if ((this.totalMultiDisbursed + principal) <= this.currentPrincipalAmount) { + this.disbursementDataSource = this.disbursementDataSource.concat(response.data.value); + this.pristine = false; + } + } + }); + } + + /** + * Edit the Disbursement Data entry form to given Disbursement Data entry. + */ + editDisbursementDataEntry(index: number) { + const principal: number = this.disbursementDataSource[index]['principal'] * 1; + const expectedDisbursementDate: Date = this.dateUtils.parseDate(this.disbursementDataSource[index]['expectedDisbursementDate']); + + const data = { + title: 'Edit Disbursement Details', + layout: { addButtonText: 'Save' }, + formfields: this.buildForm(expectedDisbursementDate, principal) + }; + const disbursementDialogRef = this.dialog.open(FormDialogComponent, { data }); + disbursementDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + const newPrincipal = response.data.value.principal * 1; + if ((this.totalMultiDisbursed - principal + newPrincipal) <= this.currentPrincipalAmount) { + this.disbursementDataSource[index]['principal'] = newPrincipal; + this.disbursementDataSource[index]['expectedDisbursementDate'] = response.data.value.expectedDisbursementDate; + this.pristine = false; + } + } + }); + } + + removeDisbursementDataEntry(index: any) { + const dialogRef = this.dialog.open(DeleteDialogComponent, { + data: { deleteContext: `this` } + }); + dialogRef.afterClosed().subscribe((response: any) => { + if (response.delete) { + const principal = this.disbursementDataSource[index]['principal'] * 1; + this.disbursementDataSource.splice(index, 1); + this.disbursementDataSource = this.disbursementDataSource.concat([]); + this.totalMultiDisbursed -= principal; + this.pristine = false; + } + }); + } + + editDisbursementData() { + const disbursementData: any = []; + this.disbursementDataSource.forEach((item: any) => { + disbursementData.push({ + expectedDisbursementDate: this.dateUtils.formatDate(item.expectedDisbursementDate, this.settingsService.dateFormat), + principal: item.principal + }); + }); + + const payload = { + disbursementData: disbursementData, + dateFormat: this.settingsService.dateFormat, + locale: this.settingsService.language.code + }; + this.loanServices.editDisbursements(this.loanId, payload).toPromise() + .then(result => { + this.pristine = true; + }); + } + } diff --git a/src/app/loans/loans.service.ts b/src/app/loans/loans.service.ts index 82f8cdf0f..6f41caa20 100644 --- a/src/app/loans/loans.service.ts +++ b/src/app/loans/loans.service.ts @@ -239,7 +239,6 @@ export class LoansService { .set('locale', foreclosuredata.locale) .set('transactionDate', foreclosuredata.transactionDate); return this.http.get(`/loans/${loanId}/transactions/template`, { params: httpParams }); - } /** @@ -251,6 +250,14 @@ export class LoansService { return this.http.post(`/loans/${loanId}/transactions`, data, { params: httpParams }); } + /** + * @param {string|number} loanId Loan Id + * @param {any} data Data + */ + editDisbursements(loanId: any, data: any) { + return this.http.put(`/loans/${loanId}/disbursements/editDisbursements`, data); + } + /** * Returns the Reschedule Loans Template */