You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ar...@apache.org on 2022/11/14 10:19:03 UTC

[fineract] branch develop updated: [FINERACT-1678] Loan COB - skip non-owned locked loan accounts

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 c9a4aab46 [FINERACT-1678] Loan COB - skip non-owned locked loan accounts
c9a4aab46 is described below

commit c9a4aab466347aa2b40aea56df3142d839d1b997
Author: taskain7 <ta...@gmail.com>
AuthorDate: Thu Nov 10 09:55:18 2022 +0100

    [FINERACT-1678] Loan COB - skip non-owned locked loan accounts
---
 ...=> LoanAccountWasAlreadyLockedOrProcessed.java} |  6 ++--
 .../fineract/cob/loan/AbstractLoanItemReader.java  |  8 ++---
 .../fineract/cob/loan/ApplyLoanLockTasklet.java    | 42 ++++++++++------------
 .../apache/fineract/cob/loan/LoanCOBConstant.java  |  2 +-
 .../cob/loan/LoanCOBWorkerConfiguration.java       |  2 +-
 .../apache/fineract/cob/loan/LoanItemReader.java   |  3 +-
 .../loan/ApplyLoanLockTaskletStepDefinitions.java  | 10 +++---
 .../cob/loan/LoanItemReaderStepDefinitions.java    |  3 +-
 8 files changed, 36 insertions(+), 40 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/exceptions/LoanAccountWasAlreadyLocked.java b/fineract-provider/src/main/java/org/apache/fineract/cob/exceptions/LoanAccountWasAlreadyLockedOrProcessed.java
similarity index 77%
rename from fineract-provider/src/main/java/org/apache/fineract/cob/exceptions/LoanAccountWasAlreadyLocked.java
rename to fineract-provider/src/main/java/org/apache/fineract/cob/exceptions/LoanAccountWasAlreadyLockedOrProcessed.java
index c33f4cd0f..8580567e8 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/exceptions/LoanAccountWasAlreadyLocked.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/exceptions/LoanAccountWasAlreadyLockedOrProcessed.java
@@ -18,9 +18,9 @@
  */
 package org.apache.fineract.cob.exceptions;
 
-public class LoanAccountWasAlreadyLocked extends Exception {
+public class LoanAccountWasAlreadyLockedOrProcessed extends Exception {
 
-    public LoanAccountWasAlreadyLocked(Long loanId) {
-        super(String.format("Loan is in already locked state! loanId: %d", loanId));
+    public LoanAccountWasAlreadyLockedOrProcessed(Long loanId) {
+        super(String.format("Loan is in already locked state, or has been already processed! loanId: %d", loanId));
     }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemReader.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemReader.java
index 3a4499185..1c795065c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemReader.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/AbstractLoanItemReader.java
@@ -23,7 +23,7 @@ import lombok.AccessLevel;
 import lombok.RequiredArgsConstructor;
 import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.fineract.cob.exceptions.LoanAccountWasAlreadyLocked;
+import org.apache.fineract.cob.exceptions.LoanAccountWasAlreadyLockedOrProcessed;
 import org.apache.fineract.cob.exceptions.LoanReadException;
 import org.apache.fineract.portfolio.loanaccount.domain.Loan;
 import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
@@ -41,7 +41,7 @@ public abstract class AbstractLoanItemReader implements ItemReader<Loan> {
     private final LoanRepository loanRepository;
 
     @Setter(AccessLevel.PROTECTED)
-    private List<Long> alreadyLockedAccounts;
+    private List<Long> alreadyLockedOrProcessedAccounts;
     @Setter(AccessLevel.PROTECTED)
     private List<Long> remainingData;
     private Long loanId;
@@ -51,8 +51,8 @@ public abstract class AbstractLoanItemReader implements ItemReader<Loan> {
         try {
             if (remainingData.size() > 0) {
                 loanId = remainingData.remove(0);
-                if (alreadyLockedAccounts != null && alreadyLockedAccounts.remove(loanId)) {
-                    throw new LoanAccountWasAlreadyLocked(loanId);
+                if (alreadyLockedOrProcessedAccounts != null && alreadyLockedOrProcessedAccounts.remove(loanId)) {
+                    throw new LoanAccountWasAlreadyLockedOrProcessed(loanId);
                 }
                 return loanRepository.findById(loanId).orElseThrow(() -> new LoanNotFoundException(loanId));
             }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/ApplyLoanLockTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/ApplyLoanLockTasklet.java
index 41f3b6110..fbfb39a47 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/ApplyLoanLockTasklet.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/ApplyLoanLockTasklet.java
@@ -45,41 +45,35 @@ public class ApplyLoanLockTasklet implements Tasklet {
     public RepeatStatus execute(@NotNull StepContribution contribution, @NotNull ChunkContext chunkContext) throws Exception {
         ExecutionContext executionContext = contribution.getStepExecution().getExecutionContext();
         List<Long> loanIds = (List<Long>) executionContext.get(LoanCOBConstant.LOAN_IDS);
-        List<Long> remainingLoanIds = new ArrayList<>(loanIds);
 
-        List<LoanAccountLock> accountLocks = accountLockRepository.findAllByLoanIdIn(remainingLoanIds);
-
-        List<Long> alreadyHardLockedAccountIds = accountLocks.stream()
-                .filter(e -> LockOwner.LOAN_COB_CHUNK_PROCESSING.equals(e.getLockOwner())).map(LoanAccountLock::getLoanId).toList();
-
-        List<Long> alreadyUnderProcessingAccountIds = accountLocks.stream()
-                .filter(e -> LockOwner.LOAN_INLINE_COB_PROCESSING.equals(e.getLockOwner())).map(LoanAccountLock::getLoanId).toList();
+        List<LoanAccountLock> accountLocks = accountLockRepository.findAllByLoanIdIn(loanIds);
 
         Map<Long, LoanAccountLock> alreadySoftLockedAccountsMap = accountLocks.stream()
                 .filter(e -> LockOwner.LOAN_COB_PARTITIONING.equals(e.getLockOwner()))
                 .collect(Collectors.toMap(LoanAccountLock::getLoanId, Function.identity()));
 
-        remainingLoanIds.removeAll(alreadyHardLockedAccountIds);
-        remainingLoanIds.removeAll(alreadyUnderProcessingAccountIds);
+        List<Long> alreadyLockedByChunkProcessingAccountIds = accountLocks.stream()
+                .filter(e -> LockOwner.LOAN_COB_CHUNK_PROCESSING.equals(e.getLockOwner())).map(LoanAccountLock::getLoanId).toList();
 
-        for (Long loanId : remainingLoanIds) {
-            LoanAccountLock loanAccountLock = addLock(loanId, alreadySoftLockedAccountsMap);
-            accountLockRepository.save(loanAccountLock);
+        List<Long> toBeProcessedLoanIds = new ArrayList<>(alreadySoftLockedAccountsMap.keySet());
+
+        for (Long loanId : toBeProcessedLoanIds) {
+            upgradeToHardLock(loanId, alreadySoftLockedAccountsMap);
         }
 
-        executionContext.put(LoanCOBConstant.ALREADY_LOCKED_LOAN_IDS, new ArrayList<>(alreadyUnderProcessingAccountIds));
+        toBeProcessedLoanIds.addAll(alreadyLockedByChunkProcessingAccountIds);
+        List<Long> alreadyLockedByInlineCOBOrProcessedLoanIds = new ArrayList<>(loanIds);
+        alreadyLockedByInlineCOBOrProcessedLoanIds.removeAll(toBeProcessedLoanIds);
+
+        executionContext.put(LoanCOBConstant.ALREADY_LOCKED_BY_INLINE_COB_OR_PROCESSED_LOAN_IDS,
+                new ArrayList<>(alreadyLockedByInlineCOBOrProcessedLoanIds));
         return RepeatStatus.FINISHED;
     }
 
-    private LoanAccountLock addLock(Long loanId, Map<Long, LoanAccountLock> alreadySoftLockedAccountsMap) {
-        LoanAccountLock loanAccountLock;
-        if (alreadySoftLockedAccountsMap.containsKey(loanId)) {
-            // Upgrade lock
-            loanAccountLock = alreadySoftLockedAccountsMap.get(loanId);
-            loanAccountLock.setNewLockOwner(LockOwner.LOAN_COB_CHUNK_PROCESSING);
-        } else {
-            loanAccountLock = new LoanAccountLock(loanId, LockOwner.LOAN_COB_CHUNK_PROCESSING);
-        }
-        return loanAccountLock;
+    private void upgradeToHardLock(Long loanId, Map<Long, LoanAccountLock> alreadySoftLockedAccountsMap) {
+        LoanAccountLock loanAccountLock = alreadySoftLockedAccountsMap.get(loanId);
+        // Upgrade lock
+        loanAccountLock.setNewLockOwner(LockOwner.LOAN_COB_CHUNK_PROCESSING);
+        accountLockRepository.save(loanAccountLock);
     }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
index ccb889b12..bce9222af 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBConstant.java
@@ -26,7 +26,7 @@ public final class LoanCOBConstant {
     public static final String BUSINESS_STEP_MAP = "businessStepMap";
     public static final String LOAN_COB_WORKER_STEP = "loanCOBWorkerStep";
 
-    public static final String ALREADY_LOCKED_LOAN_IDS = "alreadyLockedLoanIds";
+    public static final String ALREADY_LOCKED_BY_INLINE_COB_OR_PROCESSED_LOAN_IDS = "alreadyLockedOrProcessedLoanIds";
     public static final String INLINE_LOAN_COB_JOB_NAME = "INLINE_LOAN_COB";
 
     private LoanCOBConstant() {
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java
index 823675a31..0f6bccbb7 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBWorkerConfiguration.java
@@ -149,7 +149,7 @@ public class LoanCOBWorkerConfiguration {
     @Bean
     public ExecutionContextPromotionListener promotionListener() {
         ExecutionContextPromotionListener listener = new ExecutionContextPromotionListener();
-        listener.setKeys(new String[] { LoanCOBConstant.ALREADY_LOCKED_LOAN_IDS });
+        listener.setKeys(new String[] { LoanCOBConstant.ALREADY_LOCKED_BY_INLINE_COB_OR_PROCESSED_LOAN_IDS });
         return listener;
     }
 }
diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemReader.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemReader.java
index 8237ba928..2b7993e88 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemReader.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanItemReader.java
@@ -39,7 +39,8 @@ public class LoanItemReader extends AbstractLoanItemReader {
         ExecutionContext executionContext = stepExecution.getExecutionContext();
         ExecutionContext jobExecutionContext = stepExecution.getJobExecution().getExecutionContext();
         List<Long> loanIds = (List<Long>) executionContext.get(LoanCOBConstant.LOAN_IDS);
-        setAlreadyLockedAccounts((List<Long>) jobExecutionContext.get(LoanCOBConstant.ALREADY_LOCKED_LOAN_IDS));
+        setAlreadyLockedOrProcessedAccounts(
+                (List<Long>) jobExecutionContext.get(LoanCOBConstant.ALREADY_LOCKED_BY_INLINE_COB_OR_PROCESSED_LOAN_IDS));
         setRemainingData(new ArrayList<>(loanIds));
     }
 }
diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/ApplyLoanLockTaskletStepDefinitions.java b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/ApplyLoanLockTaskletStepDefinitions.java
index aa0b8dce4..fe8030eb9 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/ApplyLoanLockTaskletStepDefinitions.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/ApplyLoanLockTaskletStepDefinitions.java
@@ -73,14 +73,14 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
 
         Then("ApplyLoanLockTasklet.execute result should match", () -> {
             assertEquals(RepeatStatus.FINISHED, resultItem);
-            assertEquals(3L,
-                    ((List) stepContribution.getStepExecution().getExecutionContext().get(LoanCOBConstant.ALREADY_LOCKED_LOAN_IDS)).get(0));
-            verify(this.accountLockRepository, Mockito.times(2)).save(valueCaptor.capture());
+            assertEquals(3L, ((List) stepContribution.getStepExecution().getExecutionContext()
+                    .get(LoanCOBConstant.ALREADY_LOCKED_BY_INLINE_COB_OR_PROCESSED_LOAN_IDS)).get(0));
+            assertEquals(4L, ((List) stepContribution.getStepExecution().getExecutionContext()
+                    .get(LoanCOBConstant.ALREADY_LOCKED_BY_INLINE_COB_OR_PROCESSED_LOAN_IDS)).get(1));
+            verify(this.accountLockRepository, Mockito.times(1)).save(valueCaptor.capture());
             List<LoanAccountLock> values = valueCaptor.getAllValues();
             assertEquals(2L, values.get(0).getLoanId());
             assertEquals(LockOwner.LOAN_COB_CHUNK_PROCESSING, values.get(0).getLockOwner());
-            assertEquals(4L, values.get(1).getLoanId());
-            assertEquals(LockOwner.LOAN_COB_CHUNK_PROCESSING, values.get(1).getLockOwner());
         });
 
         Then("throw exception ApplyLoanLockTasklet.execute method", () -> {
diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderStepDefinitions.java b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderStepDefinitions.java
index 1d30d048d..f8f1758ad 100644
--- a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderStepDefinitions.java
+++ b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/LoanItemReaderStepDefinitions.java
@@ -57,7 +57,8 @@ public class LoanItemReaderStepDefinitions implements En {
                 List<String> splitLockedAccountsStr = Splitter.on(',').splitToList(lockedAccounts);
                 splitLockedAccounts = splitLockedAccountsStr.stream().map(Long::parseLong).toList();
             }
-            jobExecutionContext.put(LoanCOBConstant.ALREADY_LOCKED_LOAN_IDS, new ArrayList<>(splitLockedAccounts));
+            jobExecutionContext.put(LoanCOBConstant.ALREADY_LOCKED_BY_INLINE_COB_OR_PROCESSED_LOAN_IDS,
+                    new ArrayList<>(splitLockedAccounts));
             jobExecution.setExecutionContext(jobExecutionContext);
             StepExecution stepExecution = new StepExecution("test", jobExecution);
             ExecutionContext stepExecutionContext = new ExecutionContext();