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 1c53fe213 FINERACT-2090: Restructure Withdraw Loan Application Logic
1c53fe213 is described below

commit 1c53fe2136b6e453e81a2f82b99259d49e24e4ee
Author: Ruchi Dhamankar <[email protected]>
AuthorDate: Wed Jun 19 11:34:54 2024 +0530

    FINERACT-2090: Restructure Withdraw Loan Application Logic
---
 .../portfolio/loanaccount/domain/Loan.java         | 62 -----------------
 .../LoanApplicationTransitionValidator.java        | 64 ++++++++++++++----
 ...ationWritePlatformServiceJpaRepositoryImpl.java | 77 ++++++++--------------
 .../loanaccount/service/LoanAssembler.java         | 49 ++++++++++++++
 4 files changed, 129 insertions(+), 123 deletions(-)

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 3f7f49aa1..f8e960e39 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
@@ -42,7 +42,6 @@ import jakarta.validation.constraints.NotNull;
 import java.math.BigDecimal;
 import java.math.MathContext;
 import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -1741,54 +1740,6 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom<Long> {
         return maturityDate;
     }
 
-    public Map<String, Object> loanApplicationWithdrawnByApplicant(final 
AppUser currentUser, final JsonCommand command,
-            final LoanLifecycleStateMachine loanLifecycleStateMachine) {
-        final Map<String, Object> actualChanges = new LinkedHashMap<>();
-
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_WITHDRAWN, this);
-        if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
-            loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAWN, 
this);
-            actualChanges.put(PARAM_STATUS, 
LoanEnumerations.status(this.loanStatus));
-
-            LocalDate withdrawnOn = 
command.localDateValueOfParameterNamed(WITHDRAWN_ON_DATE);
-            if (withdrawnOn == null) {
-                withdrawnOn = 
command.localDateValueOfParameterNamed(EVENT_DATE);
-            }
-
-            final Locale locale = new Locale(command.locale());
-            final DateTimeFormatter fmt = 
DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
-
-            this.withdrawnOnDate = withdrawnOn;
-            this.withdrawnBy = currentUser;
-            this.closedOnDate = withdrawnOn;
-            this.closedBy = currentUser;
-
-            actualChanges.put(LOCALE, command.locale());
-            actualChanges.put(DATE_FORMAT, command.dateFormat());
-            actualChanges.put(WITHDRAWN_ON_DATE, withdrawnOn.format(fmt));
-            actualChanges.put(CLOSED_ON_DATE, withdrawnOn.format(fmt));
-
-            if (DateUtils.isBefore(withdrawnOn, getSubmittedOnDate())) {
-                final String errorMessage = "The date on which a loan is 
withdrawn cannot be before its submittal date: "
-                        + getSubmittedOnDate().toString();
-                throw new InvalidLoanStateTransitionException("withdraw", 
"cannot.be.before.submittal.date", errorMessage, command,
-                        getSubmittedOnDate());
-            }
-
-            
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_WITHDRAWN, 
withdrawnOn);
-
-            if (DateUtils.isDateInTheFuture(withdrawnOn)) {
-                final String errorMessage = "The date on which a loan is 
withdrawn cannot be in the future.";
-                throw new InvalidLoanStateTransitionException("withdraw", 
"cannot.be.a.future.date", errorMessage, command);
-            }
-        } else {
-            final String errorMessage = "Only the loan applications with 
status 'Submitted and pending approval' are allowed to be withdrawn by 
applicant.";
-            throw new InvalidLoanStateTransitionException("withdraw", 
"cannot.withdraw", errorMessage);
-        }
-
-        return actualChanges;
-    }
-
     public Map<String, Object> loanApplicationApproval(final AppUser 
currentUser, final JsonCommand command,
             final JsonArray disbursementDataArray, final 
LoanLifecycleStateMachine loanLifecycleStateMachine) {
         validateAccountStatus(LoanEvent.LOAN_APPROVED);
@@ -4278,11 +4229,6 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom<Long> {
                         action = "repayment.or.waiver";
                         postfix = "cannot.be.made.before.client.transfer.date";
                     }
-                    case LOAN_WITHDRAWN -> {
-                        errorMessage = "The date on which a loan is withdrawn 
cannot be earlier than client's transfer date to this office";
-                        action = "withdraw";
-                        postfix = "cannot.be.before.client.transfer.date";
-                    }
                     case WRITE_OFF_OUTSTANDING -> {
                         errorMessage = "The date on which a write off is made 
cannot be earlier than client's transfer date to this office";
                         action = "writeoff";
@@ -4478,14 +4424,6 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom<Long> {
                     dataValidationErrors.add(error);
                 }
             }
-            case LOAN_WITHDRAWN -> {
-                if (!isSubmittedAndPendingApproval()) {
-                    final String defaultUserMessage = "Loan application cannot 
be withdrawn. Loan Account is not in Submitted and Pending approval state.";
-                    final ApiParameterError error = ApiParameterError
-                            
.generalError("error.msg.loan.withdrawn.account.is.not.submitted.pending.approval.state",
 defaultUserMessage);
-                    dataValidationErrors.add(error);
-                }
-            }
             case WRITE_OFF_OUTSTANDING -> {
                 if (!isOpen()) {
                     final String defaultUserMessage = "Loan Written off is not 
allowed. Loan Account is not active.";
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 a8c343538..34d40c727 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
@@ -29,6 +29,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import lombok.RequiredArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.ApiParameterError;
@@ -47,18 +48,14 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanEvent;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanLifecycleStateMachine;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
 import 
org.apache.fineract.portfolio.loanaccount.exception.InvalidLoanStateTransitionException;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 @Component
+@RequiredArgsConstructor
 public final class LoanApplicationTransitionValidator {
 
     private final FromJsonHelper fromApiJsonHelper;
-
-    @Autowired
-    public LoanApplicationTransitionValidator(final FromJsonHelper 
fromApiJsonHelper) {
-        this.fromApiJsonHelper = fromApiJsonHelper;
-    }
+    private final LoanLifecycleStateMachine defaultLoanLifecycleStateMachine;
 
     private void throwExceptionIfValidationWarningsExist(final 
List<ApiParameterError> dataValidationErrors) {
         if (!dataValidationErrors.isEmpty()) {
@@ -112,13 +109,13 @@ public final class LoanApplicationTransitionValidator {
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
-    public void validateRejection(final JsonCommand command, final Loan loan, 
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
+    public void validateRejection(final JsonCommand command, final Loan loan) {
         // validate request body
         final String json = command.json();
         validateLoanRejectionRequestBody(json);
 
         // validate loan rejection
-        validateLoanRejection(command, loan, loanLifecycleStateMachine);
+        validateLoanRejection(command, loan);
     }
 
     private void validateLoanRejectionRequestBody(String json) {
@@ -146,8 +143,7 @@ public final class LoanApplicationTransitionValidator {
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
-    private void validateLoanRejection(final JsonCommand command, final Loan 
loan,
-            final LoanLifecycleStateMachine loanLifecycleStateMachine) {
+    private void validateLoanRejection(final JsonCommand command, final Loan 
loan) {
         // validate client or group is active
         checkClientOrGroupActive(loan);
 
@@ -156,7 +152,7 @@ public final class LoanApplicationTransitionValidator {
 
         // validate loan state transition
 
-        final LoanStatus statusEnum = 
loanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_REJECTED, loan);
+        final LoanStatus statusEnum = 
defaultLoanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_REJECTED, loan);
         if (!statusEnum.hasStateOf(LoanStatus.fromInt(loan.getLoanStatus()))) {
             final LocalDate rejectedOn = 
command.localDateValueOfParameterNamed(Loan.REJECTED_ON_DATE);
             if (DateUtils.isBefore(rejectedOn, loan.getSubmittedOnDate())) {
@@ -178,8 +174,16 @@ public final class LoanApplicationTransitionValidator {
         }
     }
 
-    public void validateApplicantWithdrawal(final String json) {
+    public void validateApplicantWithdrawal(final JsonCommand command, final 
Loan loan) {
+        // validate request body
+        final String json = command.json();
+        validateApplicantWithdrawalRequestBody(json);
 
+        // validate Loan application withdrawal by applicant
+        validateLoanApplicantWithdrawal(command, loan);
+    }
+
+    private void validateApplicantWithdrawalRequestBody(String json) {
         if (StringUtils.isBlank(json)) {
             throw new InvalidJsonException();
         }
@@ -204,6 +208,37 @@ public final class LoanApplicationTransitionValidator {
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
+    private void validateLoanApplicantWithdrawal(final JsonCommand command, 
final Loan loan) {
+        // validate client or group is active
+        checkClientOrGroupActive(loan);
+
+        // validate loan state transition
+        final LoanStatus statusEnum = 
defaultLoanLifecycleStateMachine.dryTransition(LoanEvent.LOAN_WITHDRAWN, loan);
+        if (!statusEnum.hasStateOf(LoanStatus.fromInt(loan.getLoanStatus()))) {
+            LocalDate withdrawnOn = 
command.localDateValueOfParameterNamed(Loan.WITHDRAWN_ON_DATE);
+            if (withdrawnOn == null) {
+                withdrawnOn = 
command.localDateValueOfParameterNamed(Loan.EVENT_DATE);
+            }
+            if (DateUtils.isBefore(withdrawnOn, loan.getSubmittedOnDate())) {
+                final String errorMessage = "The date on which a loan is 
withdrawn cannot be before its submittal date: "
+                        + loan.getSubmittedOnDate().toString();
+                throw new InvalidLoanStateTransitionException("withdraw", 
"cannot.be.before.submittal.date", errorMessage, command,
+                        loan.getSubmittedOnDate());
+            }
+
+            validateActivityNotBeforeClientOrGroupTransferDate(loan, 
LoanEvent.LOAN_WITHDRAWN, withdrawnOn);
+
+            if (DateUtils.isDateInTheFuture(withdrawnOn)) {
+                final String errorMessage = "The date on which a loan is 
withdrawn cannot be in the future.";
+                throw new InvalidLoanStateTransitionException("withdraw", 
"cannot.be.a.future.date", errorMessage, command);
+            }
+        } else {
+            final String errorMessage = "Only the loan applications with 
status 'Submitted and pending approval' are allowed to be withdrawn by 
applicant.";
+            throw new InvalidLoanStateTransitionException("withdraw", 
"cannot.withdraw", errorMessage);
+        }
+
+    }
+
     private void validateActivityNotBeforeClientOrGroupTransferDate(final Loan 
loan, final LoanEvent event, final LocalDate activityDate) {
         if (loan.getClient() != null && 
loan.getClient().getOfficeJoiningDate() != null) {
             final LocalDate clientOfficeJoiningDate = 
loan.getClient().getOfficeJoiningDate();
@@ -217,6 +252,11 @@ public final class LoanApplicationTransitionValidator {
                         action = "reject";
                         postfix = "cannot.be.before.client.transfer.date";
                     }
+                    case LOAN_WITHDRAWN -> {
+                        errorMessage = "The date on which a loan is withdrawn 
cannot be earlier than client's transfer date to this office";
+                        action = "withdraw";
+                        postfix = "cannot.be.before.client.transfer.date";
+                    }
                     default -> {
                     }
                 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
index fae97c795..94aad8ec9 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanApplicationWritePlatformServiceJpaRepositoryImpl.java
@@ -26,13 +26,10 @@ import com.google.gson.JsonObject;
 import jakarta.persistence.PersistenceException;
 import java.math.BigDecimal;
 import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoField;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import lombok.RequiredArgsConstructor;
@@ -96,7 +93,6 @@ import 
org.apache.fineract.portfolio.loanaccount.serialization.LoanApplicationTr
 import 
org.apache.fineract.portfolio.loanaccount.serialization.LoanApplicationValidator;
 import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
 import 
org.apache.fineract.portfolio.loanproduct.domain.RecalculationFrequencyType;
-import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
 import org.apache.fineract.portfolio.note.domain.Note;
 import org.apache.fineract.portfolio.note.domain.NoteRepository;
 import 
org.apache.fineract.portfolio.savings.data.GroupSavingsIndividualMonitoringAccountData;
@@ -492,6 +488,7 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
             this.accountAssociationsRepository.delete(accountAssociations);
         }
 
+        // Note: check if releaseAttachedCollaterals method can be used here
         Set<LoanCollateralManagement> loanCollateralManagements = 
loan.getLoanCollateralManagements();
         for (LoanCollateralManagement loanCollateralManagement : 
loanCollateralManagements) {
             BigDecimal quantity = loanCollateralManagement.getQuantity();
@@ -797,20 +794,23 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
         Loan loan = retrieveLoanBy(loanId);
 
         // validate loan rejection
-        loanApplicationTransitionValidator.validateRejection(command, loan, 
defaultLoanLifecycleStateMachine);
+        loanApplicationTransitionValidator.validateRejection(command, loan);
 
         // check for mandatory entities
         
entityDatatableChecksWritePlatformService.runTheCheckForProduct(loanId, 
EntityTables.LOAN.getName(),
                 StatusEnum.REJECTED.getCode().longValue(), 
EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), loan.productId());
 
         // loan application rejection
-        final Map<String, Object> changes = loanApplicationRejection(loan, 
command);
+        final AppUser currentUser = getAppUserIfPresent();
+        defaultLoanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECTED, 
loan);
+        final Map<String, Object> changes = 
loanAssembler.updateLoanApplicationAttributesForRejection(loan, command, 
currentUser);
 
         if (!changes.isEmpty()) {
             loanRepositoryWrapper.saveAndFlush(loan);
             final String noteText = 
command.stringValueOfParameterNamed("note");
             createNote(noteText, loan);
         }
+
         businessEventNotifierService.notifyPostBusinessEvent(new 
LoanRejectedBusinessEvent(loan));
         return new CommandProcessingResultBuilder() //
                 .withCommandId(command.commandId()) //
@@ -824,63 +824,31 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
                 .build();
     }
 
-    private Map<String, Object> loanApplicationRejection(Loan loan, final 
JsonCommand command) {
-
-        final AppUser currentUser = getAppUserIfPresent();
-        final LocalDate rejectedOn = 
command.localDateValueOfParameterNamed(Loan.REJECTED_ON_DATE);
-
-        loan.setRejectedOnDate(rejectedOn);
-        loan.setRejectedBy(currentUser);
-        loan.setClosedOnDate(rejectedOn);
-        loan.setClosedBy(currentUser);
-
-        defaultLoanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECTED, 
loan);
-
-        final Map<String, Object> actualChanges = new LinkedHashMap<>();
-        final Locale locale = new Locale(command.locale());
-        final DateTimeFormatter fmt = 
DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
-
-        actualChanges.put(Loan.PARAM_STATUS, 
LoanEnumerations.status(loan.getStatus()));
-        actualChanges.put(Loan.LOCALE, command.locale());
-        actualChanges.put(Loan.DATE_FORMAT, command.dateFormat());
-        actualChanges.put(Loan.REJECTED_ON_DATE, rejectedOn.format(fmt));
-        actualChanges.put(Loan.CLOSED_ON_DATE, rejectedOn.format(fmt));
-
-        return actualChanges;
-    }
-
     @Transactional
     @Override
     public CommandProcessingResult applicantWithdrawsFromApplication(final 
Long loanId, final JsonCommand command) {
 
-        final AppUser currentUser = getAppUserIfPresent();
-
-        
this.loanApplicationTransitionValidator.validateApplicantWithdrawal(command.json());
-
+        // retrieve loan
         final Loan loan = retrieveLoanBy(loanId);
-        loanApplicationTransitionValidator.checkClientOrGroupActive(loan);
 
+        // validate withdrawal
+        
loanApplicationTransitionValidator.validateApplicantWithdrawal(command, loan);
+
+        // check for mandatory entities
         
entityDatatableChecksWritePlatformService.runTheCheckForProduct(loanId, 
EntityTables.LOAN.getName(),
                 StatusEnum.WITHDRAWN.getCode().longValue(), 
EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(), loan.productId());
 
-        final Map<String, Object> changes = 
loan.loanApplicationWithdrawnByApplicant(currentUser, command,
-                defaultLoanLifecycleStateMachine);
-
+        // loan application withdrawal
+        final AppUser currentUser = getAppUserIfPresent();
+        defaultLoanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAWN, 
loan);
+        final Map<String, Object> changes = 
loanAssembler.updateLoanApplicationAttributesForWithdrawal(loan, command, 
currentUser);
         // Release attached collaterals
         if (loan.getLoanType().isIndividualAccount()) {
-            Set<LoanCollateralManagement> loanCollateralManagements = 
loan.getLoanCollateralManagements();
-            for (LoanCollateralManagement loanCollateralManagement : 
loanCollateralManagements) {
-                ClientCollateralManagement clientCollateralManagement = 
loanCollateralManagement.getClientCollateralManagement();
-                clientCollateralManagement
-                        
.updateQuantity(clientCollateralManagement.getQuantity().add(loanCollateralManagement.getQuantity()));
-                
loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement);
-                loanCollateralManagement.setIsReleased(true);
-            }
-            loan.updateLoanCollateral(loanCollateralManagements);
+            releaseAttachedCollaterals(loan);
         }
 
         if (!changes.isEmpty()) {
-            this.loanRepositoryWrapper.saveAndFlush(loan);
+            loanRepositoryWrapper.saveAndFlush(loan);
 
             final String noteText = 
command.stringValueOfParameterNamed("note");
             createNote(noteText, loan);
@@ -983,4 +951,15 @@ public class 
LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
         }
     }
 
+    private void releaseAttachedCollaterals(Loan loan) {
+        Set<LoanCollateralManagement> loanCollateralManagements = 
loan.getLoanCollateralManagements();
+        for (LoanCollateralManagement loanCollateralManagement : 
loanCollateralManagements) {
+            ClientCollateralManagement clientCollateralManagement = 
loanCollateralManagement.getClientCollateralManagement();
+            
clientCollateralManagement.updateQuantity(clientCollateralManagement.getQuantity().add(loanCollateralManagement.getQuantity()));
+            
loanCollateralManagement.setClientCollateralManagement(clientCollateralManagement);
+            loanCollateralManagement.setIsReleased(true);
+        }
+        loan.updateLoanCollateral(loanCollateralManagements);
+    }
+
 }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java
index a62e25b8c..ebfce389e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanAssembler.java
@@ -22,9 +22,11 @@ import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -96,8 +98,10 @@ import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProduct;
 import 
org.apache.fineract.portfolio.loanproduct.domain.LoanProductRelatedDetail;
 import org.apache.fineract.portfolio.loanproduct.domain.LoanProductRepository;
 import 
org.apache.fineract.portfolio.loanproduct.exception.LoanProductNotFoundException;
+import org.apache.fineract.portfolio.loanproduct.service.LoanEnumerations;
 import org.apache.fineract.portfolio.rate.domain.Rate;
 import org.apache.fineract.portfolio.rate.service.RateAssembler;
+import org.apache.fineract.useradministration.domain.AppUser;
 
 @RequiredArgsConstructor
 public class LoanAssembler {
@@ -833,4 +837,49 @@ public class LoanAssembler {
 
         return changes;
     }
+
+    public Map<String, Object> 
updateLoanApplicationAttributesForWithdrawal(Loan loan, JsonCommand command, 
AppUser currentUser) {
+        final Map<String, Object> actualChanges = new LinkedHashMap<>();
+
+        LocalDate withdrawnOn = 
command.localDateValueOfParameterNamed(Loan.WITHDRAWN_ON_DATE);
+        if (withdrawnOn == null) {
+            withdrawnOn = 
command.localDateValueOfParameterNamed(Loan.EVENT_DATE);
+        }
+
+        loan.setWithdrawnOnDate(withdrawnOn);
+        loan.setWithdrawnBy(currentUser);
+        loan.setClosedOnDate(withdrawnOn);
+        loan.setClosedBy(currentUser);
+
+        final Locale locale = new Locale(command.locale());
+        final DateTimeFormatter fmt = 
DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
+
+        actualChanges.put(Loan.PARAM_STATUS, 
LoanEnumerations.status(loan.getStatus()));
+        actualChanges.put(Loan.LOCALE, command.locale());
+        actualChanges.put(Loan.DATE_FORMAT, command.dateFormat());
+        actualChanges.put(Loan.WITHDRAWN_ON_DATE, withdrawnOn.format(fmt));
+        actualChanges.put(Loan.CLOSED_ON_DATE, withdrawnOn.format(fmt));
+        return actualChanges;
+    }
+
+    public Map<String, Object> 
updateLoanApplicationAttributesForRejection(Loan loan, JsonCommand command, 
AppUser currentUser) {
+        final Map<String, Object> actualChanges = new LinkedHashMap<>();
+
+        final LocalDate rejectedOn = 
command.localDateValueOfParameterNamed(Loan.REJECTED_ON_DATE);
+
+        loan.setRejectedOnDate(rejectedOn);
+        loan.setRejectedBy(currentUser);
+        loan.setClosedOnDate(rejectedOn);
+        loan.setClosedBy(currentUser);
+
+        final Locale locale = new Locale(command.locale());
+        final DateTimeFormatter fmt = 
DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
+
+        actualChanges.put(Loan.PARAM_STATUS, 
LoanEnumerations.status(loan.getStatus()));
+        actualChanges.put(Loan.LOCALE, command.locale());
+        actualChanges.put(Loan.DATE_FORMAT, command.dateFormat());
+        actualChanges.put(Loan.REJECTED_ON_DATE, rejectedOn.format(fmt));
+        actualChanges.put(Loan.CLOSED_ON_DATE, rejectedOn.format(fmt));
+        return actualChanges;
+    }
 }

Reply via email to