-
Notifications
You must be signed in to change notification settings - Fork 921
WEB-657: Working Capital loan update period payment rates #3524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /** | ||
| * Copyright since 2025 Mifos Initiative | ||
| * | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| */ | ||
|
|
||
| /** Angular Imports */ | ||
| import { Injectable, inject } from '@angular/core'; | ||
| import { ActivatedRouteSnapshot } from '@angular/router'; | ||
| import { LoansService } from 'app/loans/loans.service'; | ||
|
|
||
| /** rxjs Imports */ | ||
| import { Observable } from 'rxjs'; | ||
|
|
||
| /** | ||
| * Working Capital Period Payment Rates resolver. | ||
| */ | ||
| @Injectable() | ||
| export class LoanPeriodPaymentRatesResolver { | ||
| private loansService = inject(LoansService); | ||
|
|
||
| /** | ||
| * Returns the Loans data. | ||
| * @returns {Observable<any>} | ||
| */ | ||
| resolve(route: ActivatedRouteSnapshot): Observable<any> { | ||
| const loanId = route.paramMap.get('loanId') || route.parent.paramMap.get('loanId'); | ||
| return this.loansService.getWorkingCapitalPeriodPaymentRates(loanId); | ||
|
Comment on lines
+29
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Verify resolver route shape and service method signature.
rg -n --type ts -C3 "LoanPeriodPaymentRatesResolver|payment-rates|:loanId" src/app/loans/loans-routing.module.ts
rg -n --type ts -C3 "getWorkingCapitalPeriodPaymentRates\\s*\\(" src/app/loans/loans.service.tsRepository: openMF/web-app Length of output: 3052 🏁 Script executed: # Read the resolver file to see the actual implementation
cat -n src/app/loans/loans-view/working-capital/common-resolvers/loan-period-payment-rates.resolver.tsRepository: openMF/web-app Length of output: 1250 🏁 Script executed: # Check the parent route structure more carefully to understand the nesting
rg -n --type ts -B10 -A10 "path: 'payment-rates'" src/app/loans/loans-routing.module.ts | head -40Repository: openMF/web-app Length of output: 907 🏁 Script executed: # Look at other resolvers in the same directory to see how they handle parent routes
find src/app/loans -name "*.resolver.ts" -type f -exec wc -l {} + | head -10Repository: openMF/web-app Length of output: 822 🏁 Script executed: # Check if other resolvers use parent.paramMap pattern
rg -n "route\.parent" src/app/loans --type tsRepository: openMF/web-app Length of output: 8987 Guard Line 29 accesses Recommended fix resolve(route: ActivatedRouteSnapshot): Observable<any> {
- const loanId = route.paramMap.get('loanId') || route.parent.paramMap.get('loanId');
+ const loanId = route.paramMap.get('loanId') ?? route.parent?.paramMap.get('loanId');
+ if (!loanId) {
+ throw new Error('Missing route param: loanId');
+ }
return this.loansService.getWorkingCapitalPeriodPaymentRates(loanId);
}🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,61 @@ | ||||||||||||||||||||||||||||||||||||||
| <!-- | ||||||||||||||||||||||||||||||||||||||
| Copyright since 2025 Mifos Initiative | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| This Source Code Form is subject to the terms of the Mozilla Public | ||||||||||||||||||||||||||||||||||||||
| License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||||||||||||||||||||||||||||||||||
| file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||||||||||||||||||||||||||||||||||
| --> | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| <div class="container"> | ||||||||||||||||||||||||||||||||||||||
| <h3>{{ 'labels.inputs.Period Payment Rates' | translate }}</h3> | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| <div class="layout-row transaction-buttons align-end gap-20px"> | ||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use an 8px-grid spacing token here.
As per coding guidelines, 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| <button | ||||||||||||||||||||||||||||||||||||||
| mat-raised-button | ||||||||||||||||||||||||||||||||||||||
| color="primary" | ||||||||||||||||||||||||||||||||||||||
| (click)="addPaymentRate()" | ||||||||||||||||||||||||||||||||||||||
| *mifosxHasPermission="'UPDATERATE_WORKINGCAPITALLOAN'" | ||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||
| {{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Period Payment Rate' | translate }} | ||||||||||||||||||||||||||||||||||||||
| </button> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| <table mat-table [dataSource]="loanPaymentRatesData"> | ||||||||||||||||||||||||||||||||||||||
| <ng-container matColumnDef="id"> | ||||||||||||||||||||||||||||||||||||||
| <th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Id' | translate }}</th> | ||||||||||||||||||||||||||||||||||||||
| <td mat-cell *matCellDef="let item" [ngClass]="periodPaymentRateStyle(item.reversed)"> | ||||||||||||||||||||||||||||||||||||||
| {{ item.id }} | ||||||||||||||||||||||||||||||||||||||
| </td> | ||||||||||||||||||||||||||||||||||||||
| </ng-container> | ||||||||||||||||||||||||||||||||||||||
| <ng-container matColumnDef="effectiveDate"> | ||||||||||||||||||||||||||||||||||||||
| <th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Effective Date' | translate }}</th> | ||||||||||||||||||||||||||||||||||||||
| <td mat-cell *matCellDef="let item" [ngClass]="periodPaymentRateStyle(item.reversed)"> | ||||||||||||||||||||||||||||||||||||||
| {{ item.effectiveDate | dateFormat }} | ||||||||||||||||||||||||||||||||||||||
| </td> | ||||||||||||||||||||||||||||||||||||||
| </ng-container> | ||||||||||||||||||||||||||||||||||||||
| <ng-container matColumnDef="previousRate"> | ||||||||||||||||||||||||||||||||||||||
| <th mat-header-cell *matHeaderCellDef> | ||||||||||||||||||||||||||||||||||||||
| {{ 'labels.buttons.Previous' | translate }} {{ 'labels.inputs.Rate' | translate }} | ||||||||||||||||||||||||||||||||||||||
| </th> | ||||||||||||||||||||||||||||||||||||||
| <td mat-cell *matCellDef="let item" [ngClass]="periodPaymentRateStyle(item.reversed)"> | ||||||||||||||||||||||||||||||||||||||
| {{ item.previousRate | formatNumber }} % | ||||||||||||||||||||||||||||||||||||||
| </td> | ||||||||||||||||||||||||||||||||||||||
| </ng-container> | ||||||||||||||||||||||||||||||||||||||
| <ng-container matColumnDef="newRate"> | ||||||||||||||||||||||||||||||||||||||
| <th mat-header-cell *matHeaderCellDef> | ||||||||||||||||||||||||||||||||||||||
| {{ 'labels.catalogs.New' | translate }} {{ 'labels.inputs.Rate' | translate }} | ||||||||||||||||||||||||||||||||||||||
| </th> | ||||||||||||||||||||||||||||||||||||||
| <td mat-cell *matCellDef="let item" [ngClass]="periodPaymentRateStyle(item.reversed)"> | ||||||||||||||||||||||||||||||||||||||
| {{ item.newRate | formatNumber }} % | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+41
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove the hard-coded space before The current template renders values like 🧹 Suggested formatting fix- {{ item.previousRate | formatNumber }} %
+ {{ item.previousRate | formatNumber }}%
...
- {{ item.newRate | formatNumber }} %
+ {{ item.newRate | formatNumber }}%📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| </td> | ||||||||||||||||||||||||||||||||||||||
| </ng-container> | ||||||||||||||||||||||||||||||||||||||
| <ng-container matColumnDef="createdDate"> | ||||||||||||||||||||||||||||||||||||||
| <th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Created On' | translate }}</th> | ||||||||||||||||||||||||||||||||||||||
| <td mat-cell *matCellDef="let item" [ngClass]="periodPaymentRateStyle(item.reversed)"> | ||||||||||||||||||||||||||||||||||||||
| {{ item.createdDate | dateFormat }} | ||||||||||||||||||||||||||||||||||||||
| </td> | ||||||||||||||||||||||||||||||||||||||
| </ng-container> | ||||||||||||||||||||||||||||||||||||||
| <tr mat-header-row *matHeaderRowDef="loanPaymentRatesColumns"></tr> | ||||||||||||||||||||||||||||||||||||||
| <tr mat-row *matRowDef="let row; columns: loanPaymentRatesColumns"></tr> | ||||||||||||||||||||||||||||||||||||||
| </table> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| /** | ||
| * Copyright since 2025 Mifos Initiative | ||
| * | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| */ | ||
| @use 'assets/styles/helper'; | ||
| @use 'assets/styles/colours' as *; | ||
|
|
||
| .container { | ||
| padding-bottom: 2%; | ||
| max-width: 100%; | ||
|
|
||
| table { | ||
| width: 100%; | ||
|
|
||
| .reversed { | ||
| text-decoration: line-through; | ||
| color: $status-active-overdue; | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,128 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Copyright since 2025 Mifos Initiative | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Component, inject, OnInit } from '@angular/core'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatTable, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatColumnDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatHeaderCellDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatHeaderCell, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatCellDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatCell, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatHeaderRowDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatHeaderRow, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatRowDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatRow | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from '@angular/material/table'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { FormatNumberPipe } from '@pipes/format-number.pipe'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ActivatedRoute } from '@angular/router'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { PeriodPaymentRateChange } from 'app/loans/models/working-capital-loan-account.model'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { MatDialog } from '@angular/material/dialog'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { TranslateService } from '@ngx-translate/core'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { LoansService } from 'app/loans/loans.service'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { SettingsService } from 'app/settings/settings.service'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Component({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| selector: 'mifosx-loan-period-payment-rates', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| templateUrl: './loan-period-payment-rates.component.html', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| styleUrl: './loan-period-payment-rates.component.scss', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imports: [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...STANDALONE_SHARED_IMPORTS, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatTable, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatColumnDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatHeaderCellDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatHeaderCell, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatCellDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatCell, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatHeaderRowDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatHeaderRow, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatRowDef, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatRow, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FormatNumberPipe | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export class LoanPeriodPaymentRatesComponent implements OnInit { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private route = inject(ActivatedRoute); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private dialog = inject(MatDialog); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private translateService = inject(TranslateService); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private loanService = inject(LoansService); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private settingsService = inject(SettingsService); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loanPaymentRatesData: PeriodPaymentRateChange[] = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loanId: number | null = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| loanPaymentRatesColumns: string[] = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'id', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'effectiveDate', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'previousRate', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'newRate', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'createdDate' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constructor() {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ngOnInit(): void { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.loanId = this.route.parent.snapshot.params['loanId']; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+61
to
+74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Also, 🛡️ Proposed fix ngOnInit(): void {
- this.loanId = this.route.parent.snapshot.params['loanId'];
+ this.loanId = Number(this.route.parent?.snapshot.params['loanId']);
this.route.data.subscribe((data: { loanPaymentRatesData: PeriodPaymentRateChange[] }) => {
this.loanPaymentRatesData = data.loanPaymentRatesData;
});
}As per coding guidelines, use TypeScript with strict typing conventions ( 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.route.data.subscribe((data: { loanPaymentRatesData: PeriodPaymentRateChange[] }) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.loanPaymentRatesData = data.loanPaymentRatesData; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| addPaymentRate(): void { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const labelHeadingText: string = this.translateService.instant('labels.inputs.Period Payment Rate'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const formfields: FormfieldBase[] = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new InputBase({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| controlName: 'periodPaymentRate', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: labelHeadingText, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: '', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: 'number', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| order: 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| new InputBase({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| controlName: 'note', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| label: this.translateService.instant('labels.inputs.Note'), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| value: '', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: 'text', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| required: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| order: 2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const data = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: this.translateService.instant('labels.buttons.Add') + ' ' + labelHeadingText, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| layout: { addButtonText: this.translateService.instant('labels.buttons.Add') }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+101
to
+103
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use a full translation key for the dialog title too. This has the same localization issue as the template buttons: translated fragments may not compose correctly across locales. 🌐 Suggested wording fix- title: this.translateService.instant('labels.buttons.Add') + ' ' + labelHeadingText,
+ title: this.translateService.instant('labels.buttons.Add Period Payment Rate'),As per coding guidelines, use “proper i18n variables from 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| formfields: formfields | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const dialogRef = this.dialog.open(FormDialogComponent, { data }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dialogRef.afterClosed().subscribe((response: any) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (response?.data) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
coderabbitai[bot] marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { periodPaymentRate, note } = response.data.value; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const payload = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| periodPaymentRate: periodPaymentRate, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| note: note || '', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| locale: this.settingsService.language.code, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dateFormat: this.settingsService.dateFormat | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.loanService.addWorkingCapitalPeriodPaymentRate(this.loanId, payload).subscribe((response: any) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.loanService.getWorkingCapitalPeriodPaymentRates(this.loanId).subscribe((data: any) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.loanPaymentRatesData = data; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| periodPaymentRateStyle(reversed: boolean): string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return reversed ? 'reversed' : ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| /** | ||
| * Copyright since 2025 Mifos Initiative | ||
| * | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| */ | ||
|
|
||
| export interface PeriodPaymentRateChange { | ||
| id: number; | ||
| loanId: number; | ||
| effectiveDate: number[]; | ||
| previousRate: number; | ||
| newRate: number; | ||
| reversed: boolean; | ||
| createdDate: number[]; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| <!-- | ||
| Copyright since 2025 Mifos Initiative | ||
|
|
||
| This Source Code Form is subject to the terms of the Mozilla Public | ||
| License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| --> | ||
|
|
||
| <h1 mat-dialog-title>{{ 'labels.heading.Undo' | translate }} {{ data.undoContext }}</h1> | ||
| <div> | ||
| <form [formGroup]="undoActionForm"> | ||
| <mat-dialog-content> | ||
| <mat-form-field class="flex-100"> | ||
| <textarea formControlName="note" matInput placeholder="{{ 'labels.inputs.Notes' | translate }}"></textarea> | ||
| </mat-form-field> | ||
| </mat-dialog-content> | ||
| <mat-dialog-actions align="end"> | ||
| <button mat-raised-button mat-dialog-close>{{ 'labels.buttons.Cancel' | translate }}</button> | ||
| <button mat-raised-button color="primary" [mat-dialog-close]="{ confirm: true, data: undoActionForm.value }"> | ||
| {{ 'labels.buttons.Undo' | translate }} | ||
| </button> | ||
| </mat-dialog-actions> | ||
| </form> | ||
| </div> | ||
|
Comment on lines
+10
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Expected after the fix: no matches.
rg -nP '<form(?=[^>]*\[formGroup\])(?=[^>]*#\w+="ngForm")' --type htmlRepository: openMF/web-app Length of output: 490 🏁 Script executed: # Check if formRef is used in the component TypeScript files for all three instances
for file in \
"src/app/shared/undo-dialog/undo-dialog.component.ts" \
"src/app/organization/currencies/manage-currencies/manage-currencies.component.ts" \
"src/app/clients/clients-view/custom-dialogs/edit-notes-dialog/edit-notes-dialog.component.ts"
do
echo "=== Checking: $file ==="
if [ -f "$file" ]; then
rg -n "formRef" "$file" || echo "No matches for formRef"
else
echo "File not found"
fi
echo ""
doneRepository: openMF/web-app Length of output: 523 🏁 Script executed: # Also check the HTML templates more thoroughly to see if formRef is referenced anywhere
for file in \
"src/app/shared/undo-dialog/undo-dialog.component.html" \
"src/app/organization/currencies/manage-currencies/manage-currencies.component.html" \
"src/app/clients/clients-view/custom-dialogs/edit-notes-dialog/edit-notes-dialog.component.html"
do
echo "=== HTML file: $file ==="
if [ -f "$file" ]; then
rg -n "formRef" "$file" || echo "No references to formRef in template"
else
echo "File not found"
fi
echo ""
doneRepository: openMF/web-app Length of output: 550 🏁 Script executed: # Read the full HTML templates to see the complete structure and usage
echo "=== undo-dialog.component.html ===" && cat -n src/app/shared/undo-dialog/undo-dialog.component.html || echo "File not found"Repository: openMF/web-app Length of output: 1292 Remove the unused The Proposed fix-<div>
- <form `#formRef`="ngForm" [formGroup]="undoActionForm">
+<form [formGroup]="undoActionForm">
+ <mat-dialog-content>
<mat-form-field class="flex-100">
<textarea formControlName="note" matInput placeholder="{{ 'labels.inputs.Notes' | translate }}"></textarea>
</mat-form-field>
+ </mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-raised-button mat-dialog-close>{{ 'labels.buttons.Cancel' | translate }}</button>
<button
mat-raised-button
color="primary"
[disabled]="undoActionForm.pristine"
[mat-dialog-close]="{ confirm: true, data: undoActionForm.value }"
>
{{ 'labels.buttons.Undo' | translate }}
</button>
</mat-dialog-actions>
- </form>
-</div>
+</form>🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| /** | ||
| * Copyright since 2025 Mifos Initiative | ||
| * | ||
| * This Source Code Form is subject to the terms of the Mozilla Public | ||
| * License, v. 2.0. If a copy of the MPL was not distributed with this | ||
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use translation keys instead of hardcoded route labels.
Line 157 introduces new user-facing strings (
title/breadcrumb) as literals. Please switch to i18n keys and update extraction so the labels are translatable.As per coding guidelines, "Use proper i18n variables from
@ngx-translate/corefor all user-facing strings instead of hardcoded text" and "Runnpm run translations:extractto extract i18n variables whenever new strings are added to code."🤖 Prompt for AI Agents