From 993393b519dd6a9f4288ebb05fb234db565db125 Mon Sep 17 00:00:00 2001 From: "mark.vituska" Date: Tue, 18 Mar 2025 13:51:43 +0100 Subject: [PATCH] FINERACT-2080: use enums instead of integers in Loan, LoanProduct and LoanTransaction --- ...oGLAccountMappingWritePlatformService.java | 3 +- .../ExternalAssetOwnersWriteServiceImpl.java | 4 +- .../ExternalAssetOwnersWriteServiceTest.java | 10 +- .../cob/data/LoanDataForExternalTransfer.java | 3 +- .../LoanDelinquencyDomainServiceImpl.java | 4 +- ...InterestPauseWritePlatformServiceImpl.java | 2 +- .../loanaccount/api/LoanApiConstants.java | 20 +-- .../loanaccount/data/LoanStatusEnumData.java | 2 +- .../data/LoanTransactionBalance.java | 3 +- .../domain/AccountingRuleTypeConverter.java | 37 ++++++ .../DefaultLoanLifecycleStateMachine.java | 8 +- .../portfolio/loanaccount/domain/Loan.java | 42 +++--- .../domain/LoanAccrualActivityRepository.java | 5 +- ...epaymentScheduleInstallmentRepository.java | 4 +- .../loanaccount/domain/LoanRepository.java | 125 ++++++++++-------- .../domain/LoanRepositoryWrapper.java | 59 ++++++--- .../domain/LoanStatusConverter.java | 36 +++++ .../domain/LoanSubStatusConverter.java | 36 +++++ .../domain/LoanSummaryBalancesRepository.java | 2 +- .../loanaccount/domain/LoanTransaction.java | 47 ++++--- .../domain/LoanTransactionRepository.java | 4 +- .../domain/LoanTransactionTypeConverter.java | 36 +++++ .../SetLoanDelinquencyTagsTasklet.java | 6 +- .../LoanApplicationTransitionValidator.java | 4 +- .../service/LoanTransactionReadService.java | 8 +- .../loanproduct/domain/LoanProduct.java | 19 ++- ...ccountMappingWritePlatformServiceImpl.java | 3 +- ...RetrieveAllNonClosedLoanIdServiceImpl.java | 28 ++-- .../service/InteropServiceImpl.java | 6 +- .../starter/InteroperationConfiguration.java | 13 +- .../domain/CalendarInstanceRepository.java | 10 +- ...WritePlatformServiceJpaRepositoryImpl.java | 4 +- .../domain/LoanAccountDomainServiceJpa.java | 2 +- .../AccrualActivityPostingTasklet.java | 5 +- .../ApplyHolidaysToLoansTasklet.java | 4 +- .../LoanApplicationValidator.java | 10 +- .../CommonLoanSummaryDataProvider.java | 40 +++--- ...nAccrualActivityProcessingServiceImpl.java | 4 +- .../LoanAccrualsProcessingServiceImpl.java | 4 +- .../service/LoanAssemblerImpl.java | 5 +- .../service/LoanTransactionAssembler.java | 4 +- ...WritePlatformServiceJpaRepositoryImpl.java | 21 ++- ...gressiveLoanInterestRefundServiceImpl.java | 12 +- .../reaging/LoanReAgingServiceImpl.java | 4 +- .../LoanReAmortizationServiceImpl.java | 2 +- .../LoanProductDataValidator.java | 4 +- ...WritePlatformServiceJpaRepositoryImpl.java | 7 +- ...ntDelinquencyRangeEventSerializerTest.java | 2 +- .../LoanDelinquencyDomainServiceTest.java | 6 +- .../DefaultLoanLifecycleStateMachineTest.java | 13 +- .../loanaccount/domain/LoanTest.java | 16 +-- 51 files changed, 467 insertions(+), 291 deletions(-) create mode 100644 fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/AccountingRuleTypeConverter.java create mode 100644 fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanStatusConverter.java create mode 100644 fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSubStatusConverter.java create mode 100644 fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionTypeConverter.java diff --git a/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformService.java b/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformService.java index 1b11d4d06..d24a6e34d 100644 --- a/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformService.java +++ b/fineract-accounting/src/main/java/org/apache/fineract/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformService.java @@ -19,6 +19,7 @@ package org.apache.fineract.accounting.producttoaccountmapping.service; import java.util.Map; +import org.apache.fineract.accounting.common.AccountingRuleType; import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.portfolio.savings.DepositAccountType; @@ -29,7 +30,7 @@ public interface ProductToGLAccountMappingWritePlatformService { void createSavingProductToGLAccountMapping(Long savingProductId, JsonCommand command, DepositAccountType accountType); Map updateLoanProductToGLAccountMapping(Long loanProductId, JsonCommand command, boolean accountingRuleChanged, - int accountingRuleTypeId); + AccountingRuleType accountingRuleTypeId); Map updateSavingsProductToGLAccountMapping(Long savingsProductId, JsonCommand command, boolean accountingRuleChanged, int accountingRuleTypeId, DepositAccountType accountType); diff --git a/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java index d1712ebed..0ba4f709c 100644 --- a/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java +++ b/fineract-investor/src/main/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceImpl.java @@ -380,14 +380,14 @@ public class ExternalAssetOwnersWriteServiceImpl implements ExternalAssetOwnersW } private void validateLoanStatus(LoanDataForExternalTransfer loanDataForExternalTransfer, boolean isDelayedSettlementEnabled) { - LoanStatus loanStatus = LoanStatus.fromInt(loanDataForExternalTransfer.getLoanStatus()); + LoanStatus loanStatus = loanDataForExternalTransfer.getLoanStatus(); if (!getValidLoanStatusList(isDelayedSettlementEnabled).contains(loanStatus)) { throw new ExternalAssetOwnerInitiateTransferException(String.format("Loan status %s is not valid for transfer.", loanStatus)); } } private void validateLoanStatusIntermediarySale(LoanDataForExternalTransfer loanDataForExternalTransfer) { - LoanStatus loanStatus = LoanStatus.fromInt(loanDataForExternalTransfer.getLoanStatus()); + LoanStatus loanStatus = loanDataForExternalTransfer.getLoanStatus(); if (!ACTIVE_LOAN_STATUSES.contains(loanStatus)) { throw new ExternalAssetOwnerInitiateTransferException(String.format("Loan status %s is not valid for transfer.", loanStatus)); } diff --git a/fineract-investor/src/test/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceTest.java b/fineract-investor/src/test/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceTest.java index 5edaaad9d..71d910266 100644 --- a/fineract-investor/src/test/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceTest.java +++ b/fineract-investor/src/test/java/org/apache/fineract/investor/service/ExternalAssetOwnersWriteServiceTest.java @@ -185,7 +185,7 @@ public class ExternalAssetOwnersWriteServiceTest { .thenReturn(Optional.of(testContext.loanDataForExternalTransfer)); when(testContext.externalAssetOwnerRepository.findByExternalId(any(ExternalId.class))) .thenReturn(Optional.of(testContext.externalAssetOwner)); - when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus.getValue()); + when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus); when(testContext.delayedSettlementAttributeService.isEnabled(testContext.loanProductId)).thenReturn(true); // when @@ -209,7 +209,7 @@ public class ExternalAssetOwnersWriteServiceTest { // given final JsonCommand command = createJsonCommand(testContext.jsonCommand, testContext.loanId); - when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus.getValue()); + when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus); when(testContext.delayedSettlementAttributeService.isEnabled(testContext.loanProductId)).thenReturn(true); when(testContext.loanRepository.findLoanDataForExternalTransferByLoanId(testContext.loanId)) .thenReturn(Optional.of(testContext.loanDataForExternalTransfer)); @@ -242,7 +242,7 @@ public class ExternalAssetOwnersWriteServiceTest { // given final JsonCommand command = createJsonCommand(testContext.jsonCommand, testContext.loanId); - when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus.getValue()); + when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus); when(testContext.delayedSettlementAttributeService.isEnabled(testContext.loanProductId)).thenReturn(true); when(testContext.loanRepository.findLoanDataForExternalTransferByLoanId(testContext.loanId)) .thenReturn(Optional.of(testContext.loanDataForExternalTransfer)); @@ -278,7 +278,7 @@ public class ExternalAssetOwnersWriteServiceTest { // given final JsonCommand command = createJsonCommand(testContext.jsonCommand, testContext.loanId); - when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus.getValue()); + when(testContext.loanDataForExternalTransfer.getLoanStatus()).thenReturn(loanStatus); when(testContext.delayedSettlementAttributeService.isEnabled(testContext.loanProductId)).thenReturn(true); when(testContext.loanRepository.findLoanDataForExternalTransferByLoanId(testContext.loanId)) .thenReturn(Optional.of(testContext.loanDataForExternalTransfer)); @@ -924,7 +924,7 @@ public class ExternalAssetOwnersWriteServiceTest { lenient().when(loanDataForExternalTransfer.getId()).thenReturn(loanId); lenient().when(loanDataForExternalTransfer.getExternalId()).thenReturn(new ExternalId(externalLoanId)); - lenient().when(loanDataForExternalTransfer.getLoanStatus()).thenReturn(LoanStatus.ACTIVE.getValue()); + lenient().when(loanDataForExternalTransfer.getLoanStatus()).thenReturn(LoanStatus.ACTIVE); lenient().when(loanDataForExternalTransfer.getLoanProductId()).thenReturn(loanProductId); lenient().when(loanDataForExternalTransfer.getLoanProductShortName()).thenReturn(loanProductShortName); } diff --git a/fineract-loan/src/main/java/org/apache/fineract/cob/data/LoanDataForExternalTransfer.java b/fineract-loan/src/main/java/org/apache/fineract/cob/data/LoanDataForExternalTransfer.java index e443d4065..4913293c2 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/cob/data/LoanDataForExternalTransfer.java +++ b/fineract-loan/src/main/java/org/apache/fineract/cob/data/LoanDataForExternalTransfer.java @@ -21,6 +21,7 @@ package org.apache.fineract.cob.data; import lombok.AllArgsConstructor; import lombok.Getter; import org.apache.fineract.infrastructure.core.domain.ExternalId; +import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; @AllArgsConstructor @Getter @@ -28,7 +29,7 @@ public class LoanDataForExternalTransfer { Long id; ExternalId externalId; - Integer loanStatus; + LoanStatus loanStatus; Long loanProductId; String loanProductShortName; } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java index 0158f8dad..27edfa341 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java @@ -266,7 +266,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe final MonetaryCurrency loanCurrency = loan.getCurrency(); LoanRepaymentScheduleInstallment latestInstallment = loan.getLastLoanRepaymentScheduleInstallment(); List chargebackTransactions = loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, - LoanTransactionType.CHARGEBACK.getValue()); + LoanTransactionType.CHARGEBACK); LocalDate overdueSinceDate = null; CollectionData collectionData = CollectionData.template(); BigDecimal outstandingAmount = BigDecimal.ZERO; @@ -324,7 +324,7 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe BigDecimal delinquentPenalty = BigDecimal.ZERO; List chargebackTransactions = loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, - LoanTransactionType.CHARGEBACK.getValue()); + LoanTransactionType.CHARGEBACK); BigDecimal amountAvailable = installment.getTotalPaid(loanCurrency).getAmount(); for (LoanTransaction loanTransaction : chargebackTransactions) { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformServiceImpl.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformServiceImpl.java index 003d1126f..2a44bcc43 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformServiceImpl.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/interestpauses/service/InterestPauseWritePlatformServiceImpl.java @@ -207,7 +207,7 @@ public class InterestPauseWritePlatformServiceImpl implements InterestPauseWrite } private void validateActiveLoan(Loan loan) { - if (!Objects.equals(loan.getLoanStatus(), ACTIVE.getValue())) { + if (!Objects.equals(loan.getLoanStatus(), ACTIVE)) { throw new GeneralPlatformDomainRuleException("loan.must.be.active", "Operations on interest pauses are restricted to active loans."); } 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 00506db2c..db722ddde 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 @@ -181,16 +181,16 @@ public interface LoanApiConstants { String INTEREST_RECOGNITION_ON_DISBURSEMENT_DATE = "interestRecognitionOnDisbursementDate"; // Loan Summary Transaction Types - List LOAN_SUMMARY_TRANSACTION_TYPES = List.of(LoanTransactionType.CHARGE_ADJUSTMENT.getValue(), // - LoanTransactionType.CHARGEBACK.getValue(), // - LoanTransactionType.CREDIT_BALANCE_REFUND.getValue(), // - LoanTransactionType.DOWN_PAYMENT.getValue(), // - LoanTransactionType.GOODWILL_CREDIT.getValue(), // - LoanTransactionType.INTEREST_PAYMENT_WAIVER.getValue(), // - LoanTransactionType.INTEREST_REFUND.getValue(), // - LoanTransactionType.MERCHANT_ISSUED_REFUND.getValue(), // - LoanTransactionType.PAYOUT_REFUND.getValue(), // - LoanTransactionType.REPAYMENT.getValue() // + List LOAN_SUMMARY_TRANSACTION_TYPES = List.of(LoanTransactionType.CHARGE_ADJUSTMENT, // + LoanTransactionType.CHARGEBACK, // + LoanTransactionType.CREDIT_BALANCE_REFUND, // + LoanTransactionType.DOWN_PAYMENT, // + LoanTransactionType.GOODWILL_CREDIT, // + LoanTransactionType.INTEREST_PAYMENT_WAIVER, // + LoanTransactionType.INTEREST_REFUND, // + LoanTransactionType.MERCHANT_ISSUED_REFUND, // + LoanTransactionType.PAYOUT_REFUND, // + LoanTransactionType.REPAYMENT // ); } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanStatusEnumData.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanStatusEnumData.java index 04ff5c933..c47742f9e 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanStatusEnumData.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanStatusEnumData.java @@ -59,7 +59,7 @@ public class LoanStatusEnumData { public interface Mapper { default LoanStatusEnumData map(Loan source) { - return LoanEnumerations.status(source.getPlainStatus()); + return LoanEnumerations.status(source.getStatus()); } } } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionBalance.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionBalance.java index bd9b2016f..0a3e5675d 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionBalance.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionBalance.java @@ -20,11 +20,12 @@ package org.apache.fineract.portfolio.loanaccount.data; import java.math.BigDecimal; import lombok.Data; +import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType; @Data public class LoanTransactionBalance { - private final Integer transactionType; + private final LoanTransactionType transactionType; private final boolean reversed; private final boolean manuallyAdjustedOrReversed; private final BigDecimal amount; diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/AccountingRuleTypeConverter.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/AccountingRuleTypeConverter.java new file mode 100644 index 000000000..5faaef16e --- /dev/null +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/AccountingRuleTypeConverter.java @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.loanaccount.domain; + +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; +import org.apache.fineract.accounting.common.AccountingRuleType; + +@Converter(autoApply = true) +public class AccountingRuleTypeConverter implements AttributeConverter { + + @Override + public Integer convertToDatabaseColumn(AccountingRuleType attribute) { + return attribute == null ? null : attribute.getValue(); + } + + @Override + public AccountingRuleType convertToEntityAttribute(Integer dbData) { + return AccountingRuleType.fromInt(dbData); + } +} diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachine.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachine.java index ccb056d82..76659ad30 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachine.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachine.java @@ -50,8 +50,7 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi LoanStatus oldStatus = loan.getStatus(); LoanStatus newStatus = getNextStatus(loanEvent, loan); if (newStatus != null) { - Integer newPlainStatus = newStatus.getValue(); - loan.setLoanStatus(newPlainStatus); + loan.setLoanStatus(newStatus); if (isNotLoanCreation(loanEvent)) { // in case of Loan creation, a LoanCreatedBusinessEvent is also raised, no need to send a status change @@ -85,12 +84,11 @@ public class DefaultLoanLifecycleStateMachine implements LoanLifecycleStateMachi } private LoanStatus getNextStatus(LoanEvent loanEvent, Loan loan) { - Integer plainFrom = loan.getPlainStatus(); - if (loanEvent.equals(LoanEvent.LOAN_CREATED) && plainFrom == null) { + LoanStatus from = loan.getStatus(); + if (loanEvent.equals(LoanEvent.LOAN_CREATED) && from == null) { return submittedTransition(); } - LoanStatus from = loan.getStatus(); LoanStatus newState = null; switch (loanEvent) { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 240bb33bb..21c4fae08 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -28,6 +28,7 @@ import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; +import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinTable; @@ -183,8 +184,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { @JoinColumn(name = "glim_id") private GroupLoanIndividualMonitoringAccount glim; + @Enumerated @Column(name = "loan_type_enum", nullable = false) - private Integer loanType; + private AccountType loanType; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "product_id", nullable = false) @@ -227,12 +229,13 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { private Integer termFrequency; @Setter() + @Enumerated @Column(name = "term_period_frequency_enum", nullable = false) - private Integer termPeriodFrequencyType; + private PeriodFrequencyType termPeriodFrequencyType; @Setter(AccessLevel.PACKAGE) @Column(name = "loan_status_id", nullable = false) - private Integer loanStatus; + private LoanStatus loanStatus; @Setter() @Column(name = "sync_disbursement_with_meeting") @@ -435,7 +438,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { @Setter @Column(name = "loan_sub_status_id") - private Integer loanSubStatus; + private LoanSubStatus loanSubStatus; @Column(name = "is_topup", nullable = false) private boolean isTopup = false; @@ -553,7 +556,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { } this.client = client; this.group = group; - this.loanType = loanType.getValue(); + this.loanType = loanType; this.fund = fund; this.loanOfficer = loanOfficer; this.loanPurpose = loanPurpose; @@ -562,11 +565,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { this.transactionProcessingStrategyName = transactionProcessingStrategy.getName(); this.loanProduct = loanProduct; - if (loanStatus != null) { - this.loanStatus = loanStatus.getValue(); - } else { - this.loanStatus = null; - } + this.loanStatus = loanStatus; if (loanCharges != null && !loanCharges.isEmpty()) { this.charges = associateChargesWithThisLoan(loanCharges); this.summary = updateSummaryWithTotalFeeChargesDueAtDisbursement(deriveSumTotalOfChargesDueAtDisbursement()); @@ -607,10 +606,10 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { // Add net get net disbursal amount from charges and principal this.netDisbursalAmount = this.approvedPrincipal.subtract(deriveSumTotalOfChargesDueAtDisbursement()); - this.loanStatus = LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(); + this.loanStatus = LoanStatus.SUBMITTED_AND_PENDING_APPROVAL; this.externalId = externalId; this.termFrequency = loanApplicationTerms.getLoanTermFrequency(); - this.termPeriodFrequencyType = loanApplicationTerms.getLoanTermPeriodFrequencyType().getValue(); + this.termPeriodFrequencyType = loanApplicationTerms.getLoanTermPeriodFrequencyType(); this.expectedDisbursementDate = loanApplicationTerms.getExpectedDisbursementDate(); this.expectedFirstRepaymentOnDate = loanApplicationTerms.getRepaymentStartFromDate(); this.interestChargedFromDate = loanApplicationTerms.getInterestChargedFromDate(); @@ -1827,10 +1826,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { } public LoanStatus getStatus() { - return this.loanStatus == null ? null : LoanStatus.fromInt(this.loanStatus); - } - - public Integer getPlainStatus() { return this.loanStatus; } @@ -2450,11 +2445,11 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { } public boolean isGroupLoan() { - return AccountType.fromInt(this.loanType).isGroupAccount(); + return this.loanType.isGroupAccount(); } public boolean isJLGLoan() { - return AccountType.fromInt(this.loanType).isJLGAccount(); + return this.loanType.isJLGAccount(); } public void updateInterestRateFrequencyType() { @@ -2738,7 +2733,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { public LoanApplicationTerms constructLoanApplicationTerms(final ScheduleGeneratorDTO scheduleGeneratorDTO) { final Integer loanTermFrequency = this.termFrequency; - final PeriodFrequencyType loanTermPeriodFrequencyType = PeriodFrequencyType.fromInt(this.termPeriodFrequencyType); NthDayType nthDayType = null; DayOfWeekType dayOfWeekType = null; final List disbursementData = new ArrayList<>(); @@ -2782,7 +2776,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { interestChargedFromDate = getDisbursementDate(); } - return LoanApplicationTerms.assembleFrom(scheduleGeneratorDTO.getCurrency(), loanTermFrequency, loanTermPeriodFrequencyType, + return LoanApplicationTerms.assembleFrom(scheduleGeneratorDTO.getCurrency(), loanTermFrequency, this.termPeriodFrequencyType, nthDayType, dayOfWeekType, getDisbursementDate(), getExpectedFirstRepaymentOnDate(), scheduleGeneratorDTO.getCalculatedRepaymentsStartingFromDate(), getInArrearsTolerance(), this.loanRepaymentScheduleDetail, this.loanProduct.isMultiDisburseLoan(), this.fixedEmiAmount, disbursementData, this.maxOutstandingLoanBalance, @@ -3386,7 +3380,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { public boolean isForeclosure() { boolean isForeClosure = false; if (this.loanSubStatus != null) { - isForeClosure = LoanSubStatus.fromInt(loanSubStatus).isForeclosed(); + isForeClosure = loanSubStatus.isForeclosed(); } return isForeClosure; @@ -3464,15 +3458,15 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { } public boolean hasInvalidLoanType() { - return AccountType.fromInt(this.loanType).isInvalid(); + return getLoanType().isInvalid(); } public boolean isIndividualLoan() { - return AccountType.fromInt(this.loanType).isIndividualAccount(); + return getLoanType().isIndividualAccount(); } public AccountType getLoanType() { - return AccountType.fromInt(loanType); + return this.loanType == null ? AccountType.INVALID : this.loanType; } public void adjustNetDisbursalAmount(BigDecimal adjustedAmount) { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccrualActivityRepository.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccrualActivityRepository.java index d30d4a75c..07af9bb09 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccrualActivityRepository.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccrualActivityRepository.java @@ -26,7 +26,8 @@ import org.springframework.data.repository.query.Param; public interface LoanAccrualActivityRepository extends Repository { - @Query("select loan.id from Loan loan left join LoanTransaction lt on lt.loan = loan and lt.typeOf = 32 and lt.reversed = false and lt.dateOf = :currentDate inner join LoanRepaymentScheduleInstallment rs on rs.loan = loan and rs.isDownPayment = false and rs.additional = false and rs.dueDate = :currentDate where loan.loanRepaymentScheduleDetail.enableAccrualActivityPosting = true and loan.loanStatus = 300 and lt.id is null ") - Set fetchLoanIdsForAccrualActivityPosting(@Param("currentDate") LocalDate currentDate); + @Query("select loan.id from Loan loan left join LoanTransaction lt on lt.loan = loan and lt.typeOf = :loanType and lt.reversed = false and lt.dateOf = :currentDate inner join LoanRepaymentScheduleInstallment rs on rs.loan = loan and rs.isDownPayment = false and rs.additional = false and rs.dueDate = :currentDate where loan.loanRepaymentScheduleDetail.enableAccrualActivityPosting = true and loan.loanStatus = :loanStatus and lt.id is null ") + Set fetchLoanIdsForAccrualActivityPosting(@Param("currentDate") LocalDate currentDate, + @Param("loanType") LoanTransactionType loanTransactionType, @Param("loanStatus") LoanStatus loanStatus); } diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentRepository.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentRepository.java index 58c569852..8cbf1748b 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentRepository.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepaymentScheduleInstallmentRepository.java @@ -43,7 +43,7 @@ public interface LoanRepaymentScheduleInstallmentRepository lrs.loan.loanProduct.delinquencyBucket IS NOT NULL GROUP BY lrs.loan """) - Collection fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") Integer loanStatus, + Collection fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") LoanStatus loanStatus, @Param("businessDate") LocalDate businessDate, @Param("obligationsMet") boolean obligationsMet); @Query(""" @@ -60,7 +60,7 @@ public interface LoanRepaymentScheduleInstallmentRepository lrs.loan.id NOT IN :loanIds GROUP BY lrs.loan """) - Collection fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") Integer loanStatus, + Collection fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") LoanStatus loanStatus, @Param("businessDate") LocalDate businessDate, @Param("obligationsMet") boolean obligationsMet, @Param("loanIds") List loanIds); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java index 128ffe153..7e0a3afd2 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepository.java @@ -22,10 +22,12 @@ import java.time.LocalDate; import java.util.Collection; import java.util.List; import java.util.Optional; +import org.apache.fineract.accounting.common.AccountingRuleType; import org.apache.fineract.cob.data.LoanDataForExternalTransfer; import org.apache.fineract.cob.data.LoanIdAndExternalIdAndAccountNo; import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate; import org.apache.fineract.infrastructure.core.domain.ExternalId; +import org.apache.fineract.portfolio.accountdetails.domain.AccountType; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; @@ -68,43 +70,43 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat String FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_GROUP = "Select loan.loanProduct.id from Loan loan where " + "loan.group.id = :groupId and loan.loanStatus = :loanStatus and loan.client.id is NULL group by loan.loanProduct.id"; - String DOES_CLIENT_HAVE_NON_CLOSED_LOANS = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.client.id = :clientId and loan.loanStatus in (100,200,300,303,304,700)"; + String DOES_CLIENT_HAVE_LOANS_WITH_STATUSES = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.client.id = :clientId and loan.loanStatus in :loanStatuses"; - String DOES_PRODUCT_HAVE_NON_CLOSED_LOANS = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.loanProduct.id = :productId and loan.loanStatus in (100,200,300,303,304,700)"; + String DOES_PRODUCT_HAVE_LOANS_WITH_STATUSES = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.loanProduct.id = :productId and loan.loanStatus in :loanStatuses"; - String FIND_NON_CLOSED_BY_ACCOUNT_NUMBER = "select loan from Loan loan where loan.accountNumber = :accountNumber and loan.loanStatus in (100,200,300,303,304)"; + String FIND_LOANS_BY_ACCOUNT_NUMBER_AND_STATUSES = "select loan from Loan loan where loan.accountNumber = :accountNumber and loan.loanStatus in :loanStatuses"; - String FIND_ALL_NON_CLOSED = "select loan.id from Loan loan where loan.loanStatus in (100,200,300,303,304)"; + String FIND_ALL_BY_STATUSES = "select loan.id from Loan loan where loan.loanStatus in :loanStatuses"; - String FIND_NON_CLOSED_LOAN_THAT_BELONGS_TO_CLIENT = "select loan from Loan loan where loan.id = :loanId and loan.loanStatus = 300 and loan.client.id = :clientId"; + String FIND_LOAN_BY_CLIENT_AND_STATUS = "select loan from Loan loan where loan.id = :loanId and loan.loanStatus = :loanStatus and loan.client.id = :clientId"; String FIND_BY_ACCOUNT_NUMBER = "select loan from Loan loan where loan.accountNumber = :accountNumber"; String FIND_LOAN_DATA_FOR_EXTERNAL_TRANSFER = "select new org.apache.fineract.cob.data.LoanDataForExternalTransfer(loan.id, loan.externalId, loan.loanStatus, loan.loanProduct.id, loan.loanProduct.shortName) from Loan loan where loan.id = :loanId"; - String EXISTS_NON_CLOSED_BY_EXTERNAL_LOAN_ID = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.externalId = :externalLoanId and loan.loanStatus in (100,200,300,303,304)"; + String EXISTS_BY_EXTERNAL_LOAN_ID_AND_STATUSES = "select case when (count (loan) > 0) then 'true' else 'false' end from Loan loan where loan.externalId = :externalLoanId and loan.loanStatus in :loanStatuses"; String FIND_ID_BY_EXTERNAL_ID = "SELECT loan.id FROM Loan loan WHERE loan.externalId = :externalId"; String FIND_IDS_BY_EXTERNAL_IDS = "SELECT loan.id FROM Loan loan WHERE loan.externalId IN :externalIds ORDER BY loan.id ASC"; - // should follow the logic of `FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE` query - String FIND_OLDEST_COB_PROCESSED_LOAN = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.loanStatus in (100,200,300,303,304) and loan.lastClosedBusinessDate = (select min(l.lastClosedBusinessDate) from Loan l where l" - + ".loanStatus in (100,200,300,303,304) and l.lastClosedBusinessDate < :cobBusinessDate)"; + // should follow the logic of `FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE` query + String FIND_OLDEST_COB_PROCESSED_LOAN = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.loanStatus in :loanStatuses and loan.lastClosedBusinessDate = (select min(l.lastClosedBusinessDate) from Loan l where l" + + ".loanStatus in :loanStatuses and l.lastClosedBusinessDate < :cobBusinessDate)"; - String FIND_ALL_NON_CLOSED_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.id IN :loanIds and loan.loanStatus in (100,200,300,303,304) and (loan.lastClosedBusinessDate < :cobBusinessDate or " + String FIND_ALL_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS_AND_STATUSES = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.id IN :loanIds and loan.loanStatus in :loanStatuses and (loan.lastClosedBusinessDate < :cobBusinessDate or " + "loan.lastClosedBusinessDate is null)"; - String FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_AND_MIN_AND_MAX_LOAN_ID = "select loan.id from Loan loan where loan.id BETWEEN :minLoanId and :maxLoanId and loan.loanStatus in (100,200,300,303,304) and (:cobBusinessDate = loan.lastClosedBusinessDate or loan.lastClosedBusinessDate is NULL)"; + String FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_AND_MIN_AND_MAX_LOAN_ID_AND_STATUSES = "select loan.id from Loan loan where loan.id BETWEEN :minLoanId and :maxLoanId and loan.loanStatus in :loanStatuses and (:cobBusinessDate = loan.lastClosedBusinessDate or loan.lastClosedBusinessDate is NULL)"; - String FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_NOT_NULL_AND_MIN_AND_MAX_LOAN_ID = "select loan.id from Loan loan where loan.id BETWEEN :minLoanId and :maxLoanId and loan.loanStatus in (100,200,300,303,304) and :cobBusinessDate = loan.lastClosedBusinessDate"; - String FIND_ALL_NON_CLOSED_LOANS_BEHIND_BY_LOAN_IDS = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.id IN :loanIds and loan.loanStatus in (100,200,300,303,304) and loan.lastClosedBusinessDate < :cobBusinessDate"; + String FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_NOT_NULL_AND_MIN_AND_MAX_LOAN_ID_AND_STATUSES = "select loan.id from Loan loan where loan.id BETWEEN :minLoanId and :maxLoanId and loan.loanStatus in :loanStatuses and :cobBusinessDate = loan.lastClosedBusinessDate"; + String FIND_ALL_LOANS_BEHIND_BY_LOAN_IDS_AND_STATUSES = "select loan.id, loan.lastClosedBusinessDate from Loan loan where loan.id IN :loanIds and loan.loanStatus in :loanStatuses and loan.lastClosedBusinessDate < :cobBusinessDate"; String FIND_ALL_STAYED_LOCKED_BY_COB_BUSINESS_DATE = "select loan.id, loan.externalId, loan.accountNumber from LoanAccountLock lock left join Loan loan on lock.loanId = loan.id where lock.lockPlacedOnCobBusinessDate = :cobBusinessDate"; - String FIND_ALL_LOAN_IDS_BY_STATUS_ID = "SELECT loan.id FROM Loan loan WHERE loan.loanStatus = :statusId"; + String FIND_ALL_LOAN_IDS_BY_STATUS = "SELECT loan.id FROM Loan loan WHERE loan.loanStatus = :loanStatus"; String LOANS_FOR_ACCRUAL = "select l from Loan l left join l.loanInterestRecalculationDetails recalcDetails " - + "where l.loanStatus = 300 and l.isNpa = false and l.chargedOff = false " + + "where l.loanStatus = :loanStatus and l.isNpa = false and l.chargedOff = false " + "and l.loanProduct.accountingRule = :accountingType " + "and (recalcDetails.isCompoundingToBePostedAsTransaction is null or recalcDetails.isCompoundingToBePostedAsTransaction = false) " + "and (exists (select ls.id from LoanRepaymentScheduleInstallment ls where ls.loan.id = l.id and ls.isDownPayment = false " @@ -119,17 +121,17 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat @Query(FIND_GROUP_LOANS_DISBURSED_AFTER) List getGroupLoansDisbursedAfter(@Param("disbursementDate") LocalDate disbursementDate, @Param("groupId") Long groupId, - @Param("loanType") Integer loanType); + @Param("loanType") AccountType loanType); @Query(FIND_CLIENT_OR_JLG_LOANS_DISBURSED_AFTER) List getClientOrJLGLoansDisbursedAfter(@Param("disbursementDate") LocalDate disbursementDate, @Param("clientId") Long clientId); @Query(FIND_MAX_GROUP_LOAN_COUNTER_QUERY) - Integer getMaxGroupLoanCounter(@Param("groupId") Long groupId, @Param("loanType") Integer loanType); + Integer getMaxGroupLoanCounter(@Param("groupId") Long groupId, @Param("loanType") AccountType loanType); @Query(FIND_MAX_GROUP_LOAN_PRODUCT_COUNTER_QUERY) Integer getMaxGroupLoanProductCounter(@Param("productId") Long productId, @Param("groupId") Long groupId, - @Param("loanType") Integer loanType); + @Param("loanType") AccountType loanType); @Query(FIND_MAX_CLIENT_OR_JLG_LOAN_COUNTER_QUERY) Integer getMaxClientOrJLGLoanCounter(@Param("clientId") Long clientId); @@ -139,14 +141,14 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat @Query(FIND_GROUP_LOANS_TO_UPDATE) List getGroupLoansToUpdateLoanCounter(@Param("loanCounter") Integer loanCounter, @Param("groupId") Long groupId, - @Param("groupLoanType") Integer groupLoanType); + @Param("groupLoanType") AccountType groupLoanType); @Query(FIND_CLIENT_OR_JLG_LOANS_TO_UPDATE) List getClientOrJLGLoansToUpdateLoanCounter(@Param("loanCounter") Integer loanCounter, @Param("clientId") Long clientId); @Query(FIND_GROUP_LOANS_TO_UPDATE_LOANPRODUCT_COUNTER) List getGroupLoansToUpdateLoanProductCounter(@Param("loanProductCounter") Integer loanProductCounter, - @Param("groupId") Long groupId, @Param("groupLoanType") Integer groupLoanType); + @Param("groupId") Long groupId, @Param("groupLoanType") AccountType groupLoanType); @Query(FIND_CLIENT_LOANS_TO_UPDATE_LOANPRODUCT_COUNTER) List getClientLoansToUpdateLoanProductCounter(@Param("loanProductCounter") Integer loanProductCounter, @@ -157,7 +159,7 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat @Query("select loan from Loan loan where loan.client.id = :clientId and loan.group.id = :groupId and loan.loanStatus IN :loanStatuses") List findByClientIdAndGroupIdAndLoanStatus(@Param("clientId") Long clientId, @Param("groupId") Long groupId, - @Param("loanStatuses") Collection loanStatuses); + @Param("loanStatuses") Collection loanStatuses); @Query("select loan from Loan loan where loan.client.id = :clientId") List findLoanByClientId(@Param("clientId") Long clientId); @@ -170,37 +172,41 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat @Query("select loan from Loan loan where loan.id IN :ids and loan.loanStatus IN :loanStatuses and loan.loanType IN :loanTypes") List findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection ids, - @Param("loanStatuses") Collection loanStatuses, @Param("loanTypes") Collection loanTypes); + @Param("loanStatuses") Collection loanStatuses, @Param("loanTypes") Collection loanTypes); @Query("select loan.id from Loan loan where loan.actualDisbursementDate > :disbursalDate order by loan.actualDisbursementDate") List getLoansDisbursedAfter(@Param("disbursalDate") LocalDate disbursalDate); @Query("select loan from Loan loan where loan.client.office.id IN :officeIds and loan.loanStatus IN :loanStatuses") List findByClientOfficeIdsAndLoanStatus(@Param("officeIds") Collection officeIds, - @Param("loanStatuses") Collection loanStatuses); + @Param("loanStatuses") Collection loanStatuses); @Query("select loan from Loan loan where loan.group.office.id IN :officeIds and loan.loanStatus IN :loanStatuses") List findByGroupOfficeIdsAndLoanStatus(@Param("officeIds") Collection officeIds, - @Param("loanStatuses") Collection loanStatuses); + @Param("loanStatuses") Collection loanStatuses); /*** FIXME: Add more appropriate names for the query ***/ @Query(FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_CLIENT) - List findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") Integer loanStatus); + List findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") LoanStatus loanStatus); @Query(FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_GROUP) - List findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") Integer loanStatus); + List findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") LoanStatus loanStatus); - @Query(DOES_CLIENT_HAVE_NON_CLOSED_LOANS) - boolean doNonClosedLoanAccountsExistForClient(@Param("clientId") Long clientId); + @Query(DOES_CLIENT_HAVE_LOANS_WITH_STATUSES) + boolean doLoanAccountsWithLoansInStatusesExistForClient(@Param("clientId") Long clientId, + @Param("loanStatuses") Collection loanStatuses); - @Query(DOES_PRODUCT_HAVE_NON_CLOSED_LOANS) - boolean doNonClosedLoanAccountsExistForProduct(@Param("productId") Long productId); + @Query(DOES_PRODUCT_HAVE_LOANS_WITH_STATUSES) + boolean doLoanAccountsWithLoansInStatusesExistForProduct(@Param("productId") Long productId, + @Param("loanStatuses") Collection loanStatuses); - @Query(FIND_NON_CLOSED_BY_ACCOUNT_NUMBER) - Loan findNonClosedLoanByAccountNumber(@Param("accountNumber") String accountNumber); + @Query(FIND_LOANS_BY_ACCOUNT_NUMBER_AND_STATUSES) + Loan findLoanByAccountNumberAndStatuses(@Param("accountNumber") String accountNumber, + @Param("loanStatuses") Collection loanStatuses); - @Query(FIND_NON_CLOSED_LOAN_THAT_BELONGS_TO_CLIENT) - Loan findNonClosedLoanThatBelongsToClient(@Param("loanId") Long loanId, @Param("clientId") Long clientId); + @Query(FIND_LOAN_BY_CLIENT_AND_STATUS) + Loan findLoanByClientAndStatus(@Param("loanId") Long loanId, @Param("clientId") Long clientId, + @Param("loanStatus") LoanStatus loanStatus); @Query(FIND_BY_ACCOUNT_NUMBER) Loan findLoanAccountByAccountNumber(@Param("accountNumber") String accountNumber); @@ -208,13 +214,14 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat @Query(FIND_LOAN_DATA_FOR_EXTERNAL_TRANSFER) Optional findLoanDataForExternalTransferByLoanId(@Param("loanId") Long loanId); - @Query(EXISTS_NON_CLOSED_BY_EXTERNAL_LOAN_ID) - boolean existsNonClosedLoanByExternalLoanId(@Param("externalLoanId") ExternalId externalLoanId); + @Query(EXISTS_BY_EXTERNAL_LOAN_ID_AND_STATUSES) + boolean existsLoanByExternalLoanIdAndStatuses(@Param("externalLoanId") ExternalId externalLoanId, + @Param("loanStatuses") Collection loanStatuses); boolean existsByExternalId(@Param("externalId") ExternalId externalId); - @Query(FIND_ALL_NON_CLOSED) - List findAllNonClosedLoanIds(); + @Query(FIND_ALL_BY_STATUSES) + List findAllLoanIdsByStatuses(@Param("loanStatuses") Collection loanStatuses); @Query(FIND_ID_BY_EXTERNAL_ID) Long findIdByExternalId(@Param("externalId") ExternalId externalId); @@ -222,38 +229,42 @@ public interface LoanRepository extends JpaRepository, JpaSpecificat @Query(FIND_IDS_BY_EXTERNAL_IDS) List findIdsByExternalIds(@Param("externalIds") List externalIds); - @Query(FIND_ALL_NON_CLOSED_LOANS_BEHIND_BY_LOAN_IDS) - List findAllNonClosedLoansBehindByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate, - @Param("loanIds") List loanIds); + @Query(FIND_ALL_LOANS_BEHIND_BY_LOAN_IDS_AND_STATUSES) + List findAllLoansBehindByLoanIdsAndStatuses(@Param("cobBusinessDate") LocalDate cobBusinessDate, + @Param("loanIds") List loanIds, @Param("loanStatuses") Collection loanStatuses); - @Query(FIND_ALL_NON_CLOSED_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS) - List findAllNonClosedLoansBehindOrNullByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate, - @Param("loanIds") List loanIds); + @Query(FIND_ALL_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS_AND_STATUSES) + List findAllLoansBehindOrNullByLoanIdsAndStatuses(@Param("cobBusinessDate") LocalDate cobBusinessDate, + @Param("loanIds") List loanIds, @Param("loanStatuses") Collection loanStatuses); - @Query(FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_AND_MIN_AND_MAX_LOAN_ID) - List findAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(@Param("minLoanId") Long minLoanId, - @Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate); + @Query(FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_AND_MIN_AND_MAX_LOAN_ID_AND_STATUSES) + List findAllLoansByLastClosedBusinessDateAndMinAndMaxLoanIdAndStatuses(@Param("minLoanId") Long minLoanId, + @Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate, + @Param("loanStatuses") Collection loanStatuses); - @Query(FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_NOT_NULL_AND_MIN_AND_MAX_LOAN_ID) - List findAllNonClosedLoansByLastClosedBusinessDateNotNullAndMinAndMaxLoanId(@Param("minLoanId") Long minLoanId, - @Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate); + @Query(FIND_ALL_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_NOT_NULL_AND_MIN_AND_MAX_LOAN_ID_AND_STATUSES) + List findAllLoansByLastClosedBusinessDateNotNullAndMinAndMaxLoanIdAndStatuses(@Param("minLoanId") Long minLoanId, + @Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate, + @Param("loanStatuses") Collection loanStatuses); @Query(FIND_OLDEST_COB_PROCESSED_LOAN) - List findOldestCOBProcessedLoan(@Param("cobBusinessDate") LocalDate cobBusinessDate); + List findOldestCOBProcessedLoan(@Param("cobBusinessDate") LocalDate cobBusinessDate, + @Param("loanStatuses") Collection loanStatuses); @Query(FIND_ALL_STAYED_LOCKED_BY_COB_BUSINESS_DATE) List findAllStayedLockedByCobBusinessDate(@Param("cobBusinessDate") LocalDate cobBusinessDate); - @Query(FIND_ALL_LOAN_IDS_BY_STATUS_ID) - List findLoanIdByStatusId(@Param("statusId") Integer statusId); + @Query(FIND_ALL_LOAN_IDS_BY_STATUS) + List findLoanIdByStatus(@Param("loanStatus") LoanStatus loanStatus); @Query(FIND_LOANS_FOR_PERIODIC_ACCRUAL) - List findLoansForPeriodicAccrual(@Param("accountingType") Integer accountingType, @Param("tillDate") LocalDate tillDate, - @Param("futureCharges") boolean futureCharges); + List findLoansForPeriodicAccrual(@Param("accountingType") AccountingRuleType accountingType, + @Param("tillDate") LocalDate tillDate, @Param("futureCharges") boolean futureCharges, + @Param("loanStatus") LoanStatus loanStatus); @Query(FIND_LOANS_FOR_ADD_ACCRUAL) - List findLoansForAddAccrual(@Param("accountingType") Integer accountingType, @Param("tillDate") LocalDate tillDate, - @Param("futureCharges") boolean futureCharges); + List findLoansForAddAccrual(@Param("accountingType") AccountingRuleType accountingType, @Param("tillDate") LocalDate tillDate, + @Param("futureCharges") boolean futureCharges, @Param("loanStatus") LoanStatus loanStatus); @Query(FIND_LOAN_BY_EXTERNAL_ID) Optional findByExternalId(@Param("externalId") ExternalId externalId); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepositoryWrapper.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepositoryWrapper.java index f8669b4cc..b00ecca58 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepositoryWrapper.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanRepositoryWrapper.java @@ -25,8 +25,10 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; import lombok.RequiredArgsConstructor; +import org.apache.fineract.accounting.common.AccountingRuleType; import org.apache.fineract.infrastructure.core.config.FineractProperties; import org.apache.fineract.infrastructure.core.domain.ExternalId; +import org.apache.fineract.portfolio.accountdetails.domain.AccountType; import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Service; @@ -41,6 +43,13 @@ import org.springframework.transaction.annotation.Transactional; @RequiredArgsConstructor public class LoanRepositoryWrapper { + private static final Collection NON_CLOSED_LOAN_STATUSES = new ArrayList<>( + Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE, + LoanStatus.TRANSFER_IN_PROGRESS, LoanStatus.TRANSFER_ON_HOLD)); + private static final Collection NON_CLOSED_AND_OVERPAID_LOAN_STATUSES = new ArrayList<>( + Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE, + LoanStatus.TRANSFER_IN_PROGRESS, LoanStatus.TRANSFER_ON_HOLD, LoanStatus.OVERPAID)); + private final LoanRepository repository; private final FineractProperties fineractProperties; @@ -74,8 +83,8 @@ public class LoanRepositoryWrapper { // Root Entities are enough public Collection findActiveLoansByLoanIdAndGroupId(Long clientId, Long groupId) { - final Collection loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(), - LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue(), LoanStatus.OVERPAID.getValue())); + final Collection loanStatuses = new ArrayList<>( + Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE, LoanStatus.OVERPAID)); return this.repository.findByClientIdAndGroupIdAndLoanStatus(clientId, groupId, loanStatuses); } @@ -102,7 +111,7 @@ public class LoanRepositoryWrapper { // Only root entities is enough public List getGroupLoansDisbursedAfter(@Param("disbursementDate") LocalDate disbursementDate, @Param("groupId") Long groupId, - @Param("loanType") Integer loanType) { + @Param("loanType") AccountType loanType) { return this.repository.getGroupLoansDisbursedAfter(disbursementDate, groupId, loanType); } @@ -112,12 +121,12 @@ public class LoanRepositoryWrapper { return this.repository.getClientOrJLGLoansDisbursedAfter(disbursementDate, clientId); } - public Integer getMaxGroupLoanCounter(@Param("groupId") Long groupId, @Param("loanType") Integer loanType) { + public Integer getMaxGroupLoanCounter(@Param("groupId") Long groupId, @Param("loanType") AccountType loanType) { return this.repository.getMaxGroupLoanCounter(groupId, loanType); } public Integer getMaxGroupLoanProductCounter(@Param("productId") Long productId, @Param("groupId") Long groupId, - @Param("loanType") Integer loanType) { + @Param("loanType") AccountType loanType) { return this.repository.getMaxGroupLoanProductCounter(productId, groupId, loanType); } @@ -140,7 +149,7 @@ public class LoanRepositoryWrapper { // Only root entities are enough public List getGroupLoansToUpdateLoanCounter(@Param("loanCounter") Integer loanCounter, @Param("groupId") Long groupId, - @Param("groupLoanType") Integer groupLoanType) { + @Param("groupLoanType") AccountType groupLoanType) { return this.repository.getGroupLoansToUpdateLoanCounter(loanCounter, groupId, groupLoanType); } @@ -151,7 +160,7 @@ public class LoanRepositoryWrapper { // Only root entities are enough public List getGroupLoansToUpdateLoanProductCounter(@Param("loanProductCounter") Integer loanProductCounter, - @Param("groupId") Long groupId, @Param("groupLoanType") Integer groupLoanType) { + @Param("groupId") Long groupId, @Param("groupLoanType") AccountType groupLoanType) { return this.repository.getGroupLoansToUpdateLoanProductCounter(loanProductCounter, groupId, groupLoanType); } @@ -193,7 +202,7 @@ public class LoanRepositoryWrapper { // Looks like we need complete Data public List findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection ids, - @Param("loanStatuses") Collection loanStatuses, @Param("loanTypes") Collection loanTypes) { + @Param("loanStatuses") Collection loanStatuses, @Param("loanTypes") Collection loanTypes) { List loans = new ArrayList<>(); List> partitions = Lists.partition(ids.stream().toList(), fineractProperties.getQuery().getInClauseParameterSizeLimit()); partitions @@ -213,7 +222,7 @@ public class LoanRepositoryWrapper { // Repayments Schedule public List findByClientOfficeIdsAndLoanStatus(@Param("officeIds") Collection officeIds, - @Param("loanStatuses") Collection loanStatuses) { + @Param("loanStatuses") Collection loanStatuses) { List loans = this.repository.findByClientOfficeIdsAndLoanStatus(officeIds, loanStatuses); if (loans != null && loans.size() > 0) { for (Loan loan : loans) { @@ -225,7 +234,7 @@ public class LoanRepositoryWrapper { // Repayments Schedule public List findByGroupOfficeIdsAndLoanStatus(@Param("officeIds") Collection officeIds, - @Param("loanStatuses") Collection loanStatuses) { + @Param("loanStatuses") Collection loanStatuses) { List loans = this.repository.findByGroupOfficeIdsAndLoanStatus(officeIds, loanStatuses); if (loans != null && loans.size() > 0) { for (Loan loan : loans) { @@ -235,34 +244,42 @@ public class LoanRepositoryWrapper { return loans; } - public List findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") Integer loanStatus) { + public List findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") LoanStatus loanStatus) { return this.repository.findActiveLoansLoanProductIdsByClient(clientId, loanStatus); } - public List findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") Integer loanStatus) { + public List findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") LoanStatus loanStatus) { return this.repository.findActiveLoansLoanProductIdsByGroup(groupId, loanStatus); } public boolean doNonClosedLoanAccountsExistForClient(@Param("clientId") Long clientId) { - return this.repository.doNonClosedLoanAccountsExistForClient(clientId); + return this.repository.doLoanAccountsWithLoansInStatusesExistForClient(clientId, NON_CLOSED_AND_OVERPAID_LOAN_STATUSES); } public boolean doNonClosedLoanAccountsExistForProduct(@Param("productId") Long productId) { - return this.repository.doNonClosedLoanAccountsExistForProduct(productId); + return this.repository.doLoanAccountsWithLoansInStatusesExistForProduct(productId, NON_CLOSED_AND_OVERPAID_LOAN_STATUSES); } public Loan findNonClosedLoanByAccountNumber(@Param("accountNumber") String accountNumber) { - return this.repository.findNonClosedLoanByAccountNumber(accountNumber); + return this.repository.findLoanByAccountNumberAndStatuses(accountNumber, NON_CLOSED_LOAN_STATUSES); + } + + public boolean existsNonClosedLoanByExternalLoanId(final ExternalId externalId) { + return this.repository.existsLoanByExternalLoanIdAndStatuses(externalId, NON_CLOSED_LOAN_STATUSES); } public boolean existLoanByExternalId(final ExternalId externalId) { return this.repository.existsByExternalId(externalId); } + public List findAllNonClosedLoanIds() { + return this.repository.findAllLoanIdsByStatuses(NON_CLOSED_LOAN_STATUSES); + } + // Looks like we need complete entity @Transactional(readOnly = true) public Loan findNonClosedLoanThatBelongsToClient(@Param("loanId") Long loanId, @Param("clientId") Long clientId) { - Loan loan = this.repository.findNonClosedLoanThatBelongsToClient(loanId, clientId); + Loan loan = this.repository.findLoanByClientAndStatus(loanId, clientId, LoanStatus.ACTIVE); if (loan != null) { loan.initializeTransactions(); } @@ -274,15 +291,15 @@ public class LoanRepositoryWrapper { } public List findLoanIdsByStatusId(Integer statusId) { - return repository.findLoanIdByStatusId(statusId); + return repository.findLoanIdByStatus(LoanStatus.fromInt(statusId)); } - public List findLoansForPeriodicAccrual(Integer accountingType, LocalDate tillDate, boolean futureCharges) { - return repository.findLoansForPeriodicAccrual(accountingType, tillDate, futureCharges); + public List findLoansForPeriodicAccrual(AccountingRuleType accountingType, LocalDate tillDate, boolean futureCharges) { + return repository.findLoansForPeriodicAccrual(accountingType, tillDate, futureCharges, LoanStatus.ACTIVE); } - public List findLoansForAddAccrual(Integer accountingType, LocalDate tillDate, boolean futureCharges) { - return repository.findLoansForAddAccrual(accountingType, tillDate, futureCharges); + public List findLoansForAddAccrual(AccountingRuleType accountingType, LocalDate tillDate, boolean futureCharges) { + return repository.findLoansForAddAccrual(accountingType, tillDate, futureCharges, LoanStatus.ACTIVE); } public List findIdByExternalIds(List externalIds) { diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanStatusConverter.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanStatusConverter.java new file mode 100644 index 000000000..67f2afd1f --- /dev/null +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanStatusConverter.java @@ -0,0 +1,36 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.loanaccount.domain; + +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; + +@Converter(autoApply = true) +public class LoanStatusConverter implements AttributeConverter { + + @Override + public Integer convertToDatabaseColumn(LoanStatus attribute) { + return attribute == null ? null : attribute.getValue(); + } + + @Override + public LoanStatus convertToEntityAttribute(Integer dbData) { + return LoanStatus.fromInt(dbData); + } +} diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSubStatusConverter.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSubStatusConverter.java new file mode 100644 index 000000000..4ab55ebac --- /dev/null +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSubStatusConverter.java @@ -0,0 +1,36 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.loanaccount.domain; + +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; + +@Converter(autoApply = true) +public class LoanSubStatusConverter implements AttributeConverter { + + @Override + public Integer convertToDatabaseColumn(LoanSubStatus attribute) { + return attribute == null ? null : attribute.getValue(); + } + + @Override + public LoanSubStatus convertToEntityAttribute(Integer dbData) { + return dbData == null ? null : LoanSubStatus.fromInt(dbData); + } +} diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummaryBalancesRepository.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummaryBalancesRepository.java index 6890aa989..d32293849 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummaryBalancesRepository.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSummaryBalancesRepository.java @@ -42,7 +42,7 @@ public class LoanSummaryBalancesRepository { private final CriteriaQueryFactory criteriaQueryFactory; public Collection retrieveLoanSummaryBalancesByTransactionType(final Long loanId, - final List transactionTypes) { + final List transactionTypes) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery query = cb.createQuery(LoanTransactionBalance.class); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java index a83b9f884..abf89be14 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java @@ -75,7 +75,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom fetchLoanTransactionsByTypeAndLessOrEqualDate(@Param("transactionType") Integer transactionType, - @Param("businessDate") LocalDate businessDate); + Collection fetchLoanTransactionsByTypeAndLessOrEqualDate( + @Param("transactionType") LoanTransactionType transactionType, @Param("businessDate") LocalDate businessDate); @Query(FIND_ID_BY_EXTERNAL_ID) Long findIdByExternalId(@Param("externalId") ExternalId externalId); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionTypeConverter.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionTypeConverter.java new file mode 100644 index 000000000..f15d27c54 --- /dev/null +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionTypeConverter.java @@ -0,0 +1,36 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.fineract.portfolio.loanaccount.domain; + +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; + +@Converter(autoApply = true) +public class LoanTransactionTypeConverter implements AttributeConverter { + + @Override + public Integer convertToDatabaseColumn(LoanTransactionType attribute) { + return attribute == null ? null : attribute.getValue(); + } + + @Override + public LoanTransactionType convertToEntityAttribute(Integer dbData) { + return dbData == null ? null : LoanTransactionType.fromInt(dbData); + } +} diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/setloandelinquencytags/SetLoanDelinquencyTagsTasklet.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/setloandelinquencytags/SetLoanDelinquencyTagsTasklet.java index d1cd7ab39..ccf54f3dd 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/setloandelinquencytags/SetLoanDelinquencyTagsTasklet.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/setloandelinquencytags/SetLoanDelinquencyTagsTasklet.java @@ -62,7 +62,7 @@ public class SetLoanDelinquencyTagsTasklet implements Tasklet { // Read Loan Ids with Loan Transaction Charge back Collection loanScheduleDelinquencyData = this.loanTransactionRepository - .fetchLoanTransactionsByTypeAndLessOrEqualDate(LoanTransactionType.CHARGEBACK.getValue(), businessDate); + .fetchLoanTransactionsByTypeAndLessOrEqualDate(LoanTransactionType.CHARGEBACK, businessDate); List processedLoans = applyDelinquencyTagToLoans(loanScheduleDelinquencyData); log.debug("{}: Records affected by setLoanDelinquencyTags: {}", ThreadLocalContextUtil.getTenant().getName(), processedLoans.size()); @@ -70,10 +70,10 @@ public class SetLoanDelinquencyTagsTasklet implements Tasklet { // Read Loan Ids with overdue installments if (processedLoans.isEmpty()) { loanScheduleDelinquencyData = this.loanRepaymentScheduleInstallmentRepository - .fetchLoanScheduleDataByDueDateAndObligationsMet(LoanStatus.ACTIVE.getValue(), businessDate, false); + .fetchLoanScheduleDataByDueDateAndObligationsMet(LoanStatus.ACTIVE, businessDate, false); } else { loanScheduleDelinquencyData = this.loanRepaymentScheduleInstallmentRepository - .fetchLoanScheduleDataByDueDateAndObligationsMet(LoanStatus.ACTIVE.getValue(), businessDate, false, processedLoans); + .fetchLoanScheduleDataByDueDateAndObligationsMet(LoanStatus.ACTIVE, businessDate, false, processedLoans); } applyDelinquencyTagToLoans(loanScheduleDelinquencyData); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationTransitionValidator.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationTransitionValidator.java index 34d40c727..c2212a1ae 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationTransitionValidator.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationTransitionValidator.java @@ -153,7 +153,7 @@ public final class LoanApplicationTransitionValidator { // validate loan state transition final LoanStatus statusEnum = defaultLoanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_REJECTED, loan); - if (!statusEnum.hasStateOf(LoanStatus.fromInt(loan.getLoanStatus()))) { + if (!statusEnum.hasStateOf(loan.getLoanStatus())) { final LocalDate rejectedOn = command.localDateValueOfParameterNamed(Loan.REJECTED_ON_DATE); if (DateUtils.isBefore(rejectedOn, loan.getSubmittedOnDate())) { final String errorMessage = "The date on which a loan is rejected cannot be before its submittal date: " @@ -214,7 +214,7 @@ public final class LoanApplicationTransitionValidator { // validate loan state transition final LoanStatus statusEnum = defaultLoanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_WITHDRAWN, loan); - if (!statusEnum.hasStateOf(LoanStatus.fromInt(loan.getLoanStatus()))) { + if (!statusEnum.hasStateOf(loan.getLoanStatus())) { LocalDate withdrawnOn = command.localDateValueOfParameterNamed(Loan.WITHDRAWN_ON_DATE); if (withdrawnOn == null) { withdrawnOn = command.localDateValueOfParameterNamed(Loan.EVENT_DATE); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionReadService.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionReadService.java index 926caba72..f8a614bca 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionReadService.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionReadService.java @@ -32,6 +32,7 @@ import java.util.List; import lombok.RequiredArgsConstructor; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanTransaction; +import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @@ -42,14 +43,15 @@ public class LoanTransactionReadService { private final EntityManager entityManager; - public List fetchLoanTransactionsByType(final Long loanId, final String externalId, final Integer transactionType) { - final List transactionTypes = new ArrayList<>(); + public List fetchLoanTransactionsByType(final Long loanId, final String externalId, + final LoanTransactionType transactionType) { + final List transactionTypes = new ArrayList<>(); transactionTypes.add(transactionType); return fetchLoanTransactionsByTypes(loanId, externalId, transactionTypes); } public List fetchLoanTransactionsByTypes(final Long loanId, final String externalId, - final List transactionTypes) { + final List transactionTypes) { final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaQuery query = cb.createQuery(LoanTransaction.class); diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java index c5792f700..c010ae42b 100644 --- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java +++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java @@ -132,7 +132,7 @@ public class LoanProduct extends AbstractPersistableCustom { private LoanProductMinMaxConstraints loanProductMinMaxConstraints; @Column(name = "accounting_type", nullable = false) - private Integer accountingRule; + private AccountingRuleType accountingRule; @Column(name = "include_in_borrower_cycle") private boolean includeInBorrowerCycle; @@ -767,9 +767,7 @@ public class LoanProduct extends AbstractPersistableCustom { defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod, defaultMinNumberOfInstallments, defaultMaxNumberOfInstallments); - if (accountingRuleType != null) { - this.accountingRule = accountingRuleType.getValue(); - } + this.accountingRule = accountingRuleType; this.includeInBorrowerCycle = includeInBorrowerCycle; this.useBorrowerCycle = useBorrowerCycle; @@ -994,10 +992,11 @@ public class LoanProduct extends AbstractPersistableCustom { } final String accountingTypeParamName = "accountingRule"; - if (command.isChangeInIntegerParameterNamed(accountingTypeParamName, this.accountingRule)) { + Integer currentValue = this.accountingRule == null ? null : this.accountingRule.getValue(); + if (command.isChangeInIntegerParameterNamed(accountingTypeParamName, currentValue)) { final Integer newValue = command.integerValueOfParameterNamed(accountingTypeParamName); actualChanges.put(accountingTypeParamName, newValue); - this.accountingRule = newValue; + this.accountingRule = AccountingRuleType.fromInt(newValue); } final String nameParamName = "name"; @@ -1414,19 +1413,19 @@ public class LoanProduct extends AbstractPersistableCustom { } public boolean isAccountingDisabled() { - return AccountingRuleType.NONE.getValue().equals(this.accountingRule); + return AccountingRuleType.NONE.equals(this.accountingRule); } public boolean isCashBasedAccountingEnabled() { - return AccountingRuleType.CASH_BASED.getValue().equals(this.accountingRule); + return AccountingRuleType.CASH_BASED.equals(this.accountingRule); } public boolean isUpfrontAccrualAccountingEnabled() { - return AccountingRuleType.ACCRUAL_UPFRONT.getValue().equals(this.accountingRule); + return AccountingRuleType.ACCRUAL_UPFRONT.equals(this.accountingRule); } public boolean isPeriodicAccrualAccountingEnabled() { - return AccountingRuleType.ACCRUAL_PERIODIC.getValue().equals(this.accountingRule); + return AccountingRuleType.ACCRUAL_PERIODIC.equals(this.accountingRule); } public Money getPrincipalAmount() { diff --git a/fineract-provider/src/main/java/org/apache/fineract/accounting/productaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/accounting/productaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java index 05d8a530c..9bd101107 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/accounting/productaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/accounting/productaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java @@ -357,13 +357,12 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc @Override @Transactional public Map updateLoanProductToGLAccountMapping(final Long loanProductId, final JsonCommand command, - final boolean accountingRuleChanged, final int accountingRuleTypeId) { + final boolean accountingRuleChanged, final AccountingRuleType accountingRuleType) { /*** * Variable tracks all accounting mapping properties that have been updated ***/ Map changes = new HashMap<>(); final JsonElement element = this.fromApiJsonHelper.parse(command.json()); - final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(accountingRuleTypeId); /*** * If the accounting rule has been changed, delete all existing mapping for the product and recreate a new set diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveAllNonClosedLoanIdServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveAllNonClosedLoanIdServiceImpl.java index d7fa9e07f..b5c757ee3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveAllNonClosedLoanIdServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/RetrieveAllNonClosedLoanIdServiceImpl.java @@ -21,6 +21,9 @@ package org.apache.fineract.cob.loan; import java.sql.ResultSet; import java.sql.SQLException; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.List; import lombok.RequiredArgsConstructor; import org.apache.fineract.cob.data.LoanCOBParameter; @@ -30,12 +33,17 @@ import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; +import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; @RequiredArgsConstructor public class RetrieveAllNonClosedLoanIdServiceImpl implements RetrieveLoanIdService { + private static final Collection NON_CLOSED_LOAN_STATUSES = new ArrayList<>( + Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE, + LoanStatus.TRANSFER_IN_PROGRESS, LoanStatus.TRANSFER_ON_HOLD)); + private final LoanRepository loanRepository; private final NamedParameterJdbcTemplate namedParameterJdbcTemplate; @@ -69,30 +77,32 @@ public class RetrieveAllNonClosedLoanIdServiceImpl implements RetrieveLoanIdServ @Override public List retrieveLoanIdsBehindDate(LocalDate businessDate, List loanIds) { - return loanRepository.findAllNonClosedLoansBehindByLoanIds(businessDate, loanIds); + return loanRepository.findAllLoansBehindByLoanIdsAndStatuses(businessDate, loanIds, NON_CLOSED_LOAN_STATUSES); } @Override public List retrieveLoanIdsBehindDateOrNull(LocalDate businessDate, List loanIds) { - return loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(businessDate, loanIds); + return loanRepository.findAllLoansBehindOrNullByLoanIdsAndStatuses(businessDate, loanIds, NON_CLOSED_LOAN_STATUSES); } @Override public List retrieveLoanIdsOldestCobProcessed(LocalDate businessDate) { - return loanRepository.findOldestCOBProcessedLoan(businessDate); + return loanRepository.findOldestCOBProcessedLoan(businessDate, NON_CLOSED_LOAN_STATUSES); } @Override public List retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(LoanCOBParameter loanCOBParameter, boolean isCatchUp) { if (isCatchUp) { - return loanRepository.findAllNonClosedLoansByLastClosedBusinessDateNotNullAndMinAndMaxLoanId(loanCOBParameter.getMinLoanId(), - loanCOBParameter.getMaxLoanId(), ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE) - .minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND)); + return loanRepository.findAllLoansByLastClosedBusinessDateNotNullAndMinAndMaxLoanIdAndStatuses( + loanCOBParameter.getMinLoanId(), loanCOBParameter.getMaxLoanId(), ThreadLocalContextUtil + .getBusinessDateByType(BusinessDateType.COB_DATE).minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND), + NON_CLOSED_LOAN_STATUSES); } else { - return loanRepository.findAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter.getMinLoanId(), - loanCOBParameter.getMaxLoanId(), ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE) - .minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND)); + return loanRepository.findAllLoansByLastClosedBusinessDateAndMinAndMaxLoanIdAndStatuses( + loanCOBParameter.getMinLoanId(), loanCOBParameter.getMaxLoanId(), ThreadLocalContextUtil + .getBusinessDateByType(BusinessDateType.COB_DATE).minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND), + NON_CLOSED_LOAN_STATUSES); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java index ce5a25e82..a911a64db 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/service/InteropServiceImpl.java @@ -89,7 +89,7 @@ import org.apache.fineract.organisation.monetary.domain.Money; import org.apache.fineract.portfolio.account.exception.DifferentCurrenciesException; import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData; import org.apache.fineract.portfolio.loanaccount.domain.Loan; -import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException; import org.apache.fineract.portfolio.note.domain.Note; import org.apache.fineract.portfolio.note.domain.NoteRepository; @@ -128,7 +128,7 @@ public class InteropServiceImpl implements InteropService { private final NoteRepository noteRepository; private final PaymentTypeRepository paymentTypeRepository; private final InteropIdentifierRepository identifierRepository; - private final LoanRepository loanRepository; + private final LoanRepositoryWrapper loanRepositoryWrapper; private final SavingsHelper savingsHelper; private final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper; @@ -556,7 +556,7 @@ public class InteropServiceImpl implements InteropService { } private Loan validateAndGetLoan(String accountId) { - Loan loan = loanRepository.findNonClosedLoanByAccountNumber(accountId); + Loan loan = loanRepositoryWrapper.findNonClosedLoanByAccountNumber(accountId); if (loan == null) { throw new LoanNotFoundException(accountId); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/interoperation/starter/InteroperationConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/interoperation/starter/InteroperationConfiguration.java index 3f3da24ae..325baf588 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/interoperation/starter/InteroperationConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/interoperation/starter/InteroperationConfiguration.java @@ -28,7 +28,7 @@ import org.apache.fineract.interoperation.service.InteropService; import org.apache.fineract.interoperation.service.InteropServiceImpl; import org.apache.fineract.organisation.monetary.domain.ApplicationCurrencyRepository; import org.apache.fineract.portfolio.loanaccount.data.LoanAccountData; -import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; +import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; import org.apache.fineract.portfolio.note.domain.NoteRepository; import org.apache.fineract.portfolio.paymenttype.domain.PaymentTypeRepository; import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepository; @@ -49,14 +49,15 @@ public class InteroperationConfiguration { public InteropService interopService(PlatformSecurityContext securityContext, InteropDataValidator interopDataValidator, SavingsAccountRepository savingsAccountRepository, SavingsAccountTransactionRepository savingsAccountTransactionRepository, ApplicationCurrencyRepository applicationCurrencyRepository, NoteRepository noteRepository, - PaymentTypeRepository paymentTypeRepository, InteropIdentifierRepository identifierRepository, LoanRepository loanRepository, - SavingsHelper savingsHelper, SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper, + PaymentTypeRepository paymentTypeRepository, InteropIdentifierRepository identifierRepository, + LoanRepositoryWrapper loanRepositoryWrapper, SavingsHelper savingsHelper, + SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper, SavingsAccountDomainService savingsAccountService, JdbcTemplate jdbcTemplate, PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, DefaultToApiJsonSerializer toApiJsonSerializer, DatabaseSpecificSQLGenerator sqlGenerator) { return new InteropServiceImpl(securityContext, interopDataValidator, savingsAccountRepository, savingsAccountTransactionRepository, - applicationCurrencyRepository, noteRepository, paymentTypeRepository, identifierRepository, loanRepository, savingsHelper, - savingsAccountTransactionSummaryWrapper, savingsAccountService, jdbcTemplate, commandsSourceWritePlatformService, - toApiJsonSerializer, sqlGenerator); + applicationCurrencyRepository, noteRepository, paymentTypeRepository, identifierRepository, loanRepositoryWrapper, + savingsHelper, savingsAccountTransactionSummaryWrapper, savingsAccountService, jdbcTemplate, + commandsSourceWritePlatformService, toApiJsonSerializer, sqlGenerator); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarInstanceRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarInstanceRepository.java index bbce01c36..2ec0fae95 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarInstanceRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/domain/CalendarInstanceRepository.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.fineract.portfolio.client.domain.Client; import org.apache.fineract.portfolio.group.domain.Group; import org.apache.fineract.portfolio.loanaccount.domain.Loan; +import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; import org.apache.fineract.portfolio.savings.domain.SavingsAccount; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; @@ -52,15 +53,16 @@ public interface CalendarInstanceRepository extends JpaRepository findByCalendarIdAndEntityTypeId(Long calendarId, Integer entityTypeId); /** Should use in clause, can I do it without creating a new class? **/ - @Query("select ci from CalendarInstance ci where ci.entityId in (select loan.id from Loan loan where loan.client.id = :clientId and loan.group.id = :groupId and (loan.loanStatus = 100 or loan.loanStatus = 200 or loan.loanStatus = 300)) and ci.entityTypeId = 3") - List findCalendarInstancesForActiveLoansByGroupIdAndClientId(@Param("groupId") Long groupId, - @Param("clientId") Long clientId); + @Query("select ci from CalendarInstance ci where ci.entityId in (select loan.id from Loan loan where loan.client.id = :clientId and loan.group.id = :groupId and loan.loanStatus in :loanStatuses) and ci.entityTypeId = 3") + List findCalendarInstancesForLoansByGroupIdAndClientIdAndStatuses(@Param("groupId") Long groupId, + @Param("clientId") Long clientId, @Param("loanStatuses") Collection loanStatuses); /** * EntityType = 3 is for loan */ @Query("SELECT COUNT(ci.id) FROM CalendarInstance ci, Loan loan WHERE loan.id = ci.entityId AND ci.entityTypeId = 3 AND ci.calendar.id = :calendarId AND loan.loanStatus IN :loanStatuses ") - Integer countOfLoansSyncedWithCalendar(@Param("calendarId") Long calendarId, @Param("loanStatuses") Collection loanStatuses); + Integer countOfLoansSyncedWithCalendar(@Param("calendarId") Long calendarId, + @Param("loanStatuses") Collection loanStatuses); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java index a61ac9638..63176405b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/calendar/service/CalendarWritePlatformServiceJpaRepositoryImpl.java @@ -196,8 +196,8 @@ public class CalendarWritePlatformServiceJpaRepositoryImpl implements CalendarWr Boolean areActiveEntitiesSynced = false; final Long calendarId = command.entityId(); - final Collection loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(), - LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue())); + final Collection loanStatuses = new ArrayList<>( + Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE)); final Integer numberOfActiveLoansSyncedWithThisCalendar = this.calendarInstanceRepository.countOfLoansSyncedWithCalendar(calendarId, loanStatuses); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java index 95ca92eda..21ac0cced 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java @@ -1065,7 +1065,7 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { private void handleForeClosureTransactions(final Loan loan, final LoanTransaction repaymentTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine, final ScheduleGeneratorDTO scheduleGeneratorDTO) { - loan.setLoanSubStatus(LoanSubStatus.FORECLOSED.getValue()); + loan.setLoanSubStatus(LoanSubStatus.FORECLOSED); loanDownPaymentHandlerService.handleRepaymentOrRecoveryOrWaiverTransaction(loan, repaymentTransaction, loanLifecycleStateMachine, null, scheduleGeneratorDTO); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/accrualactivityposting/AccrualActivityPostingTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/accrualactivityposting/AccrualActivityPostingTasklet.java index 58edf038d..8b721deed 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/accrualactivityposting/AccrualActivityPostingTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/accrualactivityposting/AccrualActivityPostingTasklet.java @@ -27,6 +27,8 @@ import lombok.extern.slf4j.Slf4j; import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException; import org.apache.fineract.portfolio.loanaccount.domain.LoanAccrualActivityRepository; +import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; +import org.apache.fineract.portfolio.loanaccount.domain.LoanTransactionType; import org.apache.fineract.portfolio.loanaccount.service.LoanAccrualActivityProcessingService; import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.scope.context.ChunkContext; @@ -46,7 +48,8 @@ public class AccrualActivityPostingTasklet implements Tasklet { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { final LocalDate yesterday = DateUtils.getBusinessLocalDate().minusDays(1); List errors = new ArrayList<>(); - Set loanAccounts = loanAccrualActivityRepository.fetchLoanIdsForAccrualActivityPosting(yesterday); + Set loanAccounts = loanAccrualActivityRepository.fetchLoanIdsForAccrualActivityPosting(yesterday, + LoanTransactionType.ACCRUAL_ACTIVITY, LoanStatus.ACTIVE); for (Long accountId : loanAccounts) { try { loanAccrualActivityProcessingService.makeAccrualActivityTransaction(accountId, yesterday); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/applyholidaystoloans/ApplyHolidaysToLoansTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/applyholidaystoloans/ApplyHolidaysToLoansTasklet.java index 690004ada..76cb3eb1a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/applyholidaystoloans/ApplyHolidaysToLoansTasklet.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/jobs/applyholidaystoloans/ApplyHolidaysToLoansTasklet.java @@ -68,8 +68,8 @@ public class ApplyHolidaysToLoansTasklet implements Tasklet { return RepeatStatus.FINISHED; } - final Collection loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(), - LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue())); + final Collection loanStatuses = new ArrayList<>( + Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE)); final List holidays = holidayRepository.findUnprocessed(); for (final Holiday holiday : holidays) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationValidator.java index c3e5741e9..e7d204bb4 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanApplicationValidator.java @@ -210,7 +210,7 @@ public final class LoanApplicationValidator { expectedFirstRepaymentOnDate); } - validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType(), + validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType().getValue(), loan.repaymentScheduleDetail().getNumberOfRepayments(), loan.repaymentScheduleDetail().getRepayEvery(), loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType().getValue(), loan); } @@ -224,7 +224,7 @@ public final class LoanApplicationValidator { expectedFirstRepaymentOnDate); } - validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType(), + validateLoanTermAndRepaidEveryValues(loan.getTermFrequency(), loan.getTermPeriodFrequencyType().getValue(), loan.repaymentScheduleDetail().getNumberOfRepayments(), loan.repaymentScheduleDetail().getRepayEvery(), loan.repaymentScheduleDetail().getRepaymentPeriodFrequencyType().getValue(), loan); } @@ -1850,11 +1850,9 @@ public final class LoanApplicationValidator { final Long clientId = this.fromApiJsonHelper.extractLongNamed(LoanApiConstants.clientIdParameterName, element); if (groupId != null) { - activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByGroup(groupId, - LoanStatus.ACTIVE.getValue()); + activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByGroup(groupId, LoanStatus.ACTIVE); } else { - activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByClient(clientId, - LoanStatus.ACTIVE.getValue()); + activeLoansLoanProductIds = this.loanRepositoryWrapper.findActiveLoansLoanProductIdsByClient(clientId, LoanStatus.ACTIVE); } checkForProductMixRestrictions(activeLoansLoanProductIds, productId); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/CommonLoanSummaryDataProvider.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/CommonLoanSummaryDataProvider.java index 10b1ffcbb..bda2bf37b 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/CommonLoanSummaryDataProvider.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/CommonLoanSummaryDataProvider.java @@ -56,40 +56,36 @@ public abstract class CommonLoanSummaryDataProvider implements LoanSummaryDataPr BigDecimal totalUnpaidPayableDueInterest = BigDecimal.ZERO; BigDecimal totalUnpaidPayableNotDueInterest = BigDecimal.ZERO; - totalChargeAdjustment = fetchLoanTransactionBalanceByType(loanTransactionBalances, - LoanTransactionType.CHARGE_ADJUSTMENT.getValue()); + totalChargeAdjustment = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.CHARGE_ADJUSTMENT); totalChargeAdjustmentReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances, - LoanTransactionType.CHARGE_ADJUSTMENT.getValue()); + LoanTransactionType.CHARGE_ADJUSTMENT); - totalChargeback = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.CHARGEBACK.getValue()); + totalChargeback = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.CHARGEBACK); - totalCreditBalanceRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, - LoanTransactionType.CREDIT_BALANCE_REFUND.getValue()); + totalCreditBalanceRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.CREDIT_BALANCE_REFUND); totalCreditBalanceRefundReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances, - LoanTransactionType.CREDIT_BALANCE_REFUND.getValue()); + LoanTransactionType.CREDIT_BALANCE_REFUND); - totalGoodwillCredit = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.GOODWILL_CREDIT.getValue()); + totalGoodwillCredit = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.GOODWILL_CREDIT); totalGoodwillCreditReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances, - LoanTransactionType.GOODWILL_CREDIT.getValue()); + LoanTransactionType.GOODWILL_CREDIT); - totalInterestRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.INTEREST_REFUND.getValue()); + totalInterestRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.INTEREST_REFUND); totalInterestPaymentWaiver = fetchLoanTransactionBalanceByType(loanTransactionBalances, - LoanTransactionType.INTEREST_PAYMENT_WAIVER.getValue()); + LoanTransactionType.INTEREST_PAYMENT_WAIVER); - totalMerchantRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, - LoanTransactionType.MERCHANT_ISSUED_REFUND.getValue()); + totalMerchantRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.MERCHANT_ISSUED_REFUND); totalMerchantRefundReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances, - LoanTransactionType.MERCHANT_ISSUED_REFUND.getValue()); + LoanTransactionType.MERCHANT_ISSUED_REFUND); - totalPayoutRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.PAYOUT_REFUND.getValue()); - totalPayoutRefundReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances, - LoanTransactionType.PAYOUT_REFUND.getValue()); + totalPayoutRefund = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.PAYOUT_REFUND); + totalPayoutRefundReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances, LoanTransactionType.PAYOUT_REFUND); - totalRepaymentTransaction = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.REPAYMENT.getValue()) - .add(fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.DOWN_PAYMENT.getValue())); + totalRepaymentTransaction = fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.REPAYMENT) + .add(fetchLoanTransactionBalanceByType(loanTransactionBalances, LoanTransactionType.DOWN_PAYMENT)); totalRepaymentTransactionReversed = fetchLoanTransactionBalanceReversedByType(loanTransactionBalances, - LoanTransactionType.REPAYMENT.getValue()); + LoanTransactionType.REPAYMENT); if (repaymentSchedule != null) { // Outstanding Interest on Past due installments @@ -142,14 +138,14 @@ public abstract class CommonLoanSummaryDataProvider implements LoanSummaryDataPr } private static BigDecimal fetchLoanTransactionBalanceByType(final Collection loanTransactionBalances, - final Integer transactionType) { + final LoanTransactionType transactionType) { final Optional optLoanTransactionBalance = loanTransactionBalances.stream() .filter(balance -> balance.getTransactionType().equals(transactionType) && !balance.isReversed()).findFirst(); return optLoanTransactionBalance.isPresent() ? optLoanTransactionBalance.get().getAmount() : BigDecimal.ZERO; } private static BigDecimal fetchLoanTransactionBalanceReversedByType(final Collection loanTransactionBalances, - final Integer transactionType) { + final LoanTransactionType transactionType) { final Optional optLoanTransactionBalance = loanTransactionBalances.stream() .filter(balance -> balance.getTransactionType().equals(transactionType) && balance.isReversed() && balance.isManuallyAdjustedOrReversed()) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java index c837a63db..40e65e437 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualActivityProcessingServiceImpl.java @@ -147,8 +147,8 @@ public class LoanAccrualActivityProcessingServiceImpl implements LoanAccrualActi if (MathUtil.isGreaterThanZero(feeChargesPortion) || MathUtil.isGreaterThanZero(penaltyChargesPortion) || MathUtil.isGreaterThanZero(interestPortion)) { BigDecimal transactionAmount = MathUtil.add(feeChargesPortion, penaltyChargesPortion, interestPortion); - LoanTransaction newActivity = new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.ACCRUAL_ACTIVITY.getValue(), - closureDate, transactionAmount, null, interestPortion, feeChargesPortion, penaltyChargesPortion, null, false, null, + LoanTransaction newActivity = new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.ACCRUAL_ACTIVITY, closureDate, + transactionAmount, null, interestPortion, feeChargesPortion, penaltyChargesPortion, null, false, null, externalIdFactory.create()); makeAccrualActivityTransaction(loan, newActivity); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java index 29008d011..ac399c918 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAccrualsProcessingServiceImpl.java @@ -106,7 +106,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing @Override @Transactional public void addPeriodicAccruals(@NotNull LocalDate tillDate) throws JobExecutionException { - List loans = loanRepositoryWrapper.findLoansForPeriodicAccrual(AccountingRuleType.ACCRUAL_PERIODIC.getValue(), tillDate, + List loans = loanRepositoryWrapper.findLoansForPeriodicAccrual(AccountingRuleType.ACCRUAL_PERIODIC, tillDate, !isChargeOnDueDate()); List errors = new ArrayList<>(); for (Loan loan : loans) { @@ -141,7 +141,7 @@ public class LoanAccrualsProcessingServiceImpl implements LoanAccrualsProcessing @Override @Transactional public void addAccruals(@NotNull LocalDate tillDate) throws JobExecutionException { - List loans = loanRepositoryWrapper.findLoansForAddAccrual(AccountingRuleType.ACCRUAL_PERIODIC.getValue(), tillDate, + List loans = loanRepositoryWrapper.findLoansForAddAccrual(AccountingRuleType.ACCRUAL_PERIODIC, tillDate, !isChargeOnDueDate()); List errors = new ArrayList<>(); for (Loan loan : loans) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssemblerImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssemblerImpl.java index d56285305..64656b1a2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssemblerImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssemblerImpl.java @@ -61,6 +61,7 @@ import org.apache.fineract.portfolio.charge.domain.Charge; import org.apache.fineract.portfolio.client.domain.Client; import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper; import org.apache.fineract.portfolio.collateralmanagement.service.LoanCollateralAssembler; +import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType; import org.apache.fineract.portfolio.fund.domain.Fund; import org.apache.fineract.portfolio.fund.domain.FundRepository; import org.apache.fineract.portfolio.fund.exception.FundNotFoundException; @@ -720,10 +721,10 @@ public class LoanAssemblerImpl implements LoanAssembler { } if (command.isChangeInIntegerParameterNamed(LoanApiConstants.loanTermFrequencyTypeParameterName, - loan.getTermPeriodFrequencyType())) { + loan.getTermPeriodFrequencyType().getValue())) { final Integer newValue = command.integerValueOfParameterNamed(LoanApiConstants.loanTermFrequencyTypeParameterName); changes.put(LoanApiConstants.loanTermFrequencyTypeParameterName, newValue); - loan.setTermPeriodFrequencyType(newValue); + loan.setTermPeriodFrequencyType(PeriodFrequencyType.fromInt(newValue)); } if (command.isChangeInBigDecimalParameterNamed(LoanApiConstants.principalParameterName, loan.getApprovedPrincipal())) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionAssembler.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionAssembler.java index 11f60232a..cc8004727 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionAssembler.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanTransactionAssembler.java @@ -78,8 +78,8 @@ public class LoanTransactionAssembler { BigDecimal penaltyChargesPortion = installment.getPenaltyCharges(); BigDecimal transactionAmount = MathUtil.add(interestPortion, feeChargesPortion, penaltyChargesPortion); return MathUtil.isGreaterThanZero(transactionAmount) - ? new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.ACCRUAL_ACTIVITY.getValue(), transactionDate, - transactionAmount, null, interestPortion, feeChargesPortion, penaltyChargesPortion, null, false, null, externalId) + ? new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.ACCRUAL_ACTIVITY, transactionDate, transactionAmount, + null, interestPortion, feeChargesPortion, penaltyChargesPortion, null, false, null, externalId) : null; } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index dc689e91b..018c9255c 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -1003,7 +1003,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf loan.setClosedOnDate(transactionDate); loan.setActualMaturityDate(transactionDate); loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, loan); - } else if (LoanStatus.fromInt(loan.getLoanStatus()).isOverpaid()) { + } else if (loan.getLoanStatus().isOverpaid()) { if (loan.getTotalOverpaid() == null || BigDecimal.ZERO.compareTo(loan.getTotalOverpaid()) == 0) { loan.setOverpaidOnDate(null); } @@ -1306,8 +1306,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf .orElseThrow(() -> new LoanTransactionNotFoundException(command.entityId(), command.getLoanId())); Loan loan = this.loanAssembler.assembleFrom(loanId); - if (loan.getStatus().isClosed() && loan.getLoanSubStatus() != null - && loan.getLoanSubStatus().equals(LoanSubStatus.FORECLOSED.getValue())) { + if (loan.getStatus().isClosed() && loan.getLoanSubStatus() != null && loan.getLoanSubStatus().equals(LoanSubStatus.FORECLOSED)) { final String defaultUserMessage = "The loan cannot reopened as it is foreclosed."; throw new LoanForeclosureException("loan.cannot.be.reopened.as.it.is.foreclosured", defaultUserMessage, loanId); } @@ -2067,9 +2066,9 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final WorkingDays workingDays = this.workingDaysRepository.findOne(); final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); - final Collection loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(), - LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue())); - final Collection loanTypes = new ArrayList<>(Arrays.asList(AccountType.GROUP.getValue(), AccountType.JLG.getValue())); + final Collection loanStatuses = new ArrayList<>( + Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE)); + final Collection loanTypes = new ArrayList<>(Arrays.asList(AccountType.GROUP, AccountType.JLG)); final Collection loanIds = new ArrayList<>(loanCalendarInstances.size()); // loop through loanCalendarInstances to get loan ids for (final CalendarInstance calendarInstance : loanCalendarInstances) { @@ -2134,10 +2133,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf if (loan.isGroupLoan()) { if (loan.loanProduct().isIncludeInBorrowerCycle()) { loansToUpdate = this.loanRepositoryWrapper.getGroupLoansToUpdateLoanCounter(loan.getCurrentLoanCounter(), loan.getGroupId(), - AccountType.GROUP.getValue()); + AccountType.GROUP); } else { loansToUpdate = this.loanRepositoryWrapper.getGroupLoansToUpdateLoanProductCounter(loan.getLoanProductLoanCounter(), - loan.getGroupId(), AccountType.GROUP.getValue()); + loan.getGroupId(), AccountType.GROUP); } } else { @@ -2162,7 +2161,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf if (loan.isGroupLoan()) { final List loansToUpdateForLoanCounter = this.loanRepositoryWrapper.getGroupLoansDisbursedAfter(actualDisbursementDate, - loan.getGroupId(), AccountType.GROUP.getValue()); + loan.getGroupId(), AccountType.GROUP); final Integer newLoanCounter = getNewGroupLoanCounter(loan); final Integer newLoanProductCounter = getNewGroupLoanProductCounter(loan); updateLoanCounter(loan, loansToUpdateForLoanCounter, newLoanCounter, newLoanProductCounter); @@ -2177,7 +2176,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private Integer getNewGroupLoanCounter(final Loan loan) { - Integer maxClientLoanCounter = this.loanRepositoryWrapper.getMaxGroupLoanCounter(loan.getGroupId(), AccountType.GROUP.getValue()); + Integer maxClientLoanCounter = this.loanRepositoryWrapper.getMaxGroupLoanCounter(loan.getGroupId(), AccountType.GROUP); if (maxClientLoanCounter == null) { maxClientLoanCounter = 1; } else { @@ -2189,7 +2188,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private Integer getNewGroupLoanProductCounter(final Loan loan) { Integer maxLoanProductLoanCounter = this.loanRepositoryWrapper.getMaxGroupLoanProductCounter(loan.loanProduct().getId(), - loan.getGroupId(), AccountType.GROUP.getValue()); + loan.getGroupId(), AccountType.GROUP); if (maxLoanProductLoanCounter == null) { maxLoanProductLoanCounter = 1; } else { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestRefundServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestRefundServiceImpl.java index 062d0b4b4..bbeccfae6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestRefundServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/ProgressiveLoanInterestRefundServiceImpl.java @@ -63,18 +63,16 @@ public class ProgressiveLoanInterestRefundServiceImpl implements InterestRefundS private static void simulateRepaymentForDisbursements(LoanTransaction lt, final AtomicReference refundFinal, List collect) { - collect.add(new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), lt.getTypeOf().getValue(), lt.getDateOf(), lt.getAmount(), + collect.add(new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), lt.getTypeOf(), lt.getDateOf(), lt.getAmount(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null)); if (lt.getTypeOf().isDisbursement() && MathUtil.isGreaterThanZero(refundFinal.get())) { if (lt.getAmount().compareTo(refundFinal.get()) <= 0) { - collect.add( - new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), REPAYMENT.getValue(), lt.getDateOf(), lt.getAmount(), - BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null)); + collect.add(new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), REPAYMENT, lt.getDateOf(), lt.getAmount(), + BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null)); refundFinal.set(refundFinal.get().subtract(lt.getAmount())); } else { - collect.add( - new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), REPAYMENT.getValue(), lt.getDateOf(), refundFinal.get(), - BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null)); + collect.add(new LoanTransaction(lt.getLoan(), lt.getLoan().getOffice(), REPAYMENT, lt.getDateOf(), refundFinal.get(), + BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, false, null, null)); refundFinal.set(BigDecimal.ZERO); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reaging/LoanReAgingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reaging/LoanReAgingServiceImpl.java index bd8d32043..0f77393f6 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reaging/LoanReAgingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reaging/LoanReAgingServiceImpl.java @@ -176,8 +176,8 @@ public class LoanReAgingServiceImpl { Money txPrincipal = loan.getTotalPrincipalOutstandingUntil(transactionDate); BigDecimal txPrincipalAmount = txPrincipal.getAmount(); - return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.REAGE.getValue(), transactionDate, txPrincipalAmount, - txPrincipalAmount, ZERO, ZERO, ZERO, null, false, null, txExternalId); + return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.REAGE, transactionDate, txPrincipalAmount, txPrincipalAmount, + ZERO, ZERO, ZERO, null, false, null, txExternalId); } private LoanReAgeParameter createReAgeParameter(LoanTransaction reAgeTransaction, JsonCommand command) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java index ef85d3f1a..ea17d40e2 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/reamortization/LoanReAmortizationServiceImpl.java @@ -156,7 +156,7 @@ public class LoanReAmortizationServiceImpl { Money txPrincipal = loan.getTotalPrincipalOutstandingUntil(transactionDate); BigDecimal txPrincipalAmount = txPrincipal.getAmount(); - return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.REAMORTIZE.getValue(), transactionDate, txPrincipalAmount, + return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.REAMORTIZE, transactionDate, txPrincipalAmount, txPrincipalAmount, ZERO, ZERO, ZERO, null, false, null, txExternalId); } } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java index e8733e6be..d2e29d0ad 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java @@ -1704,8 +1704,8 @@ public final class LoanProductDataValidator { } if (actualValue) { Integer ruleType = accountingRuleType; - if (ruleType == null) { - ruleType = loanProduct.getAccountingRule(); + if (ruleType == null && loanProduct.getAccountingRule() != null) { + ruleType = loanProduct.getAccountingRule().getValue(); } if (!AccountingValidations.isAccrualBasedAccounting(ruleType)) { baseDataValidator.reset().parameter(LoanProductConstants.ENABLE_ACCRUAL_ACTIVITY_POSTING) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java index e0155dc74..cdd191aeb 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java @@ -22,6 +22,8 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import java.time.LocalDate; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.List; import lombok.RequiredArgsConstructor; import org.apache.fineract.infrastructure.core.api.JsonCommand; @@ -52,6 +54,7 @@ import org.apache.fineract.portfolio.group.exception.ClientNotInGroupException; import org.apache.fineract.portfolio.group.exception.GroupNotActiveException; import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepositoryWrapper; +import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus; import org.apache.fineract.portfolio.loanaccount.service.LoanOfficerService; import org.apache.fineract.portfolio.loanaccount.service.LoanWritePlatformService; import org.apache.fineract.portfolio.note.service.NoteWritePlatformService; @@ -151,8 +154,10 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr final CalendarInstance sourceGroupCalendarInstance = this.calendarInstanceRepository.findByEntityIdAndEntityTypeIdAndCalendarTypeId( sourceGroup.getId(), CalendarEntityType.GROUPS.getValue(), CalendarType.COLLECTION.getValue()); // get all customer loans synced with this group calendar Instance + final Collection activeLoanStatuses = new ArrayList<>( + Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE)); final List activeLoanCalendarInstances = this.calendarInstanceRepository - .findCalendarInstancesForActiveLoansByGroupIdAndClientId(sourceGroup.getId(), client.getId()); + .findCalendarInstancesForLoansByGroupIdAndClientIdAndStatuses(sourceGroup.getId(), client.getId(), activeLoanStatuses); /** * if a calendar is present in the source group along with loans synced with it, we should ensure that the diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java index 6299535e9..4e17fc342 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanAccountDelinquencyRangeEventSerializerTest.java @@ -337,7 +337,7 @@ public class LoanAccountDelinquencyRangeEventSerializerTest { delinquencyEffectivePauseHelper, configurationDomainService); Loan loan = Mockito.spy(Loan.class); - ReflectionTestUtils.setField(loan, "loanStatus", 300); + ReflectionTestUtils.setField(loan, "loanStatus", LoanStatus.ACTIVE); LoanTransaction transaction1 = Mockito.mock(LoanTransaction.class); LoanTransaction transaction2 = Mockito.mock(LoanTransaction.class); CollectionData collectionData = Mockito.mock(CollectionData.class); diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java index 037120297..593a37bd0 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java @@ -154,7 +154,7 @@ public class LoanDelinquencyDomainServiceTest { when(loanProductRelatedDetail.getGraceOnArrearsAgeing()).thenReturn(0); when(loan.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail); when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments); - when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK.getValue())) + when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK)) .thenReturn(Collections.emptyList()); when(loan.getLastLoanRepaymentScheduleInstallment()).thenReturn(repaymentScheduleInstallments.get(0)); when(loan.getCurrency()).thenReturn(currency); @@ -223,7 +223,7 @@ public class LoanDelinquencyDomainServiceTest { when(loanProductRelatedDetail.getGraceOnArrearsAgeing()).thenReturn(0); when(loan.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail); when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments); - when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK.getValue())) + when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK)) .thenReturn(Collections.emptyList()); when(loan.getLastLoanRepaymentScheduleInstallment()).thenReturn(repaymentScheduleInstallments.get(0)); when(loan.getCurrency()).thenReturn(currency); @@ -279,7 +279,7 @@ public class LoanDelinquencyDomainServiceTest { when(loan.isEnableInstallmentLevelDelinquency()).thenReturn(true); when(loan.getCurrency()).thenReturn(currency); when(loan.getStatus()).thenReturn(LoanStatus.ACTIVE); - when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK.getValue())) + when(loanTransactionReadService.fetchLoanTransactionsByType(loan.getId(), null, LoanTransactionType.CHARGEBACK)) .thenReturn(Arrays.asList(loanTransaction)); when(delinquencyEffectivePauseHelper.getPausedDaysBeforeDate(effectiveDelinquencyList, businessDate)).thenReturn(0L); diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachineTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachineTest.java index a93177cde..32ac828bf 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachineTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachineTest.java @@ -142,7 +142,6 @@ class DefaultLoanLifecycleStateMachineTest { Loan loan = Mockito.mock(Loan.class); LoanSummary loanSummary = Mockito.mock(LoanSummary.class); Mockito.when(loan.getCurrency()).thenReturn(currency); - Mockito.when(loan.getPlainStatus()).thenReturn(LoanStatus.OVERPAID.getValue()); Mockito.when(loan.getStatus()).thenReturn(LoanStatus.OVERPAID); Mockito.when(loan.getTotalOverpaidAsMoney()).thenReturn(zero); Mockito.when(loan.getSummary()).thenReturn(loanSummary); @@ -150,7 +149,7 @@ class DefaultLoanLifecycleStateMachineTest { // when underTest.transition(LoanEvent.LOAN_DISBURSED, loan); // then - verify(loan, Mockito.times(1)).setLoanStatus(LoanStatus.ACTIVE.getValue()); + verify(loan, Mockito.times(1)).setLoanStatus(LoanStatus.ACTIVE); verify(businessEventNotifierService).notifyPostBusinessEvent(any(LoanStatusChangedBusinessEvent.class)); } @@ -162,7 +161,6 @@ class DefaultLoanLifecycleStateMachineTest { Loan loan = Mockito.mock(Loan.class); LoanSummary loanSummary = Mockito.mock(LoanSummary.class); Mockito.when(loan.getCurrency()).thenReturn(currency); - Mockito.when(loan.getPlainStatus()).thenReturn(LoanStatus.OVERPAID.getValue()); Mockito.when(loan.getStatus()).thenReturn(LoanStatus.OVERPAID); Mockito.when(loan.getTotalOverpaidAsMoney()).thenReturn(zero); Mockito.when(loan.getSummary()).thenReturn(loanSummary); @@ -170,7 +168,7 @@ class DefaultLoanLifecycleStateMachineTest { // when underTest.transition(LoanEvent.LOAN_DISBURSED, loan); // then - verify(loan, Mockito.times(1)).setLoanStatus(LoanStatus.CLOSED_OBLIGATIONS_MET.getValue()); + verify(loan, Mockito.times(1)).setLoanStatus(LoanStatus.CLOSED_OBLIGATIONS_MET); verify(businessEventNotifierService).notifyPostBusinessEvent(any(LoanStatusChangedBusinessEvent.class)); } @@ -179,13 +177,12 @@ class DefaultLoanLifecycleStateMachineTest { // given Money overpayment = Money.of(new MonetaryCurrency("USD", 2, null), BigDecimal.TEN); Loan loan = Mockito.mock(Loan.class); - Mockito.when(loan.getPlainStatus()).thenReturn(LoanStatus.OVERPAID.getValue()); Mockito.when(loan.getStatus()).thenReturn(LoanStatus.OVERPAID); Mockito.when(loan.getTotalOverpaidAsMoney()).thenReturn(overpayment); // when underTest.transition(LoanEvent.LOAN_DISBURSED, loan); // then - verify(loan, Mockito.never()).setLoanStatus(LoanStatus.ACTIVE.getValue()); + verify(loan, Mockito.never()).setLoanStatus(LoanStatus.ACTIVE); verify(businessEventNotifierService, Mockito.never()).notifyPostBusinessEvent(any(LoanStatusChangedBusinessEvent.class)); } @@ -422,9 +419,7 @@ class DefaultLoanLifecycleStateMachineTest { private Loan createLoanWithStatus(LoanStatus status) { Loan result = new Loan(); - if (status != null) { - result.setLoanStatus(status.getValue()); - } + result.setLoanStatus(status); return result; } } diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTest.java index 6b3d6054c..e0f725be5 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTest.java @@ -208,40 +208,40 @@ public class LoanTest { LoanTransaction lt1 = new LoanTransaction(); ReflectionTestUtils.setField(lt1, "id", 1L); - ReflectionTestUtils.setField(lt1, "typeOf", LoanTransactionType.DISBURSEMENT.getValue()); + ReflectionTestUtils.setField(lt1, "typeOf", LoanTransactionType.DISBURSEMENT); ReflectionTestUtils.setField(lt1, "dateOf", today); ReflectionTestUtils.setField(lt1, "createdDate", now); LoanTransaction lt2 = new LoanTransaction(); ReflectionTestUtils.setField(lt2, "id", 2L); - ReflectionTestUtils.setField(lt2, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue()); + ReflectionTestUtils.setField(lt2, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER); ReflectionTestUtils.setField(lt2, "dateOf", today); ReflectionTestUtils.setField(lt2, "createdDate", now); LoanTransaction lt3 = new LoanTransaction(); ReflectionTestUtils.setField(lt3, "id", 3L); - ReflectionTestUtils.setField(lt3, "typeOf", LoanTransactionType.REPAYMENT.getValue()); + ReflectionTestUtils.setField(lt3, "typeOf", LoanTransactionType.REPAYMENT); ReflectionTestUtils.setField(lt3, "dateOf", today); ReflectionTestUtils.setField(lt3, "createdDate", now); ReflectionTestUtils.setField(lt3, "reversed", true); LoanTransaction lt4 = new LoanTransaction(); ReflectionTestUtils.setField(lt4, "id", 4L); - ReflectionTestUtils.setField(lt4, "typeOf", LoanTransactionType.WAIVE_INTEREST.getValue()); + ReflectionTestUtils.setField(lt4, "typeOf", LoanTransactionType.WAIVE_INTEREST); ReflectionTestUtils.setField(lt4, "dateOf", today); ReflectionTestUtils.setField(lt4, "createdDate", now); LoanTransaction lt5 = new LoanTransaction(); ReflectionTestUtils.setField(lt5, "id", 5L); - ReflectionTestUtils.setField(lt5, "typeOf", LoanTransactionType.INCOME_POSTING.getValue()); + ReflectionTestUtils.setField(lt5, "typeOf", LoanTransactionType.INCOME_POSTING); ReflectionTestUtils.setField(lt5, "dateOf", today); ReflectionTestUtils.setField(lt5, "createdDate", now); LoanTransaction lt6 = new LoanTransaction(); - ReflectionTestUtils.setField(lt6, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue()); + ReflectionTestUtils.setField(lt6, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER); ReflectionTestUtils.setField(lt6, "dateOf", today.minusDays(2)); LoanTransaction lt7 = new LoanTransaction(); ReflectionTestUtils.setField(lt7, "id", 7L); - ReflectionTestUtils.setField(lt7, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue()); + ReflectionTestUtils.setField(lt7, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER); ReflectionTestUtils.setField(lt7, "dateOf", today.minusDays(2)); LoanTransaction lt8 = new LoanTransaction(); ReflectionTestUtils.setField(lt8, "id", 8L); - ReflectionTestUtils.setField(lt8, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER.getValue()); + ReflectionTestUtils.setField(lt8, "typeOf", LoanTransactionType.WITHDRAW_TRANSFER); ReflectionTestUtils.setField(lt8, "dateOf", today.minusDays(2)); ReflectionTestUtils.setField(lt8, "createdDate", now.minusMinutes(2));