From 205b39ddf0912601bb05dda044b671f5f18a2a2b Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Tue, 22 Apr 2025 22:29:00 -0500 Subject: [PATCH] FINERACT-2232: Loan account capitalized income transaction template --- .../loanaccount/api/LoanApiConstants.java | 1 + .../LoanTransactionsApiResourceSwagger.java | 16 ++++++++++- .../loanaccount/data/LoanTransactionData.java | 9 ++++++ .../data/LoanTransactionEnumData.java | 2 ++ .../domain/LoanTransactionType.java | 6 ++++ .../loanproduct/service/LoanEnumerations.java | 2 ++ .../api/LoanTransactionsApiResource.java | 3 ++ .../service/LoanReadPlatformService.java | 2 ++ .../service/LoanReadPlatformServiceImpl.java | 9 ++++-- .../starter/LoanAccountConfiguration.java | 10 +++---- .../integrationtests/LoanTransactionTest.java | 28 +++++++++++++++++++ 11 files changed, 78 insertions(+), 10 deletions(-) diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java index db722ddde..62dfbd146 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanApiConstants.java @@ -174,6 +174,7 @@ public interface LoanApiConstants { // Commands String CHARGEBACK_TRANSACTION_COMMAND = "chargeback"; String MARK_AS_FRAUD_COMMAND = "markAsFraud"; + String CAPITALIZED_INCOME_TRANSACTION_COMMAND = "capitalizedIncome"; // Data Validator names String LOAN_FRAUD_DATAVALIDATOR_PREFIX = "loans.fraud"; diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanTransactionsApiResourceSwagger.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanTransactionsApiResourceSwagger.java index ac724097e..1ee205ae8 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanTransactionsApiResourceSwagger.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanTransactionsApiResourceSwagger.java @@ -75,7 +75,19 @@ final class LoanTransactionsApiResourceSwagger { public String displaySymbolValue; } - public GetLoansTransactionType transactionType; + static final class GetPaymentTypeOptions { + + private GetPaymentTypeOptions() {} + + @Schema(example = "10") + public Long id; + @Schema(example = "check") + public String name; + @Schema(example = "1") + public Integer position; + } + + public GetLoansTransactionType type; @Schema(example = "[2009, 8, 1]") public LocalDate date; public GetLoansTotal total; @@ -94,6 +106,8 @@ final class LoanTransactionsApiResourceSwagger { public GetLoanCurrency currency; public List chargeOffReasonOptions; + + public List paymentTypeOptions; } public static final class GetLoanCurrency { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionData.java index 8ca3d7808..c9a9ced86 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionData.java @@ -216,7 +216,16 @@ public class LoanTransactionData implements Serializable { loanTransactionData.externalId, loanTransactionData.transfer, loanTransactionData.fixedEmiAmount, loanTransactionData.outstandingLoanBalance, loanTransactionData.manuallyReversed, loanTransactionData.loanId, loanTransactionData.externalLoanId); + } + public static LoanTransactionData templateOnTop(final LoanTransactionData loanTransactionData, final LoanTransactionEnumData typeOf) { + return new LoanTransactionData(loanTransactionData.id, loanTransactionData.officeId, loanTransactionData.officeName, typeOf, + loanTransactionData.paymentDetailData, loanTransactionData.currency, loanTransactionData.date, loanTransactionData.amount, + loanTransactionData.netDisbursalAmount, loanTransactionData.principalPortion, loanTransactionData.interestPortion, + loanTransactionData.feeChargesPortion, loanTransactionData.penaltyChargesPortion, loanTransactionData.overpaymentPortion, + loanTransactionData.unrecognizedIncomePortion, loanTransactionData.paymentTypeOptions, loanTransactionData.externalId, + loanTransactionData.transfer, loanTransactionData.fixedEmiAmount, loanTransactionData.outstandingLoanBalance, + loanTransactionData.manuallyReversed, loanTransactionData.loanId, loanTransactionData.externalLoanId); } @Default // Default constructor for mapper diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java index ddfa5538a..bc0aa9a30 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java @@ -67,6 +67,7 @@ public class LoanTransactionEnumData implements Serializable { private final boolean accrualActivity; private final boolean interestRefund; private final boolean accrualAdjustment; + private final boolean capitalizedIncome; public LoanTransactionEnumData(final Long id, final String code, final String value) { this.id = id; @@ -103,6 +104,7 @@ public class LoanTransactionEnumData implements Serializable { this.reAmortize = Long.valueOf(LoanTransactionType.REAMORTIZE.getValue()).equals(this.id); this.interestRefund = Long.valueOf(LoanTransactionType.INTEREST_REFUND.getValue()).equals(this.id); this.accrualAdjustment = Long.valueOf(LoanTransactionType.ACCRUAL_ADJUSTMENT.getValue()).equals(this.id); + this.capitalizedIncome = Long.valueOf(LoanTransactionType.CAPITALIZED_INCOME.getValue()).equals(this.id); } public boolean isRepaymentType() { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java index 967f24a2f..709d3cf0e 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java @@ -67,6 +67,7 @@ public enum LoanTransactionType { ACCRUAL_ACTIVITY(32, "loanTransactionType.accrualActivity"), // INTEREST_REFUND(33, "loanTransactionType.interestRefund"), // ACCRUAL_ADJUSTMENT(34, "loanTransactionType.accrualAdjustment"), // + CAPITALIZED_INCOME(35, "loanTransactionType.capitalizedIncome"), // ; private final Integer value; @@ -117,6 +118,7 @@ public enum LoanTransactionType { case 32 -> LoanTransactionType.ACCRUAL_ACTIVITY; case 33 -> LoanTransactionType.INTEREST_REFUND; case 34 -> LoanTransactionType.ACCRUAL_ADJUSTMENT; + case 35 -> LoanTransactionType.CAPITALIZED_INCOME; default -> LoanTransactionType.INVALID; }; } @@ -233,4 +235,8 @@ public enum LoanTransactionType { public boolean isAccrualAdjustment() { return this == LoanTransactionType.ACCRUAL_ADJUSTMENT; } + + public boolean isCapitalizedIncome() { + return this == LoanTransactionType.CAPITALIZED_INCOME; + } } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java index 2ae4d3fa8..9093c8642 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java @@ -325,6 +325,8 @@ public final class LoanEnumerations { LoanTransactionType.INTEREST_REFUND.getCode(), "Interest Refund"); case ACCRUAL_ADJUSTMENT -> new LoanTransactionEnumData(LoanTransactionType.ACCRUAL_ADJUSTMENT.getValue().longValue(), LoanTransactionType.ACCRUAL_ADJUSTMENT.getCode(), "Accrual Adjustment"); + case CAPITALIZED_INCOME -> new LoanTransactionEnumData(LoanTransactionType.CAPITALIZED_INCOME.getValue().longValue(), + LoanTransactionType.CAPITALIZED_INCOME.getCode(), "Capitalized Income"); }; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanTransactionsApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanTransactionsApiResource.java index 1a94ef27d..386ed322d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanTransactionsApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanTransactionsApiResource.java @@ -664,6 +664,9 @@ public class LoanTransactionsApiResource { transactionData = this.loanReadPlatformService.retrieveLoanChargeOffTemplate(resolvedLoanId); } else if (CommandParameterUtil.is(commandParam, DOWN_PAYMENT)) { transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(resolvedLoanId); + } else if (CommandParameterUtil.is(commandParam, LoanApiConstants.CAPITALIZED_INCOME_TRANSACTION_COMMAND)) { + transactionData = this.loanReadPlatformService.retrieveLoanTransactionTemplate(resolvedLoanId, + LoanTransactionType.CAPITALIZED_INCOME); } else { throw new UnrecognizedQueryParamException("command", commandParam); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java index 02eddf327..c81a5d73f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformService.java @@ -63,6 +63,8 @@ public interface LoanReadPlatformService { LoanTransactionData retrieveLoanTransactionTemplate(Long loanId); + LoanTransactionData retrieveLoanTransactionTemplate(Long loanId, LoanTransactionType transactionType); + LoanTransactionData retrieveWaiveInterestDetails(Long loanId); LoanTransactionData retrieveLoanTransaction(Long loanId, Long transactionId); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 908a657a9..f853b38d5 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -111,7 +111,6 @@ import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeCal import org.apache.fineract.portfolio.loanaccount.domain.LoanCapitalizedIncomeStrategy; import org.apache.fineract.portfolio.loanaccount.domain.LoanChargeOffBehaviour; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment; -import org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleTransactionProcessorFactory; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; import org.apache.fineract.portfolio.loanaccount.domain.LoanSubStatus; @@ -166,7 +165,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa private final StaffReadPlatformService staffReadPlatformService; private final PaginationHelper paginationHelper; private final PaymentTypeReadPlatformService paymentTypeReadPlatformService; - private final LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory; private final FloatingRatesReadPlatformService floatingRatesReadPlatformService; private final LoanUtilService loanUtilService; private final ConfigurationDomainService configurationDomainService; @@ -179,7 +177,6 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa private final LoanTransactionRelationReadService loanTransactionRelationReadService; private final LoanForeclosureValidator loanForeclosureValidator; private final LoanTransactionMapper loanTransactionMapper; - private final org.apache.fineract.portfolio.loanaccount.mapper.LoanMapper loanMapper; private final LoanTransactionProcessingService loadTransactionProcessingService; @Override @@ -452,6 +449,12 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa return loanDetails; } + @Override + public LoanTransactionData retrieveLoanTransactionTemplate(final Long loanId, LoanTransactionType transactionType) { + return LoanTransactionData.templateOnTop(retrieveLoanTransactionTemplate(loanId), + LoanEnumerations.transactionType(transactionType)); + } + @Override public LoanTransactionData retrieveLoanTransactionTemplate(final Long loanId) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java index 21423934a..10f65716c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/starter/LoanAccountConfiguration.java @@ -323,22 +323,20 @@ public class LoanAccountConfiguration { CodeValueReadPlatformService codeValueReadPlatformService, CalendarReadPlatformService calendarReadPlatformService, StaffReadPlatformService staffReadPlatformService, PaginationHelper paginationHelper, PaymentTypeReadPlatformService paymentTypeReadPlatformService, - LoanRepaymentScheduleTransactionProcessorFactory loanRepaymentScheduleTransactionProcessorFactory, FloatingRatesReadPlatformService floatingRatesReadPlatformService, LoanUtilService loanUtilService, ConfigurationDomainService configurationDomainService, AccountDetailsReadPlatformService accountDetailsReadPlatformService, ColumnValidator columnValidator, DatabaseSpecificSQLGenerator sqlGenerator, DelinquencyReadPlatformService delinquencyReadPlatformService, LoanTransactionRepository loanTransactionRepository, LoanChargePaidByReadService loanChargePaidByReadService, LoanTransactionRelationReadService loanTransactionRelationReadService, - LoanForeclosureValidator loanForeclosureValidator, LoanTransactionMapper loanTransactionMapper, LoanMapper loanMapper, + LoanForeclosureValidator loanForeclosureValidator, LoanTransactionMapper loanTransactionMapper, LoanTransactionProcessingService loanTransactionProcessingService) { return new LoanReadPlatformServiceImpl(jdbcTemplate, context, loanRepositoryWrapper, applicationCurrencyRepository, loanProductReadPlatformService, clientReadPlatformService, groupReadPlatformService, loanDropdownReadPlatformService, fundReadPlatformService, chargeReadPlatformService, codeValueReadPlatformService, calendarReadPlatformService, - staffReadPlatformService, paginationHelper, paymentTypeReadPlatformService, - loanRepaymentScheduleTransactionProcessorFactory, floatingRatesReadPlatformService, loanUtilService, - configurationDomainService, accountDetailsReadPlatformService, columnValidator, sqlGenerator, + staffReadPlatformService, paginationHelper, paymentTypeReadPlatformService, floatingRatesReadPlatformService, + loanUtilService, configurationDomainService, accountDetailsReadPlatformService, columnValidator, sqlGenerator, delinquencyReadPlatformService, loanTransactionRepository, loanChargePaidByReadService, loanTransactionRelationReadService, - loanForeclosureValidator, loanTransactionMapper, loanMapper, loanTransactionProcessingService); + loanForeclosureValidator, loanTransactionMapper, loanTransactionProcessingService); } @Bean diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionTest.java index 4500bb14b..63b0c6cb6 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanTransactionTest.java @@ -18,11 +18,15 @@ */ package org.apache.fineract.integrationtests; +import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; + import java.math.BigDecimal; import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; import org.apache.fineract.client.models.GetLoansLoanIdTransactionsResponse; +import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTemplateResponse; import org.apache.fineract.client.models.PostClientsResponse; import org.apache.fineract.client.models.PostLoanProductsResponse; import org.apache.fineract.client.models.TransactionType; @@ -86,4 +90,28 @@ public class LoanTransactionTest extends BaseLoanIntegrationTest { }); } + @Test + public void testGetLoanTransactionTemplateForCapitalizedIncome() { + final PostClientsResponse client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()); + + final PostLoanProductsResponse loanProductsResponse = loanProductHelper.createLoanProduct(create4IProgressive()); + + final String loanExternalIdStr = UUID.randomUUID().toString(); + + final String command = "capitalizedIncome"; + runAt("20 December 2024", () -> { + Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProductsResponse.getResourceId(), "20 December 2024", + 430.0, 7.0, 6, (request) -> request.externalId(loanExternalIdStr)); + + disburseLoan(loanId, BigDecimal.valueOf(430), "20 December 2024"); + + final GetLoansLoanIdTransactionsTemplateResponse transactionTemplate = loanTransactionHelper.retrieveTransactionTemplate(loanId, + command, null, null, null); + + assertNotNull(transactionTemplate); + assertEquals("loanTransactionType." + command, transactionTemplate.getType().getCode()); + assertThat(transactionTemplate.getPaymentTypeOptions().size() > 0); + }); + } + }