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

arnold 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 d06c3655a FINERACT-1734: Loan status can and only be set using the 
State Machine
d06c3655a is described below

commit d06c3655af923899caabcaea33f018d9e916beb5
Author: Arnold Galovics <[email protected]>
AuthorDate: Fri Sep 9 13:26:56 2022 +0200

    FINERACT-1734: Loan status can and only be set using the State Machine
---
 .../domain/DefaultLoanLifecycleStateMachine.java   |  23 +++--
 .../portfolio/loanaccount/domain/Loan.java         | 102 ++++++++-------------
 .../domain/LoanLifecycleStateMachine.java          |   4 +-
 .../LoanWritePlatformServiceJpaRepositoryImpl.java |  15 +--
 4 files changed, 62 insertions(+), 82 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachine.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachine.java
index 35afd16e9..977ca5c93 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachine.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/DefaultLoanLifecycleStateMachine.java
@@ -27,16 +27,26 @@ public class DefaultLoanLifecycleStateMachine implements 
LoanLifecycleStateMachi
     private final List<LoanStatus> allowedLoanStatuses;
 
     @Override
-    public LoanStatus transition(final LoanEvent loanEvent, final LoanStatus 
from) {
+    public LoanStatus dryTransition(final LoanEvent loanEvent, final Loan 
loan) {
+        return getNextState(loanEvent, loan);
+    }
+
+    @Override
+    public void transition(final LoanEvent loanEvent, final Loan loan) {
+        LoanStatus newState = getNextState(loanEvent, loan);
+        loan.setLoanStatus(newState.getValue());
+    }
+
+    private LoanStatus getNextState(LoanEvent loanEvent, Loan loan) {
+        Integer plainFrom = loan.getPlainStatus();
+        if (loanEvent.equals(LoanEvent.LOAN_CREATED) && plainFrom == null) {
+            return submittedTransition();
+        }
 
+        LoanStatus from = loan.status();
         LoanStatus newState = from;
 
         switch (loanEvent) {
-            case LOAN_CREATED:
-                if (from == null) {
-                    newState = submittedTransition();
-                }
-            break;
             case LOAN_REJECTED:
                 if 
(from.hasStateOf(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL)) {
                     newState = rejectedTransition();
@@ -126,7 +136,6 @@ public class DefaultLoanLifecycleStateMachine implements 
LoanLifecycleStateMachi
             default:
             break;
         }
-
         return newState;
     }
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index cb41f4d1c..fb71c7a72 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -700,9 +700,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
                 chargesPayment.getAmount(getCurrency()).getAmount(), 
installmentNumber);
         chargesPayment.getLoanChargesPaid().add(loanChargePaidBy);
         addLoanTransaction(chargesPayment);
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_CHARGE_PAYMENT,
-                LoanStatus.fromInt(this.loanStatus));
-        this.loanStatus = statusEnum.getValue();
+        loanLifecycleStateMachine.transition(LoanEvent.LOAN_CHARGE_PAYMENT, 
this);
 
         final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
                 .determineProcessor(this.transactionProcessingStrategy);
@@ -2025,13 +2023,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
         updateLoanSchedule(loanSchedule);
 
-        LoanStatus from = null;
-        if (this.loanStatus != null) {
-            from = LoanStatus.fromInt(this.loanStatus);
-        }
-
-        final LoanStatus statusEnum = 
lifecycleStateMachine.transition(LoanEvent.LOAN_CREATED, from);
-        this.loanStatus = statusEnum.getValue();
+        lifecycleStateMachine.transition(LoanEvent.LOAN_CREATED, this);
 
         this.externalId = externalId;
         this.termFrequency = loanApplicationTerms.getLoanTermFrequency();
@@ -2114,9 +2106,9 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
         final Map<String, Object> actualChanges = new LinkedHashMap<>();
 
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECTED, 
LoanStatus.fromInt(this.loanStatus));
+        final LoanStatus statusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_REJECTED, this);
         if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
-            this.loanStatus = statusEnum.getValue();
+            loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECTED, 
this);
             actualChanges.put("status", 
LoanEnumerations.status(this.loanStatus));
 
             final LocalDate rejectedOn = 
command.localDateValueOfParameterNamed("rejectedOnDate");
@@ -2160,9 +2152,9 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
         final Map<String, Object> actualChanges = new LinkedHashMap<>();
 
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAWN, 
LoanStatus.fromInt(this.loanStatus));
+        final LoanStatus statusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_WITHDRAWN, this);
         if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
-            this.loanStatus = statusEnum.getValue();
+            loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAWN, 
this);
             actualChanges.put("status", 
LoanEnumerations.status(this.loanStatus));
 
             LocalDate withdrawnOn = 
command.localDateValueOfParameterNamed("withdrawnOnDate");
@@ -2215,7 +2207,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
          * statusEnum is holding the possible new status derived from 
loanLifecycleStateMachine.transition.
          */
 
-        final LoanStatus newStatusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVED, 
LoanStatus.fromInt(this.loanStatus));
+        final LoanStatus newStatusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_APPROVED, this);
 
         /*
          * FIXME: There is no need to check below condition, if 
loanLifecycleStateMachine.transition is doing it's
@@ -2225,7 +2217,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
          */
 
         if (!newStatusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
-            this.loanStatus = newStatusEnum.getValue();
+            loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVED, 
this);
             actualChanges.put("status", 
LoanEnumerations.status(this.loanStatus));
 
             // only do below if status has changed in the 'approval' case
@@ -2363,9 +2355,9 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         final Map<String, Object> actualChanges = new LinkedHashMap<>();
 
         final LoanStatus currentStatus = LoanStatus.fromInt(this.loanStatus);
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVAL_UNDO, 
currentStatus);
+        final LoanStatus statusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_APPROVAL_UNDO, this);
         if (!statusEnum.hasStateOf(currentStatus)) {
-            this.loanStatus = statusEnum.getValue();
+            loanLifecycleStateMachine.transition(LoanEvent.LOAN_APPROVAL_UNDO, 
this);
             actualChanges.put("status", 
LoanEnumerations.status(this.loanStatus));
 
             this.approvedOnDate = null;
@@ -2414,12 +2406,10 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
     public ChangedTransactionDetail disburse(final AppUser currentUser, final 
JsonCommand command, final Map<String, Object> actualChanges,
             final ScheduleGeneratorDTO scheduleGeneratorDTO, final 
PaymentDetail paymentDetail) {
 
-        final LoanStatus statusEnum = 
this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED,
-                LoanStatus.fromInt(this.loanStatus));
+        this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED, 
this);
 
         final LocalDate actualDisbursementDate = 
command.localDateValueOfParameterNamed("actualDisbursementDate");
 
-        this.loanStatus = statusEnum.getValue();
         actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
 
         this.disbursedBy = currentUser;
@@ -2526,8 +2516,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
     public boolean canDisburse(final LocalDate actualDisbursementDate) {
         LocalDate lastDisburseDate = this.actualDisbursementDate;
-        final LoanStatus statusEnum = 
this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSED,
-                LoanStatus.fromInt(this.loanStatus));
+        final LoanStatus statusEnum = 
this.loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_DISBURSED, this);
 
         boolean isMultiTrancheDisburse = false;
         LoanStatus actualLoanStatus = LoanStatus.fromInt(this.loanStatus);
@@ -2921,12 +2910,12 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
         final Map<String, Object> actualChanges = new LinkedHashMap<>();
         final LoanStatus currentStatus = LoanStatus.fromInt(this.loanStatus);
-        final LoanStatus statusEnum = 
this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, 
currentStatus);
+        final LoanStatus statusEnum = 
this.loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_DISBURSAL_UNDO, 
this);
         
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_DISBURSAL_UNDO,
 getDisbursementDate());
         existingTransactionIds.addAll(findExistingTransactionIds());
         
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
         if (!statusEnum.hasStateOf(currentStatus)) {
-            this.loanStatus = statusEnum.getValue();
+            
this.loanLifecycleStateMachine.transition(LoanEvent.LOAN_DISBURSAL_UNDO, this);
             actualChanges.put("status", 
LoanEnumerations.status(this.loanStatus));
 
             final LocalDate actualDisbursementDate = getDisbursementDate();
@@ -3162,9 +3151,9 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         }
 
         if (loanTransaction.isRecoveryRepayment()) {
-            statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_RECOVERY_PAYMENT, 
LoanStatus.fromInt(this.loanStatus));
+            
loanLifecycleStateMachine.transition(LoanEvent.LOAN_RECOVERY_PAYMENT, this);
         } else {
-            statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, 
LoanStatus.fromInt(this.loanStatus));
+            
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, this);
         }
 
         if (loanTransaction.isRecoveryRepayment()
@@ -3173,8 +3162,6 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
             throw new InvalidLoanStateTransitionException("transaction", 
"cannot.be.greater.than.total.written.off", errorMessage);
         }
 
-        this.loanStatus = statusEnum.getValue();
-
         loanTransaction.updateLoan(this);
 
         final boolean isTransactionChronologicallyLatest = 
isChronologicallyLatestRepaymentOrWaiver(loanTransaction, 
getLoanTransactions());
@@ -3392,16 +3379,12 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
             }
         }
         if (isAllChargesPaid) {
-            final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL,
-                    LoanStatus.fromInt(this.loanStatus));
-            this.loanStatus = statusEnum.getValue();
+            loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, 
this);
 
             this.closedOnDate = transactionDate;
             this.actualMaturityDate = transactionDate;
         } else if (LoanStatus.fromInt(this.loanStatus).isOverpaid()) {
-            final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER,
-                    LoanStatus.fromInt(this.loanStatus));
-            this.loanStatus = statusEnum.getValue();
+            
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, this);
         }
         processIncomeAccrualTransactionOnLoanClosure();
     }
@@ -3473,8 +3456,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
     private void handleLoanOverpayment(final LoanLifecycleStateMachine 
loanLifecycleStateMachine) {
 
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_OVERPAYMENT, 
LoanStatus.fromInt(this.loanStatus));
-        this.loanStatus = statusEnum.getValue();
+        loanLifecycleStateMachine.transition(LoanEvent.LOAN_OVERPAYMENT, this);
 
         this.closedOnDate = null;
         this.actualMaturityDate = null;
@@ -3635,9 +3617,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         }
 
         if (isClosedObligationsMet() || isClosedWrittenOff() || 
isClosedWithOutsandingAmountMarkedForReschedule()) {
-            LoanStatus loanStatusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_ADJUST_TRANSACTION,
-                    LoanStatus.fromInt(this.loanStatus));
-            this.loanStatus = loanStatusEnum.getValue();
+            
loanLifecycleStateMachine.transition(LoanEvent.LOAN_ADJUST_TRANSACTION, this);
         }
 
         if (newTransactionDetail.isRepaymentType() || 
newTransactionDetail.isInterestWaiver()) {
@@ -3657,9 +3637,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
         final LoanTransaction writeOffTransaction = findWriteOffTransaction();
         writeOffTransaction.reverse();
-        LoanStatus loanStatusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO,
-                LoanStatus.fromInt(this.loanStatus));
-        this.loanStatus = loanStatusEnum.getValue();
+        
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING_UNDO, 
this);
         final LoanRepaymentScheduleTransactionProcessor 
loanRepaymentScheduleTransactionProcessor = this.transactionProcessorFactory
                 .determineProcessor(this.transactionProcessingStrategy);
         final List<LoanTransaction> allNonContraTransactionsPostDisbursement = 
retreiveListOfTransactionsPostDisbursement();
@@ -3740,12 +3718,11 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
         validateAccountStatus(LoanEvent.WRITE_OFF_OUTSTANDING);
 
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING,
-                LoanStatus.fromInt(this.loanStatus));
+        final LoanStatus statusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.WRITE_OFF_OUTSTANDING, this);
 
         LoanTransaction loanTransaction = null;
         if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
-            this.loanStatus = statusEnum.getValue();
+            
loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING, this);
             changes.put("status", LoanEnumerations.status(this.loanStatus));
 
             existingTransactionIds.addAll(findExistingTransactionIds());
@@ -3866,10 +3843,9 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
             final Money totalOutstanding = 
this.summary.getTotalOutstanding(loanCurrency());
             if (totalOutstanding.isGreaterThanZero() && 
getInArrearsTolerance().isGreaterThanOrEqualTo(totalOutstanding)) {
 
-                final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL,
-                        LoanStatus.fromInt(this.loanStatus));
+                final LoanStatus statusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.REPAID_IN_FULL, this);
                 if 
(!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
-                    this.loanStatus = statusEnum.getValue();
+                    
loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, this);
                     changes.put("status", 
LoanEnumerations.status(this.loanStatus));
                 }
                 this.closedOnDate = closureDate;
@@ -3899,10 +3875,9 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
                 // TODO - KW - technically should set somewhere that this loan
                 // has
                 // 'overpaid' amount
-                final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL,
-                        LoanStatus.fromInt(this.loanStatus));
+                final LoanStatus statusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.REPAID_IN_FULL, this);
                 if 
(!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
-                    this.loanStatus = statusEnum.getValue();
+                    
loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, this);
                     changes.put("status", 
LoanEnumerations.status(this.loanStatus));
                 }
                 this.closedOnDate = closureDate;
@@ -3928,9 +3903,9 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
         final LocalDate rescheduledOn = 
command.localDateValueOfParameterNamed("transactionDate");
 
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_RESCHEDULE, 
LoanStatus.fromInt(this.loanStatus));
+        final LoanStatus statusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_RESCHEDULE, this);
         if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
-            this.loanStatus = statusEnum.getValue();
+            loanLifecycleStateMachine.transition(LoanEvent.LOAN_RESCHEDULE, 
this);
             changes.put("status", LoanEnumerations.status(this.loanStatus));
         }
 
@@ -3961,6 +3936,10 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         return LoanStatus.fromInt(this.loanStatus);
     }
 
+    public Integer getPlainStatus() {
+        return this.loanStatus;
+    }
+
     public boolean isSubmittedAndPendingApproval() {
         return status().isSubmittedAndPendingApproval();
     }
@@ -4793,7 +4772,9 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         this.loanTransactions.remove(loanTransaction);
     }
 
-    public void setLoanStatus(final Integer loanStatus) {
+    // Intentionally kept as package-private. Nobody should set the status 
directly but use the
+    // DefaultLoanLifecycleStateMachine to transition
+    void setLoanStatus(final Integer loanStatus) {
         this.loanStatus = loanStatus;
     }
 
@@ -6073,9 +6054,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         updateLoanSummaryDerivedFields();
 
         if (this.totalOverpaid == null || 
BigDecimal.ZERO.compareTo(this.totalOverpaid) == 0) {
-            LoanStatus statusEnum = 
defaultLoanLifecycleStateMachine.transition(LoanEvent.LOAN_CREDIT_BALANCE_REFUND,
-                    LoanStatus.fromInt(this.loanStatus));
-            this.loanStatus = statusEnum.getValue();
+            
defaultLoanLifecycleStateMachine.transition(LoanEvent.LOAN_CREDIT_BALANCE_REFUND,
 this);
         }
 
     }
@@ -6116,15 +6095,10 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
         ChangedTransactionDetail changedTransactionDetail = null;
 
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REFUND, 
LoanStatus.fromInt(this.loanStatus));
-        this.loanStatus = statusEnum.getValue();
+        loanLifecycleStateMachine.transition(LoanEvent.LOAN_REFUND, this);
 
         loanTransaction.updateLoan(this);
 
-        // final boolean isTransactionChronologicallyLatest =
-        // isChronologicallyLatestRefund(loanTransaction,
-        // this.loanTransactions);
-
         if (status().isOverpaid() || status().isClosed()) {
 
             final String errorMessage = "This refund option is only for active 
loans ";
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanLifecycleStateMachine.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanLifecycleStateMachine.java
index ad8ec1ed5..e4fc99d64 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanLifecycleStateMachine.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanLifecycleStateMachine.java
@@ -20,5 +20,7 @@ package org.apache.fineract.portfolio.loanaccount.domain;
 
 public interface LoanLifecycleStateMachine {
 
-    LoanStatus transition(LoanEvent loanEvent, LoanStatus from);
+    LoanStatus dryTransition(LoanEvent loanEvent, Loan loan);
+
+    void transition(LoanEvent loanEvent, Loan loan);
 }
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 248f7e3d4..94e9f4467 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
@@ -2261,8 +2261,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final LoanTransaction newTransferTransaction = 
LoanTransaction.initiateTransfer(loan.getOffice(), loan, transferDate);
         loan.addLoanTransaction(newTransferTransaction);
         LoanLifecycleStateMachine loanLifecycleStateMachine = 
defaultLoanLifecycleStateMachine();
-        LoanStatus loanStatusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_INITIATE_TRANSFER, 
loan.status());
-        loan.setLoanStatus(loanStatusEnum.getValue());
+        loanLifecycleStateMachine.transition(LoanEvent.LOAN_INITIATE_TRANSFER, 
loan);
 
         this.loanTransactionRepository.saveAndFlush(newTransferTransaction);
         saveLoanWithDataIntegrityViolationChecks(loan);
@@ -2284,13 +2283,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final LoanTransaction newTransferAcceptanceTransaction = 
LoanTransaction.approveTransfer(acceptedInOffice, loan, transferDate);
         loan.addLoanTransaction(newTransferAcceptanceTransaction);
         LoanLifecycleStateMachine loanLifecycleStateMachine = 
defaultLoanLifecycleStateMachine();
-        LoanStatus loanStatusEnum;
         if (loan.getTotalOverpaid() != null) {
-            loanStatusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_OVERPAYMENT, loan.status());
+            loanLifecycleStateMachine.transition(LoanEvent.LOAN_OVERPAYMENT, 
loan);
         } else {
-            loanStatusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, 
loan.status());
+            
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REPAYMENT_OR_WAIVER, loan);
         }
-        loan.setLoanStatus(loanStatusEnum.getValue());
         if (loanOfficer != null) {
             loan.reassignLoanOfficer(loanOfficer, transferDate);
         }
@@ -2316,8 +2313,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         final LoanTransaction newTransferAcceptanceTransaction = 
LoanTransaction.withdrawTransfer(loan.getOffice(), loan, transferDate);
         loan.addLoanTransaction(newTransferAcceptanceTransaction);
         LoanLifecycleStateMachine loanLifecycleStateMachine = 
defaultLoanLifecycleStateMachine();
-        LoanStatus loanStatusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAW_TRANSFER, 
loan.status());
-        loan.setLoanStatus(loanStatusEnum.getValue());
+        loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAW_TRANSFER, 
loan);
 
         
this.loanTransactionRepository.saveAndFlush(newTransferAcceptanceTransaction);
         saveLoanWithDataIntegrityViolationChecks(loan);
@@ -2334,8 +2330,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         this.loanAssembler.setHelpers(loan);
         businessEventNotifierService.notifyPreBusinessEvent(new 
LoanRejectTransferBusinessEvent(loan));
         LoanLifecycleStateMachine loanLifecycleStateMachine = 
defaultLoanLifecycleStateMachine();
-        LoanStatus loanStatusEnum = 
loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECT_TRANSFER, 
loan.status());
-        loan.setLoanStatus(loanStatusEnum.getValue());
+        loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECT_TRANSFER, 
loan);
         saveLoanWithDataIntegrityViolationChecks(loan);
         businessEventNotifierService.notifyPostBusinessEvent(new 
LoanRejectTransferBusinessEvent(loan));
     }

Reply via email to