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)