Skip to content

FINERACT-2727: Fix loan product visibility when office-specific-products-enabled is on - #6209

Open
aya-abdallah-FOO wants to merge 2 commits into
apache:developfrom
foodeveloper:port/CBS-520-office-loan-product-mapping
Open

FINERACT-2727: Fix loan product visibility when office-specific-products-enabled is on#6209
aya-abdallah-FOO wants to merge 2 commits into
apache:developfrom
foodeveloper:port/CBS-520-office-loan-product-mapping

Conversation

@aya-abdallah-FOO

Copy link
Copy Markdown
Contributor

Description:

Bug

Fineract has a global configuration flag office-specific-products-enabled
intended to restrict which loan products each office can offer. When enabled,
only the products explicitly mapped to an office (via Entity to Entity
Mapping) should be available to that office's users.

In practice, enabling this flag causes the opposite of the intended behavior:

  1. Entity to Entity Mapping screen — the Loan Product dropdown in
    Admin → System → Entity to Entity Mapping → Offices → Loan Products
    shows only "All" and no individual products. This makes it impossible
    to create the mappings the feature depends on.

  2. Loan product listing — all loan products disappear from the listing
    page for branch users, even products that should be visible (e.g. products
    mapped to "All" or products with no mapping at all).

  3. Loan application template — the /loans/template API returns an
    empty product list, blocking any new loan application when the flag is on.
    The root cause is that retrieveAllLoanProducts() ignores the
    office-specific-products-enabled flag entirely. There is no code path that
    filters or resolves the entity mappings to determine which products are
    visible to a given office.

Fix

Introduce office-aware loan product retrieval:

  • FineractEntityAccessReadServiceImpl: add
    getSQLQueryInClauseIDList_ForLoanProductsVisibleToOffice(officeId) which
    resolves the entity mappings for an office (including parent–child hierarchy,
    so a product mapped to a parent office is also available to child branches).

  • LoanProductReadPlatformService / LoanProductReadPlatformServiceImpl:
    add retrieveAllLoanProductsV2() and overloads that use the above query
    when office-specific-products-enabled is on, falling back to the original
    behavior when it is off.

  • LoanProductsApiResourceV2: new API endpoint that calls
    retrieveAllLoanProductsV2(), used by the Entity to Entity Mapping screen
    and the self-service loan products endpoint.

  • LoansApiResource and BulkImportWorkbookPopulatorServiceImpl: updated to
    use the office-aware method so the loans template and bulk import respect
    the same visibility rules.

Visibility rules when office-specific-products-enabled is ON

A loan product is visible to an office if:

  • It has no entity mapping at all, OR
  • It is mapped to "All", OR
  • It is explicitly mapped to the user's office or any office in its
    parent hierarchy.

@elnafateh

Copy link
Copy Markdown
Contributor

Run these before pushing any changes:
./gradlew --no-daemon spotlessApply spotbugsMain spotbugsTest checkstyleMain checkstyleTest
./gradlew --no-daemon build -x test -x cucumber -x doc

@elnafateh elnafateh left a comment

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.

squash the two commits into one

@aya-abdallah-FOO

Copy link
Copy Markdown
Contributor Author

squash the two commits into one

@elnafateh it would be better to keep the 2 commits seperated by the 2 tickets as they are related to each other and the second depends on the fixes in the first

@elnafateh

elnafateh commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

squash the two commits into one

@elnafateh it would be better to keep the 2 commits seperated by the 2 tickets as they are related to each other and the second depends on the fixes in the first

Yeah Maybe but It does'nt matter, It's a fineract rule...

@aya-abdallah-FOO

Copy link
Copy Markdown
Contributor Author

squash the two commits into one

@elnafateh it would be better to keep the 2 commits seperated by the 2 tickets as they are related to each other and the second depends on the fixes in the first

Yeah Maybe but It does'nt matter, It's a fineract rule...

@elnafateh what is the rule?

@adamsaghy

Copy link
Copy Markdown
Contributor

squash the two commits into one

@elnafateh it would be better to keep the 2 commits seperated by the 2 tickets as they are related to each other and the second depends on the fixes in the first

Yeah Maybe but It does'nt matter, It's a fineract rule...

@elnafateh what is the rule?

Since the PR says:
FINERACT-2727: Fix loan product visibility when office-specific-products-enabled is on, it should contains only these changes.

@elnafateh is asking you to create a new PR for theFINERACT-2728: Apply office-based charge filtering aligned with loan product visibility commit.

@aya-abdallah-FOO

Copy link
Copy Markdown
Contributor Author

squash the two commits into one

@elnafateh it would be better to keep the 2 commits seperated by the 2 tickets as they are related to each other and the second depends on the fixes in the first

Yeah Maybe but It does'nt matter, It's a fineract rule...

@elnafateh what is the rule?

Since the PR says: FINERACT-2727: Fix loan product visibility when office-specific-products-enabled is on, it should contains only these changes.

@elnafateh is asking you to create a new PR for theFINERACT-2728: Apply office-based charge filtering aligned with loan product visibility commit.

@adamsaghy the issue here is that for the commit 2 if i want to create the new PR it needs commit 1 to be merged first or i need to base from the PR branch instead of develop

@adamsaghy

Copy link
Copy Markdown
Contributor

squash the two commits into one

@elnafateh it would be better to keep the 2 commits seperated by the 2 tickets as they are related to each other and the second depends on the fixes in the first

Yeah Maybe but It does'nt matter, It's a fineract rule...

@elnafateh what is the rule?

Since the PR says: FINERACT-2727: Fix loan product visibility when office-specific-products-enabled is on, it should contains only these changes.
@elnafateh is asking you to create a new PR for theFINERACT-2728: Apply office-based charge filtering aligned with loan product visibility commit.

@adamsaghy the issue here is that for the commit 2 if i want to create the new PR it needs commit 1 to be merged first or i need to base from the PR branch instead of develop

Yes, thats the way... You have this PR with first commit, and based on this you create the new PR and once this is merged, you can auto rebase the 2nd and that way it is clear which PR is addressing which stories.

@adamsaghy

Copy link
Copy Markdown
Contributor
[ant:checkstyle] [ERROR] /home/runner/work/fineract/fineract/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformService.java:60:5: 'METHOD_DEF' should be separated from previous line. [EmptyLineSeparator]
> Task :fineract-loan:checkstyleMain

> Task :fineract-loan:checkstyleMain FAILED
> Task :fineract-accounting:compileTestJava
> Task :fineract-working-capital-loan:checkstyleMain

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':fineract-loan:checkstyleMain'.
> A failure occurred while executing org.gradle.api.plugins.quality.internal.CheckstyleAction
   > Checkstyle rule violations were found. See the report at: file:///home/runner/work/fineract/fineract/fineract-loan/build/reports/checkstyle/main.html
     Checkstyle files with violations: 1
     Checkstyle violations by severity: [error:1]

@adamsaghy

Copy link
Copy Markdown
Contributor
Execution failed for task ':fineract-charge:spotlessJavaCheck'.
> The following files had format violations:
      src/main/java/org/apache/fineract/portfolio/charge/service/ChargeReadPlatformService.java
          @@ -177,8 +177,8 @@
           ····List<ChargeData>·retrieveShareProductCharges(Long·shareProductId);
           
           ····/**
          -·····*·Office-scoped·variant:·filters·share·product·charges·by·product·AND·the·given·office's·visibility.
          -·····*·Used·by·client-level·share·account·templates·where·both·clientId·and·productId·are·provided.
For more on this, please refer to https://docs.gradle.org/8.14.5/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
          +·····*·Office-scoped·variant:·filters·share·product·charges·by·product·AND·the·given·office's·visibility.·Used·by
          +·····*·client-level·share·account·templates·where·both·clientId·and·productId·are·provided.
           ·····*/
           ····List<ChargeData>·retrieveShareProductCharges(Long·shareProductId,·Long·officeId);
           
  Run './gradlew :fineract-charge:spotlessApply' to fix these violations.

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.

3 participants