HuangXi created FINERACT-2559:
---------------------------------

             Summary: Loan product details retrieval executes redundant DB 
query in classification mapping flow
                 Key: FINERACT-2559
                 URL: https://issues.apache.org/jira/browse/FINERACT-2559
             Project: Apache Fineract
          Issue Type: Bug
          Components: Accounting
    Affects Versions: 1.14.0
            Reporter: HuangXi


*Problem* In the loan product details read path, the classification mapping 
flow executes an additional repository query whose result is immediately 
discarded. This creates an unnecessary database round trip with no functional 
benefit.

*Code location*
 * Discarded query call: 
{{fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingReadPlatformServiceImpl.java}}

 * Repository query definition: 
{{fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/domain/ProductToGLAccountMappingRepository.java}}

 * Upstream API entry point: 
{{fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java}}

*Relevant code*
 private List<ClassificationToGLAccountData> fetchClassificationMappings(
         final PortfolioProductType portfolioProductType,
         final Long loanProductId,
         LoanProductAccountingParams classificationParameter) {
 ​
     final List<ProductToGLAccountMapping> mappings = classificationParameter
             
.equals(LoanProductAccountingParams.CAPITALIZED_INCOME_CLASSIFICATION_TO_INCOME_ACCOUNT_MAPPINGS)
                     ? 
productToGLAccountMappingRepository.findAllCapitalizedIncomeClassificationsMappings(
                             loanProductId, portfolioProductType.getValue())
                     : 
productToGLAccountMappingRepository.findAllBuyDownFeeClassificationsMappings(
                             loanProductId, portfolioProductType.getValue());
 ​
     productToGLAccountMappingRepository.findAllChargeOffReasonsMappings(
             loanProductId, portfolioProductType.getValue());
 ​
     List<ClassificationToGLAccountData> classificationToGLAccountMappers = 
mappings.isEmpty() ? null : new ArrayList<>();
     for (final ProductToGLAccountMapping mapping : mappings) {
         ...
     }
     return classificationToGLAccountMappers;
 }
 @Query("select mapping from ProductToGLAccountMapping mapping " +
        "where mapping.productId = :productId and mapping.productType = 
:productType " +
        "and mapping.chargeOffReason is not NULL")
 List<ProductToGLAccountMapping> findAllChargeOffReasonsMappings(
         @Param("productId") Long productId,
         @Param("productType") int productType);
*Why this is a database performance issue*
 * The repository method is a pure {{select}} query.

 * Its return value is not assigned, checked, logged, or otherwise consumed.

 * There is no visible side-effect semantics such as update, delete, lock 
acquisition, or entity callback usage.

 * The method continues to build the response only from {{mappings}}, which 
come from the classification queries.

Therefore, this query adds database load, object materialization, and 
response-time overhead without any business value.

*Impact* When loan product details are retrieved for accounting-enabled 
products, this redundant query is executed in the classification mapping flow 
even though its result is unused. This causes avoidable database round trips 
and unnecessary performance overhead in a read-heavy path.

*Expected result* Only functionally required queries should be executed during 
loan product details retrieval.

*Actual result* An extra charge-off-reason mapping query is executed in the 
classification mapping flow, and its result is discarded.

*Likely root cause* This appears to be leftover or copy-pasted code in the 
classification mapping read path, rather than intentional logic.

*Proposed fix* Remove the unused call to:
 productToGLAccountMappingRepository.findAllChargeOffReasonsMappings(
         loanProductId, portfolioProductType.getValue());
*Validation*
 * Loan product details response payload should remain unchanged.

 * SQL logs should show one fewer unnecessary query execution in this 
classification path.

 * Charge-off reason mapping retrieval in its actual usage path should remain 
unaffected.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to