Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@
>
{{ 'labels.buttons.Submit' | translate }}
</button>
<button
type="button"
mat-raised-button
color="accent"
[disabled]="!reamortizeLoanForm.valid"
*mifosxHasPermission="'REAMORTIZE_LOAN'"
(click)="preview()"
>
{{ 'labels.buttons.Preview' | translate }}
</button>
</mat-card-actions>
</mat-card-content>
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { Component, Input, OnInit } 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 { SettingsService } from 'app/settings/settings.service';
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 { ReAmortizePreviewDialogComponent } from './re-amortize-preview-dialog/re-amortize-preview-dialog.component';

@Component({
selector: 'mifosx-loan-reamortize',
Expand All @@ -27,7 +31,9 @@ export class LoanReamortizeComponent implements OnInit {
private formBuilder: UntypedFormBuilder,
private route: ActivatedRoute,
private router: Router,
private loanService: LoansService
private loanService: LoansService,
private settingsService: SettingsService,
private dialog: MatDialog
) {
this.loanId = this.route.snapshot.params['loanId'];
}
Expand All @@ -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 });
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<h1 mat-dialog-title>{{ 'labels.heading.Repayment Schedule Preview' | translate }}</h1>

<mat-dialog-content class="mat-typography">
<mifosx-repayment-schedule-tab
[repaymentScheduleDetails]="repaymentSchedule"
[currencyCode]="currencyCode"
[forEditing]="false"
>
</mifosx-repayment-schedule-tab>
</mat-dialog-content>

<mat-dialog-actions align="end">
<button mat-raised-button type="button" (click)="close()">
{{ 'labels.buttons.Go back' | translate }}
</button>
</mat-dialog-actions>
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Component, 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 {
repaymentSchedule: RepaymentSchedule;
currencyCode: string;

constructor(
public dialogRef: MatDialogRef<ReAmortizePreviewDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: ReAmortizePreviewDialogData
) {
this.repaymentSchedule = data.repaymentSchedule;
this.currencyCode = data.currencyCode;
}

close(): void {
this.dialogRef.close();
}
}
18 changes: 18 additions & 0 deletions src/app/loans/loans.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,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<any> {
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<any> {
const httpParams = new HttpParams().set('entityId', '1').set('typeId', '0');
return this.http.get(`/templates`, { params: httpParams });
Expand Down