FINERACT-1678-loan-cob-drop-softlocking-use-lastclosedbusinessdate
This commit is contained in:
committed by
Adam Saghy
parent
005af94291
commit
e9bc0fe8c2
+2
-4
@@ -50,11 +50,9 @@ public interface LoanAccountLockRepository extends JpaRepository<LoanAccountLock
|
|||||||
void updateLoanFromAccountLocks();
|
void updateLoanFromAccountLocks();
|
||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
update LoanAccountLock lck set
|
delete from LoanAccountLock lck where lck.lockPlacedOnCobBusinessDate is not null and lck.error is not null and
|
||||||
lck.error = null, lck.lockOwner=org.apache.fineract.cob.domain.LockOwner.LOAN_COB_PARTITIONING
|
|
||||||
where lck.lockPlacedOnCobBusinessDate is not null and lck.error is not null and
|
|
||||||
lck.lockOwner in (org.apache.fineract.cob.domain.LockOwner.LOAN_COB_CHUNK_PROCESSING,org.apache.fineract.cob.domain.LockOwner.LOAN_INLINE_COB_PROCESSING)
|
lck.lockOwner in (org.apache.fineract.cob.domain.LockOwner.LOAN_COB_CHUNK_PROCESSING,org.apache.fineract.cob.domain.LockOwner.LOAN_INLINE_COB_PROCESSING)
|
||||||
""")
|
""")
|
||||||
@Modifying(flushAutomatically = true)
|
@Modifying(flushAutomatically = true)
|
||||||
void updateToSoftLockByOwner();
|
void removeLockByOwner();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,5 +19,5 @@
|
|||||||
package org.apache.fineract.cob.domain;
|
package org.apache.fineract.cob.domain;
|
||||||
|
|
||||||
public enum LockOwner {
|
public enum LockOwner {
|
||||||
LOAN_COB_PARTITIONING, LOAN_COB_CHUNK_PROCESSING, LOAN_INLINE_COB_PROCESSING;
|
LOAN_COB_CHUNK_PROCESSING, LOAN_INLINE_COB_PROCESSING;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-16
@@ -22,10 +22,7 @@ import com.google.common.collect.Lists;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.fineract.cob.common.CustomJobParameterResolver;
|
import org.apache.fineract.cob.common.CustomJobParameterResolver;
|
||||||
@@ -69,23 +66,13 @@ public class ApplyLoanLockTasklet implements Tasklet {
|
|||||||
List<LoanAccountLock> accountLocks = new ArrayList<>();
|
List<LoanAccountLock> accountLocks = new ArrayList<>();
|
||||||
loanIdPartitions.forEach(loanIdPartition -> accountLocks.addAll(loanLockingService.findAllByLoanIdIn(loanIdPartition)));
|
loanIdPartitions.forEach(loanIdPartition -> accountLocks.addAll(loanLockingService.findAllByLoanIdIn(loanIdPartition)));
|
||||||
|
|
||||||
Map<Long, LoanAccountLock> alreadySoftLockedAccountsMap = accountLocks.stream()
|
|
||||||
.filter(e -> LockOwner.LOAN_COB_PARTITIONING.equals(e.getLockOwner()))
|
|
||||||
.collect(Collectors.toMap(LoanAccountLock::getLoanId, Function.identity()));
|
|
||||||
|
|
||||||
List<Long> alreadyLockedByChunkProcessingAccountIds = accountLocks.stream()
|
List<Long> alreadyLockedByChunkProcessingAccountIds = accountLocks.stream()
|
||||||
.filter(e -> LockOwner.LOAN_COB_CHUNK_PROCESSING.equals(e.getLockOwner())).map(LoanAccountLock::getLoanId).toList();
|
.filter(e -> LockOwner.LOAN_COB_CHUNK_PROCESSING.equals(e.getLockOwner())).map(LoanAccountLock::getLoanId).toList();
|
||||||
|
|
||||||
List<Long> toBeProcessedLoanIds = new ArrayList<>(alreadySoftLockedAccountsMap.keySet());
|
List<Long> toBeProcessedLoanIds = new ArrayList<>(loanIds);
|
||||||
|
toBeProcessedLoanIds.removeAll(alreadyLockedByChunkProcessingAccountIds);
|
||||||
loanLockingService.upgradeLock(toBeProcessedLoanIds, LockOwner.LOAN_COB_CHUNK_PROCESSING);
|
|
||||||
|
|
||||||
toBeProcessedLoanIds.addAll(alreadyLockedByChunkProcessingAccountIds);
|
|
||||||
List<Long> alreadyLockedByInlineCOBOrProcessedLoanIds = new ArrayList<>(loanIds);
|
|
||||||
alreadyLockedByInlineCOBOrProcessedLoanIds.removeAll(toBeProcessedLoanIds);
|
|
||||||
|
|
||||||
loanIds.removeAll(alreadyLockedByInlineCOBOrProcessedLoanIds);
|
|
||||||
|
|
||||||
|
loanLockingService.applyLock(toBeProcessedLoanIds, LockOwner.LOAN_COB_CHUNK_PROCESSING);
|
||||||
return RepeatStatus.FINISHED;
|
return RepeatStatus.FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-14
@@ -73,8 +73,6 @@ public class LoanCOBManagerConfiguration {
|
|||||||
private BusinessEventNotifierService businessEventNotifierService;
|
private BusinessEventNotifierService businessEventNotifierService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private CustomJobParameterResolver customJobParameterResolver;
|
private CustomJobParameterResolver customJobParameterResolver;
|
||||||
@Autowired
|
|
||||||
private LoanLockingService loanLockingService;
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@JobScope
|
@JobScope
|
||||||
@@ -93,11 +91,6 @@ public class LoanCOBManagerConfiguration {
|
|||||||
return localStepBuilderFactory.get("Set loan ID parameter - Step").tasklet(loanIdParameterTasklet()).build();
|
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
|
@Bean
|
||||||
public Step resolveCustomJobParametersStep() {
|
public Step resolveCustomJobParametersStep() {
|
||||||
return localStepBuilderFactory.get("Resolve custom job parameters - Step").tasklet(resolveCustomJobParametersTasklet())
|
return localStepBuilderFactory.get("Resolve custom job parameters - Step").tasklet(resolveCustomJobParametersTasklet())
|
||||||
@@ -115,12 +108,6 @@ public class LoanCOBManagerConfiguration {
|
|||||||
return new LoanIdParameterTasklet(retrieveLoanIdService, customJobParameterResolver);
|
return new LoanIdParameterTasklet(retrieveLoanIdService, customJobParameterResolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
@JobScope
|
|
||||||
public LockLoanTasklet lockLoanTasklet() {
|
|
||||||
return new LockLoanTasklet(loanLockingService, customJobParameterResolver);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@JobScope
|
@JobScope
|
||||||
public ResolveLoanCOBCustomJobParametersTasklet resolveCustomJobParametersTasklet() {
|
public ResolveLoanCOBCustomJobParametersTasklet resolveCustomJobParametersTasklet() {
|
||||||
@@ -138,7 +125,7 @@ public class LoanCOBManagerConfiguration {
|
|||||||
return jobBuilderFactory.get(JobName.LOAN_COB.name()) //
|
return jobBuilderFactory.get(JobName.LOAN_COB.name()) //
|
||||||
.listener(new COBExecutionListenerRunner(applicationContext, JobName.LOAN_COB.name())) //
|
.listener(new COBExecutionListenerRunner(applicationContext, JobName.LOAN_COB.name())) //
|
||||||
.start(resolveCustomJobParametersStep()) //
|
.start(resolveCustomJobParametersStep()) //
|
||||||
.next(loanIdParameterStep()).next(lockStep()).next(loanCOBStep()).next(stayedLockedStep()) //
|
.next(loanIdParameterStep()).next(loanCOBStep()).next(stayedLockedStep()) //
|
||||||
.incrementer(new RunIdIncrementer()) //
|
.incrementer(new RunIdIncrementer()) //
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-4
@@ -18,16 +18,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.cob.loan;
|
package org.apache.fineract.cob.loan;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.apache.fineract.cob.data.LoanCOBParameter;
|
|
||||||
import org.apache.fineract.cob.domain.LoanAccountLock;
|
import org.apache.fineract.cob.domain.LoanAccountLock;
|
||||||
import org.apache.fineract.cob.domain.LockOwner;
|
import org.apache.fineract.cob.domain.LockOwner;
|
||||||
|
|
||||||
public interface LoanLockingService {
|
public interface LoanLockingService {
|
||||||
|
|
||||||
void applySoftLock(LocalDate lastClosedBusinessDate, LoanCOBParameter loanCOBParameter, boolean isCatchUp);
|
|
||||||
|
|
||||||
void upgradeLock(List<Long> accountsToLock, LockOwner lockOwner);
|
void upgradeLock(List<Long> accountsToLock, LockOwner lockOwner);
|
||||||
|
|
||||||
void deleteByLoanIdInAndLockOwner(List<Long> loanIds, LockOwner lockOwner);
|
void deleteByLoanIdInAndLockOwner(List<Long> loanIds, LockOwner lockOwner);
|
||||||
@@ -35,4 +31,6 @@ public interface LoanLockingService {
|
|||||||
List<LoanAccountLock> findAllByLoanIdIn(List<Long> loanIds);
|
List<LoanAccountLock> findAllByLoanIdIn(List<Long> loanIds);
|
||||||
|
|
||||||
LoanAccountLock findByLoanIdAndLockOwner(Long loanId, LockOwner lockOwner);
|
LoanAccountLock findByLoanIdAndLockOwner(Long loanId, LockOwner lockOwner);
|
||||||
|
|
||||||
|
void applyLock(List<Long> loanIds, LockOwner lockOwner);
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-16
@@ -18,11 +18,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.apache.fineract.cob.loan;
|
package org.apache.fineract.cob.loan;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
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.LoanAccountLock;
|
||||||
import org.apache.fineract.cob.domain.LoanAccountLockRepository;
|
import org.apache.fineract.cob.domain.LoanAccountLockRepository;
|
||||||
import org.apache.fineract.cob.domain.LockOwner;
|
import org.apache.fineract.cob.domain.LockOwner;
|
||||||
@@ -53,25 +53,14 @@ public class LoanLockingServiceImpl implements LoanLockingService {
|
|||||||
AND (? = loan.last_closed_business_date)
|
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 JdbcTemplate jdbcTemplate;
|
||||||
private final FineractProperties fineractProperties;
|
private final FineractProperties fineractProperties;
|
||||||
private final LoanAccountLockRepository loanAccountLockRepository;
|
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
|
@Override
|
||||||
public void upgradeLock(List<Long> accountsToLock, LockOwner lockOwner) {
|
public void upgradeLock(List<Long> accountsToLock, LockOwner lockOwner) {
|
||||||
jdbcTemplate.batchUpdate("""
|
jdbcTemplate.batchUpdate("""
|
||||||
@@ -96,6 +85,18 @@ public class LoanLockingServiceImpl implements LoanLockingService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyLock(List<Long> 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
|
@Override
|
||||||
public void deleteByLoanIdInAndLockOwner(List<Long> loanIds, LockOwner lockOwner) {
|
public void deleteByLoanIdInAndLockOwner(List<Long> loanIds, LockOwner lockOwner) {
|
||||||
loanAccountLockRepository.deleteByLoanIdInAndLockOwner(loanIds, lockOwner);
|
loanAccountLockRepository.deleteByLoanIdInAndLockOwner(loanIds, lockOwner);
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -226,7 +226,7 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService<L
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLockOverrulable(LoanAccountLock loanAccountLock) {
|
private boolean isLockOverrulable(LoanAccountLock loanAccountLock) {
|
||||||
if (LockOwner.LOAN_COB_PARTITIONING.equals(loanAccountLock.getLockOwner()) || isBypassUser()) {
|
if (isBypassUser()) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return StringUtils.isNotBlank(loanAccountLock.getError());
|
return StringUtils.isNotBlank(loanAccountLock.getError());
|
||||||
|
|||||||
-2
@@ -27,7 +27,5 @@ public interface LoanAccountLockService {
|
|||||||
|
|
||||||
boolean isLoanHardLocked(Long loanId);
|
boolean isLoanHardLocked(Long loanId);
|
||||||
|
|
||||||
boolean isLoanSoftLocked(Long loanId);
|
|
||||||
|
|
||||||
void updateCobAndRemoveLocks();
|
void updateCobAndRemoveLocks();
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-6
@@ -49,16 +49,11 @@ public class LoanAccountLockServiceImpl implements LoanAccountLockService {
|
|||||||
|| loanAccountLockRepository.existsByLoanIdAndLockOwner(loanId, LockOwner.LOAN_INLINE_COB_PROCESSING);
|
|| loanAccountLockRepository.existsByLoanIdAndLockOwner(loanId, LockOwner.LOAN_INLINE_COB_PROCESSING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoanSoftLocked(Long loanId) {
|
|
||||||
return loanAccountLockRepository.existsByLoanIdAndLockOwner(loanId, LockOwner.LOAN_COB_PARTITIONING);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||||
public void updateCobAndRemoveLocks() {
|
public void updateCobAndRemoveLocks() {
|
||||||
loanAccountLockRepository.updateLoanFromAccountLocks();
|
loanAccountLockRepository.updateLoanFromAccountLocks();
|
||||||
loanAccountLockRepository.updateToSoftLockByOwner();
|
loanAccountLockRepository.removeLockByOwner();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-12
@@ -121,7 +121,7 @@ public class LoanCOBApiFilter extends OncePerRequestFilter implements BatchReque
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
List<Long> loanIds = calculateRelevantLoanIds(request.getPathInfo());
|
List<Long> loanIds = calculateRelevantLoanIds(request.getPathInfo());
|
||||||
if (!loanIds.isEmpty() && (isLoanSoftLocked(loanIds) || isLoanBehind(loanIds))) {
|
if (!loanIds.isEmpty() && isLoanBehind(loanIds)) {
|
||||||
executeInlineCob(loanIds);
|
executeInlineCob(loanIds);
|
||||||
}
|
}
|
||||||
proceed(filterChain, request, response);
|
proceed(filterChain, request, response);
|
||||||
@@ -184,17 +184,8 @@ public class LoanCOBApiFilter extends OncePerRequestFilter implements BatchReque
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLoanSoftLocked(List<Long> loanIds) {
|
|
||||||
return isLoanLocked(loanIds, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isLoanHardLocked(List<Long> loanIds) {
|
private boolean isLoanHardLocked(List<Long> loanIds) {
|
||||||
return isLoanLocked(loanIds, true);
|
return loanIds.stream().anyMatch(loanAccountLockService::isLoanHardLocked);
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isLoanLocked(List<Long> loanIds, boolean isHardLock) {
|
|
||||||
return isHardLock ? loanIds.stream().anyMatch(loanAccountLockService::isLoanHardLocked)
|
|
||||||
: loanIds.stream().anyMatch(loanAccountLockService::isLoanSoftLocked);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void proceed(FilterChain filterChain, HttpServletRequest request, HttpServletResponse response)
|
private void proceed(FilterChain filterChain, HttpServletRequest request, HttpServletResponse response)
|
||||||
@@ -256,7 +247,7 @@ public class LoanCOBApiFilter extends OncePerRequestFilter implements BatchReque
|
|||||||
boolean bypassUser = isBypassUser();
|
boolean bypassUser = isBypassUser();
|
||||||
if (!bypassUser) {
|
if (!bypassUser) {
|
||||||
List<Long> result = calculateRelevantLoanIds(relativeUrl);
|
List<Long> result = calculateRelevantLoanIds(relativeUrl);
|
||||||
if (!result.isEmpty() && (isLoanSoftLocked(result) || isLoanBehind(result))) {
|
if (!result.isEmpty() && isLoanBehind(result)) {
|
||||||
executeInlineCob(result);
|
executeInlineCob(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,4 +127,5 @@
|
|||||||
<include file="parts/0105_add_indices_loan_table.xml" relativeToChangelogFile="true" />
|
<include file="parts/0105_add_indices_loan_table.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/0106_new_repayment_strategy.xml" relativeToChangelogFile="true" />
|
<include file="parts/0106_new_repayment_strategy.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/0107_add_configuration_charges_accrual_date.xml" relativeToChangelogFile="true" />
|
<include file="parts/0107_add_configuration_charges_accrual_date.xml" relativeToChangelogFile="true" />
|
||||||
|
<include file="parts/0108_precondition_check_cob_loan_account_lock.xml" relativeToChangelogFile="true" />
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
|
||||||
|
<changeSet author="fineract" id="1">
|
||||||
|
<preConditions onFail="HALT" onFailMessage="Loan COB check failed: There should not be any soft locks for loan account.">
|
||||||
|
<sqlCheck expectedResult="0">select count(*) from m_loan_account_locks where lock_owner = 'LOAN_COB_PARTITIONING'</sqlCheck>
|
||||||
|
</preConditions>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
+2
-3
@@ -83,10 +83,9 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
|
|||||||
lenient().when(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenThrow(new RuntimeException("fail"));
|
lenient().when(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenThrow(new RuntimeException("fail"));
|
||||||
} else {
|
} else {
|
||||||
LoanAccountLock lock1 = new LoanAccountLock(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()));
|
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,
|
LoanAccountLock lock3 = new LoanAccountLock(3L, LockOwner.LOAN_INLINE_COB_PROCESSING,
|
||||||
LocalDate.now(ZoneId.systemDefault()));
|
LocalDate.now(ZoneId.systemDefault()));
|
||||||
List<LoanAccountLock> accountLocks = List.of(lock1, lock2, lock3);
|
List<LoanAccountLock> accountLocks = List.of(lock1, lock3);
|
||||||
lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
|
lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
|
||||||
lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
|
lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
|
||||||
lenient().when(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenReturn(accountLocks);
|
lenient().when(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenReturn(accountLocks);
|
||||||
@@ -101,7 +100,7 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
|
|||||||
|
|
||||||
Then("ApplyLoanLockTasklet.execute result should match", () -> {
|
Then("ApplyLoanLockTasklet.execute result should match", () -> {
|
||||||
assertEquals(RepeatStatus.FINISHED, resultItem);
|
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<Long> values = valueCaptor.getValue();
|
List<Long> values = valueCaptor.getValue();
|
||||||
assertEquals(2L, values.get(0));
|
assertEquals(2L, values.get(0));
|
||||||
assertEquals(LockOwner.LOAN_COB_CHUNK_PROCESSING, lockOwnerValueCaptor.getValue());
|
assertEquals(LockOwner.LOAN_COB_CHUNK_PROCESSING, lockOwnerValueCaptor.getValue());
|
||||||
|
|||||||
-178
@@ -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<LocalDate> dateValueCaptor = ArgumentCaptor.forClass(LocalDate.class);
|
|
||||||
ArgumentCaptor<LoanCOBParameter> loanCOBParameterValueCaptor = ArgumentCaptor.forClass(LoanCOBParameter.class);
|
|
||||||
|
|
||||||
ArgumentCaptor<Boolean> 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<BusinessDateType, LocalDate> 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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-25
@@ -193,7 +193,6 @@ class LoanCOBApiFilterTest {
|
|||||||
given(request.getPathInfo()).willReturn("/v1/loans/2/charges");
|
given(request.getPathInfo()).willReturn("/v1/loans/2/charges");
|
||||||
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
||||||
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
||||||
given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false);
|
|
||||||
given(context.authenticatedUser()).willReturn(appUser);
|
given(context.authenticatedUser()).willReturn(appUser);
|
||||||
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
||||||
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
|
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
|
||||||
@@ -221,7 +220,6 @@ class LoanCOBApiFilterTest {
|
|||||||
given(request.getPathInfo()).willReturn("/v1/loans/external-id/" + uuid + "/charges");
|
given(request.getPathInfo()).willReturn("/v1/loans/external-id/" + uuid + "/charges");
|
||||||
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
||||||
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
||||||
given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false);
|
|
||||||
given(context.authenticatedUser()).willReturn(appUser);
|
given(context.authenticatedUser()).willReturn(appUser);
|
||||||
given(loanRepository.findIdByExternalId(any())).willReturn(2L);
|
given(loanRepository.findIdByExternalId(any())).willReturn(2L);
|
||||||
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
||||||
@@ -250,7 +248,6 @@ class LoanCOBApiFilterTest {
|
|||||||
given(request.getPathInfo()).willReturn("/v1/rescheduleloans/" + resourceId + "/charges");
|
given(request.getPathInfo()).willReturn("/v1/rescheduleloans/" + resourceId + "/charges");
|
||||||
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
||||||
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
||||||
given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false);
|
|
||||||
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
||||||
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
|
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
|
||||||
LoanRescheduleRequest rescheduleRequest = mock(LoanRescheduleRequest.class);
|
LoanRescheduleRequest rescheduleRequest = mock(LoanRescheduleRequest.class);
|
||||||
@@ -265,24 +262,6 @@ class LoanCOBApiFilterTest {
|
|||||||
verify(filterChain, times(1)).doFilter(request, response);
|
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
|
@Test
|
||||||
void shouldRunInlineCOBAndProceedWhenLoanIsBehind() throws ServletException, IOException {
|
void shouldRunInlineCOBAndProceedWhenLoanIsBehind() throws ServletException, IOException {
|
||||||
MockHttpServletRequest request = mock(MockHttpServletRequest.class);
|
MockHttpServletRequest request = mock(MockHttpServletRequest.class);
|
||||||
@@ -299,16 +278,15 @@ class LoanCOBApiFilterTest {
|
|||||||
|
|
||||||
LoanIdAndLastClosedBusinessDate result = mock(LoanIdAndLastClosedBusinessDate.class);
|
LoanIdAndLastClosedBusinessDate result = mock(LoanIdAndLastClosedBusinessDate.class);
|
||||||
given(result.getId()).willReturn(2L);
|
given(result.getId()).willReturn(2L);
|
||||||
|
given(result.getLastClosedBusinessDate()).willReturn(businessDate.minusDays(2));
|
||||||
given(request.getPathInfo()).willReturn("/v1/loans/2?command=approve");
|
given(request.getPathInfo()).willReturn("/v1/loans/2?command=approve");
|
||||||
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
||||||
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
||||||
given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(true);
|
|
||||||
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
||||||
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
|
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
|
||||||
given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
|
given(loanRepository.findAllNonClosedLoansBehindByLoanIds(
|
||||||
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList()))
|
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList()))
|
||||||
.willReturn(Collections.singletonList(result));
|
.willReturn(Collections.singletonList(result));
|
||||||
|
|
||||||
given(context.authenticatedUser()).willReturn(appUser);
|
given(context.authenticatedUser()).willReturn(appUser);
|
||||||
|
|
||||||
testObj.doFilterInternal(request, response, filterChain);
|
testObj.doFilterInternal(request, response, filterChain);
|
||||||
@@ -335,7 +313,6 @@ class LoanCOBApiFilterTest {
|
|||||||
given(request.getPathInfo()).willReturn("/v1/loans/2?command=approve");
|
given(request.getPathInfo()).willReturn("/v1/loans/2?command=approve");
|
||||||
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
given(request.getMethod()).willReturn(HTTPMethods.POST.value());
|
||||||
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
|
||||||
given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false);
|
|
||||||
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
|
||||||
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
|
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
|
||||||
given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
|
given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
|
||||||
|
|||||||
@@ -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 <action>
|
|
||||||
When FetchAndLockLoanTasklet.execute method executed
|
|
||||||
Then FetchAndLockLoanTasklet.execute result should match
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|action|
|
|
||||||
|empty loanIds|
|
|
||||||
|good|
|
|
||||||
|soft lock|
|
|
||||||
|inline cob|
|
|
||||||
|chunk processing|
|
|
||||||
-5
@@ -284,7 +284,6 @@ public class InlineLoanCOBTest {
|
|||||||
|
|
||||||
requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec);
|
requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec);
|
||||||
|
|
||||||
loanAccountLockHelper.placeSoftLockOnLoanAccount(loanID, "LOAN_COB_PARTITIONING");
|
|
||||||
loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
|
loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
|
||||||
|
|
||||||
loanTransactionHelper.makeRepayment("10 March 2020", 10.0f, loanID);
|
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));
|
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, LocalDate.of(2020, 3, 10));
|
||||||
|
|
||||||
requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec);
|
requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec);
|
||||||
|
|
||||||
loanAccountLockHelper.placeSoftLockOnLoanAccount(loanID, "LOAN_COB_PARTITIONING");
|
|
||||||
loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
|
loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
|
||||||
|
|
||||||
final BatchRequest br1 = BatchHelper.oldRepayLoanRequestWithGivenLoanId(4730L, loanID, "10", LocalDate.of(2020, 3, 10));
|
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));
|
BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, LocalDate.of(2020, 3, 10));
|
||||||
|
|
||||||
requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec);
|
requestSpec = UserHelper.getSimpleUserWithoutBypassPermission(requestSpec, responseSpec);
|
||||||
|
|
||||||
loanAccountLockHelper.placeSoftLockOnLoanAccount(loanID, "LOAN_COB_PARTITIONING");
|
|
||||||
loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
|
loanTransactionHelper = new LoanTransactionHelper(requestSpec, responseSpec);
|
||||||
|
|
||||||
final BatchRequest br1 = BatchHelper.repayLoanRequestWithGivenLoanId(4730L, loanID, "10", LocalDate.of(2020, 3, 10));
|
final BatchRequest br1 = BatchHelper.repayLoanRequestWithGivenLoanId(4730L, loanID, "10", LocalDate.of(2020, 3, 10));
|
||||||
|
|||||||
Reference in New Issue
Block a user