From d3b626558f1636b3e837b83f7c347018fbb70ff6 Mon Sep 17 00:00:00 2001 From: Ruchi Dhamankar Date: Thu, 28 Dec 2023 15:40:34 +0530 Subject: [PATCH] FINERACT-1971:Installment Delinquency value with delinquency pause --- .../SetLoanDelinquencyTagsBusinessStep.java | 7 ++- .../DelinquencyActionIntegrationTests.java | 48 ++++++++++++++++++- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/SetLoanDelinquencyTagsBusinessStep.java b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/SetLoanDelinquencyTagsBusinessStep.java index c94ad88bd..732af1ba3 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/cob/loan/SetLoanDelinquencyTagsBusinessStep.java +++ b/fineract-provider/src/main/java/org/apache/fineract/cob/loan/SetLoanDelinquencyTagsBusinessStep.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType; import org.apache.fineract.infrastructure.core.domain.ActionContext; import org.apache.fineract.infrastructure.core.domain.ExternalId; import org.apache.fineract.infrastructure.core.service.DateUtils; @@ -97,9 +96,9 @@ public class SetLoanDelinquencyTagsBusinessStep implements LoanCOBBusinessStep { } private boolean isDelinquencyOnPause(Loan loan, List effectiveDelinquencyList) { - LocalDate cobBusinessDate = ThreadLocalContextUtil.getBusinessDateByType(BusinessDateType.COB_DATE); - boolean isPaused = isPausedOnDate(cobBusinessDate, effectiveDelinquencyList); - boolean wasPausedOneDayBefore = isPausedOnDate(cobBusinessDate.minusDays(1), effectiveDelinquencyList); + LocalDate businessDate = DateUtils.getBusinessLocalDate(); + boolean isPaused = isPausedOnDate(businessDate, effectiveDelinquencyList); + boolean wasPausedOneDayBefore = isPausedOnDate(businessDate.minusDays(1), effectiveDelinquencyList); if ((isPaused && !wasPausedOneDayBefore) || (!isPaused && wasPausedOneDayBefore)) { businessEventNotifierService.notifyPostBusinessEvent(new LoanDelinquencyRangeChangeBusinessEvent(loan)); } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyActionIntegrationTests.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyActionIntegrationTests.java index f7c8284fb..90207ebb8 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyActionIntegrationTests.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyActionIntegrationTests.java @@ -49,6 +49,7 @@ import org.apache.fineract.client.util.CallFailedRuntimeException; import org.apache.fineract.integrationtests.common.ClientHelper; import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension; import org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper; +import org.apache.fineract.integrationtests.inlinecob.InlineLoanCOBHelper; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -266,7 +267,7 @@ public class DelinquencyActionIntegrationTests extends BaseLoanIntegrationTest { Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId(); // Create Loan Product - Long loanProductId = createLoanProductWith25PctDownPaymentAndDelinquencyBucket(true, true, true); + Long loanProductId = createLoanProductWith25PctDownPaymentAndDelinquencyBucket(true, true, true, 3); // Apply and Approve Loan Long loanId = applyAndApproveLoan(clientId, loanProductId, "25 December 2022", 1500.0, 3, @@ -322,6 +323,48 @@ public class DelinquencyActionIntegrationTests extends BaseLoanIntegrationTest { }); } + @Test + public void testLoanAndInstallmentDelinquencyCalculationForCOBAfterPausePeriodEndTest() { + runAt("01 November 2023", () -> { + // Create Client + Long clientId = clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId(); + + // Create Loan Product + Long loanProductId = createLoanProductWith25PctDownPaymentAndDelinquencyBucket(true, true, true, 0); + + // Apply and Approve Loan + Long loanId = applyAndApproveLoan(clientId, loanProductId, "01 November 2023", 1000.0, 3, req -> { + req.submittedOnDate("01 November 2023"); + req.setLoanTermFrequency(45); + req.setRepaymentEvery(15); + req.setGraceOnArrearsAgeing(0); + }); + + // Partial Loan amount Disbursement + disburseLoan(loanId, BigDecimal.valueOf(100.00), "01 November 2023"); + + // Update business date + businessDateHelper.updateBusinessDate(new BusinessDateRequest().type(BUSINESS_DATE.getName()).date("05 November 2023") + .dateFormat(DATETIME_PATTERN).locale("en")); + + // Create Delinquency Pause for the Loan + PostLoansDelinquencyActionResponse response = loanTransactionHelper.createLoanDelinquencyAction(loanId, PAUSE, + "16 November 2023", "25 November 2023"); + + // run cob for business date 26 November + final InlineLoanCOBHelper inlineLoanCOBHelper = new InlineLoanCOBHelper(requestSpec, responseSpec); + businessDateHelper.updateBusinessDate(new BusinessDateRequest().type(BUSINESS_DATE.getName()).date("26 November 2023") + .dateFormat(DATETIME_PATTERN).locale("en")); + inlineLoanCOBHelper.executeInlineCOB(List.of(loanId.longValue())); + + // Loan delinquency data + verifyLoanDelinquencyData(loanId, 1, new InstallmentDelinquencyData(1, 3, BigDecimal.valueOf(25.0))); + + // Validate Delinquency Pause Period on Loan + validateLoanDelinquencyPausePeriods(loanId, pausePeriods("16 November 2023", "25 November 2023", false)); + }); + } + private void validateLoanDelinquencyPausePeriods(Long loanId, GetLoansLoanIdDelinquencyPausePeriod... pausePeriods) { GetLoansLoanIdResponse loan = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId.intValue()); Assertions.assertNotNull(loan.getDelinquent()); @@ -388,7 +431,7 @@ public class DelinquencyActionIntegrationTests extends BaseLoanIntegrationTest { } private Long createLoanProductWith25PctDownPaymentAndDelinquencyBucket(boolean autoDownPaymentEnabled, boolean multiDisburseEnabled, - boolean installmentLevelDelinquencyEnabled) { + boolean installmentLevelDelinquencyEnabled, Integer graceOnArrearsAging) { // Create DelinquencyBuckets Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec, List.of(// Pair.of(1, 3), // @@ -400,6 +443,7 @@ public class DelinquencyActionIntegrationTests extends BaseLoanIntegrationTest { product.setDelinquencyBucketId(delinquencyBucketId.longValue()); product.setMultiDisburseLoan(multiDisburseEnabled); product.setEnableDownPayment(true); + product.setGraceOnArrearsAgeing(graceOnArrearsAging); product.setDisbursedAmountPercentageForDownPayment(DOWN_PAYMENT_PERCENTAGE); product.setEnableAutoRepaymentForDownPayment(autoDownPaymentEnabled);