From f6b403804e8245a41b43d27d102bb27ecc64143d Mon Sep 17 00:00:00 2001 From: mariiaKraievska Date: Thu, 4 Dec 2025 17:32:06 +0200 Subject: [PATCH] WEB-477: Re-amortization:- Preview Schedule API during re-amortization --- .../loan-reamortize.component.html | 10 +++ .../loan-reamortize.component.ts | 76 ++++++++++++++++++- .../re-amortize-preview-dialog.component.html | 16 ++++ .../re-amortize-preview-dialog.component.ts | 45 +++++++++++ src/app/loans/loans.service.ts | 18 +++++ 5 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/app/loans/loans-view/loan-account-actions/loan-reamortize/re-amortize-preview-dialog/re-amortize-preview-dialog.component.html create mode 100644 src/app/loans/loans-view/loan-account-actions/loan-reamortize/re-amortize-preview-dialog/re-amortize-preview-dialog.component.ts diff --git a/src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.html b/src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.html index 938e085b3..dd3577525 100644 --- a/src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.html +++ b/src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.html @@ -60,6 +60,16 @@ > {{ 'labels.buttons.Submit' | translate }} + diff --git a/src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.ts b/src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.ts index d0743ea2b..9d8a6628f 100644 --- a/src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.ts @@ -1,10 +1,14 @@ import { Component, Input, OnInit, inject } from '@angular/core'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; +import { MatDialog } from '@angular/material/dialog'; import { LoansService } from 'app/loans/loans.service'; +import { RepaymentSchedule } from 'app/loans/models/loan-account.model'; import { CodeValue } from 'app/shared/models/general.model'; import { OptionData } from 'app/shared/models/option-data.model'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; +import { SettingsService } from 'app/settings/settings.service'; +import { ReAmortizePreviewDialogComponent } from './re-amortize-preview-dialog/re-amortize-preview-dialog.component'; @Component({ selector: 'mifosx-loan-reamortize', @@ -19,6 +23,8 @@ export class LoanReamortizeComponent implements OnInit { private route = inject(ActivatedRoute); private router = inject(Router); private loanService = inject(LoansService); + private settingsService = inject(SettingsService); + private dialog = inject(MatDialog); @Input() dataObject: any; /** Loan Id */ @@ -50,8 +56,76 @@ export class LoanReamortizeComponent implements OnInit { }); } - submit(): void { + private prepareReAmortizeData() { const data = this.reamortizeLoanForm.value; + const locale = this.settingsService.language.code; + const dateFormat = this.settingsService.dateFormat; + + return { + ...data, + dateFormat, + locale + }; + } + + private prepareReAmortizePreviewData() { + const reamortizeLoanFormData = { ...this.reamortizeLoanForm.value }; + const locale = this.settingsService.language.code; + const dateFormat = this.settingsService.dateFormat; + + // Prepare reAmortizationInterestHandling for preview API + let reAmortizationInterestHandling = reamortizeLoanFormData.reAmortizationInterestHandling; + if (reAmortizationInterestHandling && typeof reAmortizationInterestHandling === 'object') { + reAmortizationInterestHandling = reAmortizationInterestHandling.id; + } + // If no value selected, use "default" for preview + if (!reAmortizationInterestHandling && reAmortizationInterestHandling !== 0) { + reAmortizationInterestHandling = 'default'; + } + + delete reamortizeLoanFormData.reAmortizationInterestHandling; + + return { + ...reamortizeLoanFormData, + reAmortizationInterestHandling: reAmortizationInterestHandling, + dateFormat, + locale + }; + } + + preview(): void { + if (this.reamortizeLoanForm.invalid) { + return; + } + const data = this.prepareReAmortizePreviewData(); + + this.loanService.getReAmortizePreview(this.loanId, data).subscribe({ + next: (response: RepaymentSchedule) => { + const currencyCode = response.currency?.code; + + if (!currencyCode) { + console.error('Currency code is not available in API response'); + return; + } + + this.dialog.open(ReAmortizePreviewDialogComponent, { + data: { + repaymentSchedule: response, + currencyCode: currencyCode + }, + width: '95%', + maxWidth: '1400px', + height: '90vh' + }); + }, + error: (error) => { + console.error('Error loading re-amortize preview:', error); + } + }); + } + + submit(): void { + const data = this.prepareReAmortizeData(); this.loanService.submitLoanActionButton(this.loanId, data, 'reAmortize').subscribe((response: any) => { this.router.navigate(['../../transactions'], { relativeTo: this.route }); }); diff --git a/src/app/loans/loans-view/loan-account-actions/loan-reamortize/re-amortize-preview-dialog/re-amortize-preview-dialog.component.html b/src/app/loans/loans-view/loan-account-actions/loan-reamortize/re-amortize-preview-dialog/re-amortize-preview-dialog.component.html new file mode 100644 index 000000000..e33efb236 --- /dev/null +++ b/src/app/loans/loans-view/loan-account-actions/loan-reamortize/re-amortize-preview-dialog/re-amortize-preview-dialog.component.html @@ -0,0 +1,16 @@ +

{{ 'labels.heading.Repayment Schedule Preview' | translate }}

+ + + + + + + + + diff --git a/src/app/loans/loans-view/loan-account-actions/loan-reamortize/re-amortize-preview-dialog/re-amortize-preview-dialog.component.ts b/src/app/loans/loans-view/loan-account-actions/loan-reamortize/re-amortize-preview-dialog/re-amortize-preview-dialog.component.ts new file mode 100644 index 000000000..f612bc943 --- /dev/null +++ b/src/app/loans/loans-view/loan-account-actions/loan-reamortize/re-amortize-preview-dialog/re-amortize-preview-dialog.component.ts @@ -0,0 +1,45 @@ +import { Component, inject, Inject } from '@angular/core'; +import { + MAT_DIALOG_DATA, + MatDialogRef, + MatDialogTitle, + MatDialogContent, + MatDialogActions +} from '@angular/material/dialog'; +import { MatButton } from '@angular/material/button'; +import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; +import { RepaymentSchedule } from 'app/loans/models/loan-account.model'; +import { RepaymentScheduleTabComponent } from '../../../repayment-schedule-tab/repayment-schedule-tab.component'; + +export interface ReAmortizePreviewDialogData { + repaymentSchedule: RepaymentSchedule; + currencyCode: string; +} + +@Component({ + selector: 'mifosx-re-amortize-preview-dialog', + templateUrl: './re-amortize-preview-dialog.component.html', + standalone: true, + imports: [ + ...STANDALONE_SHARED_IMPORTS, + MatDialogTitle, + MatDialogContent, + MatDialogActions, + MatButton, + RepaymentScheduleTabComponent + ] +}) +export class ReAmortizePreviewDialogComponent { + // inject() replaces constructor injection + private readonly dialogRef = inject>(MatDialogRef); + + private readonly data = inject(MAT_DIALOG_DATA); + + // public fields used in template + readonly repaymentSchedule: RepaymentSchedule = this.data.repaymentSchedule; + readonly currencyCode: string = this.data.currencyCode; + + close(): void { + this.dialogRef.close(); + } +} diff --git a/src/app/loans/loans.service.ts b/src/app/loans/loans.service.ts index 870906317..0e84ca31c 100644 --- a/src/app/loans/loans.service.ts +++ b/src/app/loans/loans.service.ts @@ -258,6 +258,24 @@ export class LoansService { return this.http.get(`/loans/${loanId}/transactions/reage-preview`, { params: httpParams }); } + /** + * Get Re-Amortize preview with repayment schedule + * @param loanId Loan Id + * @param data Re-Amortize data + * @returns Observable with repayment schedule preview + */ + getReAmortizePreview(loanId: string, data: any): Observable { + let httpParams = new HttpParams(); + + Object.keys(data).forEach((key) => { + if (data[key] !== null && data[key] !== undefined && data[key] !== '') { + httpParams = httpParams.set(key, data[key].toString()); + } + }); + + return this.http.get(`/loans/${loanId}/transactions/reamortized-preview`, { params: httpParams }); + } + getLoanScreenReportsData(): Observable { const httpParams = new HttpParams().set('entityId', '1').set('typeId', '0'); return this.http.get(`/templates`, { params: httpParams });