You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ad...@apache.org on 2025/03/20 13:34:57 UTC

(fineract) branch develop updated: FINERACT-2080: use enums instead of integers in Loan, LoanProduct and LoanTransaction

This is an automated email from the ASF dual-hosted git repository.

adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new 993393b519 FINERACT-2080: use enums instead of integers in Loan, LoanProduct and LoanTransaction
993393b519 is described below

commit 993393b519dd6a9f4288ebb05fb234db565db125
Author: mark.vituska <vi...@gmail.com>
AuthorDate: Tue Mar 18 13:51:43 2025 +0100

    FINERACT-2080: use enums instead of integers in Loan, LoanProduct and LoanTransaction
---
 ...ductToGLAccountMappingWritePlatformService.java |   3 +-
 .../ExternalAssetOwnersWriteServiceImpl.java       |   4 +-
 .../ExternalAssetOwnersWriteServiceTest.java       |  10 +-
 .../cob/data/LoanDataForExternalTransfer.java      |   3 +-
 .../service/LoanDelinquencyDomainServiceImpl.java  |   4 +-
 .../InterestPauseWritePlatformServiceImpl.java     |   2 +-
 .../loanaccount/api/LoanApiConstants.java          |  20 ++--
 .../loanaccount/data/LoanStatusEnumData.java       |   2 +-
 .../loanaccount/data/LoanTransactionBalance.java   |   3 +-
 .../AccountingRuleTypeConverter.java}              |  23 ++--
 .../domain/DefaultLoanLifecycleStateMachine.java   |   8 +-
 .../portfolio/loanaccount/domain/Loan.java         |  42 +++----
 .../domain/LoanAccrualActivityRepository.java      |   5 +-
 ...LoanRepaymentScheduleInstallmentRepository.java |   4 +-
 .../loanaccount/domain/LoanRepository.java         | 125 +++++++++++----------
 .../loanaccount/domain/LoanRepositoryWrapper.java  |  59 ++++++----
 .../LoanStatusConverter.java}                      |  22 ++--
 .../LoanSubStatusConverter.java}                   |  22 ++--
 .../domain/LoanSummaryBalancesRepository.java      |   2 +-
 .../loanaccount/domain/LoanTransaction.java        |  47 ++++----
 .../domain/LoanTransactionRepository.java          |   4 +-
 .../LoanTransactionTypeConverter.java}             |  22 ++--
 .../SetLoanDelinquencyTagsTasklet.java             |   6 +-
 .../LoanApplicationTransitionValidator.java        |   4 +-
 .../service/LoanTransactionReadService.java        |   8 +-
 .../portfolio/loanproduct/domain/LoanProduct.java  |  19 ++--
 ...ToGLAccountMappingWritePlatformServiceImpl.java |   3 +-
 .../RetrieveAllNonClosedLoanIdServiceImpl.java     |  28 +++--
 .../interoperation/service/InteropServiceImpl.java |   6 +-
 .../starter/InteroperationConfiguration.java       |  13 ++-
 .../domain/CalendarInstanceRepository.java         |  10 +-
 ...endarWritePlatformServiceJpaRepositoryImpl.java |   4 +-
 .../domain/LoanAccountDomainServiceJpa.java        |   2 +-
 .../AccrualActivityPostingTasklet.java             |   5 +-
 .../ApplyHolidaysToLoansTasklet.java               |   4 +-
 .../serialization/LoanApplicationValidator.java    |  10 +-
 .../service/CommonLoanSummaryDataProvider.java     |  40 +++----
 .../LoanAccrualActivityProcessingServiceImpl.java  |   4 +-
 .../service/LoanAccrualsProcessingServiceImpl.java |   4 +-
 .../loanaccount/service/LoanAssemblerImpl.java     |   5 +-
 .../service/LoanTransactionAssembler.java          |   4 +-
 .../LoanWritePlatformServiceJpaRepositoryImpl.java |  21 ++--
 .../ProgressiveLoanInterestRefundServiceImpl.java  |  12 +-
 .../service/reaging/LoanReAgingServiceImpl.java    |   4 +-
 .../LoanReAmortizationServiceImpl.java             |   2 +-
 .../serialization/LoanProductDataValidator.java    |   4 +-
 ...nsferWritePlatformServiceJpaRepositoryImpl.java |   7 +-
 ...AccountDelinquencyRangeEventSerializerTest.java |   2 +-
 .../LoanDelinquencyDomainServiceTest.java          |   6 +-
 .../DefaultLoanLifecycleStateMachineTest.java      |  13 +--
 .../portfolio/loanaccount/domain/LoanTest.java     |  16 +--
 51 files changed, 375 insertions(+), 327 deletions(-)

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 1b11d4d064..d24a6e34dd 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<String, Object> updateLoanProductToGLAccountMapping(Long loanProductId, JsonCommand command, boolean accountingRuleChanged,
-            int accountingRuleTypeId);
+            AccountingRuleType accountingRuleTypeId);
 
     Map<String, Object> 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 d1712ebed0..0ba4f709cd 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 5edaaad9d2..71d910266e 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 e443d40655..4913293c2e 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 0158f8dad9..27edfa3419 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<LoanTransaction> 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<LoanTransaction> 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 003d1126f4..2a44bcc438 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 00506db2c3..db722dddee 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<Integer> 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<LoanTransactionType> 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 04ff5c9332..c47742f9ee 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 bd9b2016fa..0a3e5675da 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/data/LoanTransactionBalance.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/AccountingRuleTypeConverter.java
similarity index 55%
copy from fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionBalance.java
copy to fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/AccountingRuleTypeConverter.java
index bd9b2016fa..5faaef16e6 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/domain/AccountingRuleTypeConverter.java
@@ -16,17 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.fineract.portfolio.loanaccount.data;
+package org.apache.fineract.portfolio.loanaccount.domain;
 
-import java.math.BigDecimal;
-import lombok.Data;
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
+import org.apache.fineract.accounting.common.AccountingRuleType;
 
-@Data
-public class LoanTransactionBalance {
+@Converter(autoApply = true)
+public class AccountingRuleTypeConverter implements AttributeConverter<AccountingRuleType, Integer> {
 
-    private final Integer transactionType;
-    private final boolean reversed;
-    private final boolean manuallyAdjustedOrReversed;
-    private final BigDecimal amount;
+    @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 ccb056d827..76659ad30d 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 240bb33bbb..21c4fae08e 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<Long> {
     @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<Long> {
     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<Long> {
 
     @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<Long> {
         }
         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<Long> {
         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<Long> {
 
         // 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<Long> {
     }
 
     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<Long> {
     }
 
     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<Long> {
 
     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> disbursementData = new ArrayList<>();
@@ -2782,7 +2776,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
             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<Long> {
     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<Long> {
     }
 
     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 d30d4a75cb..07af9bb094 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<Loan, Long> {
 
-    @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<Long> 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<Long> 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 58c5698525..8cbf1748bb 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<LoanScheduleDelinquencyData> fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") Integer loanStatus,
+    Collection<LoanScheduleDelinquencyData> 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<LoanScheduleDelinquencyData> fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") Integer loanStatus,
+    Collection<LoanScheduleDelinquencyData> fetchLoanScheduleDataByDueDateAndObligationsMet(@Param("loanStatus") LoanStatus loanStatus,
             @Param("businessDate") LocalDate businessDate, @Param("obligationsMet") boolean obligationsMet,
             @Param("loanIds") List<Long> 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 128ffe153b..7e0a3afd27 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<Loan, Long>, 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<Loan, Long>, JpaSpecificat
 
     @Query(FIND_GROUP_LOANS_DISBURSED_AFTER)
     List<Loan> 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<Loan> 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<Loan, Long>, JpaSpecificat
 
     @Query(FIND_GROUP_LOANS_TO_UPDATE)
     List<Loan> 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<Loan> getClientOrJLGLoansToUpdateLoanCounter(@Param("loanCounter") Integer loanCounter, @Param("clientId") Long clientId);
 
     @Query(FIND_GROUP_LOANS_TO_UPDATE_LOANPRODUCT_COUNTER)
     List<Loan> 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<Loan> getClientLoansToUpdateLoanProductCounter(@Param("loanProductCounter") Integer loanProductCounter,
@@ -157,7 +159,7 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
 
     @Query("select loan from Loan loan where loan.client.id = :clientId and loan.group.id = :groupId and loan.loanStatus IN :loanStatuses")
     List<Loan> findByClientIdAndGroupIdAndLoanStatus(@Param("clientId") Long clientId, @Param("groupId") Long groupId,
-            @Param("loanStatuses") Collection<Integer> loanStatuses);
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
 
     @Query("select loan from Loan loan where loan.client.id = :clientId")
     List<Loan> findLoanByClientId(@Param("clientId") Long clientId);
@@ -170,37 +172,41 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
 
     @Query("select loan from Loan loan where loan.id IN :ids and loan.loanStatus IN :loanStatuses and loan.loanType IN :loanTypes")
     List<Loan> findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection<Long> ids,
-            @Param("loanStatuses") Collection<Integer> loanStatuses, @Param("loanTypes") Collection<Integer> loanTypes);
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses, @Param("loanTypes") Collection<AccountType> loanTypes);
 
     @Query("select loan.id from Loan loan where loan.actualDisbursementDate > :disbursalDate order by loan.actualDisbursementDate")
     List<Long> getLoansDisbursedAfter(@Param("disbursalDate") LocalDate disbursalDate);
 
     @Query("select loan from Loan loan where loan.client.office.id IN :officeIds and loan.loanStatus IN :loanStatuses")
     List<Loan> findByClientOfficeIdsAndLoanStatus(@Param("officeIds") Collection<Long> officeIds,
-            @Param("loanStatuses") Collection<Integer> loanStatuses);
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
 
     @Query("select loan from Loan loan where loan.group.office.id IN :officeIds and loan.loanStatus IN :loanStatuses")
     List<Loan> findByGroupOfficeIdsAndLoanStatus(@Param("officeIds") Collection<Long> officeIds,
-            @Param("loanStatuses") Collection<Integer> loanStatuses);
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
 
     /*** FIXME: Add more appropriate names for the query ***/
     @Query(FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_CLIENT)
-    List<Long> findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") Integer loanStatus);
+    List<Long> findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") LoanStatus loanStatus);
 
     @Query(FIND_ACTIVE_LOANS_PRODUCT_IDS_BY_GROUP)
-    List<Long> findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") Integer loanStatus);
+    List<Long> 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<LoanStatus> 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<LoanStatus> 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<LoanStatus> 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<Loan, Long>, JpaSpecificat
     @Query(FIND_LOAN_DATA_FOR_EXTERNAL_TRANSFER)
     Optional<LoanDataForExternalTransfer> 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<LoanStatus> loanStatuses);
 
     boolean existsByExternalId(@Param("externalId") ExternalId externalId);
 
-    @Query(FIND_ALL_NON_CLOSED)
-    List<Long> findAllNonClosedLoanIds();
+    @Query(FIND_ALL_BY_STATUSES)
+    List<Long> findAllLoanIdsByStatuses(@Param("loanStatuses") Collection<LoanStatus> loanStatuses);
 
     @Query(FIND_ID_BY_EXTERNAL_ID)
     Long findIdByExternalId(@Param("externalId") ExternalId externalId);
@@ -222,38 +229,42 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
     @Query(FIND_IDS_BY_EXTERNAL_IDS)
     List<Long> findIdsByExternalIds(@Param("externalIds") List<ExternalId> externalIds);
 
-    @Query(FIND_ALL_NON_CLOSED_LOANS_BEHIND_BY_LOAN_IDS)
-    List<LoanIdAndLastClosedBusinessDate> findAllNonClosedLoansBehindByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate,
-            @Param("loanIds") List<Long> loanIds);
+    @Query(FIND_ALL_LOANS_BEHIND_BY_LOAN_IDS_AND_STATUSES)
+    List<LoanIdAndLastClosedBusinessDate> findAllLoansBehindByLoanIdsAndStatuses(@Param("cobBusinessDate") LocalDate cobBusinessDate,
+            @Param("loanIds") List<Long> loanIds, @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
 
-    @Query(FIND_ALL_NON_CLOSED_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS)
-    List<LoanIdAndLastClosedBusinessDate> findAllNonClosedLoansBehindOrNullByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate,
-            @Param("loanIds") List<Long> loanIds);
+    @Query(FIND_ALL_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS_AND_STATUSES)
+    List<LoanIdAndLastClosedBusinessDate> findAllLoansBehindOrNullByLoanIdsAndStatuses(@Param("cobBusinessDate") LocalDate cobBusinessDate,
+            @Param("loanIds") List<Long> loanIds, @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
 
-    @Query(FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_AND_MIN_AND_MAX_LOAN_ID)
-    List<Long> 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<Long> findAllLoansByLastClosedBusinessDateAndMinAndMaxLoanIdAndStatuses(@Param("minLoanId") Long minLoanId,
+            @Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate,
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
 
-    @Query(FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE_NOT_NULL_AND_MIN_AND_MAX_LOAN_ID)
-    List<Long> 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<Long> findAllLoansByLastClosedBusinessDateNotNullAndMinAndMaxLoanIdAndStatuses(@Param("minLoanId") Long minLoanId,
+            @Param("maxLoanId") Long maxLoanId, @Param("cobBusinessDate") LocalDate cobBusinessDate,
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
 
     @Query(FIND_OLDEST_COB_PROCESSED_LOAN)
-    List<LoanIdAndLastClosedBusinessDate> findOldestCOBProcessedLoan(@Param("cobBusinessDate") LocalDate cobBusinessDate);
+    List<LoanIdAndLastClosedBusinessDate> findOldestCOBProcessedLoan(@Param("cobBusinessDate") LocalDate cobBusinessDate,
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses);
 
     @Query(FIND_ALL_STAYED_LOCKED_BY_COB_BUSINESS_DATE)
     List<LoanIdAndExternalIdAndAccountNo> findAllStayedLockedByCobBusinessDate(@Param("cobBusinessDate") LocalDate cobBusinessDate);
 
-    @Query(FIND_ALL_LOAN_IDS_BY_STATUS_ID)
-    List<Long> findLoanIdByStatusId(@Param("statusId") Integer statusId);
+    @Query(FIND_ALL_LOAN_IDS_BY_STATUS)
+    List<Long> findLoanIdByStatus(@Param("loanStatus") LoanStatus loanStatus);
 
     @Query(FIND_LOANS_FOR_PERIODIC_ACCRUAL)
-    List<Loan> findLoansForPeriodicAccrual(@Param("accountingType") Integer accountingType, @Param("tillDate") LocalDate tillDate,
-            @Param("futureCharges") boolean futureCharges);
+    List<Loan> findLoansForPeriodicAccrual(@Param("accountingType") AccountingRuleType accountingType,
+            @Param("tillDate") LocalDate tillDate, @Param("futureCharges") boolean futureCharges,
+            @Param("loanStatus") LoanStatus loanStatus);
 
     @Query(FIND_LOANS_FOR_ADD_ACCRUAL)
-    List<Loan> findLoansForAddAccrual(@Param("accountingType") Integer accountingType, @Param("tillDate") LocalDate tillDate,
-            @Param("futureCharges") boolean futureCharges);
+    List<Loan> findLoansForAddAccrual(@Param("accountingType") AccountingRuleType accountingType, @Param("tillDate") LocalDate tillDate,
+            @Param("futureCharges") boolean futureCharges, @Param("loanStatus") LoanStatus loanStatus);
 
     @Query(FIND_LOAN_BY_EXTERNAL_ID)
     Optional<Loan> 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 f8669b4cc0..b00ecca58a 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<LoanStatus> 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<LoanStatus> 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<Loan> findActiveLoansByLoanIdAndGroupId(Long clientId, Long groupId) {
-        final Collection<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
-                LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue(), LoanStatus.OVERPAID.getValue()));
+        final Collection<LoanStatus> 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<Loan> 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<Loan> 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<Loan> 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<Loan> findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection<Long> ids,
-            @Param("loanStatuses") Collection<Integer> loanStatuses, @Param("loanTypes") Collection<Integer> loanTypes) {
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses, @Param("loanTypes") Collection<AccountType> loanTypes) {
         List<Loan> loans = new ArrayList<>();
         List<List<Long>> partitions = Lists.partition(ids.stream().toList(), fineractProperties.getQuery().getInClauseParameterSizeLimit());
         partitions
@@ -213,7 +222,7 @@ public class LoanRepositoryWrapper {
 
     // Repayments Schedule
     public List<Loan> findByClientOfficeIdsAndLoanStatus(@Param("officeIds") Collection<Long> officeIds,
-            @Param("loanStatuses") Collection<Integer> loanStatuses) {
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses) {
         List<Loan> 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<Loan> findByGroupOfficeIdsAndLoanStatus(@Param("officeIds") Collection<Long> officeIds,
-            @Param("loanStatuses") Collection<Integer> loanStatuses) {
+            @Param("loanStatuses") Collection<LoanStatus> loanStatuses) {
         List<Loan> 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<Long> findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") Integer loanStatus) {
+    public List<Long> findActiveLoansLoanProductIdsByClient(@Param("clientId") Long clientId, @Param("loanStatus") LoanStatus loanStatus) {
         return this.repository.findActiveLoansLoanProductIdsByClient(clientId, loanStatus);
     }
 
-    public List<Long> findActiveLoansLoanProductIdsByGroup(@Param("groupId") Long groupId, @Param("loanStatus") Integer loanStatus) {
+    public List<Long> 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<Long> 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<Long> findLoanIdsByStatusId(Integer statusId) {
-        return repository.findLoanIdByStatusId(statusId);
+        return repository.findLoanIdByStatus(LoanStatus.fromInt(statusId));
     }
 
-    public List<Loan> findLoansForPeriodicAccrual(Integer accountingType, LocalDate tillDate, boolean futureCharges) {
-        return repository.findLoansForPeriodicAccrual(accountingType, tillDate, futureCharges);
+    public List<Loan> findLoansForPeriodicAccrual(AccountingRuleType accountingType, LocalDate tillDate, boolean futureCharges) {
+        return repository.findLoansForPeriodicAccrual(accountingType, tillDate, futureCharges, LoanStatus.ACTIVE);
     }
 
-    public List<Loan> findLoansForAddAccrual(Integer accountingType, LocalDate tillDate, boolean futureCharges) {
-        return repository.findLoansForAddAccrual(accountingType, tillDate, futureCharges);
+    public List<Loan> findLoansForAddAccrual(AccountingRuleType accountingType, LocalDate tillDate, boolean futureCharges) {
+        return repository.findLoansForAddAccrual(accountingType, tillDate, futureCharges, LoanStatus.ACTIVE);
     }
 
     public List<Long> findIdByExternalIds(List<ExternalId> externalIds) {
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/domain/LoanStatusConverter.java
similarity index 60%
copy from fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionBalance.java
copy to fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanStatusConverter.java
index bd9b2016fa..67f2afd1f6 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/domain/LoanStatusConverter.java
@@ -16,17 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.fineract.portfolio.loanaccount.data;
+package org.apache.fineract.portfolio.loanaccount.domain;
 
-import java.math.BigDecimal;
-import lombok.Data;
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
 
-@Data
-public class LoanTransactionBalance {
+@Converter(autoApply = true)
+public class LoanStatusConverter implements AttributeConverter<LoanStatus, Integer> {
 
-    private final Integer transactionType;
-    private final boolean reversed;
-    private final boolean manuallyAdjustedOrReversed;
-    private final BigDecimal amount;
+    @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/data/LoanTransactionBalance.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSubStatusConverter.java
similarity index 58%
copy from fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionBalance.java
copy to fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanSubStatusConverter.java
index bd9b2016fa..4ab55ebacd 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/domain/LoanSubStatusConverter.java
@@ -16,17 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.fineract.portfolio.loanaccount.data;
+package org.apache.fineract.portfolio.loanaccount.domain;
 
-import java.math.BigDecimal;
-import lombok.Data;
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
 
-@Data
-public class LoanTransactionBalance {
+@Converter(autoApply = true)
+public class LoanSubStatusConverter implements AttributeConverter<LoanSubStatus, Integer> {
 
-    private final Integer transactionType;
-    private final boolean reversed;
-    private final boolean manuallyAdjustedOrReversed;
-    private final BigDecimal amount;
+    @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 6890aa9890..d322938496 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<LoanTransactionBalance> retrieveLoanSummaryBalancesByTransactionType(final Long loanId,
-            final List<Integer> transactionTypes) {
+            final List<LoanTransactionType> transactionTypes) {
         CriteriaBuilder cb = entityManager.getCriteriaBuilder();
         CriteriaQuery<LoanTransactionBalance> 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 a83b9f8842..abf89be147 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<Long
     private PaymentDetail paymentDetail;
 
     @Column(name = "transaction_type_enum", nullable = false)
-    private Integer typeOf;
+    private LoanTransactionType typeOf;
 
     @Column(name = "transaction_date", nullable = false)
     private LocalDate dateOf;
@@ -145,13 +145,12 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
     public static LoanTransaction incomePosting(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
             final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
             final ExternalId externalId) {
-        final Integer typeOf = LoanTransactionType.INCOME_POSTING.getValue();
         final BigDecimal principalPortion = BigDecimal.ZERO;
         final BigDecimal overPaymentPortion = BigDecimal.ZERO;
         final boolean reversed = false;
         final PaymentDetail paymentDetail = null;
-        return new LoanTransaction(loan, office, typeOf, dateOf, amount, principalPortion, interestPortion, feeChargesPortion,
-                penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
+        return new LoanTransaction(loan, office, LoanTransactionType.INCOME_POSTING, dateOf, amount, principalPortion, interestPortion,
+                feeChargesPortion, penaltyChargesPortion, overPaymentPortion, reversed, paymentDetail, externalId);
     }
 
     public static LoanTransaction disbursement(final Loan loan, final Money amount, final PaymentDetail paymentDetail,
@@ -263,19 +262,19 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
     public static LoanTransaction accrueTransaction(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
             final BigDecimal interestPortion, final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion,
             final ExternalId externalId) {
-        return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL.getValue(), dateOf, amount, null, interestPortion,
-                feeChargesPortion, penaltyChargesPortion, null, false, null, externalId);
+        return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL, dateOf, amount, null, interestPortion, feeChargesPortion,
+                penaltyChargesPortion, null, false, null, externalId);
     }
 
     public static LoanTransaction accrualAdjustment(final Loan loan, final Office office, final LocalDate dateOf, final BigDecimal amount,
             final BigDecimal interestPortion, final BigDecimal feePortion, final BigDecimal penaltyPortion, final ExternalId externalId) {
-        return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL_ADJUSTMENT.getValue(), dateOf, amount, null, interestPortion,
-                feePortion, penaltyPortion, null, false, null, externalId);
+        return new LoanTransaction(loan, office, LoanTransactionType.ACCRUAL_ADJUSTMENT, dateOf, amount, null, interestPortion, feePortion,
+                penaltyPortion, null, false, null, externalId);
     }
 
     public static LoanTransaction initiateTransfer(final Office office, final Loan loan, final LocalDate transferDate,
             final ExternalId externalId) {
-        return new LoanTransaction(loan, office, LoanTransactionType.INITIATE_TRANSFER.getValue(), transferDate,
+        return new LoanTransaction(loan, office, LoanTransactionType.INITIATE_TRANSFER, transferDate,
                 loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
                 loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
                 loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, externalId);
@@ -283,7 +282,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
 
     public static LoanTransaction approveTransfer(final Office office, final Loan loan, final LocalDate transferDate,
             final ExternalId externalId) {
-        return new LoanTransaction(loan, office, LoanTransactionType.APPROVE_TRANSFER.getValue(), transferDate,
+        return new LoanTransaction(loan, office, LoanTransactionType.APPROVE_TRANSFER, transferDate,
                 loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
                 loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
                 loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, externalId);
@@ -291,7 +290,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
 
     public static LoanTransaction withdrawTransfer(final Office office, final Loan loan, final LocalDate transferDate,
             final ExternalId externalId) {
-        return new LoanTransaction(loan, office, LoanTransactionType.WITHDRAW_TRANSFER.getValue(), transferDate,
+        return new LoanTransaction(loan, office, LoanTransactionType.WITHDRAW_TRANSFER, transferDate,
                 loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(),
                 loan.getSummary().getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(),
                 loan.getSummary().getTotalPenaltyChargesOutstanding(), null, false, null, externalId);
@@ -326,8 +325,8 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
 
     public static LoanTransaction creditBalanceRefund(final Loan loan, final Office office, final Money amount, final LocalDate paymentDate,
             final ExternalId externalId, PaymentDetail paymentDetail) {
-        return new LoanTransaction(loan, office, LoanTransactionType.CREDIT_BALANCE_REFUND.getValue(), paymentDate, amount.getAmount(),
-                null, null, null, null, amount.getAmount(), false, paymentDetail, externalId);
+        return new LoanTransaction(loan, office, LoanTransactionType.CREDIT_BALANCE_REFUND, paymentDate, amount.getAmount(), null, null,
+                null, null, amount.getAmount(), false, paymentDetail, externalId);
     }
 
     public static LoanTransaction refundForActiveLoan(final Office office, final Money amount, final PaymentDetail paymentDetail,
@@ -339,8 +338,8 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
     public static LoanTransaction interestRefund(final Loan loan, final Office office, final BigDecimal amount, final BigDecimal principal,
             final BigDecimal interest, final BigDecimal feeCharges, final BigDecimal penaltyCharges, final PaymentDetail paymentDetail,
             final LocalDate refundDate, final ExternalId externalId) {
-        return new LoanTransaction(loan, office, LoanTransactionType.INTEREST_REFUND.getValue(), refundDate, amount, principal, interest,
-                feeCharges, penaltyCharges, amount, false, paymentDetail, externalId);
+        return new LoanTransaction(loan, office, LoanTransactionType.INTEREST_REFUND, refundDate, amount, principal, interest, feeCharges,
+                penaltyCharges, amount, false, paymentDetail, externalId);
     }
 
     public static boolean transactionAmountsMatch(final MonetaryCurrency currency, final LoanTransaction loanTransaction,
@@ -353,10 +352,10 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
                 && loanTransaction.getOverPaymentPortion(currency).isEqualTo(newLoanTransaction.getOverPaymentPortion(currency));
     }
 
-    public LoanTransaction(final Loan loan, final Office office, final Integer typeOf, final LocalDate dateOf, final BigDecimal amount,
-            final BigDecimal principalPortion, final BigDecimal interestPortion, final BigDecimal feeChargesPortion,
-            final BigDecimal penaltyChargesPortion, final BigDecimal overPaymentPortion, final boolean reversed,
-            final PaymentDetail paymentDetail, final ExternalId externalId) {
+    public LoanTransaction(final Loan loan, final Office office, final LoanTransactionType typeOf, final LocalDate dateOf,
+            final BigDecimal amount, final BigDecimal principalPortion, final BigDecimal interestPortion,
+            final BigDecimal feeChargesPortion, final BigDecimal penaltyChargesPortion, final BigDecimal overPaymentPortion,
+            final boolean reversed, final PaymentDetail paymentDetail, final ExternalId externalId) {
 
         this.loan = loan;
         this.typeOf = typeOf;
@@ -403,14 +402,14 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
                 : null;
         BigDecimal totalOutstanding = loan.getSummary().getTotalOutstanding();
 
-        return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.CHARGE_OFF.getValue(), chargeOffDate, totalOutstanding,
+        return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.CHARGE_OFF, chargeOffDate, totalOutstanding,
                 principalPortion, interestPortion, feePortion, penaltyPortion, null, false, null, externalId);
     }
 
     private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final BigDecimal amount,
             final LocalDate date, final ExternalId externalId) {
         this.loan = loan;
-        this.typeOf = type.getValue();
+        this.typeOf = type;
         this.amount = amount;
         this.dateOf = date;
         this.externalId = externalId;
@@ -421,7 +420,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
     private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final PaymentDetail paymentDetail,
             final BigDecimal amount, final LocalDate date, final ExternalId externalId) {
         this.loan = loan;
-        this.typeOf = type.getValue();
+        this.typeOf = type;
         this.paymentDetail = paymentDetail;
         this.amount = amount;
         this.dateOf = date;
@@ -433,7 +432,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
     private LoanTransaction(final Loan loan, final Office office, final LoanTransactionType type, final PaymentDetail paymentDetail,
             final BigDecimal amount, final LocalDate date, final ExternalId externalId, final String chargeRefundChargeType) {
         this.loan = loan;
-        this.typeOf = type.getValue();
+        this.typeOf = type;
         this.paymentDetail = paymentDetail;
         this.amount = amount;
         this.dateOf = date;
@@ -552,7 +551,7 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom<Long
     }
 
     public LoanTransactionType getTypeOf() {
-        return LoanTransactionType.fromInt(this.typeOf);
+        return this.typeOf == null ? LoanTransactionType.INVALID : this.typeOf;
     }
 
     public boolean isReversed() {
diff --git a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionRepository.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionRepository.java
index 9a48625b3f..9ffc62e3f1 100644
--- a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionRepository.java
+++ b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionRepository.java
@@ -49,8 +49,8 @@ public interface LoanTransactionRepository extends JpaRepository<LoanTransaction
             lt.loan.loanProduct.delinquencyBucket is not null
             GROUP BY lt.loan
             """)
-    Collection<LoanScheduleDelinquencyData> fetchLoanTransactionsByTypeAndLessOrEqualDate(@Param("transactionType") Integer transactionType,
-            @Param("businessDate") LocalDate businessDate);
+    Collection<LoanScheduleDelinquencyData> 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/data/LoanTransactionBalance.java b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionTypeConverter.java
similarity index 57%
copy from fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionBalance.java
copy to fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionTypeConverter.java
index bd9b2016fa..f15d27c540 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/domain/LoanTransactionTypeConverter.java
@@ -16,17 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.fineract.portfolio.loanaccount.data;
+package org.apache.fineract.portfolio.loanaccount.domain;
 
-import java.math.BigDecimal;
-import lombok.Data;
+import jakarta.persistence.AttributeConverter;
+import jakarta.persistence.Converter;
 
-@Data
-public class LoanTransactionBalance {
+@Converter(autoApply = true)
+public class LoanTransactionTypeConverter implements AttributeConverter<LoanTransactionType, Integer> {
 
-    private final Integer transactionType;
-    private final boolean reversed;
-    private final boolean manuallyAdjustedOrReversed;
-    private final BigDecimal amount;
+    @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 d1cd7ab392..ccf54f3dd0 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> loanScheduleDelinquencyData = this.loanTransactionRepository
-                .fetchLoanTransactionsByTypeAndLessOrEqualDate(LoanTransactionType.CHARGEBACK.getValue(), businessDate);
+                .fetchLoanTransactionsByTypeAndLessOrEqualDate(LoanTransactionType.CHARGEBACK, businessDate);
         List<Long> 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 34d40c7278..c2212a1aee 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 926caba722..f8a614bca3 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<LoanTransaction> fetchLoanTransactionsByType(final Long loanId, final String externalId, final Integer transactionType) {
-        final List<Integer> transactionTypes = new ArrayList<>();
+    public List<LoanTransaction> fetchLoanTransactionsByType(final Long loanId, final String externalId,
+            final LoanTransactionType transactionType) {
+        final List<LoanTransactionType> transactionTypes = new ArrayList<>();
         transactionTypes.add(transactionType);
         return fetchLoanTransactionsByTypes(loanId, externalId, transactionTypes);
     }
 
     public List<LoanTransaction> fetchLoanTransactionsByTypes(final Long loanId, final String externalId,
-            final List<Integer> transactionTypes) {
+            final List<LoanTransactionType> transactionTypes) {
 
         final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
         final CriteriaQuery<LoanTransaction> 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 c5792f700c..c010ae42be 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<Long> {
     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<Long> {
                 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<Long> {
         }
 
         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<Long> {
     }
 
     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 05d8a530c9..9bd1011074 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<String, Object> 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<String, Object> 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 d7fa9e07ff..b5c757ee31 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<LoanStatus> 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<LoanIdAndLastClosedBusinessDate> retrieveLoanIdsBehindDate(LocalDate businessDate, List<Long> loanIds) {
-        return loanRepository.findAllNonClosedLoansBehindByLoanIds(businessDate, loanIds);
+        return loanRepository.findAllLoansBehindByLoanIdsAndStatuses(businessDate, loanIds, NON_CLOSED_LOAN_STATUSES);
     }
 
     @Override
     public List<LoanIdAndLastClosedBusinessDate> retrieveLoanIdsBehindDateOrNull(LocalDate businessDate, List<Long> loanIds) {
-        return loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(businessDate, loanIds);
+        return loanRepository.findAllLoansBehindOrNullByLoanIdsAndStatuses(businessDate, loanIds, NON_CLOSED_LOAN_STATUSES);
     }
 
     @Override
     public List<LoanIdAndLastClosedBusinessDate> retrieveLoanIdsOldestCobProcessed(LocalDate businessDate) {
-        return loanRepository.findOldestCOBProcessedLoan(businessDate);
+        return loanRepository.findOldestCOBProcessedLoan(businessDate, NON_CLOSED_LOAN_STATUSES);
     }
 
     @Override
     public List<Long> 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 ce5a25e824..a911a64db8 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 3f3da24aee..325baf5884 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<LoanAccountData> 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 bbce01c365..2ec0fae95a 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<CalendarInstan
     Collection<CalendarInstance> 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<CalendarInstance> 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<CalendarInstance> findCalendarInstancesForLoansByGroupIdAndClientIdAndStatuses(@Param("groupId") Long groupId,
+            @Param("clientId") Long clientId, @Param("loanStatuses") Collection<LoanStatus> 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<Integer> loanStatuses);
+    Integer countOfLoansSyncedWithCalendar(@Param("calendarId") Long calendarId,
+            @Param("loanStatuses") Collection<LoanStatus> 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 a61ac96380..63176405be 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<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
-                LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue()));
+        final Collection<LoanStatus> 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 95ca92edac..21ac0ccede 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 58edf038db..8b721deedc 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<Throwable> errors = new ArrayList<>();
-        Set<Long> loanAccounts = loanAccrualActivityRepository.fetchLoanIdsForAccrualActivityPosting(yesterday);
+        Set<Long> 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 690004ada6..76cb3eb1ab 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<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
-                LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue()));
+        final Collection<LoanStatus> loanStatuses = new ArrayList<>(
+                Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE));
         final List<Holiday> 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 c3e5741e92..e7d204bb42 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 10b1ffcbbd..bda2bf37b3 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<LoanTransactionBalance> loanTransactionBalances,
-            final Integer transactionType) {
+            final LoanTransactionType transactionType) {
         final Optional<LoanTransactionBalance> 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<LoanTransactionBalance> loanTransactionBalances,
-            final Integer transactionType) {
+            final LoanTransactionType transactionType) {
         final Optional<LoanTransactionBalance> 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 c837a63dbf..40e65e4379 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 29008d011a..ac399c9188 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<Loan> loans = loanRepositoryWrapper.findLoansForPeriodicAccrual(AccountingRuleType.ACCRUAL_PERIODIC.getValue(), tillDate,
+        List<Loan> loans = loanRepositoryWrapper.findLoansForPeriodicAccrual(AccountingRuleType.ACCRUAL_PERIODIC, tillDate,
                 !isChargeOnDueDate());
         List<Throwable> 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<Loan> loans = loanRepositoryWrapper.findLoansForAddAccrual(AccountingRuleType.ACCRUAL_PERIODIC.getValue(), tillDate,
+        List<Loan> loans = loanRepositoryWrapper.findLoansForAddAccrual(AccountingRuleType.ACCRUAL_PERIODIC, tillDate,
                 !isChargeOnDueDate());
         List<Throwable> 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 d562853055..64656b1a21 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 11f60232a9..cc8004727b 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 dc689e91ba..018c9255c0 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<Long> existingTransactionIds = new ArrayList<>();
         final List<Long> existingReversedTransactionIds = new ArrayList<>();
-        final Collection<Integer> loanStatuses = new ArrayList<>(Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue(),
-                LoanStatus.APPROVED.getValue(), LoanStatus.ACTIVE.getValue()));
-        final Collection<Integer> loanTypes = new ArrayList<>(Arrays.asList(AccountType.GROUP.getValue(), AccountType.JLG.getValue()));
+        final Collection<LoanStatus> loanStatuses = new ArrayList<>(
+                Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE));
+        final Collection<AccountType> loanTypes = new ArrayList<>(Arrays.asList(AccountType.GROUP, AccountType.JLG));
         final Collection<Long> 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<Loan> 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 062d0b4b4f..bbeccfae69 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<BigDecimal> refundFinal,
             List<LoanTransaction> 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 bd8d320434..0f77393f63 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 ef85d3f1a3..ea17d40e21 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 e8733e6be2..d2e29d0add 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 e0155dc74e..cdd191aebc 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<LoanStatus> activeLoanStatuses = new ArrayList<>(
+                Arrays.asList(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL, LoanStatus.APPROVED, LoanStatus.ACTIVE));
         final List<CalendarInstance> 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 6299535e95..4e17fc342a 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 037120297f..593a37bd00 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 a93177cde9..32ac828bfc 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 6b3d6054c9..e0f725be5a 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));