You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ar...@apache.org on 2022/11/28 19:03:16 UTC

[fineract] branch develop updated: Fix Delinquency Classification for scenario

This is an automated email from the ASF dual-hosted git repository.

arnold 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 66aab8d15 Fix Delinquency Classification for scenario
66aab8d15 is described below

commit 66aab8d157c6fb2e7c0cda29d2d8887330fd6c56
Author: Jose Alberto Hernandez <al...@MacBook-Pro.local>
AuthorDate: Tue Nov 22 19:41:01 2022 -0600

    Fix Delinquency Classification for scenario
---
 .../service/LoanDelinquencyDomainServiceImpl.java  |   4 +-
 .../DelinquencyAndChargebackIntegrationTest.java   | 110 ++++++++++++++++++++-
 2 files changed, 108 insertions(+), 6 deletions(-)

diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java
index 26ddea7a8..1d569c90b 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/delinquency/service/LoanDelinquencyDomainServiceImpl.java
@@ -116,13 +116,13 @@ public class LoanDelinquencyDomainServiceImpl implements LoanDelinquencyDomainSe
 
         Long overdueDays = 0L;
         if (overdueSinceDate != null) {
-            overdueSinceDate = overdueSinceDate.plusDays(graceDays.longValue());
-            collectionData.setDelinquentDate(overdueSinceDate);
             overdueDays = DateUtils.getDifferenceInDays(overdueSinceDate, businessDate);
             if (overdueDays < 0) {
                 overdueDays = 0L;
             }
             collectionData.setPastDueDays(overdueDays);
+            overdueSinceDate = overdueSinceDate.plusDays(graceDays.longValue());
+            collectionData.setDelinquentDate(overdueSinceDate);
         }
         collectionData.setDelinquentAmount(outstandingAmount);
 
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyAndChargebackIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyAndChargebackIntegrationTest.java
index 191728fb4..361aaf096 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyAndChargebackIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyAndChargebackIntegrationTest.java
@@ -34,6 +34,7 @@ import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
 import org.apache.fineract.integrationtests.common.BusinessDateHelper;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
@@ -93,7 +94,7 @@ public class DelinquencyAndChargebackIntegrationTest {
 
         // Create Loan Account
         final Integer loanId = createLoanAccount(loanTransactionHelper, clientId.toString(),
-                getLoanProductsProductResponse.getId().toString(), operationDate);
+                getLoanProductsProductResponse.getId().toString(), operationDate, "12");
 
         // Move the Business date 1 month to apply the first repayment
         businessDate = businessDate.plusMonths(1);
@@ -182,6 +183,107 @@ public class DelinquencyAndChargebackIntegrationTest {
         GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
     }
 
+    @Test
+    public void testLoanClassificationStepAsPartOfCOBRepeated() {
+        GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.TRUE);
+
+        LocalDate businessDate = LocalDate.parse("2022-01-01", DateUtils.DEFAULT_DATE_FORMATTER);
+        log.info("Current Business date {}", businessDate);
+        BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, businessDate);
+
+        final SchedulerJobHelper schedulerJobHelper = new SchedulerJobHelper(requestSpec);
+        // Delinquency Bucket
+        final Integer delinquencyBucketId = DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec);
+        final GetDelinquencyBucketsResponse delinquencyBucket = DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                delinquencyBucketId);
+
+        // Client and Loan account creation
+        final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 2012");
+        final GetLoanProductsProductIdResponse getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
+                delinquencyBucket.getId());
+        assertNotNull(getLoanProductsProductResponse);
+
+        // Older date to have more than one overdue installment
+        String operationDate = Utils.dateFormatter.format(businessDate);
+        log.info("Operation date  {}", businessDate);
+
+        // Create Loan Account
+        final Integer loanId = createLoanAccount(loanTransactionHelper, clientId.toString(),
+                getLoanProductsProductResponse.getId().toString(), operationDate, "3");
+
+        // Move the Business date 1 month to apply the first repayment
+        businessDate = businessDate.plusMonths(1);
+        BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, businessDate);
+        log.info("Current Business date {}", businessDate);
+
+        String amountVal = "400.00";
+        Float transactionAmount = Float.valueOf(amountVal);
+        operationDate = Utils.dateFormatter.format(businessDate);
+        PostLoansLoanIdTransactionsResponse loanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(operationDate,
+                transactionAmount, loanId);
+        assertNotNull(loanIdTransactionsResponse);
+        Long transactionId = loanIdTransactionsResponse.getResourceId();
+        loanTransactionHelper.reviewLoanTransactionRelations(loanId, transactionId, 0);
+
+        // Move the Business date 1 month more to apply the second repayment
+        businessDate = businessDate.plusMonths(1);
+        BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, businessDate);
+        log.info("Current Business date {}", businessDate);
+
+        operationDate = Utils.dateFormatter.format(businessDate);
+        loanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(operationDate, transactionAmount, loanId);
+        assertNotNull(loanIdTransactionsResponse);
+        transactionId = loanIdTransactionsResponse.getResourceId();
+        loanTransactionHelper.reviewLoanTransactionRelations(loanId, transactionId, 0);
+
+        // Get loan details expecting to have not a delinquency classification and 1,000 as Outstanding
+        GetLoansLoanIdResponse getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        validateLoanAccount(getLoansLoanIdResponse, "0.00", "400.00", 0, doubleZERO);
+
+        // Move the Business date n days to apply the chargeback for the previous repayment
+        businessDate = businessDate.plusDays(15);
+        BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, businessDate);
+        log.info("Current Business date {}", businessDate);
+
+        // Apply the Chargeback transaction
+        final Long chargebackTransactionId = loanTransactionHelper.applyChargebackTransaction(loanId, transactionId, amountVal, 0,
+                responseSpec);
+        loanTransactionHelper.reviewLoanTransactionRelations(loanId, transactionId, 1);
+
+        // Validate the account expecting to have an adjustment for 100.00 and Outstanding 1,100
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        assertNotNull(getLoansLoanIdResponse);
+        // Past Due Days in Zero because the Charge back transaction exists and It was done with the current date
+        validateLoanAccount(getLoansLoanIdResponse, amountVal, "800.00", 0, Double.valueOf("0.00"));
+
+        // Move the Business date n days to run the COB
+        businessDate = businessDate.plusDays(23);
+        BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, BusinessDateType.BUSINESS_DATE, businessDate);
+        log.info("Current Business date {}", businessDate);
+
+        // Run the Loan COB Job
+        final String jobName = "Loan COB";
+        schedulerJobHelper.executeAndAwaitJob(jobName);
+
+        // Get loan details expecting to have a delinquency classification
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        validateLoanAccount(getLoansLoanIdResponse, amountVal, "800.00", 23, Double.valueOf("800.00"));
+
+        // Move the Business date few days to apply the repayment for Chargeback
+        businessDate = LocalDate.parse("2022-03-20", DateUtils.DEFAULT_DATE_FORMATTER);
+        operationDate = Utils.dateFormatter.format(businessDate);
+        loanIdTransactionsResponse = loanTransactionHelper.makeLoanRepayment(operationDate, transactionAmount, loanId);
+        assertNotNull(loanIdTransactionsResponse);
+        transactionId = loanIdTransactionsResponse.getResourceId();
+        loanTransactionHelper.reviewLoanTransactionRelations(loanId, transactionId, 0);
+
+        // Get loan details expecting to have a delinquency classification
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        validateLoanAccount(getLoansLoanIdResponse, amountVal, "400.00", 7, Double.valueOf("400.00"));
+
+        GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, responseSpec, Boolean.FALSE);
+    }
+
     private GetLoanProductsProductIdResponse createLoanProduct(final LoanTransactionHelper loanTransactionHelper,
             final Integer delinquencyBucketId) {
         final HashMap<String, Object> loanProductMap = new LoanProductTestBuilder().build(null, delinquencyBucketId);
@@ -190,9 +292,9 @@ public class DelinquencyAndChargebackIntegrationTest {
     }
 
     private Integer createLoanAccount(final LoanTransactionHelper loanTransactionHelper, final String clientId, final String loanProductId,
-            final String operationDate) {
-        final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency("12")
-                .withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+            final String operationDate, final String periods) {
+        final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency(periods)
+                .withLoanTermFrequencyAsMonths().withNumberOfRepayments(periods).withRepaymentEveryAfter("1")
                 .withRepaymentFrequencyTypeAsMonths() //
                 .withInterestRatePerPeriod("0") //
                 .withExpectedDisbursementDate(operationDate) //