FINERACT-1724: Use services instead of repositories in COB

This commit is contained in:
Adam Saghy
2023-04-17 17:50:44 +02:00
parent 234583c8e1
commit 748b775051
22 changed files with 283 additions and 145 deletions
@@ -30,11 +30,10 @@ import io.cucumber.java8.En;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.List;
import java.util.Optional;
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.cob.exceptions.LoanReadException;
import org.apache.fineract.cob.loan.LoanLockingService;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
@@ -45,36 +44,34 @@ import org.springframework.transaction.support.TransactionTemplate;
public class LoanItemListenerStepDefinitions implements En {
private LoanAccountLockRepository accountLockRepository = mock(LoanAccountLockRepository.class);
private LoanLockingService loanLockingService = mock(LoanLockingService.class);
private TransactionTemplate transactionTemplate = spy(TransactionTemplate.class);
private ChunkProcessingLoanItemListener loanItemListener = new ChunkProcessingLoanItemListener(accountLockRepository,
transactionTemplate);
private ChunkProcessingLoanItemListener loanItemListener = new ChunkProcessingLoanItemListener(loanLockingService, transactionTemplate);
private Exception exception;
private LoanAccountLock loanAccountLock;
private Loan loan = mock(Loan.class);
private final Loan loan = mock(Loan.class);
public LoanItemListenerStepDefinitions() {
Given("/^The LoanItemListener.onReadError method (.*)$/", (String action) -> {
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
exception = new LoanReadException(1L, new RuntimeException("fail"));
loanAccountLock = new LoanAccountLock(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()));
when(accountLockRepository.findByLoanIdAndLockOwner(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING))
.thenReturn(Optional.of(loanAccountLock));
when(loanLockingService.findByLoanIdAndLockOwner(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING)).thenReturn(loanAccountLock);
transactionTemplate.setTransactionManager(mock(PlatformTransactionManager.class));
when(loan.getId()).thenReturn(1L);
});
When("LoanItemListener.onReadError method executed", () -> {
this.loanItemListener.onReadError(exception);
loanItemListener.onReadError(exception);
});
Then("LoanItemListener.onReadError result should match", () -> {
verify(transactionTemplate, Mockito.times(1)).setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
verify(transactionTemplate, Mockito.times(1)).execute(any());
verify(accountLockRepository, Mockito.times(1)).findByLoanIdAndLockOwner(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
verify(loanLockingService, Mockito.times(1)).findByLoanIdAndLockOwner(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
assertEquals("Loan (id: 1) reading is failed", loanAccountLock.getError());
assertNotNull(loanAccountLock.getStacktrace());
});
@@ -83,20 +80,19 @@ public class LoanItemListenerStepDefinitions implements En {
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
exception = new LoanReadException(1L, new RuntimeException("fail"));
loanAccountLock = new LoanAccountLock(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()));
when(accountLockRepository.findByLoanIdAndLockOwner(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING))
.thenReturn(Optional.of(loanAccountLock));
when(loanLockingService.findByLoanIdAndLockOwner(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING)).thenReturn(loanAccountLock);
when(loan.getId()).thenReturn(2L);
transactionTemplate.setTransactionManager(mock(PlatformTransactionManager.class));
});
When("LoanItemListener.onProcessError method executed", () -> {
this.loanItemListener.onProcessError(loan, exception);
loanItemListener.onProcessError(loan, exception);
});
Then("LoanItemListener.onProcessError result should match", () -> {
verify(transactionTemplate, Mockito.times(1)).setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
verify(transactionTemplate, Mockito.times(1)).execute(any());
verify(accountLockRepository, Mockito.times(1)).findByLoanIdAndLockOwner(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
verify(loanLockingService, Mockito.times(1)).findByLoanIdAndLockOwner(2L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
assertEquals("Loan (id: 2) processing is failed", loanAccountLock.getError());
assertNotNull(loanAccountLock.getStacktrace());
});
@@ -105,20 +101,19 @@ public class LoanItemListenerStepDefinitions implements En {
ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L, "default", "Default", "Asia/Kolkata", null));
exception = new LoanReadException(3L, new RuntimeException("fail"));
loanAccountLock = new LoanAccountLock(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()));
when(accountLockRepository.findByLoanIdAndLockOwner(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING))
.thenReturn(Optional.of(loanAccountLock));
when(loanLockingService.findByLoanIdAndLockOwner(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING)).thenReturn(loanAccountLock);
when(loan.getId()).thenReturn(3L);
transactionTemplate.setTransactionManager(mock(PlatformTransactionManager.class));
});
When("LoanItemListener.onWriteError method executed", () -> {
this.loanItemListener.onWriteError(exception, List.of(loan));
loanItemListener.onWriteError(exception, List.of(loan));
});
Then("LoanItemListener.onWriteError result should match", () -> {
verify(transactionTemplate, Mockito.times(1)).setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
verify(transactionTemplate, Mockito.times(1)).execute(any());
verify(accountLockRepository, Mockito.times(1)).findByLoanIdAndLockOwner(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
verify(loanLockingService, Mockito.times(1)).findByLoanIdAndLockOwner(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING);
assertEquals("Loan (id: 3) writing is failed", loanAccountLock.getError());
assertNotNull(loanAccountLock.getStacktrace());
});
@@ -31,7 +31,6 @@ import java.util.HashMap;
import java.util.List;
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;
@@ -43,18 +42,16 @@ import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
public class ApplyLoanLockTaskletStepDefinitions implements En {
ArgumentCaptor<List> valueCaptor = ArgumentCaptor.forClass(List.class);
private LoanAccountLockRepository accountLockRepository = mock(LoanAccountLockRepository.class);
ArgumentCaptor<LockOwner> lockOwnerValueCaptor = ArgumentCaptor.forClass(LockOwner.class);
private LoanLockingService loanLockingService = mock(LoanLockingService.class);
private FineractProperties fineractProperties = mock(FineractProperties.class);
private JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
private FineractProperties.FineractQueryProperties fineractQueryProperties = mock(FineractProperties.FineractQueryProperties.class);
private RetrieveLoanIdService retrieveLoanIdService = mock(RetrieveLoanIdService.class);
private ApplyLoanLockTasklet applyLoanLockTasklet = new ApplyLoanLockTasklet(accountLockRepository, fineractProperties, jdbcTemplate,
private ApplyLoanLockTasklet applyLoanLockTasklet = new ApplyLoanLockTasklet(fineractProperties, loanLockingService,
retrieveLoanIdService);
private RepeatStatus resultItem;
private StepContribution stepContribution;
@@ -69,15 +66,15 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
ExecutionContext executionContext = new ExecutionContext();
LoanCOBParameter loanCOBParameter = new LoanCOBParameter(1L, 4L);
executionContext.put(LoanCOBConstant.LOAN_COB_PARAMETER, loanCOBParameter);
lenient().when(this.retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter))
lenient().when(retrieveLoanIdService.retrieveAllNonClosedLoansByLastClosedBusinessDateAndMinAndMaxLoanId(loanCOBParameter))
.thenReturn(List.of(1L, 2L, 3L, 4L));
stepExecution.setExecutionContext(executionContext);
this.stepContribution = new StepContribution(stepExecution);
stepContribution = new StepContribution(stepExecution);
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(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenThrow(new RuntimeException("fail"));
} else {
LoanAccountLock lock1 = new LoanAccountLock(1L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()));
LoanAccountLock lock2 = new LoanAccountLock(2L, LockOwner.LOAN_COB_PARTITIONING, LocalDate.now(ZoneId.systemDefault()));
@@ -86,26 +83,26 @@ public class ApplyLoanLockTaskletStepDefinitions implements En {
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(loanLockingService.findAllByLoanIdIn(Mockito.anyList())).thenReturn(accountLocks);
}
});
When("ApplyLoanLockTasklet.execute method executed", () -> {
resultItem = this.applyLoanLockTasklet.execute(stepContribution, null);
resultItem = applyLoanLockTasklet.execute(stepContribution, null);
});
Then("ApplyLoanLockTasklet.execute result should match", () -> {
assertEquals(RepeatStatus.FINISHED, resultItem);
verify(this.jdbcTemplate, Mockito.times(1)).batchUpdate(Mockito.anyString(), valueCaptor.capture(), Mockito.anyInt(),
Mockito.any(ParameterizedPreparedStatementSetter.class));
verify(loanLockingService, Mockito.times(1)).upgradeLock(valueCaptor.capture(), lockOwnerValueCaptor.capture());
List<Long> values = valueCaptor.getValue();
assertEquals(2L, values.get(0));
assertEquals(LockOwner.LOAN_COB_CHUNK_PROCESSING, lockOwnerValueCaptor.getValue());
});
Then("throw exception ApplyLoanLockTasklet.execute method", () -> {
assertThrows(RuntimeException.class, () -> {
resultItem = this.applyLoanLockTasklet.execute(stepContribution, null);
resultItem = applyLoanLockTasklet.execute(stepContribution, null);
});
});
}
@@ -19,8 +19,6 @@
package org.apache.fineract.cob.loan;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -39,26 +37,26 @@ 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;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
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);
private LockLoanTasklet lockLoanTasklet;
private String action;
private RepeatStatus result;
private JdbcTemplate jdbcTemplate = mock(JdbcTemplate.class);
private final LoanLockingService loanLockingService = mock(LoanLockingService.class);
public FetchAndLockLoanStepDefinitions() {
Given("/^The FetchAndLockLoanTasklet.execute method with action (.*)$/", (String action) -> {
@@ -106,18 +104,21 @@ public class FetchAndLockLoanStepDefinitions implements En {
List.of(new LoanAccountLock(3L, LockOwner.LOAN_COB_CHUNK_PROCESSING, LocalDate.now(ZoneId.systemDefault()))));
}
lockLoanTasklet = new LockLoanTasklet(jdbcTemplate);
lockLoanTasklet = new LockLoanTasklet(loanLockingService);
});
When("FetchAndLockLoanTasklet.execute method executed", () -> {
result = this.lockLoanTasklet.execute(contribution, null);
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(jdbcTemplate).update(anyString(), (PreparedStatementSetter) any());
verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture());
assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue());
assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId());
assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId());
assertEquals(RepeatStatus.FINISHED, result);
LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution()
.getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER);
@@ -125,7 +126,10 @@ public class FetchAndLockLoanStepDefinitions implements En {
assertEquals(1L, loanCOBParameter.getMinLoanId());
assertEquals(3L, loanCOBParameter.getMaxLoanId());
} else if ("soft lock".equals(action)) {
verify(jdbcTemplate).update(anyString(), (PreparedStatementSetter) any());
verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture());
assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue());
assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId());
assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId());
assertEquals(RepeatStatus.FINISHED, result);
LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution()
.getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER);
@@ -133,7 +137,10 @@ public class FetchAndLockLoanStepDefinitions implements En {
assertEquals(1L, loanCOBParameter.getMinLoanId());
assertEquals(3L, loanCOBParameter.getMaxLoanId());
} else if ("inline cob".equals(action)) {
verify(jdbcTemplate).update(anyString(), (PreparedStatementSetter) any());
verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture());
assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue());
assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId());
assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId());
assertEquals(RepeatStatus.FINISHED, result);
LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution()
.getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER);
@@ -141,7 +148,10 @@ public class FetchAndLockLoanStepDefinitions implements En {
assertEquals(1L, loanCOBParameter.getMinLoanId());
assertEquals(3L, loanCOBParameter.getMaxLoanId());
} else if ("chunk processing".equals(action)) {
verify(jdbcTemplate).update(anyString(), (PreparedStatementSetter) any());
verify(loanLockingService).applySoftLock(dateValueCaptor.capture(), loanCOBParameterValueCaptor.capture());
assertEquals(LocalDate.now(ZoneId.systemDefault()).minusDays(1), dateValueCaptor.getValue());
assertEquals(1L, loanCOBParameterValueCaptor.getValue().getMinLoanId());
assertEquals(3L, loanCOBParameterValueCaptor.getValue().getMaxLoanId());
assertEquals(RepeatStatus.FINISHED, result);
LoanCOBParameter loanCOBParameter = (LoanCOBParameter) contribution.getStepExecution().getJobExecution()
.getExecutionContext().get(LoanCOBConstant.LOAN_COB_PARAMETER);
@@ -25,17 +25,16 @@ import static org.mockito.Mockito.verify;
import io.cucumber.java8.En;
import java.util.Collections;
import java.util.List;
import org.apache.fineract.cob.domain.LoanAccountLockRepository;
import org.apache.fineract.portfolio.loanaccount.domain.Loan;
import org.apache.fineract.portfolio.loanaccount.domain.LoanRepository;
import org.mockito.Mockito;
public class LoanItemWriterStepDefinitions implements En {
private LoanAccountLockRepository accountLockRepository = mock(LoanAccountLockRepository.class);
private LoanRepository loanRepository = mock(LoanRepository.class);
private final LoanLockingService loanLockingService = mock(LoanLockingService.class);
private final LoanRepository loanRepository = mock(LoanRepository.class);
private LoanItemWriter loanItemWriter = new LoanItemWriter(accountLockRepository);
private final LoanItemWriter loanItemWriter = new LoanItemWriter(loanLockingService);
private List<Loan> items;
@@ -45,24 +44,24 @@ public class LoanItemWriterStepDefinitions implements En {
Loan loan = mock(Loan.class);
lenient().when(loan.getId()).thenReturn(1L);
if (action.equals("error")) {
this.items = Collections.emptyList();
items = Collections.emptyList();
} else {
this.items = Collections.singletonList(loan);
lenient().doNothing().when(this.accountLockRepository).deleteByLoanIdInAndLockOwner(Mockito.anyList(), Mockito.any());
items = Collections.singletonList(loan);
lenient().doNothing().when(loanLockingService).deleteByLoanIdInAndLockOwner(Mockito.anyList(), Mockito.any());
}
this.loanItemWriter.setRepository(loanRepository);
loanItemWriter.setRepository(loanRepository);
});
When("LoanItemWriter.write method executed", () -> {
this.loanItemWriter.write(items);
loanItemWriter.write(items);
});
Then("LoanItemWriter.write result should match", () -> {
verify(this.accountLockRepository, Mockito.times(1)).deleteByLoanIdInAndLockOwner(Mockito.any(), Mockito.any());
verify(loanLockingService, Mockito.times(1)).deleteByLoanIdInAndLockOwner(Mockito.any(), Mockito.any());
});
Then("LoanItemWriter.write should not call repository", () -> {
verify(this.accountLockRepository, Mockito.times(0)).deleteByLoanIdInAndLockOwner(Mockito.any(), Mockito.any());
verify(loanLockingService, Mockito.times(0)).deleteByLoanIdInAndLockOwner(Mockito.any(), Mockito.any());
});
}
}