From e8bab81ebdba0d04952e7482052ffb217ffb9b4a Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Mon, 12 Sep 2022 19:03:04 -0500 Subject: [PATCH 1/2] Management Loan tranches --- .../loan-tranche-details.component.html | 41 +++-- .../loan-tranche-details.component.ts | 172 +++++++++++++++--- src/app/loans/loans.service.ts | 9 +- 3 files changed, 179 insertions(+), 43 deletions(-) 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..a7cd82b1b 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..e899cc479 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,26 +19,41 @@ 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; + 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.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)' || @@ -40,33 +64,133 @@ export class LoanTrancheDetailsComponent implements OnInit { ) { 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) { - if ( - (!disbursementDetail.actualDisbursementDate || disbursementDetail.actualDisbursementDate === null) && - this.status === 'Approved' - ) { - return true; - } - return false; + /** + * 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 */ From 23cc4fd6d7624303f071d8379febf17781006f1b Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Tue, 13 Sep 2022 14:30:35 -0500 Subject: [PATCH 2/2] Management Loan tranches --- .../loan-tranche-details.component.html | 4 ++-- .../loan-tranche-details.component.ts | 20 ++++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) 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 a7cd82b1b..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 @@ -47,12 +47,12 @@ 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 e899cc479..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 @@ -29,6 +29,7 @@ export class LoanTrancheDetailsComponent implements OnInit { maxDate = new Date(2100, 0, 1); disbursementDataSource: {}[] = []; totalMultiDisbursed: number = null; + disallowExpectedDisbursements = false; pristine = true; /** @@ -43,6 +44,7 @@ export class LoanTrancheDetailsComponent implements OnInit { 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; }); @@ -60,7 +62,8 @@ export class LoanTrancheDetailsComponent implements OnInit { 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; } @@ -74,6 +77,21 @@ export class LoanTrancheDetailsComponent implements OnInit { return true; } + showActionsTrancheButtons() { + 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.disallowExpectedDisbursements + ) { + return false; + } + + return true; + } + /** * Adds the Principal Disbursed. */