From e9bc0fe8c265e95682f27151aaff47d9a6a95a0d Mon Sep 17 00:00:00 2001 From: Ruchi Dhamankar Date: Wed, 24 May 2023 17:22:56 +0530 Subject: [PATCH] FINERACT-1678-loan-cob-drop-softlocking-use-lastclosedbusinessdate --- .../cob/domain/LoanAccountLockRepository.java | 6 +- .../apache/fineract/cob/domain/LockOwner.java | 2 +- .../cob/loan/ApplyLoanLockTasklet.java | 19 +- .../cob/loan/LoanCOBManagerConfiguration.java | 15 +- .../fineract/cob/loan/LoanLockingService.java | 6 +- .../cob/loan/LoanLockingServiceImpl.java | 33 ++-- .../fineract/cob/loan/LockLoanTasklet.java | 59 ------ .../InlineLoanCOBExecutorServiceImpl.java | 2 +- .../cob/service/LoanAccountLockService.java | 2 - .../service/LoanAccountLockServiceImpl.java | 7 +- .../jobs/filter/LoanCOBApiFilter.java | 15 +- .../db/changelog/tenant/changelog-tenant.xml | 1 + ...econdition_check_cob_loan_account_lock.xml | 30 +++ .../ApplyLoanLockTaskletStepDefinitions.java | 5 +- .../loan/FetchAndLockLoanStepDefinitions.java | 178 ------------------ .../jobs/filter/LoanCOBApiFilterTest.java | 27 +-- .../cob/loan/cob.loan.fetch.lock.feature | 34 ---- .../inlinecob/InlineLoanCOBTest.java | 5 - 18 files changed, 66 insertions(+), 380 deletions(-) delete mode 100644 fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java create mode 100644 fineract-provider/src/main/resources/db/changelog/tenant/parts/0108_precondition_check_cob_loan_account_lock.xml delete mode 100644 fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java delete mode 100644 fineract-provider/src/test/resources/features/cob/loan/cob.loan.fetch.lock.feature diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLockRepository.java b/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLockRepository.java index d2dc59e05..9705fff60 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLockRepository.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/domain/LoanAccountLockRepository.java @@ -50,11 +50,9 @@ public interface LoanAccountLockRepository extends JpaRepository accountLocks = new ArrayList<>(); loanIdPartitions.forEach(loanIdPartition -> accountLocks.addAll(loanLockingService.findAllByLoanIdIn(loanIdPartition))); - Map alreadySoftLockedAccountsMap = accountLocks.stream() - .filter(e -> LockOwner.LOAN_COB_PARTITIONING.equals(e.getLockOwner())) - .collect(Collectors.toMap(LoanAccountLock::getLoanId, Function.identity())); - List alreadyLockedByChunkProcessingAccountIds = accountLocks.stream() .filter(e -> LockOwner.LOAN_COB_CHUNK_PROCESSING.equals(e.getLockOwner())).map(LoanAccountLock::getLoanId).toList(); - List toBeProcessedLoanIds = new ArrayList<>(alreadySoftLockedAccountsMap.keySet()); - - loanLockingService.upgradeLock(toBeProcessedLoanIds, LockOwner.LOAN_COB_CHUNK_PROCESSING); - - toBeProcessedLoanIds.addAll(alreadyLockedByChunkProcessingAccountIds); - List alreadyLockedByInlineCOBOrProcessedLoanIds = new ArrayList<>(loanIds); - alreadyLockedByInlineCOBOrProcessedLoanIds.removeAll(toBeProcessedLoanIds); - - loanIds.removeAll(alreadyLockedByInlineCOBOrProcessedLoanIds); + List toBeProcessedLoanIds = new ArrayList<>(loanIds); + toBeProcessedLoanIds.removeAll(alreadyLockedByChunkProcessingAccountIds); + loanLockingService.applyLock(toBeProcessedLoanIds, LockOwner.LOAN_COB_CHUNK_PROCESSING); return RepeatStatus.FINISHED; } diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java index 4d6a04cb7..f5d8e5ab7 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanCOBManagerConfiguration.java @@ -73,8 +73,6 @@ public class LoanCOBManagerConfiguration { private BusinessEventNotifierService businessEventNotifierService; @Autowired private CustomJobParameterResolver customJobParameterResolver; - @Autowired - private LoanLockingService loanLockingService; @Bean @JobScope @@ -93,11 +91,6 @@ public class LoanCOBManagerConfiguration { return localStepBuilderFactory.get("Set loan ID parameter - Step").tasklet(loanIdParameterTasklet()).build(); } - @Bean - public Step lockStep() { - return localStepBuilderFactory.get("Lock loan accounts - Step").tasklet(lockLoanTasklet()).build(); - } - @Bean public Step resolveCustomJobParametersStep() { return localStepBuilderFactory.get("Resolve custom job parameters - Step").tasklet(resolveCustomJobParametersTasklet()) @@ -115,12 +108,6 @@ public class LoanCOBManagerConfiguration { return new LoanIdParameterTasklet(retrieveLoanIdService, customJobParameterResolver); } - @Bean - @JobScope - public LockLoanTasklet lockLoanTasklet() { - return new LockLoanTasklet(loanLockingService, customJobParameterResolver); - } - @Bean @JobScope public ResolveLoanCOBCustomJobParametersTasklet resolveCustomJobParametersTasklet() { @@ -138,7 +125,7 @@ public class LoanCOBManagerConfiguration { return jobBuilderFactory.get(JobName.LOAN_COB.name()) // .listener(new COBExecutionListenerRunner(applicationContext, JobName.LOAN_COB.name())) // .start(resolveCustomJobParametersStep()) // - .next(loanIdParameterStep()).next(lockStep()).next(loanCOBStep()).next(stayedLockedStep()) // + .next(loanIdParameterStep()).next(loanCOBStep()).next(stayedLockedStep()) // .incrementer(new RunIdIncrementer()) // .build(); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingService.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingService.java index f049e1351..140a6e500 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingService.java @@ -18,16 +18,12 @@ */ package org.apache.fineract.cob.loan; -import java.time.LocalDate; import java.util.List; -import org.apache.fineract.cob.data.LoanCOBParameter; import org.apache.fineract.cob.domain.LoanAccountLock; import org.apache.fineract.cob.domain.LockOwner; public interface LoanLockingService { - void applySoftLock(LocalDate lastClosedBusinessDate, LoanCOBParameter loanCOBParameter, boolean isCatchUp); - void upgradeLock(List accountsToLock, LockOwner lockOwner); void deleteByLoanIdInAndLockOwner(List loanIds, LockOwner lockOwner); @@ -35,4 +31,6 @@ public interface LoanLockingService { List findAllByLoanIdIn(List loanIds); LoanAccountLock findByLoanIdAndLockOwner(Long loanId, LockOwner lockOwner); + + void applyLock(List loanIds, LockOwner lockOwner); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java index 3c44d2db6..dfb19ddc9 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LoanLockingServiceImpl.java @@ -18,11 +18,11 @@ */ package org.apache.fineract.cob.loan; +import java.sql.PreparedStatement; import java.time.LocalDate; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.fineract.cob.data.LoanCOBParameter; import org.apache.fineract.cob.domain.LoanAccountLock; import org.apache.fineract.cob.domain.LoanAccountLockRepository; import org.apache.fineract.cob.domain.LockOwner; @@ -53,25 +53,14 @@ public class LoanLockingServiceImpl implements LoanLockingService { AND (? = loan.last_closed_business_date) """; + private static final String BATCH_LOAN_LOCK_INSERT = """ + INSERT INTO m_loan_account_locks (loan_id, version, lock_owner, lock_placed_on, lock_placed_on_cob_business_date) VALUES (?,?,?,?,?) + """; + private final JdbcTemplate jdbcTemplate; private final FineractProperties fineractProperties; private final LoanAccountLockRepository loanAccountLockRepository; - @Override - public void applySoftLock(LocalDate lastClosedBusinessDate, LoanCOBParameter loanCOBParameter, boolean isCatchUp) { - - LocalDate cobBusinessDate = ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE); - jdbcTemplate.update(isCatchUp ? CATCH_UP_LOAN_INSERT : NORMAL_LOAN_INSERT, ps -> { - ps.setLong(1, 1); - ps.setString(2, LockOwner.LOAN_COB_PARTITIONING.name()); - ps.setObject(3, DateUtils.getOffsetDateTimeOfTenant()); - ps.setObject(4, cobBusinessDate); - ps.setObject(5, loanCOBParameter.getMinLoanId()); - ps.setObject(6, loanCOBParameter.getMaxLoanId()); - ps.setObject(7, lastClosedBusinessDate); - }); - } - @Override public void upgradeLock(List accountsToLock, LockOwner lockOwner) { jdbcTemplate.batchUpdate(""" @@ -96,6 +85,18 @@ public class LoanLockingServiceImpl implements LoanLockingService { }); } + @Override + public void applyLock(List loanIds, LockOwner lockOwner) { + LocalDate cobBusinessDate = ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE); + jdbcTemplate.batchUpdate(BATCH_LOAN_LOCK_INSERT, loanIds, loanIds.size(), (PreparedStatement ps, Long loanId) -> { + ps.setLong(1, loanId); + ps.setLong(2, 1); + ps.setString(3, lockOwner.name()); + ps.setObject(4, DateUtils.getOffsetDateTimeOfTenant()); + ps.setObject(5, cobBusinessDate); + }); + } + @Override public void deleteByLoanIdInAndLockOwner(List loanIds, LockOwner lockOwner) { loanAccountLockRepository.deleteByLoanIdInAndLockOwner(loanIds, lockOwner); diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java deleted file mode 100644 index d2d503974..000000000 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/LockLoanTasklet.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.fineract.cob.loan; - -import java.time.LocalDate; -import java.util.Objects; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.fineract.cob.common.CustomJobParameterResolver; -import org.apache.fineract.cob.data.LoanCOBParameter; -import org.jetbrains.annotations.NotNull; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.scope.context.ChunkContext; -import org.springframework.batch.core.step.tasklet.Tasklet; -import org.springframework.batch.repeat.RepeatStatus; - -@Slf4j -@RequiredArgsConstructor -public class LockLoanTasklet implements Tasklet { - - private final LoanLockingService loanLockingService; - private final CustomJobParameterResolver customJobParameterResolver; - - @Override - public RepeatStatus execute(@NotNull StepContribution contribution, @NotNull ChunkContext chunkContext) throws Exception { - String businessDateParameter = (String) contribution.getStepExecution().getJobExecution().getExecutionContext() - .get(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME); - LocalDate lastClosedBusinessDate = LocalDate.parse(Objects.requireNonNull(businessDateParameter)) - .minusDays(LoanCOBConstant.NUMBER_OF_DAYS_BEHIND); - LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution().getExecutionContext() - .get(LoanCOBConstant.LOAN_COB_PARAMETER); - if (Objects.isNull(loanCOBParameter) - || (Objects.isNull(loanCOBParameter.getMinLoanId()) && Objects.isNull(loanCOBParameter.getMaxLoanId()))) { - loanCOBParameter = new LoanCOBParameter(0L, 0L); - } - loanLockingService.applySoftLock(lastClosedBusinessDate, loanCOBParameter, - customJobParameterResolver - .getCustomJobParameterById(contribution.getStepExecution(), LoanCOBConstant.IS_CATCH_UP_PARAMETER_NAME) - .map(Boolean::parseBoolean).orElse(false)); - - return RepeatStatus.FINISHED; - } -} diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java index 7576f603f..a1adf9349 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/service/InlineLoanCOBExecutorServiceImpl.java @@ -226,7 +226,7 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService loanIds = calculateRelevantLoanIds(request.getPathInfo()); - if (!loanIds.isEmpty() && (isLoanSoftLocked(loanIds) || isLoanBehind(loanIds))) { + if (!loanIds.isEmpty() && isLoanBehind(loanIds)) { executeInlineCob(loanIds); } proceed(filterChain, request, response); @@ -184,17 +184,8 @@ public class LoanCOBApiFilter extends OncePerRequestFilter implements BatchReque } } - private boolean isLoanSoftLocked(List loanIds) { - return isLoanLocked(loanIds, false); - } - private boolean isLoanHardLocked(List loanIds) { - return isLoanLocked(loanIds, true); - } - - private boolean isLoanLocked(List loanIds, boolean isHardLock) { - return isHardLock ? loanIds.stream().anyMatch(loanAccountLockService::isLoanHardLocked) - : loanIds.stream().anyMatch(loanAccountLockService::isLoanSoftLocked); + return loanIds.stream().anyMatch(loanAccountLockService::isLoanHardLocked); } private void proceed(FilterChain filterChain, HttpServletRequest request, HttpServletResponse response) @@ -256,7 +247,7 @@ public class LoanCOBApiFilter extends OncePerRequestFilter implements BatchReque boolean bypassUser = isBypassUser(); if (!bypassUser) { List result = calculateRelevantLoanIds(relativeUrl); - if (!result.isEmpty() && (isLoanSoftLocked(result) || isLoanBehind(result))) { + if (!result.isEmpty() && isLoanBehind(result)) { executeInlineCob(result); } } diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml index 55a65b82c..ce63f5053 100644 --- a/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml +++ b/fineract-provider/src/main/resources/db/changelog/tenant/changelog-tenant.xml @@ -127,4 +127,5 @@ + diff --git a/fineract-provider/src/main/resources/db/changelog/tenant/parts/0108_precondition_check_cob_loan_account_lock.xml b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0108_precondition_check_cob_loan_account_lock.xml new file mode 100644 index 000000000..70a870921 --- /dev/null +++ b/fineract-provider/src/main/resources/db/changelog/tenant/parts/0108_precondition_check_cob_loan_account_lock.xml @@ -0,0 +1,30 @@ + + + + + + select count(*) from m_loan_account_locks where lock_owner = 'LOAN_COB_PARTITIONING' + + + 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 0b437e085..7e2968ec4 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 @@ -83,10 +83,9 @@ public class ApplyLoanLockTaskletStepDefinitions implements En { lenient().when(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenThrow(new RuntimeException("fail")); } else { LoanAccountLock lock1 = new LoanAccountLock(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault())); - LoanAccountLock lock2 = new LoanAccountLock(2L, LockOwner.LOAN_COB_PARTITIONING, LocalDate.now(ZoneId.systemDefault())); LoanAccountLock lock3 = new LoanAccountLock(3L, LockOwner.LOAN_INLINE_COB_PROCESSING, LocalDate.now(ZoneId.systemDefault())); - List accountLocks = List.of(lock1, lock2, lock3); + List accountLocks = List.of(lock1, lock3); lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties); lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000); lenient().when(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenReturn(accountLocks); @@ -101,7 +100,7 @@ public class ApplyLoanLockTaskletStepDefinitions implements En { Then("ApplyLoanLockTasklet.execute result should match", () -> { assertEquals(RepeatStatus.FINISHED, resultItem); - verify(loanLockingService, Mockito.times(1)).upgradeLock(valueCaptor.capture(), lockOwnerValueCaptor.capture()); + verify(loanLockingService, Mockito.times(1)).applyLock(valueCaptor.capture(), lockOwnerValueCaptor.capture()); List values = valueCaptor.getValue(); assertEquals(2L, values.get(0)); assertEquals(LockOwner.LOAN_COB_CHUNK_PROCESSING, lockOwnerValueCaptor.getValue()); diff --git a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java b/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java deleted file mode 100644 index b5cda2574..000000000 --- a/fineract-provider/src/test/java/org/apache/fineract/cob/loan/FetchAndLockLoanStepDefinitions.java +++ /dev/null @@ -1,178 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.fineract.cob.loan; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.lenient; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - -import io.cucumber.java8.En; -import java.time.LocalDate; -import java.time.ZoneId; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import org.apache.fineract.cob.common.CustomJobParameterResolver; -import org.apache.fineract.cob.data.LoanCOBParameter; -import org.apache.fineract.cob.domain.LoanAccountLock; -import org.apache.fineract.cob.domain.LoanAccountLockRepository; -import org.apache.fineract.cob.domain.LockOwner; -import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; -import org.apache.fineract.infrastructure.core.config.FineractProperties; -import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; -import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.repeat.RepeatStatus; - -public class FetchAndLockLoanStepDefinitions implements En { - - private final LoanAccountLockRepository loanAccountLockRepository = mock(LoanAccountLockRepository.class); - private final FineractProperties fineractProperties = mock(FineractProperties.class); - private final FineractProperties.FineractQueryProperties fineractQueryProperties = mock( - FineractProperties.FineractQueryProperties.class); - StepContribution contribution; - ArgumentCaptor dateValueCaptor = ArgumentCaptor.forClass(LocalDate.class); - ArgumentCaptor loanCOBParameterValueCaptor = ArgumentCaptor.forClass(LoanCOBParameter.class); - - ArgumentCaptor isCatchUpParameterCaptor = ArgumentCaptor.forClass(Boolean.class); - private LockLoanTasklet lockLoanTasklet; - private String action; - private RepeatStatus result; - private final LoanLockingService loanLockingService = mock(LoanLockingService.class); - - private final CustomJobParameterResolver customJobParameterResolver = mock(CustomJobParameterResolver.class); - - public FetchAndLockLoanStepDefinitions() { - Given("/^The FetchAndLockLoanTasklet.execute method with action (.*)$/", (String action) -> { - ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null)); - HashMap businessDateMap = new HashMap<>(); - businessDateMap.put(BusinessDateType.COB_DATE, LocalDate.now(ZoneId.systemDefault())); - ThreadLocalContextUtil.setBusinessDates(businessDateMap); - this.action = action; - - JobExecution jobExecution = new JobExecution(1L); - StepExecution stepExecution = new StepExecution("step", jobExecution); - contribution = new StepContribution(stepExecution); - contribution.getStepExecution().getJobExecution().getExecutionContext().put(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME, - LocalDate.now(ZoneId.systemDefault()).toString()); - lenient().when(customJobParameterResolver.getCustomJobParameterSet(Mockito.any())).thenReturn(Optional.empty()); - if ("empty loanIds".equals(action)) { - contribution.getStepExecution().getJobExecution().getExecutionContext().put(LoanCOBConstant.LOAN_COB_PARAMETER, - new LoanCOBParameter(0L, 0L)); - } else if ("good".equals(action)) { - contribution.getStepExecution().getJobExecution().getExecutionContext().put(LoanCOBConstant.LOAN_COB_PARAMETER, - new LoanCOBParameter(1L, 3L)); - lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties); - lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000); - lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenReturn(Collections.emptyList()); - } else if ("soft lock".equals(action)) { - contribution.getStepExecution().getJobExecution().getExecutionContext().put(LoanCOBConstant.LOAN_COB_PARAMETER, - new LoanCOBParameter(1L, 3L)); - lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties); - lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000); - lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenReturn( - List.of(new LoanAccountLock(1L, LockOwner.LOAN_COB_PARTITIONING, LocalDate.now(ZoneId.systemDefault())))); - } else if ("inline cob".equals(action)) { - contribution.getStepExecution().getJobExecution().getExecutionContext().put(LoanCOBConstant.LOAN_COB_PARAMETER, - new LoanCOBParameter(1L, 3L)); - lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties); - lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000); - lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenReturn( - List.of(new LoanAccountLock(2L, LockOwner.LOAN_INLINE_COB_PROCESSING, LocalDate.now(ZoneId.systemDefault())))); - } else if ("chunk processing".equals(action)) { - contribution.getStepExecution().getJobExecution().getExecutionContext().put(LoanCOBConstant.LOAN_COB_PARAMETER, - new LoanCOBParameter(1L, 3L)); - lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties); - lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000); - lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenReturn( - List.of(new LoanAccountLock(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault())))); - } - - lockLoanTasklet = new LockLoanTasklet(loanLockingService, customJobParameterResolver); - }); - - When("FetchAndLockLoanTasklet.execute method executed", () -> { - result = lockLoanTasklet.execute(contribution, null); - }); - - Then("FetchAndLockLoanTasklet.execute result should match", () -> { - if ("empty steps".equals(action)) { - assertEquals(RepeatStatus.FINISHED, result); - } else if ("good".equals(action)) { - verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture(), - isCatchUpParameterCaptor.capture()); - assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue()); - assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId()); - assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId()); - assertEquals(RepeatStatus.FINISHED, result); - assertEquals(false, isCatchUpParameterCaptor.getValue()); - LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution() - .getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER); - assertEquals(2, loanCOBParameter.getMaxLoanId() - loanCOBParameter.getMinLoanId()); - assertEquals(1L, loanCOBParameter.getMinLoanId()); - assertEquals(3L, loanCOBParameter.getMaxLoanId()); - } else if ("soft lock".equals(action)) { - verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture(), - isCatchUpParameterCaptor.capture()); - assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue()); - assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId()); - assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId()); - assertEquals(RepeatStatus.FINISHED, result); - assertEquals(false, isCatchUpParameterCaptor.getValue()); - LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution() - .getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER); - assertEquals(2, loanCOBParameter.getMaxLoanId() - loanCOBParameter.getMinLoanId()); - assertEquals(1L, loanCOBParameter.getMinLoanId()); - assertEquals(3L, loanCOBParameter.getMaxLoanId()); - } else if ("inline cob".equals(action)) { - verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture(), - isCatchUpParameterCaptor.capture()); - assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue()); - assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId()); - assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId()); - assertEquals(RepeatStatus.FINISHED, result); - assertEquals(false, isCatchUpParameterCaptor.getValue()); - LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution() - .getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER); - assertEquals(2, loanCOBParameter.getMaxLoanId() - loanCOBParameter.getMinLoanId()); - assertEquals(1L, loanCOBParameter.getMinLoanId()); - assertEquals(3L, loanCOBParameter.getMaxLoanId()); - } else if ("chunk processing".equals(action)) { - verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture(), - isCatchUpParameterCaptor.capture()); - assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue()); - assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId()); - assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId()); - assertEquals(RepeatStatus.FINISHED, result); - assertEquals(false, isCatchUpParameterCaptor.getValue()); - LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution() - .getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER); - assertEquals(2, loanCOBParameter.getMaxLoanId() - loanCOBParameter.getMinLoanId()); - assertEquals(1L, loanCOBParameter.getMinLoanId()); - assertEquals(3L, loanCOBParameter.getMaxLoanId()); - } - }); - } -} diff --git a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilterTest.java b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilterTest.java index 68e838eab..a54c5b921 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilterTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/jobs/filter/LoanCOBApiFilterTest.java @@ -193,7 +193,6 @@ class LoanCOBApiFilterTest { given(request.getPathInfo()).willReturn("/v1/loans/2/charges"); given(request.getMethod()).willReturn(HTTPMethods.POST.value()); given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false); - given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false); given(context.authenticatedUser()).willReturn(appUser); given(fineractProperties.getQuery()).willReturn(fineractQueryProperties); given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000); @@ -221,7 +220,6 @@ class LoanCOBApiFilterTest { given(request.getPathInfo()).willReturn("/v1/loans/external-id/" + uuid + "/charges"); given(request.getMethod()).willReturn(HTTPMethods.POST.value()); given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false); - given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false); given(context.authenticatedUser()).willReturn(appUser); given(loanRepository.findIdByExternalId(any())).willReturn(2L); given(fineractProperties.getQuery()).willReturn(fineractQueryProperties); @@ -250,7 +248,6 @@ class LoanCOBApiFilterTest { given(request.getPathInfo()).willReturn("/v1/rescheduleloans/" + resourceId + "/charges"); given(request.getMethod()).willReturn(HTTPMethods.POST.value()); given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false); - given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false); given(fineractProperties.getQuery()).willReturn(fineractQueryProperties); given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000); LoanRescheduleRequest rescheduleRequest = mock(LoanRescheduleRequest.class); @@ -265,24 +262,6 @@ class LoanCOBApiFilterTest { verify(filterChain, times(1)).doFilter(request, response); } - @Test - void shouldRunInlineCOBAndProceedWhenLoanIsSoftLocked() throws ServletException, IOException { - MockHttpServletRequest request = mock(MockHttpServletRequest.class); - MockHttpServletResponse response = mock(MockHttpServletResponse.class); - FilterChain filterChain = mock(FilterChain.class); - AppUser appUser = mock(AppUser.class); - - given(request.getPathInfo()).willReturn("/v1/loans/2/charges"); - given(request.getMethod()).willReturn(HTTPMethods.POST.value()); - given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false); - given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(true); - given(context.authenticatedUser()).willReturn(appUser); - - testObj.doFilterInternal(request, response, filterChain); - verify(inlineLoanCOBExecutorService, times(1)).execute(Collections.singletonList(2L), "INLINE_LOAN_COB"); - verify(filterChain, times(1)).doFilter(request, response); - } - @Test void shouldRunInlineCOBAndProceedWhenLoanIsBehind() throws ServletException, IOException { MockHttpServletRequest request = mock(MockHttpServletRequest.class); @@ -299,16 +278,15 @@ class LoanCOBApiFilterTest { LoanIdAndLastClosedBusinessDate result = mock(LoanIdAndLastClosedBusinessDate.class); given(result.getId()).willReturn(2L); + given(result.getLastClosedBusinessDate()).willReturn(businessDate.minusDays(2)); given(request.getPathInfo()).willReturn("/v1/loans/2?command=approve"); given(request.getMethod()).willReturn(HTTPMethods.POST.value()); given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false); - given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(true); given(fineractProperties.getQuery()).willReturn(fineractQueryProperties); given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000); - given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds( + given(loanRepository.findAllNonClosedLoansBehindByLoanIds( eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList())) .willReturn(Collections.singletonList(result)); - given(context.authenticatedUser()).willReturn(appUser); testObj.doFilterInternal(request, response, filterChain); @@ -335,7 +313,6 @@ class LoanCOBApiFilterTest { given(request.getPathInfo()).willReturn("/v1/loans/2?command=approve"); given(request.getMethod()).willReturn(HTTPMethods.POST.value()); given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false); - given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false); given(fineractProperties.getQuery()).willReturn(fineractQueryProperties); given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000); given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds( diff --git a/fineract-provider/src/test/resources/features/cob/loan/cob.loan.fetch.lock.feature b/fineract-provider/src/test/resources/features/cob/loan/cob.loan.fetch.lock.feature deleted file mode 100644 index 9df96a0e6..000000000 --- a/fineract-provider/src/test/resources/features/cob/loan/cob.loan.fetch.lock.feature +++ /dev/null @@ -1,34 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -Feature: COB Loan fetch and (soft) lock Step - - @cob - Scenario Outline: FetchAndLockLoanTasklet - run test - Given The FetchAndLockLoanTasklet.execute method with action - When FetchAndLockLoanTasklet.execute method executed - Then FetchAndLockLoanTasklet.execute result should match - - Examples: - |action| - |empty loanIds| - |good| - |soft lock| - |inline cob| - |chunk processing| \ No newline at end of file diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/inlinecob/InlineLoanCOBTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/inlinecob/InlineLoanCOBTest.java index 50ca643cd..6d1b5d606 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/inlinecob/InlineLoanCOBTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/inlinecob/InlineLoanCOBTest.java @@ -284,7 +284,6 @@ public class InlineLoanCOBTest { requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec); - loanAccountLockHelper.placeSoftLockOnLoanAccount(loanID, "LOAN_COB_PARTITIONING"); loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec); loanTransactionHelper.makeRepayment("10 March 2020", 10.0f, loanID); @@ -399,8 +398,6 @@ public class InlineLoanCOBTest { BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, LocalDate.of(2020, 3, 10)); requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec); - - loanAccountLockHelper.placeSoftLockOnLoanAccount(loanID, "LOAN_COB_PARTITIONING"); loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec); final BatchRequest br1 = BatchHelper.oldRepayLoanRequestWithGivenLoanId(4730L, loanID, "10", LocalDate.of(2020, 3, 10)); @@ -468,8 +465,6 @@ public class InlineLoanCOBTest { BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, LocalDate.of(2020, 3, 10)); requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec); - - loanAccountLockHelper.placeSoftLockOnLoanAccount(loanID, "LOAN_COB_PARTITIONING"); loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec); final BatchRequest br1 = BatchHelper.repayLoanRequestWithGivenLoanId(4730L, loanID, "10", LocalDate.of(2020, 3, 10));