Skip to content

WEB-657: Working Capital loan update period payment rates#3524

Open
alberto-art3ch wants to merge 1 commit intoopenMF:devfrom
alberto-art3ch:WEB-657/working-capital-period-payment-rate-changes
Open

WEB-657: Working Capital loan update period payment rates#3524
alberto-art3ch wants to merge 1 commit intoopenMF:devfrom
alberto-art3ch:WEB-657/working-capital-period-payment-rate-changes

Conversation

@alberto-art3ch
Copy link
Copy Markdown
Collaborator

@alberto-art3ch alberto-art3ch commented Apr 20, 2026

Description

For Working Capital loans we have a new loan tab for Payment Rates where we can see the different Payment Rate Changes that a WC Loan could have

(WEB-657)WEB-657

Related issues and discussion

Screenshots

  • Initial Tab when the WC Loan is active
Screenshot 2026-04-19 at 9 55 40 PM
  • Tab with Payment Rate changes added, even one of them reversed
Screenshot 2026-04-19 at 9 49 51 PM

Checklist

Please make sure these boxes are checked before submitting your pull request - thanks!

  • If you have multiple commits please combine them into one commit by squashing them.

  • Read and understood the contribution guidelines at web-app/.github/CONTRIBUTING.md.

Summary by CodeRabbit

  • New Features

    • Added a "Period Payment Rates" tab for working-capital loans to view period rate changes, add new rates, and undo changes (with optional notes). Actions are shown only when applicable and respect user permissions.
  • Localization

    • Added translations for the new UI labels and menu items across multiple locales.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'pre_merge_checks'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

Adds a working-capital "Period Payment Rates" feature: new route + resolver, standalone component (list/add/undo flows), service endpoints, data model, shared undo dialog, template/tab changes, styles, and translations across multiple locales.

Changes

Cohort / File(s) Summary
Routing & Module
src/app/loans/loans-routing.module.ts
Added child route payment-rates under :loanId with LoanPeriodPaymentRatesComponent, route data (title/breadcrumb/routeParamBreadcrumb), resolver loanPaymentRatesData via LoanPeriodPaymentRatesResolver, and registered resolver in providers.
Loans View Template
src/app/loans/loans-view/loans-view.component.html
Switched Transactions template reference from #dashboard to #transactions and added conditional "Period Payment Rates" tab (visible for working-capital active loans) linking to ./payment-rates.
Period Payment Rates (component + view + styles)
src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts, .html, .scss
New standalone component showing Material table of period rate changes, add & undo flows (opens FormDialogComponent / UndoDialogComponent), calls LoansService methods, handles data refresh and row styling for reversed entries.
Resolver
src/app/loans/loans-view/working-capital/common-resolvers/loan-period-payment-rates.resolver.ts
New resolver extracting loanId from route (or parent) and returning LoansService.getWorkingCapitalPeriodPaymentRates(loanId) for route resolve.
Service Layer
src/app/loans/loans.service.ts
Added three methods: getWorkingCapitalPeriodPaymentRates(loanId), addWorkingCapitalPeriodPaymentRate(loanId, payload), undoWorkingCapitalPeriodPaymentRate(loanId, payload) mapping to new REST endpoints.
Data Model
src/app/loans/models/working-capital-loan-account.model.ts
Added PeriodPaymentRateChange interface (id, loanId, effectiveDate:number[], previousRate, newRate, reversed, createdDate:number[]).
Shared Undo Dialog
src/app/shared/undo-dialog/undo-dialog.component.ts, .html, .scss
New standalone UndoDialogComponent with reactive form (note required), template returning { confirm: true, data } on confirm; SCSS header/license added.
Translations
src/assets/translations/*.json
cs-CS, de-DE, en-US, es-CL, es-MX, fr-FR, it-IT, ko-KO, lt-LT, lv-LV, ne-NE, pt-PT, sw-SW
Added translation keys: "Period Payment Rates" (inputs and text sections) and "Undo Payment Rate" (menus) across language files.

Sequence Diagrams

sequenceDiagram
    autonumber
    participant User
    participant Component as LoanPeriodPaymentRatesComponent
    participant Dialog as FormDialogComponent
    participant Service as LoansService
    participant API as Backend

    User->>Component: Click "Add Payment Rate"
    Component->>Dialog: Open form dialog
    Dialog->>User: Display form
    User->>Dialog: Submit form (rate, note)
    Dialog-->>Component: Return form data
    Component->>Service: addWorkingCapitalPeriodPaymentRate(loanId, payload)
    Service->>API: PUT /loans/{loanId}/period-rates
    API-->>Service: Success
    Service-->>Component: Observable resolved
    Component->>Service: getWorkingCapitalPeriodPaymentRates(loanId)
    Service->>API: GET /loans/{loanId}/period-rates
    API-->>Service: Payment rates data
    Service-->>Component: Updated list
    Component->>Component: Update loanPaymentRatesData
Loading
sequenceDiagram
    autonumber
    participant User
    participant Component as LoanPeriodPaymentRatesComponent
    participant Dialog as UndoDialogComponent
    participant Service as LoansService
    participant API as Backend

    User->>Component: Click "Undo Changes"
    Component->>Dialog: Open undo dialog
    Dialog->>User: Display confirmation & note
    User->>Dialog: Confirm with note
    Dialog-->>Component: { confirm: true, data }
    Component->>Service: undoWorkingCapitalPeriodPaymentRate(loanId, payload)
    Service->>API: POST /loans/{loanId}/period-rates/undo
    API-->>Service: Success
    Service-->>Component: Observable resolved
    Component->>Service: getWorkingCapitalPeriodPaymentRates(loanId)
    Service->>API: GET /loans/{loanId}/period-rates
    API-->>Service: Updated data
    Service-->>Component: Refreshed list
    Component->>Component: Update loanPaymentRatesData
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Suggested reviewers

  • adamsaghy
  • IOhacker
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main feature added: a new Period Payment Rates tab for Working Capital loans to view and manage payment rate changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🧹 Nitpick comments (5)
src/app/loans/loans.service.ts (1)

850-865: Consider narrowing loanId to string | number for type safety.

The loanId parameter should be typed more specifically than any since it's used only in URL construction. Regarding the broader typing of request/response payloads, note that this codebase uses Observable<any> as a project-wide pattern; full API response typing is tracked as a separate enhancement rather than addressed piecemeal across individual PRs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/loans/loans.service.ts` around lines 850 - 865, The three methods
getWorkingCapitalPeriodPaymentRates, addWorkingCapitalPeriodPaymentRate, and
undoWorkingCapitalPeriodPaymentRate use loanId: any — change those signatures to
use loanId: string | number for stronger typing (keep payload: any as-is per
project convention) and update any related internal references to treat loanId
as string | number so URL construction remains correct; no other behavior
changes required.
src/assets/translations/pt-PT.json (1)

3116-3116: Remove unused translation key "Undo Payment Rate" or verify it has a documented purpose.

The codebase does not reference labels.menus.Undo Payment Rate outside of translation files. The undo button is rendered using separate translation keys (labels.buttons.Undo combined with labels.inputs.Period Payment Rate), making this key appear unused.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/assets/translations/pt-PT.json` at line 3116, Remove the unused
translation key "Undo Payment Rate" from the translations file or, if it is
intended to be used, add a documented usage and update code to reference it;
specifically search for and reconcile the translation key "Undo Payment Rate"
with existing keys used for the undo UI flow (labels.buttons.Undo and
labels.inputs.Period Payment Rate) and either delete the "Undo Payment Rate"
entry or replace UI references to use this single key consistently and document
its purpose.
src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.scss (1)

12-12: Use 8px-grid spacing instead of percentage padding.

padding-bottom: 2% makes vertical spacing viewport-dependent. Prefer a fixed 8px-grid multiple for predictable layout rhythm.

Suggested change
 .container {
-  padding-bottom: 2%;
+  padding-bottom: 16px;
   max-width: 100%;

As per coding guidelines: “src/**/*.{scss,html}: Stick to the 8px grid system for visual design and spacing”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.scss`
at line 12, Replace the viewport-dependent rule "padding-bottom: 2%" with an
8px-grid based value; locate the selector in
loan-period-payment-rates.component.scss that sets "padding-bottom: 2%" and
change it to a fixed multiple of 8px (for example "padding-bottom: 16px" for 2 ×
8px) or to the project's spacing token/variable if one exists (e.g., $spacing-2)
to align with the 8px grid guideline.
src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html (1)

12-12: Use an 8px-grid spacing utility here.

gap-20px breaks the project’s spacing grid; use a 16px or 24px gap utility/SCSS variable instead. As per coding guidelines, src/**/*.{scss,html} should “Stick to the 8px grid system for visual design and spacing.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html`
at line 12, The div uses a non-compliant spacing class "gap-20px" in the class
list "layout-row transaction-buttons align-end gap-20px"; replace that token
with an 8px-grid-compliant utility (e.g., gap-16px or gap-24px) or a project
SCSS spacing variable (e.g., $spacing-16) and ensure the corresponding gap
utility exists in the global utilities/SCSS so the HTML uses a permitted spacing
class instead of "gap-20px".
src/app/shared/undo-dialog/undo-dialog.component.ts (1)

32-49: Type the dialog data and form contract.

This shared dialog currently accepts untyped MAT_DIALOG_DATA and uses UntypedFormGroup; define explicit interfaces so callers and templates get compile-time checks. As per coding guidelines, src/app/**/*.ts should “Use TypeScript for all application code with strict typing conventions.”

Suggested typing direction
-import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
+import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
+
+interface UndoDialogData {
+  undoContext: string;
+}
+
+interface UndoActionForm {
+  note: FormControl<string>;
+}
@@
-  data = inject(MAT_DIALOG_DATA);
-  private formBuilder = inject(UntypedFormBuilder);
+  data = inject<UndoDialogData>(MAT_DIALOG_DATA);
+  private formBuilder = inject(FormBuilder);
 
-  undoActionForm: UntypedFormGroup | null = null;
+  undoActionForm: FormGroup<UndoActionForm> | null = null;
@@
     this.undoActionForm = this.formBuilder.group({
-      note: [
-        '',
-        Validators.required
-      ]
+      note: this.formBuilder.nonNullable.control('', Validators.required)
     });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/shared/undo-dialog/undo-dialog.component.ts` around lines 32 - 49,
Add explicit TypeScript types for the dialog input and form model: define an
interface (e.g., UndoDialogData) for the MAT_DIALOG_DATA payload and an
interface (e.g., UndoActionFormValue) for the form value (note: string). Replace
UntypedFormBuilder/UntypedFormGroup with typed FormBuilder and
FormGroup<UndoActionFormValue>, change the data inject to
inject<UndoDialogData>(MAT_DIALOG_DATA), type dialogRef as
MatDialogRef<UndoDialogComponent, UndoActionFormValue> if it returns a value,
and update undoActionForm’s type and createUndoActionForm to build a typed group
in the createUndoActionForm function so templates and callers get compile-time
checks (refer to UndoDialogComponent, dialogRef, data, undoActionForm,
createUndoActionForm, MAT_DIALOG_DATA, UntypedFormBuilder).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html`:
- Around line 21-30: The Undo button is shown whenever
loanPaymentRatesData.length > 0 even if all rows are already reversed; add a
getter hasUndoablePaymentRates in loan-period-payment-rates.component.ts that
returns whether any item in loanPaymentRatesData is not reversed (use
Array.prototype.some on loanPaymentRatesData), then change the template
condition to use hasUndoablePaymentRates instead of loanPaymentRatesData.length
> 0 so the Undo button only appears when undoable payment rates exist; ensure
undoPaymentRate remains unchanged and wired to the button.

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts`:
- Around line 108-110: Remove the debug console output in the dialog close
handler: inside dialogRef.afterClosed().subscribe(...) (in
loan-period-payment-rates.component.ts) delete the console.log(response) line
and ensure any needed logic uses response?.data directly (or sanitizes fields)
instead of printing the full response to the browser console to avoid leaking
user-entered notes or sensitive context.
- Around line 83-104: The dialog uses the plural translation key for the
field/title; change labelHeadingText and any uses in data.title/layout to the
singular translation key so the Add dialog reads "Period Payment Rate" (not
"Period Payment Rates"). Update the assignment of labelHeadingText (currently
used by the InputBase with controlName 'periodPaymentRate' and by data.title and
layout.addButtonText) to call translateService.instant with the singular key and
ensure the input label and dialog title use that updated labelHeadingText.

In `@src/app/loans/models/working-capital-loan-account.model.ts`:
- Around line 12-16: The date fields in the WorkingCapitalLoanAccount model are
typed as Date but the API returns Fineract local-date arrays; update
effectiveDate and createdDate to type number[] to match the codebase pattern
(see other models like LoanCharge, LoanTransactionTemplate, DelinquentData),
ensuring any consumers of WorkingCapitalLoanAccount (e.g., templates using |
dateFormat) continue to work at runtime.

In `@src/app/shared/undo-dialog/undo-dialog.component.html`:
- Around line 10-27: Remove the unused template export `#formRef`="ngForm" and
replace the outer <div> wrapper with a <mat-dialog-content> element to follow
Angular Material dialog structure; keep the reactive form binding
[formGroup]="undoActionForm" and existing controls (formControlName="note",
mat-dialog-actions buttons) intact so the component uses undoActionForm
exclusively without the unused ngForm export.

In `@src/assets/translations/en-US.json`:
- Line 3159: Update the translation entry for "Undo Payment Rate" to match the
UI label by changing the key and its value from "Undo Payment Rate" to "Undo
Period Payment Rate" (i.e., replace the "Undo Payment Rate" JSON key/value pair
with "Undo Period Payment Rate": "Undo Period Payment Rate") so the button text
matches the tab/page label; ensure the exact phrase "Undo Period Payment Rate"
is used for both key and value.

In `@src/assets/translations/es-CL.json`:
- Line 3118: The Spanish translation key "Undo Payment Rate" should be changed
to match the "Period Payment Rate" terminology used elsewhere; update the value
for the key "Undo Payment Rate" in src/assets/translations/es-CL.json to
"Deshacer tasa de pago del período" so it remains consistent with the Period
Payment Rate table/tab labels.

In `@src/assets/translations/it-IT.json`:
- Line 3115: The Italian translation for the "Undo Payment Rate" label loses the
period context; update the value for the "Undo Payment Rate" key in
src/assets/translations/it-IT.json to explicitly include "period" (for example:
"Annulla il tasso di pagamento del periodo" or "Annulla il tasso di pagamento
periodico") so the label clearly refers to Period Payment Rates.

In `@src/assets/translations/ko-KO.json`:
- Line 3116: The translation for the key "Undo Payment Rate" uses inconsistent
terminology ("지불 비율 취소"); update the value to match the project's existing term
"기간별 지급률" (e.g., change to "기간별 지급률 취소") so it aligns with other labels; locate
the "Undo Payment Rate" entry in src/assets/translations/ko-KO.json and replace
its value accordingly.

---

Nitpick comments:
In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html`:
- Line 12: The div uses a non-compliant spacing class "gap-20px" in the class
list "layout-row transaction-buttons align-end gap-20px"; replace that token
with an 8px-grid-compliant utility (e.g., gap-16px or gap-24px) or a project
SCSS spacing variable (e.g., $spacing-16) and ensure the corresponding gap
utility exists in the global utilities/SCSS so the HTML uses a permitted spacing
class instead of "gap-20px".

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.scss`:
- Line 12: Replace the viewport-dependent rule "padding-bottom: 2%" with an
8px-grid based value; locate the selector in
loan-period-payment-rates.component.scss that sets "padding-bottom: 2%" and
change it to a fixed multiple of 8px (for example "padding-bottom: 16px" for 2 ×
8px) or to the project's spacing token/variable if one exists (e.g., $spacing-2)
to align with the 8px grid guideline.

In `@src/app/loans/loans.service.ts`:
- Around line 850-865: The three methods getWorkingCapitalPeriodPaymentRates,
addWorkingCapitalPeriodPaymentRate, and undoWorkingCapitalPeriodPaymentRate use
loanId: any — change those signatures to use loanId: string | number for
stronger typing (keep payload: any as-is per project convention) and update any
related internal references to treat loanId as string | number so URL
construction remains correct; no other behavior changes required.

In `@src/app/shared/undo-dialog/undo-dialog.component.ts`:
- Around line 32-49: Add explicit TypeScript types for the dialog input and form
model: define an interface (e.g., UndoDialogData) for the MAT_DIALOG_DATA
payload and an interface (e.g., UndoActionFormValue) for the form value (note:
string). Replace UntypedFormBuilder/UntypedFormGroup with typed FormBuilder and
FormGroup<UndoActionFormValue>, change the data inject to
inject<UndoDialogData>(MAT_DIALOG_DATA), type dialogRef as
MatDialogRef<UndoDialogComponent, UndoActionFormValue> if it returns a value,
and update undoActionForm’s type and createUndoActionForm to build a typed group
in the createUndoActionForm function so templates and callers get compile-time
checks (refer to UndoDialogComponent, dialogRef, data, undoActionForm,
createUndoActionForm, MAT_DIALOG_DATA, UntypedFormBuilder).

In `@src/assets/translations/pt-PT.json`:
- Line 3116: Remove the unused translation key "Undo Payment Rate" from the
translations file or, if it is intended to be used, add a documented usage and
update code to reference it; specifically search for and reconcile the
translation key "Undo Payment Rate" with existing keys used for the undo UI flow
(labels.buttons.Undo and labels.inputs.Period Payment Rate) and either delete
the "Undo Payment Rate" entry or replace UI references to use this single key
consistently and document its purpose.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 447f83cc-c267-4fd8-9df3-b6d70fb200b3

📥 Commits

Reviewing files that changed from the base of the PR and between 787647c and 91960e0.

📒 Files selected for processing (24)
  • src/app/loans/loans-routing.module.ts
  • src/app/loans/loans-view/loans-view.component.html
  • src/app/loans/loans-view/working-capital/common-resolvers/loan-period-payment-rates.resolver.ts
  • src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html
  • src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.scss
  • src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts
  • src/app/loans/loans.service.ts
  • src/app/loans/models/working-capital-loan-account.model.ts
  • src/app/shared/undo-dialog/undo-dialog.component.html
  • src/app/shared/undo-dialog/undo-dialog.component.scss
  • src/app/shared/undo-dialog/undo-dialog.component.ts
  • src/assets/translations/cs-CS.json
  • src/assets/translations/de-DE.json
  • src/assets/translations/en-US.json
  • src/assets/translations/es-CL.json
  • src/assets/translations/es-MX.json
  • src/assets/translations/fr-FR.json
  • src/assets/translations/it-IT.json
  • src/assets/translations/ko-KO.json
  • src/assets/translations/lt-LT.json
  • src/assets/translations/lv-LV.json
  • src/assets/translations/ne-NE.json
  • src/assets/translations/pt-PT.json
  • src/assets/translations/sw-SW.json

Comment on lines +12 to +16
effectiveDate: Date;
previousRate: number;
newRate: number;
reversed: boolean;
createdDate: Date;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check how similar API date fields are modeled and consumed in the app.
# Expectation: Use the same date wire type used by comparable loan models/components,
# or add explicit mapping from the endpoint response to JavaScript Date objects.

rg -n --type=ts -C3 '\b(effectiveDate|createdDate)\b\s*:\s*(Date|number\[\]|\[number,\s*number,\s*number\]|string)' src/app || true
rg -n -C2 '\|\s*dateFormat' src/app/loans src/app/shared || true

Repository: openMF/web-app

Length of output: 40066


🏁 Script executed:

# Find the service that provides getWorkingCapitalPeriodPaymentRates
rg -n "getWorkingCapitalPeriodPaymentRates" src/app --type=ts

Repository: openMF/web-app

Length of output: 744


🏁 Script executed:

# Look for the working-capital service file
fd -e ts "working.*capital.*service" src/app

Repository: openMF/web-app

Length of output: 40


🏁 Script executed:

# Check for any response mappers or interceptors
rg -n "PeriodPaymentRateChange" src/app --type=ts

Repository: openMF/web-app

Length of output: 734


🏁 Script executed:

# View the service implementation
sed -n '845,860p' src/app/loans/loans.service.ts

Repository: openMF/web-app

Length of output: 469


🏁 Script executed:

# Check the resolver implementation
cat src/app/loans/loans-view/working-capital/common-resolvers/loan-period-payment-rates.resolver.ts

Repository: openMF/web-app

Length of output: 1025


🏁 Script executed:

# Check for pipe definition of dateFormat
fd -e ts "dateFormat" src/app --type=pipe

Repository: openMF/web-app

Length of output: 40


🏁 Script executed:

# Look for dateFormat pipe definition
rg -n "dateFormat" src/app -A5 -B2 --type=ts | grep -A5 -B2 "@Pipe\|transform"

Repository: openMF/web-app

Length of output: 3815


🏁 Script executed:

# Look at other loan models to see how date fields are typed
rg -n "export interface" src/app/loans/models/ -A10 --type=ts | head -80

Repository: openMF/web-app

Length of output: 5549


🏁 Script executed:

# Check how other services handle date responses
rg -n "http.get" src/app/loans/loans.service.ts -A2 | grep -A2 "date\|Date" | head -40

Repository: openMF/web-app

Length of output: 40


Use number[] for date fields to match API response format and codebase pattern.

The interface declares effectiveDate: Date and createdDate: Date, but the service returns raw HTTP response data where these fields are number[] (Fineract's local-date format: [year, month, day]). This matches how other loan models in the same codebase type date fields—see LoanCharge, LoanTransactionTemplate, and DelinquentData which all use number[] for date fields from the API. The template uses | dateFormat pipe (which accepts any) so it works at runtime, but the type annotation is misleading. Align with the established pattern:

 export interface PeriodPaymentRateChange {
   id: number;
   loanId: number;
-  effectiveDate: Date;
+  effectiveDate: number[];
   previousRate: number;
   newRate: number;
   reversed: boolean;
-  createdDate: Date;
+  createdDate: number[];
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
effectiveDate: Date;
previousRate: number;
newRate: number;
reversed: boolean;
createdDate: Date;
export interface PeriodPaymentRateChange {
id: number;
loanId: number;
effectiveDate: number[];
previousRate: number;
newRate: number;
reversed: boolean;
createdDate: number[];
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/loans/models/working-capital-loan-account.model.ts` around lines 12 -
16, The date fields in the WorkingCapitalLoanAccount model are typed as Date but
the API returns Fineract local-date arrays; update effectiveDate and createdDate
to type number[] to match the codebase pattern (see other models like
LoanCharge, LoanTransactionTemplate, DelinquentData), ensuring any consumers of
WorkingCapitalLoanAccount (e.g., templates using | dateFormat) continue to work
at runtime.

Comment on lines +10 to +27
<div>
<form #formRef="ngForm" [formGroup]="undoActionForm">
<mat-form-field class="flex-100">
<textarea formControlName="note" matInput placeholder="{{ 'labels.inputs.Notes' | translate }}"></textarea>
</mat-form-field>
<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>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Expected after the fix: no matches.
rg -nP '<form(?=[^>]*\[formGroup\])(?=[^>]*#\w+="ngForm")' --type html

Repository: 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 ""
done

Repository: 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 ""
done

Repository: 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 ngForm export and use mat-dialog-content for proper Material Dialog structure.

The #formRef="ngForm" export is unused in this component (not referenced in the .ts file) and unnecessary with reactive form setup. Replace the wrapper <div> with <mat-dialog-content> to follow Angular Material Dialog best practices.

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
Verify each finding against the current code and only fix it if needed.

In `@src/app/shared/undo-dialog/undo-dialog.component.html` around lines 10 - 27,
Remove the unused template export `#formRef`="ngForm" and replace the outer <div>
wrapper with a <mat-dialog-content> element to follow Angular Material dialog
structure; keep the reactive form binding [formGroup]="undoActionForm" and
existing controls (formControlName="note", mat-dialog-actions buttons) intact so
the component uses undoActionForm exclusively without the unused ngForm export.

"Undo Disbursal": "Undo Disbursal",
"Undo Charge-Off": "Undo Charge-Off",
"Undo Last Disbursal": "Undo Last Disbursal",
"Undo Payment Rate": "Undo Payment Rate",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Match the undo label to the feature name.

The PR screenshot calls this action “Undo Period Payment Rate”; the current translation drops “Period”, making the button less consistent with the tab/page label.

✏️ Proposed text fix
-      "Undo Payment Rate": "Undo Payment Rate",
+      "Undo Payment Rate": "Undo Period Payment Rate",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Undo Payment Rate": "Undo Payment Rate",
"Undo Payment Rate": "Undo Period Payment Rate",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/assets/translations/en-US.json` at line 3159, Update the translation
entry for "Undo Payment Rate" to match the UI label by changing the key and its
value from "Undo Payment Rate" to "Undo Period Payment Rate" (i.e., replace the
"Undo Payment Rate" JSON key/value pair with "Undo Period Payment Rate": "Undo
Period Payment Rate") so the button text matches the tab/page label; ensure the
exact phrase "Undo Period Payment Rate" is used for both key and value.

"Undo Disbursal": "Deshacer curso",
"Undo Charge-Off": "Deshacer Cancelación",
"Undo Last Disbursal": "Deshacer el último curso",
"Undo Payment Rate": "Deshacer tasa de pago",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Keep the undo action aligned with the Period Payment Rate terminology.

This action appears to target the new “Period Payment Rate” entity, but the Spanish label drops “del período,” unlike the new table/tab labels. Consider keeping the qualifier for consistency.

🌐 Proposed wording tweak
-      "Undo Payment Rate": "Deshacer tasa de pago",
+      "Undo Payment Rate": "Deshacer tasa de pago del período",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Undo Payment Rate": "Deshacer tasa de pago",
"Undo Payment Rate": "Deshacer tasa de pago del período",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/assets/translations/es-CL.json` at line 3118, The Spanish translation key
"Undo Payment Rate" should be changed to match the "Period Payment Rate"
terminology used elsewhere; update the value for the key "Undo Payment Rate" in
src/assets/translations/es-CL.json to "Deshacer tasa de pago del período" so it
remains consistent with the Period Payment Rate table/tab labels.

"Undo Disbursal": "Annullare l'esborso",
"Undo Charge-Off": "Annullare l'addebito",
"Undo Last Disbursal": "Annulla l'ultimo esborso",
"Undo Payment Rate": "Annulla il tasso di pagamento",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Keep the period context in the undo action label.

The new screen is specifically for Period Payment Rates; this translation drops “period” and can read like a generic payment-rate undo action.

🌐 Proposed translation adjustment
-      "Undo Payment Rate": "Annulla il tasso di pagamento",
+      "Undo Payment Rate": "Annulla il tasso di pagamento del periodo",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Undo Payment Rate": "Annulla il tasso di pagamento",
"Undo Payment Rate": "Annulla il tasso di pagamento del periodo",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/assets/translations/it-IT.json` at line 3115, The Italian translation for
the "Undo Payment Rate" label loses the period context; update the value for the
"Undo Payment Rate" key in src/assets/translations/it-IT.json to explicitly
include "period" (for example: "Annulla il tasso di pagamento del periodo" or
"Annulla il tasso di pagamento periodico") so the label clearly refers to Period
Payment Rates.

"Undo Disbursal": "지급 취소",
"Undo Charge-Off": "상각 취소",
"Undo Last Disbursal": "마지막 지불 취소",
"Undo Payment Rate": "지불 비율 취소",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Keep the Korean term for “Payment Rate” consistent.

The related labels use 기간별 지급률, but this action uses 지불 비율, which may read as a different concept. Consider aligning the undo label with the same terminology.

🌐 Proposed translation consistency fix
-      "Undo Payment Rate": "지불 비율 취소",
+      "Undo Payment Rate": "기간별 지급률 취소",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/assets/translations/ko-KO.json` at line 3116, The translation for the key
"Undo Payment Rate" uses inconsistent terminology ("지불 비율 취소"); update the value
to match the project's existing term "기간별 지급률" (e.g., change to "기간별 지급률 취소") so
it aligns with other labels; locate the "Undo Payment Rate" entry in
src/assets/translations/ko-KO.json and replace its value accordingly.

@alberto-art3ch alberto-art3ch force-pushed the WEB-657/working-capital-period-payment-rate-changes branch from 91960e0 to 1ba133e Compare April 20, 2026 03:51
@alberto-art3ch alberto-art3ch force-pushed the WEB-657/working-capital-period-payment-rate-changes branch from 1ba133e to 0a1cfee Compare April 20, 2026 15:12
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts (1)

108-121: Tighten the new response typings when touching this flow.

The table data is already modeled as PeriodPaymentRateChange[], but the dialog/API callbacks fall back to any. Consider adding small close-result interfaces and typing the refreshed rate-change response in the service/component as part of this new feature.

Based on learnings, TypeScript API responses should use specific interfaces/types instead of any, while broader response-layer typing can be handled as a separate enhancement.

Also applies to: 135-144

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts`
around lines 108 - 121, The callbacks use broad any types; tighten them by
introducing small result interfaces (e.g. CloseDialogResult { data?: { value: {
periodPaymentRate: number; note?: string } } } and API response types like
AddRateResponse and PeriodPaymentRateChange[]) and use them in
dialogRef.afterClosed().subscribe, the addWorkingCapitalPeriodPaymentRate()
response, and getWorkingCapitalPeriodPaymentRates() subscription; update the
component's loanPaymentRatesData to be typed as PeriodPaymentRateChange[] and
change the local destructure to use the typed CloseDialogResult to eliminate any
usage of any in this flow (affecting dialogRef.afterClosed,
addWorkingCapitalPeriodPaymentRate, getWorkingCapitalPeriodPaymentRates, and
loanPaymentRatesData).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html`:
- Around line 51-59: Remove the hard-coded space before the percent sign in the
template so rates render as "1.00%" not "1.00 %"; update the two bindings that
render percent values (the cell showing item.previousRate and the cell showing
item.newRate in the loan-period-payment-rates template) to place the "%"
immediately after the formatted value, and audit other occurrences in this
component/template (e.g., bindings using formatNumber and
periodPaymentRateStyle) to ensure no trailing space is present; if
locale-specific spacing is required later, implement it in the formatter
(formatNumber) rather than in the template.
- Line 12: The div using class "gap-20px" violates the 8px grid — replace that
utility with an existing 8px-grid token (e.g., use a 16px or 24px gap utility
such as "gap-16px" or "gap-24px") or remove the inline gap class and define the
spacing in the component SCSS by styling the .transaction-buttons selector using
the project's spacing variables (the theme/main spacing tokens) so the
layout-row .transaction-buttons uses an 8px-grid-compliant gap.
- Around line 19-28: The template composes two translation keys which can break
word order in other locales; replace the concatenated labels in the buttons
inside loan-period-payment-rates.component.html with single, full translation
keys (e.g., use a dedicated key for the add button and one for the undo button)
instead of "{{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Period
Payment Rate' | translate }}", update the button that calls undoPaymentRate()
and the one controlled by hasUndoablePaymentRates to use the new full keys
(unique identifiers like labels.buttons.AddPeriodPaymentRate and
labels.buttons.UndoPeriodPaymentRate), and then run npm run translations:extract
to add the new i18n entries.

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts`:
- Around line 102-104: The dialog title currently composes two translated
fragments (translateService.instant('labels.buttons.Add') + ' ' +
labelHeadingText) which breaks localization; change to a single translation key
with interpolation (e.g., use translateService.instant('dialogs.addItem', {
item: labelHeadingText })) and update the layout.addButtonText similarly to use
a full key, referencing translateService.instant('dialogs.addButton') or a
parameterized key so translators see the whole phrase; ensure the translation
keys are added to i18n files and run npm run translations:extract.

---

Nitpick comments:
In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts`:
- Around line 108-121: The callbacks use broad any types; tighten them by
introducing small result interfaces (e.g. CloseDialogResult { data?: { value: {
periodPaymentRate: number; note?: string } } } and API response types like
AddRateResponse and PeriodPaymentRateChange[]) and use them in
dialogRef.afterClosed().subscribe, the addWorkingCapitalPeriodPaymentRate()
response, and getWorkingCapitalPeriodPaymentRates() subscription; update the
component's loanPaymentRatesData to be typed as PeriodPaymentRateChange[] and
change the local destructure to use the typed CloseDialogResult to eliminate any
usage of any in this flow (affecting dialogRef.afterClosed,
addWorkingCapitalPeriodPaymentRate, getWorkingCapitalPeriodPaymentRates, and
loanPaymentRatesData).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e059f403-2152-4366-a3ab-99e288d8a488

📥 Commits

Reviewing files that changed from the base of the PR and between 91960e0 and 0a1cfee.

📒 Files selected for processing (24)
  • src/app/loans/loans-routing.module.ts
  • src/app/loans/loans-view/loans-view.component.html
  • src/app/loans/loans-view/working-capital/common-resolvers/loan-period-payment-rates.resolver.ts
  • src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html
  • src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.scss
  • src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts
  • src/app/loans/loans.service.ts
  • src/app/loans/models/working-capital-loan-account.model.ts
  • src/app/shared/undo-dialog/undo-dialog.component.html
  • src/app/shared/undo-dialog/undo-dialog.component.scss
  • src/app/shared/undo-dialog/undo-dialog.component.ts
  • src/assets/translations/cs-CS.json
  • src/assets/translations/de-DE.json
  • src/assets/translations/en-US.json
  • src/assets/translations/es-CL.json
  • src/assets/translations/es-MX.json
  • src/assets/translations/fr-FR.json
  • src/assets/translations/it-IT.json
  • src/assets/translations/ko-KO.json
  • src/assets/translations/lt-LT.json
  • src/assets/translations/lv-LV.json
  • src/assets/translations/ne-NE.json
  • src/assets/translations/pt-PT.json
  • src/assets/translations/sw-SW.json
✅ Files skipped from review due to trivial changes (9)
  • src/app/shared/undo-dialog/undo-dialog.component.scss
  • src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.scss
  • src/assets/translations/en-US.json
  • src/assets/translations/es-CL.json
  • src/assets/translations/sw-SW.json
  • src/assets/translations/cs-CS.json
  • src/assets/translations/lv-LV.json
  • src/assets/translations/fr-FR.json
  • src/assets/translations/ne-NE.json
🚧 Files skipped from review as they are similar to previous changes (13)
  • src/assets/translations/ko-KO.json
  • src/app/loans/loans-view/loans-view.component.html
  • src/app/shared/undo-dialog/undo-dialog.component.html
  • src/app/loans/loans.service.ts
  • src/app/loans/loans-view/working-capital/common-resolvers/loan-period-payment-rates.resolver.ts
  • src/assets/translations/pt-PT.json
  • src/app/loans/loans-routing.module.ts
  • src/app/shared/undo-dialog/undo-dialog.component.ts
  • src/app/loans/models/working-capital-loan-account.model.ts
  • src/assets/translations/it-IT.json
  • src/assets/translations/de-DE.json
  • src/assets/translations/lt-LT.json
  • src/assets/translations/es-MX.json

<div class="container">
<h3>{{ 'labels.inputs.Period Payment Rates' | translate }}</h3>

<div class="layout-row transaction-buttons align-end gap-20px">
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use an 8px-grid spacing token here.

gap-20px falls outside the project’s 8px spacing scale. Prefer an existing 16px/24px utility or move this spacing into SCSS using the project spacing variables.

As per coding guidelines, src/**/*.{scss,html} should “Stick to the 8px grid system for visual design and spacing” and “Leverage SCSS variables defined in src/main.scss and src/theme/mifosx-theme.scss rather than generating custom classes and explicit pixel values”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html`
at line 12, The div using class "gap-20px" violates the 8px grid — replace that
utility with an existing 8px-grid token (e.g., use a 16px or 24px gap utility
such as "gap-16px" or "gap-24px") or remove the inline gap class and define the
spacing in the component SCSS by styling the .transaction-buttons selector using
the project's spacing variables (the theme/main spacing tokens) so the
layout-row .transaction-buttons uses an 8px-grid-compliant gap.

Comment on lines +19 to +28
{{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Period Payment Rate' | translate }}
</button>
@if (hasUndoablePaymentRates) {
<button
mat-raised-button
color="primary"
(click)="undoPaymentRate()"
*mifosxHasPermission="'UNDORATECHANGE_WORKINGCAPITALLOAN'"
>
{{ 'labels.buttons.Undo' | translate }} {{ 'labels.inputs.Period Payment Rate' | translate }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use full translation keys for the action labels.

Composing Add/Undo with Period Payment Rate can produce incorrect word order in non-English locales. Prefer dedicated keys for the full button labels.

🌐 Suggested wording fix
-      {{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Period Payment Rate' | translate }}
+      {{ 'labels.buttons.Add Period Payment Rate' | translate }}
...
-        {{ 'labels.buttons.Undo' | translate }} {{ 'labels.inputs.Period Payment Rate' | translate }}
+        {{ 'labels.buttons.Undo Period Payment Rate' | translate }}

As per coding guidelines, use “proper i18n variables from @ngx-translate/core for all user-facing strings” and run npm run translations:extract whenever new strings are added.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Period Payment Rate' | translate }}
</button>
@if (hasUndoablePaymentRates) {
<button
mat-raised-button
color="primary"
(click)="undoPaymentRate()"
*mifosxHasPermission="'UNDORATECHANGE_WORKINGCAPITALLOAN'"
>
{{ 'labels.buttons.Undo' | translate }} {{ 'labels.inputs.Period Payment Rate' | translate }}
{{ 'labels.buttons.Add Period Payment Rate' | translate }}
</button>
`@if` (hasUndoablePaymentRates) {
<button
mat-raised-button
color="primary"
(click)="undoPaymentRate()"
*mifosxHasPermission="'UNDORATECHANGE_WORKINGCAPITALLOAN'"
>
{{ 'labels.buttons.Undo Period Payment Rate' | translate }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html`
around lines 19 - 28, The template composes two translation keys which can break
word order in other locales; replace the concatenated labels in the buttons
inside loan-period-payment-rates.component.html with single, full translation
keys (e.g., use a dedicated key for the add button and one for the undo button)
instead of "{{ 'labels.buttons.Add' | translate }} {{ 'labels.inputs.Period
Payment Rate' | translate }}", update the button that calls undoPaymentRate()
and the one controlled by hasUndoablePaymentRates to use the new full keys
(unique identifiers like labels.buttons.AddPeriodPaymentRate and
labels.buttons.UndoPeriodPaymentRate), and then run npm run translations:extract
to add the new i18n entries.

Comment on lines +51 to +59
{{ 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 }} %
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove the hard-coded space before %.

The current template renders values like 1.00 %, while the PR screenshots show 1.00%. If locale-specific percent spacing is needed later, that should come from a formatter rather than a literal template space.

🧹 Suggested formatting fix
-        {{ item.previousRate | formatNumber }} %
+        {{ item.previousRate | formatNumber }}%
...
-        {{ item.newRate | formatNumber }} %
+        {{ item.newRate | formatNumber }}%
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{{ 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 }} %
{{ 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 }}%
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.html`
around lines 51 - 59, Remove the hard-coded space before the percent sign in the
template so rates render as "1.00%" not "1.00 %"; update the two bindings that
render percent values (the cell showing item.previousRate and the cell showing
item.newRate in the loan-period-payment-rates template) to place the "%"
immediately after the formatted value, and audit other occurrences in this
component/template (e.g., bindings using formatNumber and
periodPaymentRateStyle) to ensure no trailing space is present; if
locale-specific spacing is required later, implement it in the formatter
(formatNumber) rather than in the template.

Comment on lines +102 to +104
const data = {
title: this.translateService.instant('labels.buttons.Add') + ' ' + labelHeadingText,
layout: { addButtonText: this.translateService.instant('labels.buttons.Add') },
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

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 @ngx-translate/core for all user-facing strings” and run npm run translations:extract whenever new strings are added.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/app/loans/loans-view/working-capital/loan-period-payment-rates/loan-period-payment-rates.component.ts`
around lines 102 - 104, The dialog title currently composes two translated
fragments (translateService.instant('labels.buttons.Add') + ' ' +
labelHeadingText) which breaks localization; change to a single translation key
with interpolation (e.g., use translateService.instant('dialogs.addItem', {
item: labelHeadingText })) and update the layout.addButtonText similarly to use
a full key, referencing translateService.instant('dialogs.addButton') or a
parameterized key so translators see the whole phrase; ensure the translation
keys are added to i18n files and run npm run translations:extract.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant