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 33d781f5f Loan Delinquency Tags with Loan charges
33d781f5f is described below

commit 33d781f5fb8ff5a0db5df91cac44f2998a341b84
Author: Jose Alberto Hernandez <[email protected]>
AuthorDate: Mon Sep 12 00:23:43 2022 -0500

    Loan Delinquency Tags with Loan charges
---
 .../data/LoanRescheduleRequestDataValidator.java   |   8 +-
 .../LoanWritePlatformServiceJpaRepositoryImpl.java |   9 +-
 .../DelinquencyBucketsIntegrationTest.java         | 101 +++++++++++++++++++++
 3 files changed, 106 insertions(+), 12 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/LoanRescheduleRequestDataValidator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/LoanRescheduleRequestDataValidator.java
index 67d7b8ae6..cb20dde73 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/LoanRescheduleRequestDataValidator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/rescheduleloan/data/LoanRescheduleRequestDataValidator.java
@@ -30,6 +30,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import lombok.AllArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.fineract.infrastructure.core.api.JsonCommand;
 import org.apache.fineract.infrastructure.core.data.ApiParameterError;
@@ -42,10 +43,10 @@ import 
org.apache.fineract.portfolio.loanaccount.domain.LoanCharge;
 import 
org.apache.fineract.portfolio.loanaccount.domain.LoanRepaymentScheduleInstallment;
 import 
org.apache.fineract.portfolio.loanaccount.rescheduleloan.RescheduleLoansApiConstants;
 import 
org.apache.fineract.portfolio.loanaccount.rescheduleloan.domain.LoanRescheduleRequest;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 @Component
+@AllArgsConstructor
 public class LoanRescheduleRequestDataValidator {
 
     private final FromJsonHelper fromJsonHelper;
@@ -68,11 +69,6 @@ public class LoanRescheduleRequestDataValidator {
             Arrays.asList(RescheduleLoansApiConstants.localeParamName, 
RescheduleLoansApiConstants.dateFormatParamName,
                     RescheduleLoansApiConstants.approvedOnDateParam));
 
-    @Autowired
-    public LoanRescheduleRequestDataValidator(FromJsonHelper fromJsonHelper) {
-        this.fromJsonHelper = fromJsonHelper;
-    }
-
     /**
      * Validates the request to create a new loan reschedule entry
      *
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
index 3ecadc238..4ed29ed93 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java
@@ -1253,7 +1253,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         changes.put("transactionDate", 
command.stringValueOfParameterNamed("transactionDate"));
         changes.put("locale", command.locale());
         changes.put("dateFormat", command.dateFormat());
-        final LocalDate transactionDate = 
command.localDateValueOfParameterNamed("transactionDate");
         final Loan loan = this.loanAssembler.assembleFrom(loanId);
         if (command.hasParameter("writeoffReasonId")) {
             Long writeoffReasonId = 
command.longValueOfParameterNamed("writeoffReasonId");
@@ -1322,7 +1321,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         changes.put("transactionDate", 
command.stringValueOfParameterNamed("transactionDate"));
         changes.put("locale", command.locale());
         changes.put("dateFormat", command.dateFormat());
-        final LocalDate transactionDate = 
command.localDateValueOfParameterNamed("transactionDate");
 
         final List<Long> existingTransactionIds = new ArrayList<>();
         final List<Long> existingReversedTransactionIds = new ArrayList<>();
@@ -1557,6 +1555,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                 && loan.isFeeCompoundingEnabledForInterestRecalculation()) {
             this.loanAccountDomainService.recalculateAccruals(loan);
         }
+        this.loanAccountDomainService.setLoanDelinquencyTag(loan, 
DateUtils.getBusinessLocalDate());
+
         businessEventNotifierService.notifyPostBusinessEvent(new 
LoanAddChargeBusinessEvent(loanCharge));
         return new 
CommandProcessingResultBuilder().withCommandId(command.commandId()).withEntityId(loanCharge.getId())
                 
.withOfficeId(loan.getOfficeId()).withClientId(loan.getClientId()).withGroupId(loan.getGroupId()).withLoanId(loanId)
@@ -1588,7 +1588,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                 throw new 
PlatformApiDataValidationException(dataValidationErrors);
             }
         }
-
     }
 
     public void runScheduleRecalculation(final Loan loan, final LocalDate 
recalculateFrom) {
@@ -1606,7 +1605,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                     
this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(),
 mapEntry.getValue());
                 }
             }
-
         }
     }
 
@@ -1616,7 +1614,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
             ScheduleGeneratorDTO scheduleGeneratorDTO = 
this.loanUtilService.buildScheduleGeneratorDTO(loan, recalculateFrom);
             createLoanScheduleArchive(loan, scheduleGeneratorDTO);
         }
-
     }
 
     private boolean addCharge(final Loan loan, final Charge chargeDefinition, 
final LoanCharge loanCharge) {
@@ -1733,7 +1730,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         businessEventNotifierService.notifyPostBusinessEvent(new 
LoanBalanceChangedBusinessEvent(newChargeRefundTxn.getLoan()));
         businessEventNotifierService.notifyPostBusinessEvent(new 
LoanChargeRefundBusinessEvent(newChargeRefundTxn));
         return result;
-
     }
 
     private JsonCommand 
adaptLoanChargeRefundCommandForFurtherRepaymentProcessing(JsonCommand command, 
BigDecimal fullRefundAbleAmount) {
@@ -2076,6 +2072,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
         saveLoanWithDataIntegrityViolationChecks(loan);
 
         postJournalEntries(loan, existingTransactionIds, 
existingReversedTransactionIds);
+        this.loanAccountDomainService.setLoanDelinquencyTag(loan, 
DateUtils.getBusinessLocalDate());
 
         businessEventNotifierService.notifyPostBusinessEvent(new 
LoanWaiveChargeBusinessEvent(loanCharge));
 
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 1efd1d9af..ab5c8e10d 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
@@ -24,6 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import com.google.gson.Gson;
 import io.restassured.builder.RequestSpecBuilder;
 import io.restassured.builder.ResponseSpecBuilder;
 import io.restassured.http.ContentType;
@@ -52,9 +53,11 @@ import 
org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
 import org.apache.fineract.integrationtests.common.BusinessDateHelper;
 import 
org.apache.fineract.integrationtests.common.BusinessStepConfigurationHelper;
 import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.CommonConstants;
 import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
 import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
 import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.charges.ChargesHelper;
 import 
org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
 import 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
 import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
@@ -507,6 +510,92 @@ public class DelinquencyBucketsIntegrationTest {
         log.info("Delinquency Tag Item with Lifted On {}", 
getDelinquencyTagsHistory.get(0).getLiftedOnDate());
     }
 
+    @Test
+    public void testLoanClassificationRealtimeWithCharges() {
+        // Given
+        final LoanTransactionHelper loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+        ArrayList<Integer> rangeIds = new ArrayList<>();
+        // First Range
+        String jsonRange = DelinquencyRangesHelper.getAsJSON(1, 3);
+        PostDelinquencyRangeResponse delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec,
+                jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+        jsonRange = DelinquencyRangesHelper.getAsJSON(4, 60);
+
+        GetDelinquencyRangesResponse range = 
DelinquencyRangesHelper.getDelinquencyRange(requestSpec, responseSpec,
+                delinquencyRangeResponse.getResourceId());
+
+        // Second Range
+        delinquencyRangeResponse = 
DelinquencyRangesHelper.createDelinquencyRange(requestSpec, responseSpec, 
jsonRange);
+        rangeIds.add(delinquencyRangeResponse.getResourceId());
+
+        range = DelinquencyRangesHelper.getDelinquencyRange(requestSpec, 
responseSpec, delinquencyRangeResponse.getResourceId());
+        final String classificationExpected = range.getClassification();
+        log.info("Expected Delinquency Range classification after Disbursement 
{}", classificationExpected);
+
+        String jsonBucket = DelinquencyBucketsHelper.getAsJSON(rangeIds);
+        PostDelinquencyBucketResponse delinquencyBucketResponse = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec,
+                responseSpec, jsonBucket);
+        assertNotNull(delinquencyBucketResponse);
+        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());
+        assertNotNull(getLoanProductsProductResponse);
+        log.info("Loan Product Bucket Name: {}", 
getLoanProductsProductResponse.getDelinquencyBucket().getName());
+        
assertEquals(getLoanProductsProductResponse.getDelinquencyBucket().getName(), 
delinquencyBucket.getName());
+
+        final LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        // Older date to have more than one overdue installment
+        LocalDate transactionDate = todaysDate.minusDays(45);
+        String operationDate = Utils.dateFormatter.format(transactionDate);
+
+        // Create Loan Account
+        final Integer loanId = createLoanAccount(loanTransactionHelper, 
clientId.toString(),
+                getLoanProductsProductResponse.getId().toString(), 
operationDate);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
+        log.info("Loan Delinquency Range after Disbursement {}", 
getLoansLoanIdResponse.getDelinquencyRange().getClassification());
+        assertNotNull(getLoansLoanIdResponse);
+        // First Loan Delinquency Classification after Disbursement command
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+        printRepaymentSchedule(getLoansLoanIdResponse);
+
+        // Apply a repayment to get a full paid installment
+        operationDate = Utils.dateFormatter.format(todaysDate);
+        loanTransactionHelper.makeLoanRepayment(operationDate, 1033.33f, 
loanId);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        log.info("Loan Delinquency Range after Repayment {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse);
+        // The Loan Delinquency Classification after Repayment command must be 
null
+        assertNull(getLoansLoanIdResponse.getDelinquencyRange());
+        printRepaymentSchedule(getLoansLoanIdResponse);
+
+        transactionDate = todaysDate.minusDays(18);
+        operationDate = Utils.dateFormatter.format(transactionDate);
+
+        // Create and apply Charge for Specific Due Date
+        final Integer chargeId = ChargesHelper.createCharges(requestSpec, 
responseSpec,
+                ChargesHelper.getLoanSpecifiedDueDateJSON(1, "30", false));
+        assertNotNull(chargeId);
+        final Integer loanChargeId = 
loanTransactionHelper.addChargesForLoan(loanId, getChargeApplyJSON(chargeId, 
operationDate),
+                responseSpec);
+        assertNotNull(loanChargeId);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanId);
+        printRepaymentSchedule(getLoansLoanIdResponse);
+
+        log.info("Loan Delinquency Range after add Loan Charge {}", 
getLoansLoanIdResponse.getDelinquencyRange());
+        assertNotNull(getLoansLoanIdResponse.getDelinquencyRange());
+        // Evaluate a Delinquency Tag set after add charge to the Loan
+        
assertEquals(getLoansLoanIdResponse.getDelinquencyRange().getClassification(), 
classificationExpected);
+    }
+
     @Test
     public void testLoanClassificationRealtimeOlderLoan() {
         // Given
@@ -741,4 +830,16 @@ public class DelinquencyBucketsIntegrationTest {
         }
     }
 
+    private String getChargeApplyJSON(final Integer chargeId, final String 
dueDate) {
+        final HashMap<String, Object> map = new HashMap<>();
+        map.put("chargeId", chargeId);
+        map.put("amount", 12.0f);
+        map.put("dueDate", dueDate);
+        map.put("dateFormat", Utils.DATE_FORMAT);
+        map.put("locale", CommonConstants.LOCALE);
+        final String chargeApplyJSON = new Gson().toJson(map);
+        log.info("{}", chargeApplyJSON);
+        return chargeApplyJSON;
+    }
+
 }

Reply via email to