Skip to content

Commit f6b4038

Browse files
mariiaKraievskaadamsaghy
authored andcommitted
WEB-477: Re-amortization:- Preview Schedule API during re-amortization
1 parent 113dd81 commit f6b4038

File tree

5 files changed

+164
-1
lines changed

5 files changed

+164
-1
lines changed

src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@
6060
>
6161
{{ 'labels.buttons.Submit' | translate }}
6262
</button>
63+
<button
64+
type="button"
65+
mat-raised-button
66+
color="accent"
67+
[disabled]="!reamortizeLoanForm.valid"
68+
*mifosxHasPermission="'REAMORTIZE_LOAN'"
69+
(click)="preview()"
70+
>
71+
{{ 'labels.buttons.Preview' | translate }}
72+
</button>
6373
</mat-card-actions>
6474
</mat-card-content>
6575
</form>

src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.ts

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import { Component, Input, OnInit, inject } from '@angular/core';
22
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
33
import { ActivatedRoute, Router } from '@angular/router';
4+
import { MatDialog } from '@angular/material/dialog';
45
import { LoansService } from 'app/loans/loans.service';
6+
import { RepaymentSchedule } from 'app/loans/models/loan-account.model';
57
import { CodeValue } from 'app/shared/models/general.model';
68
import { OptionData } from 'app/shared/models/option-data.model';
79
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
10+
import { SettingsService } from 'app/settings/settings.service';
11+
import { ReAmortizePreviewDialogComponent } from './re-amortize-preview-dialog/re-amortize-preview-dialog.component';
812

913
@Component({
1014
selector: 'mifosx-loan-reamortize',
@@ -19,6 +23,8 @@ export class LoanReamortizeComponent implements OnInit {
1923
private route = inject(ActivatedRoute);
2024
private router = inject(Router);
2125
private loanService = inject(LoansService);
26+
private settingsService = inject(SettingsService);
27+
private dialog = inject(MatDialog);
2228

2329
@Input() dataObject: any;
2430
/** Loan Id */
@@ -50,8 +56,76 @@ export class LoanReamortizeComponent implements OnInit {
5056
});
5157
}
5258

53-
submit(): void {
59+
private prepareReAmortizeData() {
5460
const data = this.reamortizeLoanForm.value;
61+
const locale = this.settingsService.language.code;
62+
const dateFormat = this.settingsService.dateFormat;
63+
64+
return {
65+
...data,
66+
dateFormat,
67+
locale
68+
};
69+
}
70+
71+
private prepareReAmortizePreviewData() {
72+
const reamortizeLoanFormData = { ...this.reamortizeLoanForm.value };
73+
const locale = this.settingsService.language.code;
74+
const dateFormat = this.settingsService.dateFormat;
75+
76+
// Prepare reAmortizationInterestHandling for preview API
77+
let reAmortizationInterestHandling = reamortizeLoanFormData.reAmortizationInterestHandling;
78+
if (reAmortizationInterestHandling && typeof reAmortizationInterestHandling === 'object') {
79+
reAmortizationInterestHandling = reAmortizationInterestHandling.id;
80+
}
81+
// If no value selected, use "default" for preview
82+
if (!reAmortizationInterestHandling && reAmortizationInterestHandling !== 0) {
83+
reAmortizationInterestHandling = 'default';
84+
}
85+
86+
delete reamortizeLoanFormData.reAmortizationInterestHandling;
87+
88+
return {
89+
...reamortizeLoanFormData,
90+
reAmortizationInterestHandling: reAmortizationInterestHandling,
91+
dateFormat,
92+
locale
93+
};
94+
}
95+
96+
preview(): void {
97+
if (this.reamortizeLoanForm.invalid) {
98+
return;
99+
}
100+
const data = this.prepareReAmortizePreviewData();
101+
102+
this.loanService.getReAmortizePreview(this.loanId, data).subscribe({
103+
next: (response: RepaymentSchedule) => {
104+
const currencyCode = response.currency?.code;
105+
106+
if (!currencyCode) {
107+
console.error('Currency code is not available in API response');
108+
return;
109+
}
110+
111+
this.dialog.open(ReAmortizePreviewDialogComponent, {
112+
data: {
113+
repaymentSchedule: response,
114+
currencyCode: currencyCode
115+
},
116+
width: '95%',
117+
maxWidth: '1400px',
118+
height: '90vh'
119+
});
120+
},
121+
error: (error) => {
122+
console.error('Error loading re-amortize preview:', error);
123+
}
124+
});
125+
}
126+
127+
submit(): void {
128+
const data = this.prepareReAmortizeData();
55129
this.loanService.submitLoanActionButton(this.loanId, data, 'reAmortize').subscribe((response: any) => {
56130
this.router.navigate(['../../transactions'], { relativeTo: this.route });
57131
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<h1 mat-dialog-title>{{ 'labels.heading.Repayment Schedule Preview' | translate }}</h1>
2+
3+
<mat-dialog-content class="mat-typography">
4+
<mifosx-repayment-schedule-tab
5+
[repaymentScheduleDetails]="repaymentSchedule"
6+
[currencyCode]="currencyCode"
7+
[forEditing]="false"
8+
>
9+
</mifosx-repayment-schedule-tab>
10+
</mat-dialog-content>
11+
12+
<mat-dialog-actions align="end">
13+
<button mat-raised-button type="button" (click)="close()">
14+
{{ 'labels.buttons.Go back' | translate }}
15+
</button>
16+
</mat-dialog-actions>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Component, inject, Inject } from '@angular/core';
2+
import {
3+
MAT_DIALOG_DATA,
4+
MatDialogRef,
5+
MatDialogTitle,
6+
MatDialogContent,
7+
MatDialogActions
8+
} from '@angular/material/dialog';
9+
import { MatButton } from '@angular/material/button';
10+
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
11+
import { RepaymentSchedule } from 'app/loans/models/loan-account.model';
12+
import { RepaymentScheduleTabComponent } from '../../../repayment-schedule-tab/repayment-schedule-tab.component';
13+
14+
export interface ReAmortizePreviewDialogData {
15+
repaymentSchedule: RepaymentSchedule;
16+
currencyCode: string;
17+
}
18+
19+
@Component({
20+
selector: 'mifosx-re-amortize-preview-dialog',
21+
templateUrl: './re-amortize-preview-dialog.component.html',
22+
standalone: true,
23+
imports: [
24+
...STANDALONE_SHARED_IMPORTS,
25+
MatDialogTitle,
26+
MatDialogContent,
27+
MatDialogActions,
28+
MatButton,
29+
RepaymentScheduleTabComponent
30+
]
31+
})
32+
export class ReAmortizePreviewDialogComponent {
33+
// inject() replaces constructor injection
34+
private readonly dialogRef = inject<MatDialogRef<ReAmortizePreviewDialogComponent>>(MatDialogRef);
35+
36+
private readonly data = inject<ReAmortizePreviewDialogData>(MAT_DIALOG_DATA);
37+
38+
// public fields used in template
39+
readonly repaymentSchedule: RepaymentSchedule = this.data.repaymentSchedule;
40+
readonly currencyCode: string = this.data.currencyCode;
41+
42+
close(): void {
43+
this.dialogRef.close();
44+
}
45+
}

src/app/loans/loans.service.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,24 @@ export class LoansService {
258258
return this.http.get(`/loans/${loanId}/transactions/reage-preview`, { params: httpParams });
259259
}
260260

261+
/**
262+
* Get Re-Amortize preview with repayment schedule
263+
* @param loanId Loan Id
264+
* @param data Re-Amortize data
265+
* @returns Observable with repayment schedule preview
266+
*/
267+
getReAmortizePreview(loanId: string, data: any): Observable<any> {
268+
let httpParams = new HttpParams();
269+
270+
Object.keys(data).forEach((key) => {
271+
if (data[key] !== null && data[key] !== undefined && data[key] !== '') {
272+
httpParams = httpParams.set(key, data[key].toString());
273+
}
274+
});
275+
276+
return this.http.get(`/loans/${loanId}/transactions/reamortized-preview`, { params: httpParams });
277+
}
278+
261279
getLoanScreenReportsData(): Observable<any> {
262280
const httpParams = new HttpParams().set('entityId', '1').set('typeId', '0');
263281
return this.http.get(`/templates`, { params: httpParams });

0 commit comments

Comments
 (0)