[
https://issues.apache.org/jira/browse/FINERACT-2559?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Adam Saghy resolved FINERACT-2559.
----------------------------------
Fix Version/s: 1.15.0
Resolution: Fixed
> 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
> Priority: Major
> Labels: database, performance, query-optimization
> Fix For: 1.15.0
>
> Original Estimate: 2h
> Remaining Estimate: 2h
>
> *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)