This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 5edd18aec FINERACT-1992: Backdated delinquency pause events
5edd18aec is described below
commit 5edd18aec251df75157b272964744fdc7e64e597
Author: Ruchi Dhamankar <[email protected]>
AuthorDate: Fri Dec 15 10:47:42 2023 +0530
FINERACT-1992: Backdated delinquency pause events
---
...inquencyRangeChangeBusinessEventSerializer.java | 13 +--
.../DelinquencyWritePlatformServiceImpl.java | 4 +
...cyWritePlatformServiceRangeChangeEventTest.java | 117 +++++++++++++++++++++
3 files changed, 128 insertions(+), 6 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
index fcf9d4045..22a606c0a 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/external/service/serialization/serializer/loan/LoanDelinquencyRangeChangeBusinessEventSerializer.java
@@ -157,12 +157,13 @@ public class
LoanDelinquencyRangeChangeBusinessEventSerializer implements Busine
.build();
// get list of charges for installments in same range
- List<LoanCharge> chargesForInstallmentsInSameRange =
loan.getLoanCharges().stream()
- .filter(loanCharge -> !loanCharge.isPaid() &&
delinquentInstallmentsInSameRange.stream().anyMatch(
- installmentForCharge ->
(DateUtils.isAfter(loanCharge.getDueDate(), installmentForCharge.getFromDate())
- ||
DateUtils.isEqual(loanCharge.getDueDate(), installmentForCharge.getFromDate()))
- &&
(DateUtils.isBefore(loanCharge.getDueDate(), installmentForCharge.getDueDate())
- ||
DateUtils.isEqual(loanCharge.getDueDate(), installmentForCharge.getDueDate()))))
+ List<LoanCharge> chargesForInstallmentsInSameRange =
loan.getLoanCharges().stream().filter(loanCharge -> !loanCharge
+ .isPaid()
+ &&
delinquentInstallmentsInSameRange.stream().anyMatch(installmentForCharge ->
(DateUtils
+ .isAfter(loanCharge.getEffectiveDueDate(),
installmentForCharge.getFromDate())
+ ||
DateUtils.isEqual(loanCharge.getEffectiveDueDate(),
installmentForCharge.getFromDate()))
+ &&
(DateUtils.isBefore(loanCharge.getEffectiveDueDate(),
installmentForCharge.getDueDate())
+ ||
DateUtils.isEqual(loanCharge.getEffectiveDueDate(),
installmentForCharge.getDueDate()))))
.toList();
List<LoanChargeDataRangeViewV1> charges = new
ArrayList<>();
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java
index 23a0f0cda..204029977 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/DelinquencyWritePlatformServiceImpl.java
@@ -236,6 +236,10 @@ public class DelinquencyWritePlatformServiceImpl
implements DelinquencyWritePlat
if (DateUtils.isBefore(parsedDelinquencyAction.getStartDate(),
businessDate)
&&
DelinquencyAction.PAUSE.equals(parsedDelinquencyAction.getAction())) {
recalculateLoanDelinquencyData(loan);
+ // if pause end date is after current business date, loan
delinquency pause flag is changed, emit event
+ if (DateUtils.isAfter(parsedDelinquencyAction.getEndDate(),
businessDate)) {
+ businessEventNotifierService.notifyPostBusinessEvent(new
LoanDelinquencyRangeChangeBusinessEvent(loan));
+ }
}
businessEventNotifierService.notifyPostBusinessEvent(new
LoanAccountDelinquencyPauseChangedBusinessEvent(loan));
return new
CommandProcessingResultBuilder().withCommandId(command.commandId()) //
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java
b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java
index 63663d77f..67ad3e7f7 100644
---
a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java
+++
b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/DelinquencyWritePlatformServiceRangeChangeEventTest.java
@@ -22,6 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyIterable;
+import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -30,6 +31,7 @@ import static org.mockito.Mockito.when;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.ZoneId;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -38,23 +40,31 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.ActionContext;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
+import
org.apache.fineract.infrastructure.event.business.domain.loan.LoanAccountDelinquencyPauseChangedBusinessEvent;
import
org.apache.fineract.infrastructure.event.business.domain.loan.LoanDelinquencyRangeChangeBusinessEvent;
import
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
+import org.apache.fineract.portfolio.delinquency.domain.DelinquencyAction;
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket;
import
org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketMappingsRepository;
import
org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucketRepository;
import org.apache.fineract.portfolio.delinquency.domain.DelinquencyRange;
import
org.apache.fineract.portfolio.delinquency.domain.DelinquencyRangeRepository;
+import org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyAction;
+import
org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyActionRepository;
import
org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyTagHistory;
import
org.apache.fineract.portfolio.delinquency.domain.LoanDelinquencyTagHistoryRepository;
import
org.apache.fineract.portfolio.delinquency.domain.LoanInstallmentDelinquencyTag;
import
org.apache.fineract.portfolio.delinquency.domain.LoanInstallmentDelinquencyTagRepository;
+import
org.apache.fineract.portfolio.delinquency.helper.DelinquencyEffectivePauseHelper;
+import
org.apache.fineract.portfolio.delinquency.service.DelinquencyReadPlatformService;
import
org.apache.fineract.portfolio.delinquency.service.DelinquencyWritePlatformServiceImpl;
import
org.apache.fineract.portfolio.delinquency.service.LoanDelinquencyDomainService;
+import
org.apache.fineract.portfolio.delinquency.validator.DelinquencyActionParseAndValidator;
import
org.apache.fineract.portfolio.delinquency.validator.DelinquencyBucketParseAndValidator;
import
org.apache.fineract.portfolio.delinquency.validator.DelinquencyRangeParseAndValidator;
import
org.apache.fineract.portfolio.delinquency.validator.LoanDelinquencyActionData;
@@ -100,6 +110,14 @@ public class
DelinquencyWritePlatformServiceRangeChangeEventTest {
private LoanDelinquencyDomainService loanDelinquencyDomainService;
@Mock
private LoanInstallmentDelinquencyTagRepository
loanInstallmentDelinquencyTagRepository;
+ @Mock
+ private DelinquencyReadPlatformService delinquencyReadPlatformService;
+ @Mock
+ private DelinquencyActionParseAndValidator
delinquencyActionParseAndValidator;
+ @Mock
+ private LoanDelinquencyActionRepository loanDelinquencyActionRepository;
+ @Mock
+ private DelinquencyEffectivePauseHelper delinquencyEffectivePauseHelper;
@InjectMocks
private DelinquencyWritePlatformServiceImpl underTest;
@@ -498,4 +516,103 @@ public class
DelinquencyWritePlatformServiceRangeChangeEventTest {
assertEquals(loanForProcessing, loanPayloadForEvent);
}
+
+ @Test
+ public void
givenLoanAccountWhenBackdatedPauseActionThenLoanDelinquencyPauseChangeBusinessEventIsRaisedTest()
{
+ ArgumentCaptor<LoanAccountDelinquencyPauseChangedBusinessEvent>
loanDelinquencyPauseChangeEvent = ArgumentCaptor
+
.forClass(LoanAccountDelinquencyPauseChangedBusinessEvent.class);
+ // given
+ Loan loanForProcessing = Mockito.mock(Loan.class);
+ loanForProcessing.setId(1L);
+
+ JsonCommand command = Mockito.mock(JsonCommand.class);
+
+ // Pause period
+ LocalDate startDate = DateUtils.getBusinessLocalDate().minusDays(8);
+ LocalDate endDate = DateUtils.getBusinessLocalDate().minusDays(1);
+
+ List<LoanDelinquencyAction> delinquencyActions = new ArrayList<>();
+ List<LoanDelinquencyActionData> effectiveDelinquency = new
ArrayList<>();
+ CollectionData loanCollectionData = CollectionData.template();
+
+
when(loanRepository.findOneWithNotFoundDetection(anyLong())).thenReturn(loanForProcessing);
+
+
when(delinquencyReadPlatformService.retrieveLoanDelinquencyActions(anyLong())).thenReturn(delinquencyActions);
+ LoanDelinquencyAction backdatedPauseAction =
Mockito.mock(LoanDelinquencyAction.class);
+ backdatedPauseAction.setId(1L);
+
+
when(delinquencyActionParseAndValidator.validateAndParseUpdate(command,
loanForProcessing, delinquencyActions,
+
DateUtils.getBusinessLocalDate())).thenReturn(backdatedPauseAction);
+ when(backdatedPauseAction.getStartDate()).thenReturn(startDate);
+ when(backdatedPauseAction.getEndDate()).thenReturn(endDate);
+
when(backdatedPauseAction.getAction()).thenReturn(DelinquencyAction.PAUSE);
+
+
when(loanDelinquencyActionRepository.saveAndFlush(backdatedPauseAction)).thenReturn(backdatedPauseAction);
+
+
when(delinquencyEffectivePauseHelper.calculateEffectiveDelinquencyList(delinquencyActions)).thenReturn(effectiveDelinquency);
+ when(loanDelinquencyDomainService.getOverdueCollectionData(any(),
anyList())).thenReturn(loanCollectionData);
+ when(loanDelinquencyTagRepository.findByLoanAndLiftedOnDate(any(),
any())).thenReturn(Optional.empty());
+
+ // when
+ underTest.createDelinquencyAction(loanForProcessing.getId(), command);
+
+ // then
+ // verify event is raised
+ verify(businessEventNotifierService,
times(1)).notifyPostBusinessEvent(loanDelinquencyPauseChangeEvent.capture());
+
+ Loan loanPayloadForEvent =
loanDelinquencyPauseChangeEvent.getValue().get();
+ assertEquals(loanForProcessing, loanPayloadForEvent);
+
+ // verify no range change event for pause flag change as both start
and end date are backdated
+ verify(businessEventNotifierService,
times(0)).notifyPostBusinessEvent(any(LoanDelinquencyRangeChangeBusinessEvent.class));
+
+ }
+
+ @Test
+ public void
givenLoanAccountWhenBackdatedPauseActionThenLoanDelinquencyRangeChangeBusinessEventIsRaisedIfPauseFlagChangeTest()
{
+ ArgumentCaptor<LoanDelinquencyRangeChangeBusinessEvent>
loanDelinquencyRangeChangeEvent = ArgumentCaptor
+ .forClass(LoanDelinquencyRangeChangeBusinessEvent.class);
+ // given
+ Loan loanForProcessing = Mockito.mock(Loan.class);
+ loanForProcessing.setId(1L);
+
+ JsonCommand command = Mockito.mock(JsonCommand.class);
+
+ // Pause period
+ LocalDate startDate = DateUtils.getBusinessLocalDate().minusDays(2);
+ LocalDate endDate = DateUtils.getBusinessLocalDate().plusDays(10);
+
+ List<LoanDelinquencyAction> delinquencyActions = new ArrayList<>();
+ List<LoanDelinquencyActionData> effectiveDelinquency = new
ArrayList<>();
+ CollectionData loanCollectionData = CollectionData.template();
+
+
when(loanRepository.findOneWithNotFoundDetection(anyLong())).thenReturn(loanForProcessing);
+
+
when(delinquencyReadPlatformService.retrieveLoanDelinquencyActions(anyLong())).thenReturn(delinquencyActions);
+ LoanDelinquencyAction backdatedPauseAction =
Mockito.mock(LoanDelinquencyAction.class);
+ backdatedPauseAction.setId(1L);
+
+
when(delinquencyActionParseAndValidator.validateAndParseUpdate(command,
loanForProcessing, delinquencyActions,
+
DateUtils.getBusinessLocalDate())).thenReturn(backdatedPauseAction);
+ when(backdatedPauseAction.getStartDate()).thenReturn(startDate);
+ when(backdatedPauseAction.getEndDate()).thenReturn(endDate);
+
when(backdatedPauseAction.getAction()).thenReturn(DelinquencyAction.PAUSE);
+
+
when(loanDelinquencyActionRepository.saveAndFlush(backdatedPauseAction)).thenReturn(backdatedPauseAction);
+
+
when(delinquencyEffectivePauseHelper.calculateEffectiveDelinquencyList(delinquencyActions)).thenReturn(effectiveDelinquency);
+ when(loanDelinquencyDomainService.getOverdueCollectionData(any(),
anyList())).thenReturn(loanCollectionData);
+ when(loanDelinquencyTagRepository.findByLoanAndLiftedOnDate(any(),
any())).thenReturn(Optional.empty());
+
+ // when
+ underTest.createDelinquencyAction(loanForProcessing.getId(), command);
+
+ // then
+ // verify event is raised
+ verify(businessEventNotifierService,
times(1)).notifyPostBusinessEvent(loanDelinquencyRangeChangeEvent.capture());
+
+ Loan loanPayloadForEvent =
loanDelinquencyRangeChangeEvent.getValue().get();
+ assertEquals(loanForProcessing, loanPayloadForEvent);
+ }
+
}