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 b1af8a3f8 FINERACT-1724: Arrears configuration at loan creation is not 
considered correctly
b1af8a3f8 is described below

commit b1af8a3f833503b65ebf42717b0d69de9c0e2891
Author: Jose Alberto Hernandez <[email protected]>
AuthorDate: Thu Jun 1 01:50:50 2023 -0600

    FINERACT-1724: Arrears configuration at loan creation is not considered 
correctly
---
 .../service/LoanDelinquencyDomainServiceImpl.java  |   7 +-
 .../loanaccount/api/LoansApiResourceSwagger.java   |   2 +
 .../api/LoanProductsApiResourceSwagger.java        |   2 +
 .../LoanDelinquencyDomainServiceTest.java          |   9 +-
 .../DelinquencyBucketsIntegrationTest.java         | 115 +++++++++++++++++++--
 5 files changed, 116 insertions(+), 19 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 90e036f82..13507cf59 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
@@ -120,11 +120,8 @@ public class LoanDelinquencyDomainServiceImpl implements 
LoanDelinquencyDomainSe
         }
 
         Integer graceDays = 0;
-        if 
(loan.getLoanProduct().getLoanProductRelatedDetail().getGraceOnArrearsAgeing() 
!= null) {
-            graceDays = 
loan.getLoanProduct().getLoanProductRelatedDetail().getGraceOnArrearsAgeing();
-            if (graceDays == null) {
-                graceDays = 0;
-            }
+        if (loan.getLoanProductRelatedDetail().getGraceOnArrearsAgeing() != 
null) {
+            graceDays = 
loan.getLoanProductRelatedDetail().getGraceOnArrearsAgeing();
         }
         log.debug("Loan id {} with overdue since date {} and outstanding 
amount {}", loan.getId(), overdueSinceDate, outstandingAmount);
 
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
index 96bf96f27..2c636e45f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
@@ -1072,6 +1072,8 @@ final class LoansApiResourceSwagger {
         public LocalDate overpaidOnDate;
         @Schema(example = "false")
         public Boolean chargedOff;
+        @Schema(example = "3")
+        public Integer inArrearsTolerance;
     }
 
     @Schema(description = "GetLoansResponse")
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
index 1f2afab08..2626ac977 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
@@ -1199,6 +1199,8 @@ final class LoanProductsApiResourceSwagger {
         public Integer dueDaysForRepaymentEvent;
         @Schema(example = "3")
         public Integer overDueDaysForRepaymentEvent;
+        @Schema(example = "3")
+        public Integer inArrearsTolerance;
     }
 
     @Schema(description = "PutLoanProductsProductIdRequest")
diff --git 
a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java
 
b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java
index 054021e56..c75580724 100644
--- 
a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java
+++ 
b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java
@@ -112,8 +112,7 @@ public class LoanDelinquencyDomainServiceTest {
 
         // when
         when(loanProductRelatedDetail.getGraceOnArrearsAgeing()).thenReturn(0);
-        
when(loanProduct.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
-        when(loan.getLoanProduct()).thenReturn(loanProduct);
+        
when(loan.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
         
when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments);
         when(loan.getCurrency()).thenReturn(currency);
 
@@ -137,8 +136,7 @@ public class LoanDelinquencyDomainServiceTest {
 
         // when
         when(loanProductRelatedDetail.getGraceOnArrearsAgeing()).thenReturn(0);
-        
when(loanProduct.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
-        when(loan.getLoanProduct()).thenReturn(loanProduct);
+        
when(loan.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
         
when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments);
         
when(loan.getLoanTransactions(Mockito.any(Predicate.class))).thenReturn(Collections.emptyList());
         
when(loan.getLastLoanRepaymentScheduleInstallment()).thenReturn(repaymentScheduleInstallments.get(0));
@@ -174,8 +172,7 @@ public class LoanDelinquencyDomainServiceTest {
 
         // when
         when(loanProductRelatedDetail.getGraceOnArrearsAgeing()).thenReturn(0);
-        
when(loanProduct.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
-        when(loan.getLoanProduct()).thenReturn(loanProduct);
+        
when(loan.getLoanProductRelatedDetail()).thenReturn(loanProductRelatedDetail);
         
when(loan.getRepaymentScheduleInstallments()).thenReturn(repaymentScheduleInstallments);
         when(loan.getCurrency()).thenReturn(currency);
 
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java
index 252c7ec64..dcac50af7 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/DelinquencyBucketsIntegrationTest.java
@@ -50,6 +50,8 @@ import 
org.apache.fineract.client.models.PostDelinquencyRangeResponse;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import org.apache.fineract.client.models.PutDelinquencyBucketResponse;
 import org.apache.fineract.client.models.PutDelinquencyRangeResponse;
+import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
+import org.apache.fineract.client.models.PutLoanProductsProductIdResponse;
 import org.apache.fineract.cob.data.JobBusinessStepConfigData;
 import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.integrationtests.common.BusinessDateHelper;
@@ -294,7 +296,7 @@ public class DelinquencyBucketsIntegrationTest {
 
             // Create Loan Account
             final Integer loanId = createLoanAccount(loanTransactionHelper, 
clientId.toString(),
-                    getLoanProductsProductResponse.getId().toString(), 
operationDate);
+                    getLoanProductsProductResponse.getId().toString(), 
operationDate, null);
 
             GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
             assertNotNull(getLoansLoanIdResponse);
@@ -390,7 +392,7 @@ public class DelinquencyBucketsIntegrationTest {
 
             // Create Loan Account
             final Integer loanId = createLoanAccount(loanTransactionHelper, 
clientId.toString(),
-                    getLoanProductsProductResponse.getId().toString(), 
operationDate);
+                    getLoanProductsProductResponse.getId().toString(), 
operationDate, null);
 
             GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
             log.info("Loan Delinquency Range after Disbursement {}", 
getLoansLoanIdResponse.getDelinquencyRange().getClassification());
@@ -488,7 +490,7 @@ public class DelinquencyBucketsIntegrationTest {
 
         // Create Loan Account
         final Integer loanId = createLoanAccount(loanTransactionHelper, 
clientId.toString(),
-                getLoanProductsProductResponse.getId().toString(), 
operationDate);
+                getLoanProductsProductResponse.getId().toString(), 
operationDate, null);
 
         GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
         assertNotNull(getLoansLoanIdResponse);
@@ -583,7 +585,7 @@ public class DelinquencyBucketsIntegrationTest {
 
         // Create Loan Account
         final Integer loanId = createLoanAccount(loanTransactionHelper, 
clientId.toString(),
-                getLoanProductsProductResponse.getId().toString(), 
operationDate);
+                getLoanProductsProductResponse.getId().toString(), 
operationDate, null);
 
         GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
         loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
@@ -689,7 +691,7 @@ public class DelinquencyBucketsIntegrationTest {
 
             // Create Loan Account
             final Integer loanId = createLoanAccount(loanTransactionHelper, 
clientId.toString(),
-                    getLoanProductsProductResponse.getId().toString(), 
operationDate);
+                    getLoanProductsProductResponse.getId().toString(), 
operationDate, null);
 
             // Run first time the Job
             final String jobName = "Loan Delinquency Classification";
@@ -777,7 +779,7 @@ public class DelinquencyBucketsIntegrationTest {
 
             // Create Loan Account
             final Integer loanId = createLoanAccount(loanTransactionHelper, 
clientId.toString(),
-                    getLoanProductsProductResponse.getId().toString(), 
operationDate);
+                    getLoanProductsProductResponse.getId().toString(), 
operationDate, null);
 
             // COB Step Validation
             final JobBusinessStepConfigData jobBusinessStepConfigData = 
BusinessStepConfigurationHelper
@@ -879,7 +881,7 @@ public class DelinquencyBucketsIntegrationTest {
 
             // Create Loan Account
             final Integer loanId = createLoanAccount(loanTransactionHelper, 
clientId.toString(),
-                    getLoanProductsProductResponse.getId().toString(), 
operationDate);
+                    getLoanProductsProductResponse.getId().toString(), 
operationDate, null);
 
             // Get loan details expecting to have a delinquency classification
             GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
@@ -911,6 +913,95 @@ public class DelinquencyBucketsIntegrationTest {
         }
     }
 
+    @Test
+    public void testLoanClassificationUsingAgeingArrears() {
+        try {
+            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
+
+            LocalDate bussinesLocalDate = Utils.getDateAsLocalDate("01 January 
2012");
+            log.info("Current date {}", bussinesLocalDate);
+            BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, bussinesLocalDate);
+
+            // Given
+            final LoanTransactionHelper loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+            final SchedulerJobHelper schedulerJobHelper = new 
SchedulerJobHelper(requestSpec);
+
+            ArrayList<Integer> rangeIds = new ArrayList<>();
+            String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
+            PostDelinquencyRangeResponse delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec,
+                    responseSpec, jsonRange);
+            rangeIds.add(delinquencyRangeResponse.getResourceId());
+            final GetDelinquencyRangesResponse range = 
DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
+                    delinquencyRangeResponse.getResourceId());
+            final String classificationExpected = range.getClassification();
+            log.info("Expected Delinquency Range classification {}", 
classificationExpected);
+
+            jsonRange = DelinquencyRangesHelper.getAsJSON(4, 60);
+            delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+            rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+            String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
+            PostDelinquencyBucketResponse delinquencyBucketResponse = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
+                    responseSpec, jsonBucket);
+            final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                    delinquencyBucketResponse.getResourceId());
+
+            // Client and Loan account creation
+            final Integer clientId = 
ClientHelper.createClient(this.requestSpec, this.responseSpec, "01 January 
2012");
+            final GetLoanProductsProductIdResponse 
getLoanProductsProductResponse = createLoanProduct(loanTransactionHelper,
+                    delinquencyBucket.getId(), "3");
+            assertNotNull(getLoanProductsProductResponse);
+            log.info("Loan Product Arrears: {}", 
getLoanProductsProductResponse.getInArrearsTolerance());
+            assertEquals(3, 
getLoanProductsProductResponse.getInArrearsTolerance());
+
+            // Older date to have more than one overdue installment
+            final LocalDate transactionDate = bussinesLocalDate;
+            String operationDate = Utils.dateFormatter.format(transactionDate);
+
+            // Create Loan Account
+            final Integer loanId = createLoanAccount(loanTransactionHelper, 
clientId.toString(),
+                    getLoanProductsProductResponse.getId().toString(), 
operationDate, "3");
+
+            // Get loan details expecting to have a delinquency classification
+            GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+            final GetDelinquencyRangesResponse firstTestCase = 
getLoansLoanIdResponse.getDelinquencyRange();
+            log.info("Loan Delinquency Range is null {}", (firstTestCase == 
null));
+            
loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
+            log.info("Loan Account Arrears {}", 
getLoansLoanIdResponse.getInArrearsTolerance());
+            assertEquals(3, getLoansLoanIdResponse.getInArrearsTolerance());
+
+            // Update the Loan Product
+            updateLoanProduct(loanTransactionHelper, 
getLoanProductsProductResponse.getId(), 0);
+            GetLoanProductsProductIdResponse loanProductsProductIdResponseUpd 
= loanTransactionHelper
+                    
.getLoanProduct(getLoanProductsProductResponse.getId().intValue());
+            assertNotNull(loanProductsProductIdResponseUpd);
+            log.info("Loan Product Arrears: {}", 
loanProductsProductIdResponseUpd.getInArrearsTolerance());
+            assertEquals(0, 
loanProductsProductIdResponseUpd.getInArrearsTolerance());
+
+            final String jobName = "Loan COB";
+
+            bussinesLocalDate = Utils.getDateAsLocalDate("31 January 2012");
+            LocalDate lastLoanCOBBusinessDate = bussinesLocalDate.minusDays(1);
+            schedulerJobHelper.fastForwardTime(lastLoanCOBBusinessDate, 
bussinesLocalDate, jobName, responseSpec);
+            log.info("Current date {}", bussinesLocalDate);
+            BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, bussinesLocalDate);
+            // Run Second time the Job
+            schedulerJobHelper.executeAndAwaitJob(jobName);
+
+            // Get loan details expecting to have a delinquency classification
+            getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+            loanTransactionHelper.printDelinquencyData(getLoansLoanIdResponse);
+
+            GetLoansLoanIdCollectionData getLoansLoanIdCollectionData = 
getLoansLoanIdResponse.getDelinquent();
+            assertNotNull(getLoansLoanIdCollectionData);
+            assertEquals(0, getLoansLoanIdCollectionData.getDelinquentDays());
+            assertEquals(0, getLoansLoanIdCollectionData.getPastDueDays());
+
+        } finally {
+            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
+        }
+    }
+
     private GetLoanProductsProductIdResponse createLoanProduct(final 
LoanTransactionHelper loanTransactionHelper,
             final Integer delinquencyBucketId, final String 
inArrearsTolerance) {
         final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().withInArrearsTolerance(inArrearsTolerance).build(null,
@@ -919,8 +1010,15 @@ public class DelinquencyBucketsIntegrationTest {
         return loanTransactionHelper.getLoanProduct(loanProductId);
     }
 
+    private PutLoanProductsProductIdResponse 
updateLoanProduct(LoanTransactionHelper loanTransactionHelper, Long id,
+            final Integer inArrearsTolerance) {
+        final PutLoanProductsProductIdRequest requestModifyLoan = new 
PutLoanProductsProductIdRequest()
+                .inArrearsTolerance(inArrearsTolerance);
+        return loanTransactionHelper.updateLoanProduct(id, requestModifyLoan);
+    }
+
     private Integer createLoanAccount(final LoanTransactionHelper 
loanTransactionHelper, final String clientId, final String loanProductId,
-            final String operationDate) {
+            final String operationDate, final String inArrearsTolerance) {
         final String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal(principalAmount).withLoanTermFrequency("12")
                 
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
                 .withRepaymentFrequencyTypeAsMonths() //
@@ -928,6 +1026,7 @@ public class DelinquencyBucketsIntegrationTest {
                 .withExpectedDisbursementDate(operationDate) //
                 .withInterestTypeAsDecliningBalance() //
                 .withSubmittedOnDate(operationDate) //
+                .withInArrearsTolerance(inArrearsTolerance) //
                 .build(clientId, loanProductId, null);
         final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
         loanTransactionHelper.approveLoan(operationDate, principalAmount, 
loanId, null);

Reply via email to