[FINERACT-1724] making partition for big parameter lists

This commit is contained in:
taskain7
2023-03-14 18:12:42 +01:00
committed by Aleksandar Vidakovic
parent ca5c7d8747
commit 071cdae69b
15 changed files with 150 additions and 32 deletions
@@ -18,6 +18,7 @@
*/ */
package org.apache.fineract.cob.loan; package org.apache.fineract.cob.loan;
import com.google.common.collect.Lists;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -28,6 +29,7 @@ import lombok.extern.slf4j.Slf4j;
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;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.scope.context.ChunkContext;
@@ -40,13 +42,15 @@ import org.springframework.batch.repeat.RepeatStatus;
public class ApplyLoanLockTasklet implements Tasklet { public class ApplyLoanLockTasklet implements Tasklet {
private final LoanAccountLockRepository accountLockRepository; private final LoanAccountLockRepository accountLockRepository;
private final FineractProperties fineractProperties;
@Override @Override
public RepeatStatus execute(@NotNull StepContribution contribution, @NotNull ChunkContext chunkContext) throws Exception { public RepeatStatus execute(@NotNull StepContribution contribution, @NotNull ChunkContext chunkContext) throws Exception {
ExecutionContext executionContext = contribution.getStepExecution().getExecutionContext(); ExecutionContext executionContext = contribution.getStepExecution().getExecutionContext();
List<Long> loanIds = (List<Long>) executionContext.get(LoanCOBConstant.LOAN_IDS); List<Long> loanIds = (List<Long>) executionContext.get(LoanCOBConstant.LOAN_IDS);
List<List<Long>> loanIdPartitions = Lists.partition(loanIds, fineractProperties.getQuery().getInClauseParameterSizeLimit());
List<LoanAccountLock> accountLocks = accountLockRepository.findAllByLoanIdIn(loanIds); List<LoanAccountLock> accountLocks = new ArrayList<>();
loanIdPartitions.forEach(loanIdPartition -> accountLocks.addAll(accountLockRepository.findAllByLoanIdIn(loanIdPartition)));
Map<Long, LoanAccountLock> alreadySoftLockedAccountsMap = accountLocks.stream() Map<Long, LoanAccountLock> alreadySoftLockedAccountsMap = accountLocks.stream()
.filter(e -> LockOwner.LOAN_COB_PARTITIONING.equals(e.getLockOwner())) .filter(e -> LockOwner.LOAN_COB_PARTITIONING.equals(e.getLockOwner()))
@@ -18,6 +18,7 @@
*/ */
package org.apache.fineract.cob.loan; package org.apache.fineract.cob.loan;
import com.google.common.collect.Lists;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -27,6 +28,7 @@ import lombok.extern.slf4j.Slf4j;
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;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.batch.core.StepContribution; import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.scope.context.ChunkContext;
@@ -43,6 +45,8 @@ public class FetchAndLockLoanTasklet implements Tasklet {
private final RetrieveLoanIdService retrieveLoanIdService; private final RetrieveLoanIdService retrieveLoanIdService;
private final FineractProperties fineractProperties;
@Override @Override
public RepeatStatus execute(@NotNull StepContribution contribution, @NotNull ChunkContext chunkContext) throws Exception { public RepeatStatus execute(@NotNull StepContribution contribution, @NotNull ChunkContext chunkContext) throws Exception {
String businessDateParameter = (String) contribution.getStepExecution().getJobExecution().getExecutionContext() String businessDateParameter = (String) contribution.getStepExecution().getJobExecution().getExecutionContext()
@@ -54,7 +58,11 @@ public class FetchAndLockLoanTasklet implements Tasklet {
} }
List<Long> remainingIds = new ArrayList<>(allNonClosedLoanIds); List<Long> remainingIds = new ArrayList<>(allNonClosedLoanIds);
List<LoanAccountLock> loanAccountLocks = loanAccountLockRepository.findAllByLoanIdIn(remainingIds); List<List<Long>> remainingIdPartitions = Lists.partition(remainingIds,
fineractProperties.getQuery().getInClauseParameterSizeLimit());
List<LoanAccountLock> loanAccountLocks = new ArrayList<>();
remainingIdPartitions.forEach(
remainingIdPartition -> loanAccountLocks.addAll(loanAccountLockRepository.findAllByLoanIdIn(remainingIdPartition)));
List<Long> alreadySoftLockedAccounts = loanAccountLocks.stream() List<Long> alreadySoftLockedAccounts = loanAccountLocks.stream()
.filter(e -> LockOwner.LOAN_COB_PARTITIONING.equals(e.getLockOwner())).map(LoanAccountLock::getLoanId).toList(); .filter(e -> LockOwner.LOAN_COB_PARTITIONING.equals(e.getLockOwner())).map(LoanAccountLock::getLoanId).toList();
@@ -23,6 +23,7 @@ import org.apache.fineract.cob.COBBusinessStepService;
import org.apache.fineract.cob.common.CustomJobParameterResolver; import org.apache.fineract.cob.common.CustomJobParameterResolver;
import org.apache.fineract.cob.domain.LoanAccountLockRepository; import org.apache.fineract.cob.domain.LoanAccountLockRepository;
import org.apache.fineract.cob.listener.COBExecutionListenerRunner; import org.apache.fineract.cob.listener.COBExecutionListenerRunner;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService; import org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import org.apache.fineract.infrastructure.jobs.service.JobName; import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.infrastructure.springbatch.PropertyService; import org.apache.fineract.infrastructure.springbatch.PropertyService;
@@ -79,6 +80,8 @@ public class LoanCOBManagerConfiguration {
private CustomJobParameterResolver customJobParameterResolver; private CustomJobParameterResolver customJobParameterResolver;
@Autowired @Autowired
private LoanRepository loanRepository; private LoanRepository loanRepository;
@Autowired
private FineractProperties fineractProperties;
@Bean @Bean
@JobScope @JobScope
@@ -111,7 +114,7 @@ public class LoanCOBManagerConfiguration {
@Bean @Bean
@JobScope @JobScope
public FetchAndLockLoanTasklet fetchAndLockLoanTasklet() { public FetchAndLockLoanTasklet fetchAndLockLoanTasklet() {
return new FetchAndLockLoanTasklet(accountLockRepository, retrieveLoanIdService); return new FetchAndLockLoanTasklet(accountLockRepository, retrieveLoanIdService, fineractProperties);
} }
@Bean @Bean
@@ -23,6 +23,7 @@ import org.apache.fineract.cob.common.InitialisationTasklet;
import org.apache.fineract.cob.common.ResetContextTasklet; import org.apache.fineract.cob.common.ResetContextTasklet;
import org.apache.fineract.cob.domain.LoanAccountLockRepository; import org.apache.fineract.cob.domain.LoanAccountLockRepository;
import org.apache.fineract.cob.listener.ChunkProcessingLoanItemListener; import org.apache.fineract.cob.listener.ChunkProcessingLoanItemListener;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.jobs.service.JobName; import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.apache.fineract.infrastructure.springbatch.PropertyService; import org.apache.fineract.infrastructure.springbatch.PropertyService;
import org.apache.fineract.portfolio.loanaccount.domain.Loan; import org.apache.fineract.portfolio.loanaccount.domain.Loan;
@@ -67,6 +68,9 @@ public class LoanCOBWorkerConfiguration {
@Autowired @Autowired
private TransactionTemplate transactionTemplate; private TransactionTemplate transactionTemplate;
@Autowired
private FineractProperties fineractProperties;
@Bean(name = LoanCOBConstant.LOAN_COB_WORKER_STEP) @Bean(name = LoanCOBConstant.LOAN_COB_WORKER_STEP)
public Step loanCOBWorkerStep() { public Step loanCOBWorkerStep() {
return stepBuilderFactory.get("Loan COB worker - Step").inputChannel(inboundRequests).flow(flow()).build(); return stepBuilderFactory.get("Loan COB worker - Step").inputChannel(inboundRequests).flow(flow()).build();
@@ -118,7 +122,7 @@ public class LoanCOBWorkerConfiguration {
@Bean @Bean
public ApplyLoanLockTasklet applyLock() { public ApplyLoanLockTasklet applyLock() {
return new ApplyLoanLockTasklet(accountLockRepository); return new ApplyLoanLockTasklet(accountLockRepository, fineractProperties);
} }
@Bean @Bean
@@ -20,6 +20,7 @@ package org.apache.fineract.cob.service;
import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW; import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW;
import com.google.common.collect.Lists;
import com.google.gson.Gson; import com.google.gson.Gson;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@@ -40,6 +41,7 @@ import org.apache.fineract.cob.exceptions.LoanAccountLockCannotBeOverruledExcept
import org.apache.fineract.cob.loan.LoanCOBConstant; import org.apache.fineract.cob.loan.LoanCOBConstant;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformInternalServerException; import org.apache.fineract.infrastructure.core.exception.PlatformInternalServerException;
@@ -85,6 +87,7 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService<L
private final CustomJobParameterRepository customJobParameterRepository; private final CustomJobParameterRepository customJobParameterRepository;
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final LoanRepository loanRepository; private final LoanRepository loanRepository;
private final FineractProperties fineractProperties;
private final Gson gson = GoogleGsonSerializerHelper.createSimpleGson(); private final Gson gson = GoogleGsonSerializerHelper.createSimpleGson();
@@ -155,7 +158,11 @@ public class InlineLoanCOBExecutorServiceImpl implements InlineExecutorService<L
} }
private List<LoanIdAndLastClosedBusinessDate> getLoansToBeProcessed(List<Long> loanIds, LocalDate cobBusinessDate) { private List<LoanIdAndLastClosedBusinessDate> getLoansToBeProcessed(List<Long> loanIds, LocalDate cobBusinessDate) {
return loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(cobBusinessDate, loanIds); List<LoanIdAndLastClosedBusinessDate> loanIdAndLastClosedBusinessDates = new ArrayList<>();
List<List<Long>> partitions = Lists.partition(loanIds, fineractProperties.getQuery().getInClauseParameterSizeLimit());
partitions.forEach(partition -> loanIdAndLastClosedBusinessDates
.addAll(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(cobBusinessDate, partition)));
return loanIdAndLastClosedBusinessDates;
} }
private List<LoanAccountLock> getLoanAccountLocks(List<Long> loanIds) { private List<LoanAccountLock> getLoanAccountLocks(List<Long> loanIds) {
@@ -55,6 +55,8 @@ public class FineractProperties {
private FineractTemplateProperties template; private FineractTemplateProperties template;
private FineractJpaProperties jpa; private FineractJpaProperties jpa;
private FineractQueryProperties query;
@Getter @Getter
@Setter @Setter
public static class FineractTenantProperties { public static class FineractTenantProperties {
@@ -255,4 +257,12 @@ public class FineractProperties {
private boolean statementLoggingEnabled; private boolean statementLoggingEnabled;
} }
@Getter
@Setter
public static class FineractQueryProperties {
private int inClauseParameterSizeLimit;
}
} }
@@ -18,8 +18,10 @@
*/ */
package org.apache.fineract.infrastructure.jobs.filter; package org.apache.fineract.infrastructure.jobs.filter;
import com.google.common.collect.Lists;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Predicate; import java.util.function.Predicate;
@@ -35,9 +37,11 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.batch.domain.BatchRequest; import org.apache.fineract.batch.domain.BatchRequest;
import org.apache.fineract.batch.domain.BatchResponse; import org.apache.fineract.batch.domain.BatchResponse;
import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
import org.apache.fineract.cob.service.InlineLoanCOBExecutorServiceImpl; import org.apache.fineract.cob.service.InlineLoanCOBExecutorServiceImpl;
import org.apache.fineract.cob.service.LoanAccountLockService; import org.apache.fineract.cob.service.LoanAccountLockService;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse; import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse;
import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.filters.BatchFilter; import org.apache.fineract.infrastructure.core.filters.BatchFilter;
@@ -64,6 +68,7 @@ public class LoanCOBApiFilter extends OncePerRequestFilter implements BatchFilte
private final PlatformSecurityContext context; private final PlatformSecurityContext context;
private final InlineLoanCOBExecutorServiceImpl inlineLoanCOBExecutorService; private final InlineLoanCOBExecutorServiceImpl inlineLoanCOBExecutorService;
private final LoanRepository loanRepository; private final LoanRepository loanRepository;
private final FineractProperties fineractProperties;
private final LoanRescheduleRequestRepository loanRescheduleRequestRepository; private final LoanRescheduleRequestRepository loanRescheduleRequestRepository;
@@ -141,8 +146,11 @@ public class LoanCOBApiFilter extends OncePerRequestFilter implements BatchFilte
} }
private boolean isLoanBehind(List<Long> loanIds) { private boolean isLoanBehind(List<Long> loanIds) {
return CollectionUtils.isNotEmpty(loanRepository List<LoanIdAndLastClosedBusinessDate> loanIdAndLastClosedBusinessDates = new ArrayList<>();
.findAllNonClosedLoansBehindByLoanIds(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE), loanIds)); List<List<Long>> partitions = Lists.partition(loanIds, fineractProperties.getQuery().getInClauseParameterSizeLimit());
partitions.forEach(partition -> loanIdAndLastClosedBusinessDates.addAll(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE), partition)));
return CollectionUtils.isNotEmpty(loanIdAndLastClosedBusinessDates);
} }
private List<Long> calculateRelevantLoanIds(String pathInfo) { private List<Long> calculateRelevantLoanIds(String pathInfo) {
@@ -25,15 +25,18 @@ import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAcc
import static org.apache.fineract.portfolio.account.api.AccountTransfersApiConstants.transferAmountParamName; import static org.apache.fineract.portfolio.account.api.AccountTransfersApiConstants.transferAmountParamName;
import static org.apache.fineract.portfolio.account.api.AccountTransfersApiConstants.transferDateParamName; import static org.apache.fineract.portfolio.account.api.AccountTransfersApiConstants.transferDateParamName;
import com.google.common.collect.Lists;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService; import org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult; import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder; import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.domain.ExternalId;
@@ -86,6 +89,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
private final GSIMRepositoy gsimRepository; private final GSIMRepositoy gsimRepository;
private final ConfigurationDomainService configurationDomainService; private final ConfigurationDomainService configurationDomainService;
private final ExternalIdFactory externalIdFactory; private final ExternalIdFactory externalIdFactory;
private final FineractProperties fineractProperties;
@Transactional @Transactional
@Override @Override
@@ -223,11 +227,13 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
@Transactional @Transactional
public void reverseTransfersWithFromAccountTransactions(final Collection<Long> fromTransactionIds, public void reverseTransfersWithFromAccountTransactions(final Collection<Long> fromTransactionIds,
final PortfolioAccountType accountTypeId) { final PortfolioAccountType accountTypeId) {
List<AccountTransferTransaction> acccountTransfers = null; List<AccountTransferTransaction> acccountTransfers = new ArrayList<>();
if (accountTypeId.isLoanAccount()) { if (accountTypeId.isLoanAccount()) {
acccountTransfers = this.accountTransferRepository.findByFromLoanTransactions(fromTransactionIds); List<List<Long>> partitions = Lists.partition(fromTransactionIds.stream().toList(),
fineractProperties.getQuery().getInClauseParameterSizeLimit());
partitions.forEach(partition -> acccountTransfers.addAll(this.accountTransferRepository.findByFromLoanTransactions(partition)));
} }
if (acccountTransfers != null && acccountTransfers.size() > 0) { if (acccountTransfers.size() > 0) {
undoTransactions(acccountTransfers); undoTransactions(acccountTransfers);
} }
@@ -192,10 +192,6 @@ public interface LoanRepository extends JpaRepository<Loan, Long>, JpaSpecificat
@Query(FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE) @Query(FIND_ALL_NON_CLOSED_LOANS_BY_LAST_CLOSED_BUSINESS_DATE)
List<Long> findAllNonClosedLoanIdsByLastClosedBusinessDate(@Param("businessDate") LocalDate businessDate); List<Long> findAllNonClosedLoanIdsByLastClosedBusinessDate(@Param("businessDate") LocalDate businessDate);
@Query(FIND_ALL_NON_CLOSED_LOANS_BEHIND_BY_LOAN_IDS)
List<LoanIdAndLastClosedBusinessDate> findAllNonClosedLoansBehindByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate,
@Param("loanIds") List<Long> loanIds);
@Query(FIND_ALL_NON_CLOSED_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS) @Query(FIND_ALL_NON_CLOSED_LOANS_BEHIND_OR_NULL_BY_LOAN_IDS)
List<LoanIdAndLastClosedBusinessDate> findAllNonClosedLoansBehindOrNullByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate, List<LoanIdAndLastClosedBusinessDate> findAllNonClosedLoansBehindOrNullByLoanIds(@Param("cobBusinessDate") LocalDate cobBusinessDate,
@Param("loanIds") List<Long> loanIds); @Param("loanIds") List<Long> loanIds);
@@ -18,14 +18,16 @@
*/ */
package org.apache.fineract.portfolio.loanaccount.domain; package org.apache.fineract.portfolio.loanaccount.domain;
import com.google.common.collect.Lists;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException; import org.apache.fineract.portfolio.loanaccount.exception.LoanNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -36,14 +38,11 @@ import org.springframework.transaction.annotation.Transactional;
* </p> * </p>
*/ */
@Service @Service
@RequiredArgsConstructor
public class LoanRepositoryWrapper { public class LoanRepositoryWrapper {
private final LoanRepository repository; private final LoanRepository repository;
private final FineractProperties fineractProperties;
@Autowired
public LoanRepositoryWrapper(final LoanRepository repository) {
this.repository = repository;
}
@Transactional(readOnly = true) @Transactional(readOnly = true)
public Loan findOneWithNotFoundDetection(final Long id) { public Loan findOneWithNotFoundDetection(final Long id) {
@@ -181,8 +180,11 @@ public class LoanRepositoryWrapper {
// Looks like we need complete Data // Looks like we need complete Data
public List<Loan> findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection<Long> ids, public List<Loan> findByIdsAndLoanStatusAndLoanType(@Param("ids") Collection<Long> ids,
@Param("loanStatuses") Collection<Integer> loanStatuses, @Param("loanTypes") Collection<Integer> loanTypes) { @Param("loanStatuses") Collection<Integer> loanStatuses, @Param("loanTypes") Collection<Integer> loanTypes) {
List<Loan> loans = this.repository.findByIdsAndLoanStatusAndLoanType(ids, loanStatuses, loanTypes); List<Loan> loans = new ArrayList<>();
if (loans != null && loans.size() > 0) { List<List<Long>> partitions = Lists.partition(ids.stream().toList(), fineractProperties.getQuery().getInClauseParameterSizeLimit());
partitions
.forEach(partition -> loans.addAll(this.repository.findByIdsAndLoanStatusAndLoanType(partition, loanStatuses, loanTypes)));
if (loans.size() > 0) {
for (Loan loan : loans) { for (Loan loan : loans) {
loan.initializeLazyCollections(); loan.initializeLazyCollections();
} }
@@ -42,6 +42,8 @@ fineract.mode.write-enabled=${FINERACT_MODE_WRITE_ENABLED:true}
fineract.mode.batch-worker-enabled=${FINERACT_MODE_BATCH_WORKER_ENABLED:true} fineract.mode.batch-worker-enabled=${FINERACT_MODE_BATCH_WORKER_ENABLED:true}
fineract.mode.batch-manager-enabled=${FINERACT_MODE_BATCH_MANAGER_ENABLED:true} fineract.mode.batch-manager-enabled=${FINERACT_MODE_BATCH_MANAGER_ENABLED:true}
fineract.query.in-clause-parameter-size-limit=${FINERACT_QUERY_PARAMETER_SIZE:1000}
fineract.correlation.enabled=${FINERACT_LOGGING_HTTP_CORRELATION_ID_ENABLED:false} fineract.correlation.enabled=${FINERACT_LOGGING_HTTP_CORRELATION_ID_ENABLED:false}
fineract.correlation.header-name=${FINERACT_LOGGING_HTTP_CORRELATION_ID_HEADER_NAME:X-Correlation-ID} fineract.correlation.header-name=${FINERACT_LOGGING_HTTP_CORRELATION_ID_HEADER_NAME:X-Correlation-ID}
@@ -29,6 +29,7 @@ import java.util.List;
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;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
@@ -42,7 +43,9 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
ArgumentCaptor<LoanAccountLock> valueCaptor = ArgumentCaptor.forClass(LoanAccountLock.class); ArgumentCaptor<LoanAccountLock> valueCaptor = ArgumentCaptor.forClass(LoanAccountLock.class);
private LoanAccountLockRepository accountLockRepository = mock(LoanAccountLockRepository.class); private LoanAccountLockRepository accountLockRepository = mock(LoanAccountLockRepository.class);
private ApplyLoanLockTasklet applyLoanLockTasklet = new ApplyLoanLockTasklet(accountLockRepository); private FineractProperties fineractProperties = mock(FineractProperties.class);
private FineractProperties.FineractQueryProperties fineractQueryProperties = mock(FineractProperties.FineractQueryProperties.class);
private ApplyLoanLockTasklet applyLoanLockTasklet = new ApplyLoanLockTasklet(accountLockRepository, fineractProperties);
private RepeatStatus resultItem; private RepeatStatus resultItem;
private StepContribution stepContribution; private StepContribution stepContribution;
@@ -56,12 +59,16 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
this.stepContribution = new StepContribution(stepExecution); this.stepContribution = new StepContribution(stepExecution);
if ("error".equals(action)) { if ("error".equals(action)) {
lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
lenient().when(this.accountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenThrow(new RuntimeException("fail")); lenient().when(this.accountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenThrow(new RuntimeException("fail"));
} else { } else {
LoanAccountLock lock1 = new LoanAccountLock(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING); LoanAccountLock lock1 = new LoanAccountLock(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
LoanAccountLock lock2 = new LoanAccountLock(2L, LockOwner.LOAN_COB_PARTITIONING); LoanAccountLock lock2 = new LoanAccountLock(2L, LockOwner.LOAN_COB_PARTITIONING);
LoanAccountLock lock3 = new LoanAccountLock(3L, LockOwner.LOAN_INLINE_COB_PROCESSING); LoanAccountLock lock3 = new LoanAccountLock(3L, LockOwner.LOAN_INLINE_COB_PROCESSING);
List<LoanAccountLock> accountLocks = List.of(lock1, lock2, lock3); List<LoanAccountLock> accountLocks = List.of(lock1, lock2, lock3);
lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
lenient().when(this.accountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenReturn(accountLocks); lenient().when(this.accountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenReturn(accountLocks);
} }
@@ -35,6 +35,7 @@ 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;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; 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.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.mockito.Mockito; import org.mockito.Mockito;
@@ -48,6 +49,9 @@ public class FetchAndLockLoanStepDefinitions implements En {
private final LoanAccountLockRepository loanAccountLockRepository = mock(LoanAccountLockRepository.class); private final LoanAccountLockRepository loanAccountLockRepository = mock(LoanAccountLockRepository.class);
private final RetrieveLoanIdService retrieveLoanIdService = mock(RetrieveLoanIdService.class); private final RetrieveLoanIdService retrieveLoanIdService = mock(RetrieveLoanIdService.class);
private final FineractProperties fineractProperties = mock(FineractProperties.class);
private final FineractProperties.FineractQueryProperties fineractQueryProperties = mock(
FineractProperties.FineractQueryProperties.class);
StepContribution contribution; StepContribution contribution;
private FetchAndLockLoanTasklet fetchAndLockLoanTasklet; private FetchAndLockLoanTasklet fetchAndLockLoanTasklet;
private String action; private String action;
@@ -65,17 +69,25 @@ public class FetchAndLockLoanStepDefinitions implements En {
lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(Collections.emptyList()); lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(Collections.emptyList());
} else if ("good".equals(action)) { } else if ("good".equals(action)) {
lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(List.of(1L, 2L, 3L)); lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(List.of(1L, 2L, 3L));
lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenReturn(Collections.emptyList()); lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList())).thenReturn(Collections.emptyList());
} else if ("soft lock".equals(action)) { } else if ("soft lock".equals(action)) {
lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(List.of(1L, 2L, 3L)); lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(List.of(1L, 2L, 3L));
lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList())) lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList()))
.thenReturn(List.of(new LoanAccountLock(1L, LockOwner.LOAN_COB_PARTITIONING))); .thenReturn(List.of(new LoanAccountLock(1L, LockOwner.LOAN_COB_PARTITIONING)));
} else if ("inline cob".equals(action)) { } else if ("inline cob".equals(action)) {
lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(List.of(1L, 2L, 3L)); lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(List.of(1L, 2L, 3L));
lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList())) lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList()))
.thenReturn(List.of(new LoanAccountLock(2L, LockOwner.LOAN_INLINE_COB_PROCESSING))); .thenReturn(List.of(new LoanAccountLock(2L, LockOwner.LOAN_INLINE_COB_PROCESSING)));
} else if ("chunk processing".equals(action)) { } else if ("chunk processing".equals(action)) {
lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(List.of(1L, 2L, 3L)); lenient().when(retrieveLoanIdService.retrieveLoanIdsNDaysBehind(anyLong(), any())).thenReturn(List.of(1L, 2L, 3L));
lenient().when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
lenient().when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList())) lenient().when(loanAccountLockRepository.findAllByLoanIdIn(Mockito.anyList()))
.thenReturn(List.of(new LoanAccountLock(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING))); .thenReturn(List.of(new LoanAccountLock(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING)));
} }
@@ -85,7 +97,7 @@ public class FetchAndLockLoanStepDefinitions implements En {
contribution = new StepContribution(stepExecution); contribution = new StepContribution(stepExecution);
contribution.getStepExecution().getJobExecution().getExecutionContext().put(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME, contribution.getStepExecution().getJobExecution().getExecutionContext().put(LoanCOBConstant.BUSINESS_DATE_PARAMETER_NAME,
LocalDate.now(ZoneId.systemDefault()).toString()); LocalDate.now(ZoneId.systemDefault()).toString());
fetchAndLockLoanTasklet = new FetchAndLockLoanTasklet(loanAccountLockRepository, retrieveLoanIdService); fetchAndLockLoanTasklet = new FetchAndLockLoanTasklet(loanAccountLockRepository, retrieveLoanIdService, fineractProperties);
}); });
When("FetchAndLockLoanTasklet.execute method executed", () -> { When("FetchAndLockLoanTasklet.execute method executed", () -> {
@@ -23,6 +23,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@@ -35,6 +37,7 @@ import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
import org.apache.fineract.cob.exceptions.LoanAccountLockCannotBeOverruledException; import org.apache.fineract.cob.exceptions.LoanAccountLockCannotBeOverruledException;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
import org.apache.fineract.infrastructure.core.api.JsonCommand; import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant; import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository; import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
@@ -59,6 +62,10 @@ class InlineLoanCOBExecutorServiceImplTest {
private InlineLoanCOBExecutionDataParser dataParser; private InlineLoanCOBExecutionDataParser dataParser;
@Mock @Mock
private LoanRepository loanRepository; private LoanRepository loanRepository;
@Mock
private FineractProperties fineractProperties;
@Mock
private FineractProperties.FineractQueryProperties fineractQueryProperties;
@Test @Test
void shouldExceptionThrownIfLoanIsAlreadyLocked() { void shouldExceptionThrownIfLoanIsAlreadyLocked() {
@@ -72,10 +79,35 @@ class InlineLoanCOBExecutorServiceImplTest {
ThreadLocalContextUtil.setBusinessDates(businessDates); ThreadLocalContextUtil.setBusinessDates(businessDates);
when(transactionTemplate.execute(any())).thenThrow(new LoanAccountLockCannotBeOverruledException("")); when(transactionTemplate.execute(any())).thenThrow(new LoanAccountLockCannotBeOverruledException(""));
when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
when(dataParser.parseExecution(any())).thenReturn(List.of(1L));
when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(65000);
when(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(any(), anyList())).thenReturn(List.of(loan)); when(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(any(), anyList())).thenReturn(List.of(loan));
assertThrows(LoanAccountLockCannotBeOverruledException.class, () -> testObj.executeInlineJob(command, "INLINE_LOAN_COB")); assertThrows(LoanAccountLockCannotBeOverruledException.class, () -> testObj.executeInlineJob(command, "INLINE_LOAN_COB"));
} }
@Test
void shouldListBePartitioned() {
JsonCommand command = mock(JsonCommand.class);
LoanIdAndLastClosedBusinessDate loan1 = mock(LoanIdAndLastClosedBusinessDate.class);
LoanIdAndLastClosedBusinessDate loan2 = mock(LoanIdAndLastClosedBusinessDate.class);
LoanIdAndLastClosedBusinessDate loan3 = mock(LoanIdAndLastClosedBusinessDate.class);
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
HashMap<BusinessDateType, LocalDate> businessDates = new HashMap<>();
LocalDate businessDate = LocalDate.now(ZoneId.systemDefault());
businessDates.put(BusinessDateType.BUSINESS_DATE, businessDate);
businessDates.put(BusinessDateType.COB_DATE, businessDate.minusDays(1));
ThreadLocalContextUtil.setBusinessDates(businessDates);
when(transactionTemplate.execute(any())).thenThrow(new LoanAccountLockCannotBeOverruledException(""));
when(fineractProperties.getQuery()).thenReturn(fineractQueryProperties);
when(dataParser.parseExecution(any())).thenReturn(List.of(1L, 2L, 3L));
when(fineractQueryProperties.getInClauseParameterSizeLimit()).thenReturn(2);
when(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(any(), anyList())).thenReturn(List.of(loan1, loan2, loan3));
assertThrows(LoanAccountLockCannotBeOverruledException.class, () -> testObj.executeInlineJob(command, "INLINE_LOAN_COB"));
verify(loanRepository, times(2)).findAllNonClosedLoansBehindOrNullByLoanIds(any(), anyList());
}
@Test @Test
void shouldOldestCloseBusinessDateReturnWithCorrectDate() void shouldOldestCloseBusinessDateReturnWithCorrectDate()
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
@@ -42,6 +42,7 @@ import org.apache.fineract.cob.data.LoanIdAndLastClosedBusinessDate;
import org.apache.fineract.cob.service.InlineLoanCOBExecutorServiceImpl; import org.apache.fineract.cob.service.InlineLoanCOBExecutorServiceImpl;
import org.apache.fineract.cob.service.LoanAccountLockService; import org.apache.fineract.cob.service.LoanAccountLockService;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; 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.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil; import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
@@ -80,6 +81,10 @@ class LoanCOBApiFilterTest {
private InlineLoanCOBExecutorServiceImpl inlineLoanCOBExecutorService; private InlineLoanCOBExecutorServiceImpl inlineLoanCOBExecutorService;
@Mock @Mock
private LoanRepository loanRepository; private LoanRepository loanRepository;
@Mock
private FineractProperties fineractProperties;
@Mock
private FineractProperties.FineractQueryProperties fineractQueryProperties;
@Mock @Mock
private LoanRescheduleRequestRepository loanRescheduleRequestRepository; private LoanRescheduleRequestRepository loanRescheduleRequestRepository;
@@ -145,7 +150,9 @@ class LoanCOBApiFilterTest {
given(request.getPathInfo()).willReturn("/loans/invalid2LoanId/charges"); given(request.getPathInfo()).willReturn("/loans/invalid2LoanId/charges");
given(request.getMethod()).willReturn(HTTPMethods.POST.value()); given(request.getMethod()).willReturn(HTTPMethods.POST.value());
given(context.authenticatedUser()).willReturn(appUser); given(context.authenticatedUser()).willReturn(appUser);
given(loanRepository.findAllNonClosedLoansBehindByLoanIds( given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList())) eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList()))
.willReturn(Collections.emptyList()); .willReturn(Collections.emptyList());
@@ -187,7 +194,9 @@ class LoanCOBApiFilterTest {
given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false); given(loanAccountLockService.isLoanHardLocked(2L)).willReturn(false);
given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false); given(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false);
given(context.authenticatedUser()).willReturn(appUser); given(context.authenticatedUser()).willReturn(appUser);
given(loanRepository.findAllNonClosedLoansBehindByLoanIds( given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList())) eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList()))
.willReturn(Collections.emptyList()); .willReturn(Collections.emptyList());
@@ -214,7 +223,9 @@ class LoanCOBApiFilterTest {
given(loanAccountLockService.isLoanSoftLocked(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(loanRepository.findAllNonClosedLoansBehindByLoanIds( given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList())) eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList()))
.willReturn(Collections.emptyList()); .willReturn(Collections.emptyList());
@@ -239,11 +250,13 @@ class LoanCOBApiFilterTest {
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(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false);
given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
LoanRescheduleRequest rescheduleRequest = mock(LoanRescheduleRequest.class); LoanRescheduleRequest rescheduleRequest = mock(LoanRescheduleRequest.class);
given(loanRescheduleRequestRepository.getLoanIdByRescheduleRequestId(resourceId)).willReturn(Optional.of(2L)); given(loanRescheduleRequestRepository.getLoanIdByRescheduleRequestId(resourceId)).willReturn(Optional.of(2L));
given(context.authenticatedUser()).willReturn(appUser); given(context.authenticatedUser()).willReturn(appUser);
given(loanRepository.findAllNonClosedLoansBehindByLoanIds( given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList())) eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList()))
.willReturn(Collections.emptyList()); .willReturn(Collections.emptyList());
@@ -288,8 +301,10 @@ class LoanCOBApiFilterTest {
given(request.getPathInfo()).willReturn("/loans/2?command=approve"); given(request.getPathInfo()).willReturn("/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(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(true);
given(loanRepository.findAllNonClosedLoansBehindByLoanIds( given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList())) eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList()))
.willReturn(Collections.singletonList(result)); .willReturn(Collections.singletonList(result));
@@ -320,7 +335,9 @@ class LoanCOBApiFilterTest {
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(loanAccountLockService.isLoanSoftLocked(2L)).willReturn(false);
given(loanRepository.findAllNonClosedLoansBehindByLoanIds( given(fineractProperties.getQuery()).willReturn(fineractQueryProperties);
given(fineractQueryProperties.getInClauseParameterSizeLimit()).willReturn(65000);
given(loanRepository.findAllNonClosedLoansBehindOrNullByLoanIds(
eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList())) eq(ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE)), anyList()))
.willReturn(Collections.emptyList()); .willReturn(Collections.emptyList());