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
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ name: build-run
on:
# Triggers the workflow on push or pull request events for specific branches
push:
branches: [main, dev, angular-update-18]
branches: [main, dev, dev-angular-19]
pull_request:
branches: [main, dev, angular-update-18]
branches: [main, dev, dev-angular-19]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/create-docker-hub-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Publish Image in Docker Hub

on:
push:
branches: [main, dev, angular-update]
branches: [main, dev, dev-angular-19]

jobs:
build:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Tests

on:
push:
branches: [main, dev, angular-update-17-2]
branches: [main, dev, dev-angular-19]
pull_request:
branches: [main, dev, angular-update-17-2]
branches: [main, dev, dev-angular-19]

jobs:
testRigor:
Expand Down
2 changes: 1 addition & 1 deletion src/app/core/shell/sidenav/sidenav.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
<mat-list-item
[routerLink]="['/collections/collection-sheet']"
[matTooltipPosition]="tooltipPosition"
matTooltip="{{ 'tooltips.Collection Sheet' | translate }}"
matTooltip="{{ 'labels.menus.Collection Sheet' | translate }}"
routerLinkActive="active-menu"
[routerLinkActiveOptions]="{ exact: false }"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,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, 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',
Expand All @@ -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 */
Expand Down Expand Up @@ -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);
}
});
}
Comment on lines +96 to +125
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add user-facing error feedback.

The preview() method logs errors to console but provides no feedback to the user when:

  1. Currency code is missing (lines 106-109)
  2. API call fails (lines 121-123)

Users will see no indication that something went wrong.

Consider using a snackbar or toast notification:

+  private snackBar = inject(MatSnackBar);  // Add to imports and inject

   preview(): void {
     // ...
     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');
+          this.snackBar.open('Unable to load preview: missing currency information', 'Close', { duration: 5000 });
           return;
         }
         // ...
       },
       error: (error) => {
         console.error('Error loading re-amortize preview:', error);
+        this.snackBar.open('Error loading preview. Please try again.', 'Close', { duration: 5000 });
       }
     });
   }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
src/app/loans/loans-view/loan-account-actions/loan-reamortize/loan-reamortize.component.ts
around lines 96 to 125, the preview() method only logs errors to the console and
gives no user-facing feedback when the currency code is missing or when the API
call fails; inject and use the app's snackbar/toast service (e.g., MatSnackBar
or the project's notification service) in the component constructor, then
replace the console.error branches: when currency is absent show a user-friendly
error toast like "Unable to preview: missing currency information" and return,
and in the API error handler show a toast like "Failed to load re-amortize
preview. Please try again." (optionally include a brief error detail in the
toast or log it to console for debugging).


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,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<ReAmortizePreviewDialogComponent>>(MatDialogRef);

private readonly data = inject<ReAmortizePreviewDialogData>(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();
}
}
18 changes: 18 additions & 0 deletions src/app/loans/loans.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<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
1 change: 1 addition & 0 deletions src/assets/translations/cs-CS.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "Všechny pevné vklady",
"All Recurring Deposits": "Všechny opakované vklady",
"All Savings": "Všechny úspory",
"Savings Account Details": "Podrobnosti spořicího účtu",
"Allocate Cash": "Přidělte hotovost",
"Allows you to create new fixed deposit product": "Tato možnost vám umožňuje vytvořit nový produkt s pevným vkladem.",
"This option allows you to create new users in your organization": "Tato možnost vám umožňuje vytvářet nové uživatele ve vaší organizaci",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "Alle Festgelder",
"All Recurring Deposits": "Alle wiederkehrenden Einzahlungen",
"All Savings": "Alle Einsparungen",
"Savings Account Details": "Sparkonto-Details",
"Allocate Cash": "Bargeld zuweisen",
"Allows you to create new fixed deposit product": "Mit dieser Option können Sie ein neues Festgeldprodukt erstellen.",
"This option allows you to create new users in your organization": "Mit dieser Option können Sie neue Benutzer in Ihrer Organisation erstellen",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -2754,6 +2754,7 @@
"All Fixed Deposits": "All Fixed Deposits",
"All Recurring Deposits": "All Recurring Deposits",
"All Savings": "All Savings",
"Savings Account Details": "Savings Account Details",
"Allocate Cash": "Allocate Cash",
"Allows you to create new fixed deposit product": "This option allows you to create a new fixed deposit product.",
"This option allows you to create new users in your organization": "This option allows you to create new users in your organization",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/es-CL.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "Todos los depósitos fijos",
"All Recurring Deposits": "Todos los depósitos recurrentes",
"All Savings": "Todos los ahorros",
"Savings Account Details": "Detalles de la cuenta de ahorros",
"Allocate Cash": "Asignar efectivo",
"Allows you to create new fixed deposit product": "Esta opción le permite crear un nuevo producto de Depósito Fijo.",
"This option allows you to create new users in your organization": "Esta opción le permite crear nuevos usuarios en su organización.",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/es-MX.json
Original file line number Diff line number Diff line change
Expand Up @@ -2746,6 +2746,7 @@
"All Fixed Deposits": "Todos los depósitos fijos",
"All Recurring Deposits": "Todos los depósitos recurrentes",
"All Savings": "Todos los ahorros",
"Savings Account Details": "Detalles de la cuenta de ahorros",
"Allocate Cash": "Asignar efectivo",
"Allows you to create new fixed deposit product": "Esta opción le permite crear un nuevo producto de Depósito Fijo.",
"This option allows you to create new users in your organization": "Esta opción le permite crear nuevos usuarios en su organización.",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "Tous les dépôts fixes",
"All Recurring Deposits": "Tous les dépôts récurrents",
"All Savings": "Toutes les économies",
"Savings Account Details": "Détails du compte d'épargne",
"Allocate Cash": "Allouer de l'argent",
"Allows you to create new fixed deposit product": "Cette option vous permet de créer un nouveau produit de dépôt fixe.",
"This option allows you to create new users in your organization": "Cette option vous permet de créer de nouveaux utilisateurs dans votre organisation",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/it-IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "Tutti i depositi fissi",
"All Recurring Deposits": "Tutti i depositi ricorrenti",
"All Savings": "Tutto il risparmio",
"Savings Account Details": "Dettagli del conto di risparmio",
"Allocate Cash": "Assegnare contanti",
"Allows you to create new fixed deposit product": "Questa opzione ti consente di creare un nuovo prodotto a deposito fisso.",
"This option allows you to create new users in your organization": "Questa opzione ti consente di creare nuovi utenti nella tua organizzazione",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/ko-KO.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "정기예금 전체",
"All Recurring Deposits": "모든 정기 예금",
"All Savings": "모든 저축",
"Savings Account Details": "저축 계좌 세부 정보",
"Allocate Cash": "현금 할당",
"Allows you to create new fixed deposit product": "이 옵션을 사용하면 새로운 정기 예금 상품을 생성할 수 있습니다.",
"This option allows you to create new users in your organization": "이 옵션을 사용하면 조직에 새 사용자를 만들 수 있습니다.",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/lt-LT.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "Visi terminuoti indėliai",
"All Recurring Deposits": "Visi periodiniai indėliai",
"All Savings": "Visos santaupos",
"Savings Account Details": "Taupomosios sąskaitos informacija",
"Allocate Cash": "Paskirstykite grynuosius pinigus",
"Allows you to create new fixed deposit product": "Ši parinktis leidžia sukurti naują terminuoto indėlio produktą.",
"This option allows you to create new users in your organization": "Ši parinktis leidžia sukurti naujų naudotojų jūsų organizacijoje",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/lv-LV.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "Visi fiksētie noguldījumi",
"All Recurring Deposits": "Visi atkārtotie noguldījumi",
"All Savings": "Visi ietaupījumi",
"Savings Account Details": "Krājkonta informācija",
"Allocate Cash": "Piešķirt skaidru naudu",
"Allows you to create new fixed deposit product": "Šī opcija ļauj izveidot jaunu fiksētā depozīta produktu.",
"This option allows you to create new users in your organization": "Šī opcija ļauj izveidot jaunus lietotājus jūsu organizācijā",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/ne-NE.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "सबै फिक्स्ड डिपोजिटहरू",
"All Recurring Deposits": "सबै आवर्ती निक्षेपहरू",
"All Savings": "सबै बचत",
"Savings Account Details": "बचत खाता विवरण",
"Allocate Cash": "नगद आवंटित गर्नुहोस्",
"Allows you to create new fixed deposit product": "यो विकल्पले तपाईंलाई नयाँ फिक्स्ड डिपोजिट उत्पादन सिर्जना गर्न अनुमति दिन्छ।",
"This option allows you to create new users in your organization": "यो विकल्पले तपाईंलाई आफ्नो संगठनमा नयाँ प्रयोगकर्ताहरू सिर्जना गर्न अनुमति दिन्छ",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/pt-PT.json
Original file line number Diff line number Diff line change
Expand Up @@ -2744,6 +2744,7 @@
"All Fixed Deposits": "Todos os depósitos fixos",
"All Recurring Deposits": "Todos os depósitos recorrentes",
"All Savings": "Todas as economias",
"Savings Account Details": "Detalhes da Conta Poupança",
"Allocate Cash": "Alocar dinheiro",
"Allows you to create new fixed deposit product": "Esta opção permite criar um novo produto de depósito fixo.",
"This option allows you to create new users in your organization": "Esta opção permite criar novos usuários em sua organização",
Expand Down
1 change: 1 addition & 0 deletions src/assets/translations/sw-SW.json
Original file line number Diff line number Diff line change
Expand Up @@ -2743,6 +2743,7 @@
"All Fixed Deposits": "Amana Zote Zisizohamishika",
"All Recurring Deposits": "Amana Zote Zinazorudiwa",
"All Savings": "Akiba Yote",
"Savings Account Details": "Maelezo ya Akaunti ya Akiba",
"Allocate Cash": "Tenga Pesa",
"Allows you to create new fixed deposit product": "Chaguo hili hukuruhusu kuunda bidhaa mpya ya amana isiyobadilika.",
"This option allows you to create new users in your organization": "Chaguo hili hukuruhusu kuunda watumiaji wapya katika shirika lako",
Expand Down