Skip to content

WEB-678: Restructure Reporting Plugin to Support Branch Model Operations#3541

Open
sakshar2303 wants to merge 3 commits intoopenMF:devfrom
sakshar2303:WEB-678-restructure-reporting-plugin
Open

WEB-678: Restructure Reporting Plugin to Support Branch Model Operations#3541
sakshar2303 wants to merge 3 commits intoopenMF:devfrom
sakshar2303:WEB-678-restructure-reporting-plugin

Conversation

@sakshar2303
Copy link
Copy Markdown

@sakshar2303 sakshar2303 commented Apr 28, 2026

Description

Restructure the existing Reporting plugin to better support branch model operations while maintaining backward compatibility with current functionality.

Key Changes:

  • Modular Restructuring: Moved ReportsService, core models (ChartData, ReportParameter, SelectOption), and resolvers (ReportsResolver, RunReportResolver) to a new dedicated directory: src/app/reporting-plugin/.
  • Branch Model Support: Enhanced ReportsService with a new getReportsByOffice(officeId: string) method to support explicit branch-based filtering.
  • Decoupling: Refactored over 15 import points across the codebase (including Loans, Clients, Savings, and SMS Campaigns) to depend on the new modular structure instead of the feature module.
  • Backward Compatibility: Added a re-export of ReportsService at the old location (src/app/reports/reports.service.ts) to ensure zero breakage for existing dependencies.
  • Compliance:
    • Applied Prettier formatting across all modified files.
    • Added mandatory Mifos Initiative license headers to all new and relocated files.
    • Verified that ESLint and Jest tests pass.

Screenshots (Mandatory for UI Changes)

  • Before: [Insert Screenshot]
  • After: [Insert Screenshot]

Impact

This change reduces coupling between the Reporting feature and other core modules, making the reporting logic easier to maintain and extend for multi-branch operations.

Summary by CodeRabbit

  • Refactor

    • Reporting logic consolidated into a new modular reporting plugin; existing report flows and exports continue to work with the new module.
    • Chart/parameter handling improved with stricter data structures (no runtime behavior changes).
  • Refactor

    • Accounting labels in tax component views now use standardized translation keys for more consistent translations.
  • Chores

    • Added license headers to reporting plugin files.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 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

Migrates reporting types and ReportsService implementation from legacy app/reports into a new app/reporting-plugin module, updates imports across components/resolvers, adds typed reporting models and a new ReportsService, and adjusts one template's account-type translation usage.

Changes

Cohort / File(s) Summary
Reporting service implementation & re-export
src/app/reporting-plugin/services/reports.service.ts, src/app/reports/reports.service.ts
Adds a full ReportsService implementation (HTTP methods for reports, params, charts, Pentaho/BIRT runs) and converts the legacy src/app/reports/reports.service.ts into a re-export of the new service.
Model additions & typing
src/app/reporting-plugin/models/chart-data.model.ts, src/app/reporting-plugin/models/report-parameter.model.ts, src/app/reporting-plugin/models/select-option.model.ts
Adds ChartDataResponse and strongly-typed ReportParameter and SelectOption (constructor signatures tightened); model file headers added.
Resolver relocation
src/app/reporting-plugin/resolvers/reports.resolver.ts, src/app/reporting-plugin/resolvers/run-report.resolver.ts, src/app/reports/reports-routing.module.ts
Resolver imports updated to use app/reporting-plugin/resolvers; routing module adjusted to reference relocated resolvers.
Component import updates (ReportsService)
src/app/clients/.../general-tab.component.ts, src/app/clients/.../personal-data-tab.component.ts, src/app/loans/.../loans-transaction-reciept.resolver.ts, src/app/loans/.../export-transactions.component.ts, src/app/reports/run-report/birt/birt.component.ts, src/app/reports/run-report/pentaho/pentaho.component.ts, src/app/reports/run-report/table-and-sms/table-and-sms.component.ts, src/app/savings/.../savings-transaction-reciept.resolver.ts, src/app/savings/.../export-transactions.component.ts
Updated imports to app/reporting-plugin/services/reports.service; no runtime logic changes.
Component import updates (models)
src/app/organization/sms-campaigns/.../*.component.ts, src/app/reports/run-report/chart/chart.component.ts, src/app/reports/run-report/run-report.component.ts
Updated imports for ReportParameter / SelectOption / ChartData to app/reporting-plugin/models/*; no logic changes.
Template change
src/app/products/manage-tax-components/view-tax-component/view-tax-component.component.html
Account-type label construction changed to use *.AccountType.code with translateKey under inputs.accounting instead of parsing .value.

Sequence Diagram(s)

sequenceDiagram
    participant Component as Client Component
    participant Service as ReportsService
    participant Http as HttpClient
    participant API as Reporting API

    Component->>Service: request report / params / run (formData)
    Service->>Http: GET /runreports or /reports with HttpParams
    Http->>API: network request
    API-->>Http: response (JSON / arraybuffer)
    Http-->>Service: response
    Service-->>Component: mapped data (ChartData / ReportParameter[] / blob response)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • IOhacker
  • alberto-art3ch
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately summarizes the main objective of the PR: restructuring the reporting plugin to support branch model operations, which is consistent with all the changes across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (6)
src/app/reports/run-report/run-report.component.ts (2)

452-484: ⚠️ Potential issue | 🟠 Major

Add error handling + ensure isProcessing always resets in runReportAndExport().

this.isProcessing = true is set (Line 454) but this.isProcessing = false only happens inside the success callback (Line 483). If the request errors, the UI can remain stuck in a processing state.

Add an error callback to the subscription (or finalize) to reset isProcessing and optionally surface a translated alert (without introducing new hardcoded strings).
As per coding guidelines, “clean observable patterns.”

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

In `@src/app/reports/run-report/run-report.component.ts` around lines 452 - 484,
The subscription in runReportAndExport sets this.isProcessing = true but only
resets it in the success handler; update
reportsService.getRunReportData(reportName, payload) to use an RxJS finalize to
always set this.isProcessing = false and add an error callback on the subscribe
to surface an alert (use alertService.alert with translateService.instant for
type/message using your existing translation keys) so errors don't leave the UI
stuck; reference runReportAndExport, reportsService.getRunReportData,
isProcessing, alertService.alert, translateService.instant and import/use
finalize from 'rxjs/operators' (or rxjs) to perform the guaranteed reset.

325-341: ⚠️ Potential issue | 🟠 Major

Fix unsubscribed valueChanges subscriptions and use setControl to update existing child controls.

The valueChanges subscriptions in setChildControls() are created but never cleaned up. On every parent parameter value change, new subscriptions accumulate, causing a memory leak. Additionally, calling addControl() on existing controls silently ignores the update—use contains() and setControl() instead to properly update child controls on subsequent parent value changes. Implement OnDestroy with takeUntil to clean up subscriptions.

Proposed fix
export class RunReportComponent implements OnInit, OnDestroy {
  private destroy$ = new Subject<void>();

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }

  setChildControls() {
    this.parentParameters.forEach((param: ReportParameter) => {
      this.reportForm.get(param.name).valueChanges
        .pipe(takeUntil(this.destroy$))
        .subscribe((option: any) => {
          param.childParameters.forEach((child: ReportParameter) => {
            const control =
              child.displayType === 'none'
                ? new UntypedFormControl(child.defaultVal)
                : new UntypedFormControl('', Validators.required);

            if (this.reportForm.contains(child.name)) {
              this.reportForm.setControl(child.name, control);
            } else {
              this.reportForm.addControl(child.name, control);
            }
            if (child.displayType === 'select') {
              const inputstring = `${child.name}?${param.inputName}=${option?.id}`;
              this.fetchSelectOptions(child, inputstring);
            }
          });
        });
    });
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/reports/run-report/run-report.component.ts` around lines 325 - 341,
The valueChanges subscriptions created in setChildControls() leak and
addControl() silently no-ops for existing controls; fix by introducing a
component-level Subject (e.g., ngDestroy$) and pipe each valueChanges with
takeUntil(this.ngDestroy$) (import Subject and takeUntil) and implement
OnDestroy to call this.ngDestroy$.next() and complete(); inside the
subscription, before adding child controls check
this.reportForm.contains(child.name) and use
this.reportForm.setControl(child.name, new UntypedFormControl(...)) to update
existing controls (otherwise addControl for new ones), and keep
fetchSelectOptions logic unchanged.
src/app/reports/run-report/table-and-sms/table-and-sms.component.ts (1)

173-203: ⚠️ Potential issue | 🟡 Minor

Fix XLS download filename (currently hardcoded).

In exportToXLS(), fileName is computed using the report name (Line 174), but the downloaded file uses a.download = 'filename.xlsx' (Line 199). This ignores the computed filename and is user-visible.

Proposed fix
-      a.download = 'filename.xlsx';
+      a.download = fileName;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/reports/run-report/table-and-sms/table-and-sms.component.ts` around
lines 173 - 203, The download currently uses a hardcoded filename
('filename.xlsx') instead of the computed fileName; inside exportToXLS() replace
the hardcoded a.download assignment with the computed fileName (ensure fileName
includes the .xlsx extension or append it if missing) so that the anchor element
uses fileName when triggering the download; update references around the
fileName constant and the a.download assignment in exportToXLS() to use the same
variable.
src/app/reports/run-report/chart/chart.component.ts (1)

145-162: ⚠️ Potential issue | 🟠 Major

Fix invalid color format in randomColor() — use rgba() instead of rgb().

The current code returns rgb(${r},${g},${b},0.6) which is invalid CSS syntax. The rgb() function does not accept an alpha channel as a fourth parameter; alpha transparency requires either rgba(r, g, b, a) or the modern rgb(r g b / a) form. This will cause Chart.js to fail parsing the color or apply unexpected defaults, breaking chart visualization.

Proposed fix
 randomColor() {
   const r = Math.floor(Math.random() * 255);
   const g = Math.floor(Math.random() * 255);
   const b = Math.floor(Math.random() * 255);
-  return `rgb(${r},${g},${b},0.6)`;
+  return `rgba(${r},${g},${b},0.6)`;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/reports/run-report/chart/chart.component.ts` around lines 145 - 162,
The color string produced by randomColor() is invalid because it uses rgb(...)
with four arguments; update randomColor() to return a valid CSS color using
rgba(r,g,b,a) (or the modern rgb(r g b / a)) including the 0.6 alpha, so
Chart.js can parse it; then ensure randomColorArray(length) continues to call
randomColor() to build the array (functions: randomColor and randomColorArray).
src/app/reporting-plugin/resolvers/run-report.resolver.ts (1)

1-16: ⚠️ Potential issue | 🟠 Major

Major: duplicate MPL license header blocks present.

This file contains the MPL header twice back-to-back (once at the top, and again in the added block around Line 9-15). This is likely to fail/complicate npm run headers:check.

Proposed fix

Remove the duplicate second header block so only one MPL header remains.

 /**
  * 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/.
  */
- 
-/**
- * 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/.
- */
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/reporting-plugin/resolvers/run-report.resolver.ts` around lines 1 -
16, The file contains two identical MPL license header blocks; remove the
duplicate second header block (the consecutive /** ... */ that appears after the
first header) so only a single MPL header remains at the top of the file,
ensuring the header:check step will pass; search for the repeated /** Copyright
since 2025 Mifos Initiative ... */ block and delete the latter occurrence.
src/app/clients/clients-view/general-tab/general-tab.component.ts (1)

111-114: ⚠️ Potential issue | 🟠 Major

Major: hardcoded user-facing error string must be i18n'd.

message: 'Failed to load Loan Application PDF report.' is hardcoded. Per repo guidelines, convert to an i18n key using TranslateService.instant(...) and run npm run translations:extract when adding the new key. This follows the established pattern in personal-data-tab.component.ts (same directory), which i18n's all alert messages.

Suggested direction
+ import { TranslateService } from '@ngx-translate/core';

export class GeneralTabComponent implements OnDestroy {
  private destroy$ = new Subject<void>();
  private alertService = inject(AlertService);
+ private translateService = inject(TranslateService);
- message: 'Failed to load Loan Application PDF report.'
+ message: this.translateService.instant('errors.loanApplicationReportLoadError')

Then add the translation key to your i18n files and run npm run translations:extract.

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

In `@src/app/clients/clients-view/general-tab/general-tab.component.ts` around
lines 111 - 114, Replace the hardcoded alert message in general-tab.component.ts
(the object with type: 'error' and message: 'Failed to load Loan Application PDF
report.') with an i18n lookup using TranslateService.instant(...) (follow the
pattern used in personal-data-tab.component.ts for alert messages), then add the
new translation key to your i18n files and run npm run translations:extract to
populate translations; ensure the alert uses the translated string instead of
the literal.
🧹 Nitpick comments (10)
src/app/reports/run-report/chart/chart.component.ts (1)

57-69: Guard against undefined dataObject in ngOnChanges()/getRunReportData().

ngOnChanges() unconditionally calls getRunReportData(), and getRunReportData() dereferences this.dataObject.report.name and this.dataObject.formData. If the input is ever undefined/null during initialization or if the parent fails to provide it, this will throw.

Add a small defensive check before calling the service.
As per coding guidelines, “strict type safety”.

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

In `@src/app/reports/run-report/chart/chart.component.ts` around lines 57 - 69,
ngOnChanges currently calls getRunReportData unconditionally which dereferences
this.dataObject; add a defensive null/undefined check in ngOnChanges (or at the
start of getRunReportData) to return early if this.dataObject is falsy or
missing required properties (e.g., this.dataObject.report or
this.dataObject.formData) before calling
reportsService.getChartRunReportData(this.dataObject.report.name,
this.dataObject.formData); keep using setPieChart(this.inputData) and
hideOutput=false only after a successful response. Ensure checks reference the
same symbols: ngOnChanges, getRunReportData, dataObject, getChartRunReportData,
and setPieChart.
src/app/reports/run-report/table-and-sms/table-and-sms.component.ts (1)

99-117: Add error handling in getRunReportData() so progress + UI recover.

The subscription in getRunReportData() (Lines 101-116) only handles success; if the request errors, progressBarService.decrease() and hideOutput state won’t be updated, potentially leaving the UI inconsistent.

Add an error callback to the subscribe and ensure UI state/progress are updated in both success and failure paths.
As per coding guidelines, “clean observable patterns.”

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

In `@src/app/reports/run-report/table-and-sms/table-and-sms.component.ts` around
lines 99 - 117, In getRunReportData(), add an error handler to the Observable
subscription so UI and progress state are always updated on failure;
specifically, extend the subscribe(...) call on
reportsService.getRunReportData(...) with an error callback that calls
progressBarService.decrease(), sets hideOutput = false (or an appropriate safe
state), and sets notExistsReportData/csvData/displayedColumns appropriately
(e.g., clear csvData and displayedColumns and set notExistsReportData = true) to
ensure the UI recovers; keep existing success handling (setOutputTable,
toBeExportedToRepo, columnTypes population) intact and only move shared
finalization into both paths or a finalize-like cleanup to avoid duplication.
src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts (2)

64-68: Avoid deep route.parent.parent without null-safety.

The constructor uses this.route.parent.parent.data.subscribe(...) which will throw if parent or parent.parent is undefined for some routing configurations.

Defensively guard (or restructure to use the correct injected ActivatedRoute at the level that owns loanDetailsData).
As per coding guidelines, “strict type safety”.

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

In
`@src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts`
around lines 64 - 68, The constructor currently accesses
this.route.parent.parent.data.subscribe(...) which can throw if parent or
parent.parent is undefined; fix by adding null-safety or using optional chaining
(e.g., check this.route.parent && this.route.parent.parent before subscribing)
or, better, inject the correct ActivatedRoute that owns loanDetailsData and
subscribe on that; ensure the subscription assigns loansAccountId =
data.loanDetailsData.accountNo only when data and loanDetailsData exist and
handle the undefined case (or bail out) to satisfy strict type safety.

94-111: Add error handling for the Pentaho run report request.

generate() subscribes to getPentahoRunReportData(...) and only sets pentahoUrl/hideOutput on success. If the request fails, there’s no error path (and no UI recovery).

Add an error callback (or finalize) to restore hideOutput/show an alert/log and prevent the component from getting stuck.
As per coding guidelines, “clean observable patterns” for src/app/**component.ts.

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

In
`@src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts`
around lines 94 - 111, The generate() method lacks error handling for the
reportsService.getPentahoRunReportData(...) Observable; add an error path (or
use pipe(finalize())) so the component doesn't get stuck with UI state.
Specifically, update generate() to handle errors from getPentahoRunReportData
(or finalize the stream) to ensure hideOutput is reset, log the error and/or
show an alert to the user, and avoid setting pentahoUrl when the request fails;
reference generate(), reportsService.getPentahoRunReportData, pentahoUrl,
hideOutput and sanitizer when making the change.
src/app/reporting-plugin/models/select-option.model.ts (1)

18-26: Avoid any[] in SelectOption constructor.

constructor(options: any[]) makes it easy to pass malformed data (wrong order/types) without TypeScript catching it.

Introduce a typed init shape (e.g., { id: number|string; name: string }) or a fixed tuple type for [id, name].
As per coding guidelines, “src/app/**/*.ts: Use TypeScript … with strict typing conventions.”

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

In `@src/app/reporting-plugin/models/select-option.model.ts` around lines 18 - 26,
The SelectOption constructor currently accepts an untyped options: any[] which
allows malformed data; change the constructor to accept a strict typed shape
(e.g., constructor(input: { id: number | string; name: string }) or a fixed
tuple type [number|string, string]) and update the assignments in the
SelectOption class to use input.id / input.name (or input[0] / input[1] with the
tuple), adding any necessary parsing (e.g., Number(...) if you need numeric ids)
and type annotations for id and name to satisfy strict TypeScript rules.
src/app/reporting-plugin/models/chart-data.model.ts (1)

17-30: Type the ChartData input instead of response: any.

constructor(response: any) and object: any parsing hides the expected API shape. This increases the chance of runtime failures if response structure changes (e.g., columnHeaders order).

Define a response interface for columnHeaders and data rows, and narrow types when mapping.
As per coding guidelines, “Use TypeScript … with strict typing conventions.”

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

In `@src/app/reporting-plugin/models/chart-data.model.ts` around lines 17 - 30,
The constructor currently uses untyped any for response and object which hides
the expected API shape; define a typed interface (e.g., ChartApiResponse {
columnHeaders: { columnName: string }[]; data: { row: (string|number)[] }[] })
and change constructor(response: ChartApiResponse) to use that type, then narrow
the mappings in ChartData (use response.columnHeaders[x].columnName and
response.data.map(r => String(r.row[0])) / Number(r.row[1]) or properly typed
tuple access) so the keysLabel, valuesLabel, keys and values are strongly typed
and not based on any/unknown; update references to columnHeaders, data and
object.row accordingly and add minimal safe guards (optional chaining or
defaults) where appropriate.
src/app/reporting-plugin/models/report-parameter.model.ts (1)

18-45: Strengthen ReportParameter typing instead of pervasive any / any[].

ReportParameter defines multiple fields as any (defaultVal, selectOne, selectAll, parentParameterName, etc.) and the constructor accepts options: any[]. That undermines the “strict typing conventions” expectation and makes downstream form logic fragile (runtime shape mismatches won’t be caught).

Consider introducing a ReportParameterInit interface (or tuple type) matching the API response order, and type each field explicitly (or at least unknown with safe narrowing).
As per coding guidelines, “src/app/**/*.ts: Use TypeScript for all application code with strict typing conventions.”

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

In `@src/app/reporting-plugin/models/report-parameter.model.ts` around lines 18 -
45, ReportParameter currently uses many any types and options: any[] in the
constructor; define a strongly-typed input shape (e.g. ReportParameterInit
interface or tuple matching the API order) and replace options: any[] with that
type in the ReportParameter constructor, then explicitly type fields like
name:string, variable:string, label:string, displayType:string,
formatType:string, defaultVal: unknown (or specific union), selectOne: boolean |
string | null, selectAll: boolean | null, parentParameterName: string | null,
inputName: string, selectOptions: Array<{ value: string; label: string }> (or
appropriate item type), childParameters: ReportParameter[] (or typed array),
pentahoName: string | null; update the constructor to safely assign values from
the typed input (use defaults and narrowing/casts where needed) and remove any /
any[] usages across the class (refer to ReportParameter, constructor, and the
fields defaultVal, selectOne, selectAll, parentParameterName, selectOptions,
childParameters, pentahoName).
src/app/savings/common-resolvers/savings-transaction-reciept.resolver.ts (1)

33-46: Recommend typing resolver output instead of Observable<any>.

resolve() returns Observable<any>. Consider updating this to a concrete return type matching ReportsService.getPentahoRunReportData() (e.g., Observable<HttpResponse<Blob>> or whatever the service actually returns), and avoid any in resolver APIs.
Please confirm the exact return type of ReportsService.getPentahoRunReportData(...) in src/app/reporting-plugin/services/reports.service.ts and then align this resolver’s signature accordingly.

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

In `@src/app/savings/common-resolvers/savings-transaction-reciept.resolver.ts`
around lines 33 - 46, The resolver signature currently returns Observable<any>;
change it to the concrete return type returned by
ReportsService.getPentahoRunReportData (e.g., Observable<HttpResponse<Blob>> or
Observable<Blob> depending on the service) by checking the exact return type in
reports.service.ts, then replace Observable<any> in the resolve(route:
ActivatedRouteSnapshot) method signature with that concrete type and import any
necessary types (HttpResponse/Blob or the service's custom type); update
SavingsTransactionRecieptResolver (resolve) and any callers to match the new
type.
src/app/loans/common-resolvers/loans-transaction-reciept.resolver.ts (1)

31-44: Recommend tightening resolver typing (avoid Observable<any>).

resolve(...): Observable<any> should be updated to a concrete type aligned with ReportsService.getPentahoRunReportData(...) return value to avoid any in resolver contracts.

Please confirm the return type in src/app/reporting-plugin/services/reports.service.ts and update the resolver signature accordingly.

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

In `@src/app/loans/common-resolvers/loans-transaction-reciept.resolver.ts` around
lines 31 - 44, The resolver currently uses a loose type Observable<any>; inspect
ReportsService.getPentahoRunReportData in
src/app/reporting-plugin/services/reports.service.ts to determine its concrete
return type (e.g., Observable<ReportData>, Observable<Blob>, or another
interface), then replace Observable<any> in
loans-transaction-reciept.resolver.ts resolve signature with that concrete type,
update the import for the type if needed, and ensure the returned Observable
from resolve and the data object (R_transactionId) remain compatible with the
chosen type.
src/app/reporting-plugin/resolvers/run-report.resolver.ts (1)

38-40: Recommend typing resolve() output (avoid Observable<any>).

resolve(...): Observable<any> should be replaced with a concrete type that matches ReportsService.getReportParams(...) to avoid any in resolver outputs.

Please confirm the return type of getReportParams(route.params['name']) in src/app/reporting-plugin/services/reports.service.ts, then update this resolver signature accordingly.

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

In `@src/app/reporting-plugin/resolvers/run-report.resolver.ts` around lines 38 -
40, The resolver return type is currently Observable<any>; inspect
ReportsService.getReportParams in
src/app/reporting-plugin/services/reports.service.ts to determine its concrete
Observable<T> return type (e.g., Observable<ReportParams> or
Observable<YourType>), then change resolve(route: ActivatedRouteSnapshot):
Observable<any> to resolve(route: ActivatedRouteSnapshot):
Observable<ThatConcreteType> (keeping the import/type reference consistent) so
resolve and ReportsService.getReportParams use the same concrete type.
🤖 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/reporting-plugin/models/chart-data.model.ts`:
- Around line 9-16: Remove the duplicated MPL license header block that appears
a second time in the file (the repeated Mozilla Public License v.2.0 header);
keep only the first canonical header at the top of the file, delete the
redundant block below it, and ensure a single license header remains with normal
spacing before the rest of the module (chart-data.model.ts).

In `@src/app/reporting-plugin/models/report-parameter.model.ts`:
- Around line 9-16: Remove the duplicated MPL header by deleting the second
header block (the one starting at line 9) and keep only the initial header at
the top of the file; then replace loose any types used in this model by
adding/using appropriate TypeScript interfaces for the constructor parameter and
properties like defaultVal, selectOne, selectAll, selectOptions,
childParameters, and pentahoName in the ReportParameter class (or similarly
named class) so those fields and the constructor are strictly typed instead of
using any.

In `@src/app/reporting-plugin/models/select-option.model.ts`:
- Around line 9-16: Remove the duplicated MPL header block (keep the first
header and delete the second identical block) and update the SelectOption
constructor signature to use a stricter type instead of options: any[]; change
it to options: [number, string] (or define and use an explicit interface like
SelectOptionEntry { id: number; label: string } and accept options:
SelectOptionEntry[]) in the SelectOption class/constructor, and then update any
internal usage of options within the SelectOption constructor and any callers of
new SelectOption(...) (or methods that pass the options array) to match the new
typed shape.

In `@src/app/reporting-plugin/services/reports.service.ts`:
- Around line 1-15: Remove the duplicated MPL license header block so only a
single header remains at the top of the file; delete the second identical
comment block that begins at line 9 in the file and keep the first header, then
run the repository header tools (npm run headers:check and npm run headers:add)
to validate/update the file header; ensure no other duplicate header comments
remain in src/app/reporting-plugin/services/reports.service.ts.

---

Outside diff comments:
In `@src/app/clients/clients-view/general-tab/general-tab.component.ts`:
- Around line 111-114: Replace the hardcoded alert message in
general-tab.component.ts (the object with type: 'error' and message: 'Failed to
load Loan Application PDF report.') with an i18n lookup using
TranslateService.instant(...) (follow the pattern used in
personal-data-tab.component.ts for alert messages), then add the new translation
key to your i18n files and run npm run translations:extract to populate
translations; ensure the alert uses the translated string instead of the
literal.

In `@src/app/reporting-plugin/resolvers/run-report.resolver.ts`:
- Around line 1-16: The file contains two identical MPL license header blocks;
remove the duplicate second header block (the consecutive /** ... */ that
appears after the first header) so only a single MPL header remains at the top
of the file, ensuring the header:check step will pass; search for the repeated
/** Copyright since 2025 Mifos Initiative ... */ block and delete the latter
occurrence.

In `@src/app/reports/run-report/chart/chart.component.ts`:
- Around line 145-162: The color string produced by randomColor() is invalid
because it uses rgb(...) with four arguments; update randomColor() to return a
valid CSS color using rgba(r,g,b,a) (or the modern rgb(r g b / a)) including the
0.6 alpha, so Chart.js can parse it; then ensure randomColorArray(length)
continues to call randomColor() to build the array (functions: randomColor and
randomColorArray).

In `@src/app/reports/run-report/run-report.component.ts`:
- Around line 452-484: The subscription in runReportAndExport sets
this.isProcessing = true but only resets it in the success handler; update
reportsService.getRunReportData(reportName, payload) to use an RxJS finalize to
always set this.isProcessing = false and add an error callback on the subscribe
to surface an alert (use alertService.alert with translateService.instant for
type/message using your existing translation keys) so errors don't leave the UI
stuck; reference runReportAndExport, reportsService.getRunReportData,
isProcessing, alertService.alert, translateService.instant and import/use
finalize from 'rxjs/operators' (or rxjs) to perform the guaranteed reset.
- Around line 325-341: The valueChanges subscriptions created in
setChildControls() leak and addControl() silently no-ops for existing controls;
fix by introducing a component-level Subject (e.g., ngDestroy$) and pipe each
valueChanges with takeUntil(this.ngDestroy$) (import Subject and takeUntil) and
implement OnDestroy to call this.ngDestroy$.next() and complete(); inside the
subscription, before adding child controls check
this.reportForm.contains(child.name) and use
this.reportForm.setControl(child.name, new UntypedFormControl(...)) to update
existing controls (otherwise addControl for new ones), and keep
fetchSelectOptions logic unchanged.

In `@src/app/reports/run-report/table-and-sms/table-and-sms.component.ts`:
- Around line 173-203: The download currently uses a hardcoded filename
('filename.xlsx') instead of the computed fileName; inside exportToXLS() replace
the hardcoded a.download assignment with the computed fileName (ensure fileName
includes the .xlsx extension or append it if missing) so that the anchor element
uses fileName when triggering the download; update references around the
fileName constant and the a.download assignment in exportToXLS() to use the same
variable.

---

Nitpick comments:
In `@src/app/loans/common-resolvers/loans-transaction-reciept.resolver.ts`:
- Around line 31-44: The resolver currently uses a loose type Observable<any>;
inspect ReportsService.getPentahoRunReportData in
src/app/reporting-plugin/services/reports.service.ts to determine its concrete
return type (e.g., Observable<ReportData>, Observable<Blob>, or another
interface), then replace Observable<any> in
loans-transaction-reciept.resolver.ts resolve signature with that concrete type,
update the import for the type if needed, and ensure the returned Observable
from resolve and the data object (R_transactionId) remain compatible with the
chosen type.

In
`@src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts`:
- Around line 64-68: The constructor currently accesses
this.route.parent.parent.data.subscribe(...) which can throw if parent or
parent.parent is undefined; fix by adding null-safety or using optional chaining
(e.g., check this.route.parent && this.route.parent.parent before subscribing)
or, better, inject the correct ActivatedRoute that owns loanDetailsData and
subscribe on that; ensure the subscription assigns loansAccountId =
data.loanDetailsData.accountNo only when data and loanDetailsData exist and
handle the undefined case (or bail out) to satisfy strict type safety.
- Around line 94-111: The generate() method lacks error handling for the
reportsService.getPentahoRunReportData(...) Observable; add an error path (or
use pipe(finalize())) so the component doesn't get stuck with UI state.
Specifically, update generate() to handle errors from getPentahoRunReportData
(or finalize the stream) to ensure hideOutput is reset, log the error and/or
show an alert to the user, and avoid setting pentahoUrl when the request fails;
reference generate(), reportsService.getPentahoRunReportData, pentahoUrl,
hideOutput and sanitizer when making the change.

In `@src/app/reporting-plugin/models/chart-data.model.ts`:
- Around line 17-30: The constructor currently uses untyped any for response and
object which hides the expected API shape; define a typed interface (e.g.,
ChartApiResponse { columnHeaders: { columnName: string }[]; data: { row:
(string|number)[] }[] }) and change constructor(response: ChartApiResponse) to
use that type, then narrow the mappings in ChartData (use
response.columnHeaders[x].columnName and response.data.map(r =>
String(r.row[0])) / Number(r.row[1]) or properly typed tuple access) so the
keysLabel, valuesLabel, keys and values are strongly typed and not based on
any/unknown; update references to columnHeaders, data and object.row accordingly
and add minimal safe guards (optional chaining or defaults) where appropriate.

In `@src/app/reporting-plugin/models/report-parameter.model.ts`:
- Around line 18-45: ReportParameter currently uses many any types and options:
any[] in the constructor; define a strongly-typed input shape (e.g.
ReportParameterInit interface or tuple matching the API order) and replace
options: any[] with that type in the ReportParameter constructor, then
explicitly type fields like name:string, variable:string, label:string,
displayType:string, formatType:string, defaultVal: unknown (or specific union),
selectOne: boolean | string | null, selectAll: boolean | null,
parentParameterName: string | null, inputName: string, selectOptions: Array<{
value: string; label: string }> (or appropriate item type), childParameters:
ReportParameter[] (or typed array), pentahoName: string | null; update the
constructor to safely assign values from the typed input (use defaults and
narrowing/casts where needed) and remove any / any[] usages across the class
(refer to ReportParameter, constructor, and the fields defaultVal, selectOne,
selectAll, parentParameterName, selectOptions, childParameters, pentahoName).

In `@src/app/reporting-plugin/models/select-option.model.ts`:
- Around line 18-26: The SelectOption constructor currently accepts an untyped
options: any[] which allows malformed data; change the constructor to accept a
strict typed shape (e.g., constructor(input: { id: number | string; name: string
}) or a fixed tuple type [number|string, string]) and update the assignments in
the SelectOption class to use input.id / input.name (or input[0] / input[1] with
the tuple), adding any necessary parsing (e.g., Number(...) if you need numeric
ids) and type annotations for id and name to satisfy strict TypeScript rules.

In `@src/app/reporting-plugin/resolvers/run-report.resolver.ts`:
- Around line 38-40: The resolver return type is currently Observable<any>;
inspect ReportsService.getReportParams in
src/app/reporting-plugin/services/reports.service.ts to determine its concrete
Observable<T> return type (e.g., Observable<ReportParams> or
Observable<YourType>), then change resolve(route: ActivatedRouteSnapshot):
Observable<any> to resolve(route: ActivatedRouteSnapshot):
Observable<ThatConcreteType> (keeping the import/type reference consistent) so
resolve and ReportsService.getReportParams use the same concrete type.

In `@src/app/reports/run-report/chart/chart.component.ts`:
- Around line 57-69: ngOnChanges currently calls getRunReportData
unconditionally which dereferences this.dataObject; add a defensive
null/undefined check in ngOnChanges (or at the start of getRunReportData) to
return early if this.dataObject is falsy or missing required properties (e.g.,
this.dataObject.report or this.dataObject.formData) before calling
reportsService.getChartRunReportData(this.dataObject.report.name,
this.dataObject.formData); keep using setPieChart(this.inputData) and
hideOutput=false only after a successful response. Ensure checks reference the
same symbols: ngOnChanges, getRunReportData, dataObject, getChartRunReportData,
and setPieChart.

In `@src/app/reports/run-report/table-and-sms/table-and-sms.component.ts`:
- Around line 99-117: In getRunReportData(), add an error handler to the
Observable subscription so UI and progress state are always updated on failure;
specifically, extend the subscribe(...) call on
reportsService.getRunReportData(...) with an error callback that calls
progressBarService.decrease(), sets hideOutput = false (or an appropriate safe
state), and sets notExistsReportData/csvData/displayedColumns appropriately
(e.g., clear csvData and displayedColumns and set notExistsReportData = true) to
ensure the UI recovers; keep existing success handling (setOutputTable,
toBeExportedToRepo, columnTypes population) intact and only move shared
finalization into both paths or a finalize-like cleanup to avoid duplication.

In `@src/app/savings/common-resolvers/savings-transaction-reciept.resolver.ts`:
- Around line 33-46: The resolver signature currently returns Observable<any>;
change it to the concrete return type returned by
ReportsService.getPentahoRunReportData (e.g., Observable<HttpResponse<Blob>> or
Observable<Blob> depending on the service) by checking the exact return type in
reports.service.ts, then replace Observable<any> in the resolve(route:
ActivatedRouteSnapshot) method signature with that concrete type and import any
necessary types (HttpResponse/Blob or the service's custom type); update
SavingsTransactionRecieptResolver (resolve) and any callers to match the new
type.
🪄 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: 48d045af-d06e-4b86-82b2-11a90915a827

📥 Commits

Reviewing files that changed from the base of the PR and between 56fd389 and c474e9f.

📒 Files selected for processing (24)
  • src/app/clients/clients-view/general-tab/general-tab.component.ts
  • src/app/clients/clients-view/personal-data-tab/personal-data-tab.component.ts
  • src/app/loans/common-resolvers/loans-transaction-reciept.resolver.ts
  • src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts
  • src/app/organization/sms-campaigns/sms-campaign-stepper/edit-sms-campaign-step/edit-business-rule-parameters/edit-business-rule-parameters.component.ts
  • src/app/organization/sms-campaigns/sms-campaign-stepper/edit-sms-campaign-step/edit-sms-campaign-step.component.ts
  • src/app/organization/sms-campaigns/sms-campaign-stepper/sms-campaign-step/business-rule-parameters/business-rule-parameters.component.ts
  • src/app/organization/sms-campaigns/sms-campaign-stepper/sms-campaign-step/sms-campaign-step.component.ts
  • src/app/products/manage-tax-components/view-tax-component/view-tax-component.component.html
  • src/app/reporting-plugin/models/chart-data.model.ts
  • src/app/reporting-plugin/models/report-parameter.model.ts
  • src/app/reporting-plugin/models/select-option.model.ts
  • src/app/reporting-plugin/resolvers/reports.resolver.ts
  • src/app/reporting-plugin/resolvers/run-report.resolver.ts
  • src/app/reporting-plugin/services/reports.service.ts
  • src/app/reports/reports-routing.module.ts
  • src/app/reports/reports.service.ts
  • src/app/reports/run-report/birt/birt.component.ts
  • src/app/reports/run-report/chart/chart.component.ts
  • src/app/reports/run-report/pentaho/pentaho.component.ts
  • src/app/reports/run-report/run-report.component.ts
  • src/app/reports/run-report/table-and-sms/table-and-sms.component.ts
  • src/app/savings/common-resolvers/savings-transaction-reciept.resolver.ts
  • src/app/savings/savings-account-view/transactions-tab/export-transactions/export-transactions.component.ts

Comment on lines +9 to +16
/**
* 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/.
*/

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Apr 28, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
FILE="src/app/reporting-plugin/models/chart-data.model.ts"
rg -n "Copyright since 2025 Mifos Initiative" "$FILE" | wc -l

Repository: openMF/web-app

Length of output: 60


🏁 Script executed:

cat -n src/app/reporting-plugin/models/chart-data.model.ts

Repository: openMF/web-app

Length of output: 1203


Remove the duplicated MPL license header block at lines 9–15.

The file contains two identical copyright headers (lines 1–7 and lines 9–15). Keep only the first header to comply with the header check requirement and maintain a single canonical license block.

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

In `@src/app/reporting-plugin/models/chart-data.model.ts` around lines 9 - 16,
Remove the duplicated MPL license header block that appears a second time in the
file (the repeated Mozilla Public License v.2.0 header); keep only the first
canonical header at the top of the file, delete the redundant block below it,
and ensure a single license header remains with normal spacing before the rest
of the module (chart-data.model.ts).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review this comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@IOhacker — The review comment is valid. Looking at the full file content, the file indeed has two identical MPL 2.0 license headers:

  • First header: Lines 1–7 (original, pre-existing)
  • Second header: Lines 9–15 (added by this PR — visible in the diff)

The fix is to remove the newly added duplicate block. Here's the corrected file header:

/**
 * 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/.
 */

/** Chart Data Model */
export class ChartData {
  // ...
}

The same duplicate-header issue may also be present in the other newly modified model files (report-parameter.model.ts, select-option.model.ts) and resolvers, since the AI summary shows identical license header additions were made to all of them. It's worth auditing those files as well before merging.


🧠 Learnings used
Learnt from: DeathGun44
Repo: openMF/web-app PR: 3179
File: src/app/savings/common-resolvers/savings-account-actions.resolver.ts:44-57
Timestamp: 2026-02-17T12:26:35.042Z
Learning: In TypeScript files (e.g., src/app/.../*.ts), avoid using Observable<any> as a project-wide pattern for API responses. Treat typing the full API response layer as a cross-cutting refactor and track it as a separate enhancement backlog item rather than addressing it in individual bug fixes. When you encounter API responses, introduce specific interfaces/types for the response shapes and use proper typing instead of any, updating services and resolvers accordingly.

Comment thread src/app/reporting-plugin/models/report-parameter.model.ts Outdated
Comment on lines +9 to +16
/**
* 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/.
*/

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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
FILE="src/app/reporting-plugin/models/select-option.model.ts"
rg -n "Copyright since 2025 Mifos Initiative" "$FILE" | wc -l

Repository: openMF/web-app

Length of output: 60


🏁 Script executed:

cat -n src/app/reporting-plugin/models/select-option.model.ts

Repository: openMF/web-app

Length of output: 928


Remove the duplicated MPL license header block (lines 9-15).

The file contains two identical copyright headers. Keep only the first header (lines 1-7) and remove the duplicate. This will ensure the file passes npm run headers:check validation.

Additionally, improve the SelectOption constructor typing by replacing options: any[] with a more specific type (e.g., options: [number, string] or an explicit interface) to comply with strict TypeScript typing conventions.

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

In `@src/app/reporting-plugin/models/select-option.model.ts` around lines 9 - 16,
Remove the duplicated MPL header block (keep the first header and delete the
second identical block) and update the SelectOption constructor signature to use
a stricter type instead of options: any[]; change it to options: [number,
string] (or define and use an explicit interface like SelectOptionEntry { id:
number; label: string } and accept options: SelectOptionEntry[]) in the
SelectOption class/constructor, and then update any internal usage of options
within the SelectOption constructor and any callers of new SelectOption(...) (or
methods that pass the options array) to match the new typed shape.

Comment thread src/app/reporting-plugin/services/reports.service.ts Outdated
Copy link
Copy Markdown
Contributor

@IOhacker IOhacker left a comment

Choose a reason for hiding this comment

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

Review the comments regarding duplicated license

Comment on lines +9 to +16
/**
* 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/.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review this comment

Comment thread src/app/reporting-plugin/models/report-parameter.model.ts Outdated
@sakshar2303
Copy link
Copy Markdown
Author

@IOhacker — I have updated the PR to address the feedback provided in the review. Key changes include:

Fixed License Headers: Removed duplicate MPL 2.0 license header blocks from all newly migrated files in src/app/reporting-plugin/. Verified with npm run headers:check.
Strict Typing Improvements:
ChartData: Introduced a ChartDataResponse interface to properly type the API response instead of using any.
ReportParameter: Refactored the class to use explicit types for properties (e.g., string | number | boolean | null) and added type casting in the constructor for safer data handling.
SelectOption: Updated the constructor to use a strictly typed tuple [number, string] for the input array.
Code Quality: Verified that the changes are lint-free using npm run lint (specifically targeting the reporting-plugin directory).
The PR is now ready for a follow-up review.

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: 1

🧹 Nitpick comments (3)
src/app/reporting-plugin/services/reports.service.ts (3)

34-78: Consider strict typing for lookup response DTOs in a dedicated refactoring.

The service still uses Observable<any> and untyped response: any in getReports*, getReportParams, getSelectOptions, getPentahoParams, and getBirtParams methods. Concrete DTOs (ReportParameter, SelectOption, ChartDataResponse) already exist in the models layer and are instantiated within these methods, so introducing proper generics like Observable<ReportParameter[]> and typed responses would improve type safety downstream.

However, introducing strict typing across all API response layers is a cross-cutting refactoring tracked separately from individual bug fix PRs. If this PR is not dedicated to typing improvements, consider deferring this enhancement.

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

In `@src/app/reporting-plugin/services/reports.service.ts` around lines 34 - 78,
Update the untyped Observables and response parameters to concrete DTO types:
change getReportParams(reportName: string): Observable<ReportParameter[]> and
getSelectOptions(inputString: string): Observable<SelectOption[]> (and replace
the map callback param from response: any to a typed response matching the API
shape); change getPentahoParams(reportId: number) and the
getReports()/getReportsByOffice(officeId: string) signatures to use the
appropriate model DTO (e.g., Observable<ChartDataResponse> or Observable<Report>
as defined in your models) and type their map callbacks accordingly so new
ReportParameter(entry.row) and new SelectOption(entry.row) map over typed
response.data instead of any.

122-185: Consider this as part of a project-wide API response typing initiative.

The type improvement to Observable<HttpResponse<ArrayBuffer>> is technically valid, but Observable<any> is a project-wide pattern across services and resolvers. Per project guidelines, comprehensive API response typing is tracked as a separate enhancement rather than addressed in individual PRs. If this improvement is desired, consider opening a dedicated issue to systematically update all services (e.g., organization.service.ts, centers.service.ts) as part of a coordinated refactoring.

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

In `@src/app/reporting-plugin/services/reports.service.ts` around lines 122 - 185,
The PR introduced more specific return types for report fetchers but the
codebase standard is to keep service return types as Observable<any>; revert any
changes that tighten typing in getPentahoRunReportData and getBirtRunReportData
(and leave getBirtParams as Observable<any>) so these methods continue returning
Observable<any> and match the project-wide pattern—if you want stronger types,
open a separate issue/PR to refactor all services consistently.

86-114: Import ChartDataResponse and tighten type signatures for the run-report methods.

The getChartRunReportData method constructs a ChartData object from a response typed as any, but ChartData's constructor explicitly expects ChartDataResponse. Additionally, both methods accept formData: object which provides no validation for parameter serialization. Add the missing import and type the response and formData parameters explicitly:

Suggested changes
-import { ChartData } from '../models/chart-data.model';
+import { ChartData, ChartDataResponse } from '../models/chart-data.model';
-  getRunReportData(reportName: string, formData: object): Observable<any> {
+  getRunReportData(reportName: string, formData: Record<string, string | number | boolean>): Observable<any> {
-  getChartRunReportData(reportName: string, formData: object): Observable<ChartData> {
+  getChartRunReportData(reportName: string, formData: Record<string, string | number | boolean>): Observable<ChartData> {
-      .pipe(map((response: any) => new ChartData(response)));
+      .pipe(map((response: ChartDataResponse) => new ChartData(response)));

Aligns with strict typing conventions per src/app/**/*.ts coding guidelines.

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

In `@src/app/reporting-plugin/services/reports.service.ts` around lines 86 - 114,
Import ChartDataResponse and tighten the method signatures: update
getRunReportData(reportName: string, formData: Record<string, string | number |
boolean>): Observable<ChartDataResponse> and getChartRunReportData(reportName:
string, formData: Record<string, string | number | boolean>):
Observable<ChartData>; in both methods iterate Object.entries(formData) but
convert each value to string when calling HttpParams.set; call
this.http.get<ChartDataResponse>(`/runreports/${reportName}`, { params:
httpParams }) in both places and in getChartRunReportData keep the
.pipe(map((response: ChartDataResponse) => new ChartData(response))); add the
missing import for ChartDataResponse used by ChartData.
🤖 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/reporting-plugin/models/report-parameter.model.ts`:
- Around line 13-40: Change the ReportParameter constructor to accept a fixed
tuple instead of a loose array (e.g. [string, string, string, string, string,
string|number|boolean|null, string|null, string|null, string|null]) so the
compiler enforces the nine expected indices used to set name, variable, label,
displayType, formatType, defaultVal, selectOne, selectAll, parentParameterName
in the ReportParameter class; update the constructor parameter type and remove
the explicit casts (as string | null) when assigning these fields. Also address
the unused pentahoName property on ReportParameter—either initialize pentahoName
in the constructor from an appropriate tuple slot or remove the pentahoName
declaration if it’s not needed. Ensure inputName is still set as
`R_${this.variable}` after assignment.

---

Nitpick comments:
In `@src/app/reporting-plugin/services/reports.service.ts`:
- Around line 34-78: Update the untyped Observables and response parameters to
concrete DTO types: change getReportParams(reportName: string):
Observable<ReportParameter[]> and getSelectOptions(inputString: string):
Observable<SelectOption[]> (and replace the map callback param from response:
any to a typed response matching the API shape); change
getPentahoParams(reportId: number) and the
getReports()/getReportsByOffice(officeId: string) signatures to use the
appropriate model DTO (e.g., Observable<ChartDataResponse> or Observable<Report>
as defined in your models) and type their map callbacks accordingly so new
ReportParameter(entry.row) and new SelectOption(entry.row) map over typed
response.data instead of any.
- Around line 122-185: The PR introduced more specific return types for report
fetchers but the codebase standard is to keep service return types as
Observable<any>; revert any changes that tighten typing in
getPentahoRunReportData and getBirtRunReportData (and leave getBirtParams as
Observable<any>) so these methods continue returning Observable<any> and match
the project-wide pattern—if you want stronger types, open a separate issue/PR to
refactor all services consistently.
- Around line 86-114: Import ChartDataResponse and tighten the method
signatures: update getRunReportData(reportName: string, formData: Record<string,
string | number | boolean>): Observable<ChartDataResponse> and
getChartRunReportData(reportName: string, formData: Record<string, string |
number | boolean>): Observable<ChartData>; in both methods iterate
Object.entries(formData) but convert each value to string when calling
HttpParams.set; call
this.http.get<ChartDataResponse>(`/runreports/${reportName}`, { params:
httpParams }) in both places and in getChartRunReportData keep the
.pipe(map((response: ChartDataResponse) => new ChartData(response))); add the
missing import for ChartDataResponse used by ChartData.
🪄 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: 88c6113a-0a1a-45d2-906f-59915463203a

📥 Commits

Reviewing files that changed from the base of the PR and between c474e9f and 4d641ca.

📒 Files selected for processing (6)
  • src/app/reporting-plugin/models/chart-data.model.ts
  • src/app/reporting-plugin/models/report-parameter.model.ts
  • src/app/reporting-plugin/models/select-option.model.ts
  • src/app/reporting-plugin/resolvers/reports.resolver.ts
  • src/app/reporting-plugin/resolvers/run-report.resolver.ts
  • src/app/reporting-plugin/services/reports.service.ts
✅ Files skipped from review due to trivial changes (2)
  • src/app/reporting-plugin/resolvers/reports.resolver.ts
  • src/app/reporting-plugin/resolvers/run-report.resolver.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/app/reporting-plugin/models/select-option.model.ts
  • src/app/reporting-plugin/models/chart-data.model.ts

Comment on lines +13 to +40
export class ReportParameter {
name: string;
variable: string;
label: string;
displayType: string;
formatType: string;
defaultVal: string | number | boolean | null;
selectOne: string | null;
selectAll: string | null;
parentParameterName: string | null;
inputName: string;
selectOptions: SelectOption[] = [];
childParameters: ReportParameter[] = [];
pentahoName: string | null;

constructor(options: (string | number | boolean | null)[]) {
this.name = options[0] as string;
this.variable = options[1] as string;
this.label = options[2] as string;
this.displayType = options[3] as string;
this.formatType = options[4] as string;
this.defaultVal = options[5];
this.selectOne = options[6];
this.selectAll = options[7];
this.parentParameterName = options[8] as string | null;
this.inputName = `R_${this.variable}`;
}
}
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
set -euo pipefail
rg -n '"strictPropertyInitialization"|"strict": true' -g 'tsconfig*.json'
rg -n 'pentahoName|constructor\(options' src/app/reporting-plugin/models/report-parameter.model.ts

Repository: openMF/web-app

Length of output: 204


🏁 Script executed:

# Find where ReportParameter is instantiated
rg -n 'new ReportParameter' -A 3 src/app/reporting-plugin/services/reports.service.ts

# Check for any usage of pentahoName
rg -n 'pentahoName' src/app/reporting-plugin/

# Check the structure of entry.row to understand the payload shape
rg -n 'entry\.row|\.row\[' src/app/reporting-plugin/services/reports.service.ts -B 2 -A 2

Repository: openMF/web-app

Length of output: 699


🏁 Script executed:

# Check all usages of pentahoName across the entire codebase
rg -n 'pentahoName' --type ts --type html --type tsx

# Get the full ReportParameter model to see the complete context
cat -n src/app/reporting-plugin/models/report-parameter.model.ts

# Check if there are any tests or other files that might show the expected payload shape
rg -n 'entry\.row' -B 3 -A 3 src/app/reporting-plugin/

Repository: openMF/web-app

Length of output: 3000


🏁 Script executed:

# Check the main tsconfig.json for strict mode setting
cat -n tsconfig.json | grep -A 5 -B 5 '"strict"'

# Also verify if there are any compilation errors reported
git status

Repository: openMF/web-app

Length of output: 258


🏁 Script executed:

# Check main tsconfig.json directly
head -50 tsconfig.json

Repository: openMF/web-app

Length of output: 741


Improve type safety of the constructor by using a tuple type instead of a loose array.

The constructor accepts (string | number | boolean | null)[] but always accesses exactly 9 indices matching the API payload from entry.row. This should be a tuple type for better type safety and to allow the compiler to guarantee the correct properties are assigned without casts.

Additionally, pentahoName is declared on line 26 but never assigned in the constructor and has no usages in the codebase—either initialize it or remove it.

🔧 Proposed fix
 export class ReportParameter {
   name: string;
   variable: string;
   label: string;
   displayType: string;
   formatType: string;
   defaultVal: string | number | boolean | null;
   selectOne: string | null;
   selectAll: string | null;
   parentParameterName: string | null;
   inputName: string;
   selectOptions: SelectOption[] = [];
   childParameters: ReportParameter[] = [];
-  pentahoName: string | null;
+  pentahoName: string | null = null;
 
-  constructor(options: (string | number | boolean | null)[]) {
-    this.name = options[0] as string;
-    this.variable = options[1] as string;
-    this.label = options[2] as string;
-    this.displayType = options[3] as string;
-    this.formatType = options[4] as string;
+  constructor(
+    options: [string, string, string, string, string, string | number | boolean | null, string | null, string | null, string | null]
+  ) {
+    this.name = options[0];
+    this.variable = options[1];
+    this.label = options[2];
+    this.displayType = options[3];
+    this.formatType = options[4];
     this.defaultVal = options[5];
     this.selectOne = options[6];
     this.selectAll = options[7];
-    this.parentParameterName = options[8] as string | null;
+    this.parentParameterName = options[8];
     this.inputName = `R_${this.variable}`;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/reporting-plugin/models/report-parameter.model.ts` around lines 13 -
40, Change the ReportParameter constructor to accept a fixed tuple instead of a
loose array (e.g. [string, string, string, string, string,
string|number|boolean|null, string|null, string|null, string|null]) so the
compiler enforces the nine expected indices used to set name, variable, label,
displayType, formatType, defaultVal, selectOne, selectAll, parentParameterName
in the ReportParameter class; update the constructor parameter type and remove
the explicit casts (as string | null) when assigning these fields. Also address
the unused pentahoName property on ReportParameter—either initialize pentahoName
in the constructor from an appropriate tuple slot or remove the pentahoName
declaration if it’s not needed. Ensure inputName is still set as
`R_${this.variable}` after assignment.

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.

2 participants