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 226a4321f FINERACT-1854: Undo last disbursal function deletes all 
disbursals on the last date
226a4321f is described below

commit 226a4321fb4b8907fbd4d852e6dbde64e1b3b501
Author: Jose Alberto Hernandez <[email protected]>
AuthorDate: Sun Jan 15 14:19:42 2023 -0600

    FINERACT-1854: Undo last disbursal function deletes all disbursals on the 
last date
---
 .../portfolio/loanaccount/domain/Loan.java         |  74 ++++-----
 .../LoanApplicationUndoLastTrancheTest.java        | 169 +++++++++++++++++++--
 .../common/loans/LoanTransactionHelper.java        |  13 ++
 3 files changed, 208 insertions(+), 48 deletions(-)

diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 6d883595a..8997c8b78 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -3408,7 +3408,7 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         return transactions;
     }
 
-    public List<LoanTransaction> 
retrieveListOfTransactionsByType(LoanTransactionType transactionType) {
+    public List<LoanTransaction> retrieveListOfTransactionsByType(final 
LoanTransactionType transactionType) {
         final List<LoanTransaction> transactions = new ArrayList<>();
         for (final LoanTransaction transaction : this.loanTransactions) {
             if (transaction.isNotReversed() && 
transaction.getTypeOf().equals(transactionType)) {
@@ -4158,10 +4158,6 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         return expectedDisbursementDate;
     }
 
-    /*
-     * Reason for derving
-     */
-
     public BigDecimal getDisburseAmountForTemplate() {
         BigDecimal principal = 
this.loanRepaymentScheduleDetail.getPrincipal().getAmount();
         Collection<LoanDisbursementDetails> details = fetchUndisbursedDetail();
@@ -5205,6 +5201,16 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
         return currentDisbursementDetails;
     }
 
+    public LoanDisbursementDetails getDisbursementDetails(final LocalDate 
transactionDate, final BigDecimal transactionAmount) {
+        for (LoanDisbursementDetails disbursementDetail : 
this.disbursementDetails) {
+            if (!disbursementDetail.isReversed() && 
disbursementDetail.getDisbursementDate().equals(transactionDate)
+                    && 
(disbursementDetail.principal().compareTo(transactionAmount) == 0)) {
+                return disbursementDetail;
+            }
+        }
+        return null;
+    }
+
     public ChangedTransactionDetail 
updateDisbursementDateAndAmountForTranche(final LoanDisbursementDetails 
disbursementDetails,
             final JsonCommand command, final Map<String, Object> 
actualChanges, final ScheduleGeneratorDTO scheduleGeneratorDTO) {
         final Locale locale = command.extractLocale();
@@ -6301,81 +6307,81 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
             List<Long> existingReversedTransactionIds, Loan loan) {
 
         validateAccountStatus(LoanEvent.LOAN_DISBURSAL_UNDO_LAST);
+        
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_DISBURSAL_UNDO_LAST,
 getDisbursementDate());
+
+        final Map<String, Object> actualChanges = new LinkedHashMap<>();
+        List<LoanTransaction> loanTransactions = 
retrieveListOfTransactionsByType(LoanTransactionType.DISBURSEMENT);
+        loanTransactions.sort(Comparator.comparing(LoanTransaction::getId));
+        final LoanTransaction lastDisbursalTransaction = 
loanTransactions.get(loanTransactions.size() - 1);
+        final LocalDate lastTransactionDate = 
lastDisbursalTransaction.getTransactionDate();
+
         existingTransactionIds.addAll(findExistingTransactionIds());
         
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
-        final Map<String, Object> actualChanges = new LinkedHashMap<>();
-        
validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_DISBURSAL_UNDO_LAST,
 getDisbursementDate());
-        LocalDate actualDisbursementDate = null;
-        LocalDate lastTransactionDate = getDisbursementDate();
-        List<LoanTransaction> loanTransactions = 
retrieveListOfTransactionsExcludeAccruals();
+
+        loanTransactions = retrieveListOfTransactionsExcludeAccruals();
         Collections.reverse(loanTransactions);
         for (final LoanTransaction previousTransaction : loanTransactions) {
             if 
(lastTransactionDate.isBefore(previousTransaction.getTransactionDate())
                     && (previousTransaction.isRepaymentType() || 
previousTransaction.isWaiver() || previousTransaction.isChargePayment())) {
                 throw new 
UndoLastTrancheDisbursementException(previousTransaction.getId());
             }
-            if (previousTransaction.isDisbursement()) {
-                lastTransactionDate = previousTransaction.getTransactionDate();
+            if 
(previousTransaction.getId().compareTo(lastDisbursalTransaction.getId()) < 0) {
                 break;
             }
         }
-        actualDisbursementDate = lastTransactionDate;
-        updateLoanToLastDisbursalState(actualDisbursementDate);
+        final LoanDisbursementDetails disbursementDetail = 
loan.getDisbursementDetails(lastTransactionDate,
+                lastDisbursalTransaction.getAmount());
+        updateLoanToLastDisbursalState(disbursementDetail);
         for (Iterator<LoanTermVariations> iterator = 
this.loanTermVariations.iterator(); iterator.hasNext();) {
             LoanTermVariations loanTermVariations = iterator.next();
-            if ((loanTermVariations.getTermType().isDueDateVariation()
-                    && 
loanTermVariations.fetchDateValue().isAfter(actualDisbursementDate))
+            if ((loanTermVariations.getTermType().isDueDateVariation() && 
loanTermVariations.fetchDateValue().isAfter(lastTransactionDate))
                     || (loanTermVariations.getTermType().isEMIAmountVariation()
-                            && 
loanTermVariations.getTermApplicableFrom().compareTo(actualDisbursementDate) == 
0 ? Boolean.TRUE
+                            && 
loanTermVariations.getTermApplicableFrom().compareTo(lastTransactionDate) == 0 
? Boolean.TRUE
                                     : Boolean.FALSE)
-                    || 
loanTermVariations.getTermApplicableFrom().isAfter(actualDisbursementDate)) {
+                    || 
loanTermVariations.getTermApplicableFrom().isAfter(lastTransactionDate)) {
                 iterator.remove();
             }
         }
-        reverseExistingTransactionsTillLastDisbursal(actualDisbursementDate);
+        reverseExistingTransactionsTillLastDisbursal(lastDisbursalTransaction);
         loan.recalculateScheduleFromLastTransaction(scheduleGeneratorDTO, 
existingTransactionIds, existingReversedTransactionIds);
         actualChanges.put("undolastdisbursal", "true");
         actualChanges.put("disbursedAmount", this.getDisbursedAmount());
         updateLoanSummaryDerivedFields();
 
+        doPostLoanTransactionChecks(getLastUserTransactionDate(), 
loanLifecycleStateMachine);
+
         return actualChanges;
     }
 
     /**
      * Reverse only disbursement, accruals, and repayments at disbursal 
transactions
      *
-     * @param actualDisbursementDate
+     * @param lastDisbursalTransaction
      * @return
      */
-    public List<LoanTransaction> 
reverseExistingTransactionsTillLastDisbursal(LocalDate actualDisbursementDate) {
-        final List<LoanTransaction> reversedTransactions = new ArrayList<>();
+    public void reverseExistingTransactionsTillLastDisbursal(LoanTransaction 
lastDisbursalTransaction) {
         for (final LoanTransaction transaction : this.loanTransactions) {
-            if 
((actualDisbursementDate.equals(transaction.getTransactionDate())
-                    || 
actualDisbursementDate.isBefore(transaction.getTransactionDate()))
+            if 
((transaction.getTransactionDate().compareTo(lastDisbursalTransaction.getTransactionDate())
 >= 0)
+                    && 
(transaction.getId().compareTo(lastDisbursalTransaction.getId()) >= 0)
                     && 
transaction.isAllowTypeTransactionAtTheTimeOfLastUndo()) {
-                reversedTransactions.add(transaction);
                 transaction.reverse();
             }
         }
-        return reversedTransactions;
     }
 
-    private void updateLoanToLastDisbursalState(LocalDate 
actualDisbursementDate) {
+    private void updateLoanToLastDisbursalState(LoanDisbursementDetails 
disbursementDetail) {
 
         for (final LoanCharge charge : getActiveCharges()) {
             if (charge.isOverdueInstallmentCharge()) {
                 charge.setActive(false);
-            } else if (charge.isTrancheDisbursementCharge() && 
actualDisbursementDate
+            } else if (charge.isTrancheDisbursementCharge() && 
disbursementDetail.getDisbursementDate()
                     
.equals(charge.getTrancheDisbursementCharge().getloanDisbursementDetails().actualDisbursementDate()))
 {
                 charge.resetToOriginal(loanCurrency());
             }
         }
-        for (final LoanDisbursementDetails details : getDisbursementDetails()) 
{
-            if 
(actualDisbursementDate.equals(details.actualDisbursementDate())) {
-                
this.loanRepaymentScheduleDetail.setPrincipal(getDisbursedAmount().subtract(details.principal()));
-                details.updateActualDisbursementDate(null);
-            }
-        }
+        
this.loanRepaymentScheduleDetail.setPrincipal(getDisbursedAmount().subtract(disbursementDetail.principal()));
+        disbursementDetail.updateActualDisbursementDate(null);
+        disbursementDetail.reverse();
         updateLoanSummaryDerivedFields();
     }
 
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java
index 65740ee72..7b1f0ca74 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanApplicationUndoLastTrancheTest.java
@@ -18,6 +18,8 @@
  */
 package org.apache.fineract.integrationtests;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
 import io.restassured.builder.RequestSpecBuilder;
 import io.restassured.builder.ResponseSpecBuilder;
 import io.restassured.http.ContentType;
@@ -25,9 +27,12 @@ import io.restassured.path.json.JsonPath;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
+import org.apache.fineract.client.models.GetLoansLoanIdResponse;
+import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.CollateralManagementHelper;
 import org.apache.fineract.integrationtests.common.Utils;
@@ -91,7 +96,7 @@ public class LoanApplicationUndoLastTrancheTest {
         
approveTranches.add(this.loanApplicationApprovalTest.createTrancheDetail("23 
June 2014", "1000"));
 
         // APPLY FOR LOAN WITH TRANCHES
-        final Integer loanID = applyForLoanApplicationWithTranches(clientID, 
loanProductID, proposedAmount, createTranches);
+        final Integer loanID = applyForLoanApplicationWithTranches(clientID, 
loanProductID, proposedAmount, "2", createTranches);
         LOG.info("-----------------------------------LOAN CREATED WITH 
LOANID------------------------------------------------- {}", loanID);
         HashMap loanStatusHashMap = 
LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
 
@@ -129,6 +134,140 @@ public class LoanApplicationUndoLastTrancheTest {
         validateDisbursedAmount(disbursedAmount);
     }
 
+    @Test
+    public void loanApplicationUndoLastTrancheToClose() {
+        final LocalDate todaysDate = Utils.getLocalDateOfTenant();
+        LocalDate transactionDate = LocalDate.of(todaysDate.getYear(), 1, 1);
+        String operationDate = Utils.dateFormatter.format(transactionDate);
+        LOG.info("Operation date {}", transactionDate);
+
+        final String proposedAmount = "1000";
+
+        // CREATE CLIENT
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2014");
+        LOG.info("---------------------------------CLIENT CREATED WITH 
ID--------------------------------------------------- {}", clientID);
+
+        // CREATE LOAN MULTIDISBURSAL PRODUCT
+        final Integer loanProductID = this.loanTransactionHelper
+                .getLoanProductId(new 
LoanProductTestBuilder().withInterestTypeAsDecliningBalance().withTranches(true)
+                        
.withDisallowExpectedDisbursements(true).withInterestCalculationPeriodTypeAsRepaymentPeriod(true).build(null));
+        LOG.info("----------------------------------LOAN PRODUCT CREATED WITH 
ID------------------------------------------- {}",
+                loanProductID);
+
+        // APPLY FOR LOAN WITH TRANCHES
+        final Integer loanID = applyForLoanApplicationWithTranches(clientID, 
loanProductID, proposedAmount, "0", new ArrayList<>());
+
+        LOG.info("-----------------------------------LOAN CREATED WITH 
LOANID------------------------------------------------- {}", loanID);
+
+        LOG.info("-----------------------------------APPROVE 
LOAN-----------------------------------------------------------");
+        this.loanTransactionHelper.approveLoan(operationDate, proposedAmount, 
loanID, null);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanID);
+        assertNotNull(getLoansLoanIdResponse);
+        loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, 
"loanStatusType.approved");
+
+        // DISBURSE A LOAN
+        loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, 
loanID, "500");
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanID);
+        assertNotNull(getLoansLoanIdResponse);
+        // VALIDATE THE LOAN IS ACTIVE STATUS
+        loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, 
"loanStatusType.active");
+        
loanTransactionHelper.evaluateLoanDisbursementDetails(getLoansLoanIdResponse, 
1, Double.valueOf("500.00"));
+
+        // DISBURSE A LOAN (second)
+        transactionDate = transactionDate.plusDays(2);
+        operationDate = Utils.dateFormatter.format(transactionDate);
+        LOG.info("Operation date {}", transactionDate);
+        loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, 
loanID, "500");
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanID);
+        assertNotNull(getLoansLoanIdResponse);
+        // VALIDATE THE LOAN IS ACTIVE STATUS
+        loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, 
"loanStatusType.active");
+        
loanTransactionHelper.evaluateLoanDisbursementDetails(getLoansLoanIdResponse, 
2, Double.valueOf("1000.00"));
+
+        // BACKDATE REPAYMENT
+        transactionDate = transactionDate.minusDays(1);
+        operationDate = Utils.dateFormatter.format(transactionDate);
+        LOG.info("Operation date {}", transactionDate);
+        Float amount = Float.valueOf("500.00");
+        PostLoansLoanIdTransactionsResponse loanIdTransactionsResponse = 
loanTransactionHelper.makeLoanRepayment(operationDate, amount,
+                loanID);
+        assertNotNull(loanIdTransactionsResponse);
+        LOG.info("Loan Transaction Id: {} {}", loanID, 
loanIdTransactionsResponse.getResourceId());
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanID);
+        assertNotNull(getLoansLoanIdResponse);
+        // VALIDATE THE LOAN IS ACTIVE STATUS
+        loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, 
"loanStatusType.active");
+        
loanTransactionHelper.evaluateLoanDisbursementDetails(getLoansLoanIdResponse, 
2, Double.valueOf("1000.00"));
+        
loanTransactionHelper.validateLoanTotalOustandingBalance(getLoansLoanIdResponse,
 Double.valueOf("500.00"));
+
+        // UNDO LAST TRANCHE
+        this.loanTransactionHelper.undoLastDisbursal(loanID);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanID);
+        assertNotNull(getLoansLoanIdResponse);
+        // VALIDATE THE LOAN IS ACTIVE STATUS
+        loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, 
"loanStatusType.closed.obligations.met");
+        
loanTransactionHelper.validateLoanTotalOustandingBalance(getLoansLoanIdResponse,
 Double.valueOf("0.00"));
+    }
+
+    @Test
+    public void loanApplicationUndoLastTrancheWithSameDate() {
+
+        final String proposedAmount = "5000";
+        final String approveDate = "01 March 2014";
+        final String disbursalDate = "01 March 2014";
+
+        // CREATE CLIENT
+        final Integer clientID = ClientHelper.createClient(this.requestSpec, 
this.responseSpec, "01 January 2014");
+        LOG.info("---------------------------------CLIENT CREATED WITH 
ID--------------------------------------------------- {}", clientID);
+
+        // CREATE LOAN MULTIDISBURSAL PRODUCT
+        final Integer loanProductID = this.loanTransactionHelper
+                .getLoanProductId(new 
LoanProductTestBuilder().withInterestTypeAsDecliningBalance().withTranches(true)
+                        
.withDisallowExpectedDisbursements(true).withInterestCalculationPeriodTypeAsRepaymentPeriod(true).build(null));
+        LOG.info("----------------------------------LOAN PRODUCT CREATED WITH 
ID------------------------------------------- {}",
+                loanProductID);
+
+        // APPLY FOR LOAN WITH TRANCHES
+        final Integer loanID = applyForLoanApplicationWithTranches(clientID, 
loanProductID, proposedAmount, "0", new ArrayList<>());
+
+        LOG.info("-----------------------------------LOAN CREATED WITH 
LOANID------------------------------------------------- {}", loanID);
+
+        LOG.info("-----------------------------------APPROVE 
LOAN-----------------------------------------------------------");
+        this.loanTransactionHelper.approveLoan(approveDate, proposedAmount, 
loanID, null);
+
+        GetLoansLoanIdResponse getLoansLoanIdResponse = 
loanTransactionHelper.getLoan(requestSpec, responseSpec, loanID);
+        assertNotNull(getLoansLoanIdResponse);
+        loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, 
"loanStatusType.approved");
+
+        // DISBURSE A LOAN
+        loanTransactionHelper.disburseLoanWithTransactionAmount(disbursalDate, 
loanID, "1000");
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanID);
+        assertNotNull(getLoansLoanIdResponse);
+        // VALIDATE THE LOAN IS ACTIVE STATUS
+        loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, 
"loanStatusType.active");
+        
loanTransactionHelper.evaluateLoanDisbursementDetails(getLoansLoanIdResponse, 
1, Double.valueOf("1000.00"));
+
+        // DISBURSE A LOAN (second)
+        loanTransactionHelper.disburseLoanWithTransactionAmount(disbursalDate, 
loanID, "2000");
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanID);
+        assertNotNull(getLoansLoanIdResponse);
+        // VALIDATE THE LOAN IS ACTIVE STATUS
+        loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, 
"loanStatusType.active");
+        
loanTransactionHelper.evaluateLoanDisbursementDetails(getLoansLoanIdResponse, 
2, Double.valueOf("3000.00"));
+
+        // UNDO LAST TRANCHE
+        this.loanTransactionHelper.undoLastDisbursal(loanID);
+
+        getLoansLoanIdResponse = loanTransactionHelper.getLoan(requestSpec, 
responseSpec, loanID);
+        assertNotNull(getLoansLoanIdResponse);
+        // VALIDATE THE LOAN IS ACTIVE STATUS
+        loanTransactionHelper.validateLoanStatus(getLoansLoanIdResponse, 
"loanStatusType.active");
+        
loanTransactionHelper.evaluateLoanDisbursementDetails(getLoansLoanIdResponse, 
1, Double.valueOf("1000.00"));
+        
loanTransactionHelper.validateLoanTotalOustandingBalance(getLoansLoanIdResponse,
 Double.valueOf("1000.00"));
+    }
+
     private void validateDisbursedAmount(Float disbursedAmount) {
         Assertions.assertEquals(Float.valueOf("1000.0"), disbursedAmount);
 
@@ -146,7 +285,7 @@ public class LoanApplicationUndoLastTrancheTest {
     }
 
     public Integer applyForLoanApplicationWithTranches(final Integer clientID, 
final Integer loanProductID, String principal,
-            List<HashMap> tranches) {
+            final String interestRate, List<HashMap> tranches) {
         LOG.info("--------------------------------APPLYING FOR LOAN 
APPLICATION--------------------------------");
         List<HashMap> collaterals = new ArrayList<>();
         final Integer collateralId = 
CollateralManagementHelper.createCollateralProduct(this.requestSpec, 
this.responseSpec);
@@ -155,21 +294,23 @@ public class LoanApplicationUndoLastTrancheTest {
                 clientID.toString(), collateralId);
         Assertions.assertNotNull(clientCollateralId);
         addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
-        final String loanApplicationJSON = new LoanApplicationTestBuilder()
-                //
-                .withPrincipal(principal)
-                //
-                .withLoanTermFrequency("5")
-                //
-                .withLoanTermFrequencyAsMonths()
-                //
-                
.withNumberOfRepayments("5").withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths()
 //
-                .withInterestRatePerPeriod("2") //
+        LoanApplicationTestBuilder loanApplication = new 
LoanApplicationTestBuilder() //
+                .withPrincipal(principal) //
+                .withLoanTermFrequency("5") //
+                .withLoanTermFrequencyAsMonths() //
+                .withNumberOfRepayments("5") //
+                .withRepaymentEveryAfter("1") //
+                .withRepaymentFrequencyTypeAsMonths() //
+                .withInterestRatePerPeriod(interestRate) //
                 .withExpectedDisbursementDate("01 March 2014") //
-                .withTranches(tranches) //
                 .withInterestTypeAsDecliningBalance() //
                 .withSubmittedOnDate("01 March 2014") //
-                .withCollaterals(collaterals).build(clientID.toString(), 
loanProductID.toString(), null);
+                .withCollaterals(collaterals);
+
+        if (tranches != null && tranches.size() > 0) {
+            loanApplication = loanApplication.withTranches(tranches);
+        }
+        final String loanApplicationJSON = 
loanApplication.build(clientID.toString(), loanProductID.toString(), null);
 
         return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
     }
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
index cb3ba3993..2b9045de5 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanTransactionHelper.java
@@ -50,6 +50,7 @@ import 
org.apache.fineract.client.models.GetLoansApprovalTemplateResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdChargesChargeIdResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdChargesTemplateResponse;
 import org.apache.fineract.client.models.GetLoansLoanIdCollectionData;
+import org.apache.fineract.client.models.GetLoansLoanIdDisbursementDetails;
 import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
 import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
 import org.apache.fineract.client.models.GetLoansLoanIdResponse;
@@ -1617,6 +1618,18 @@ public class LoanTransactionHelper extends 
IntegrationTest {
         }
     }
 
+    public void evaluateLoanDisbursementDetails(GetLoansLoanIdResponse 
getLoansLoanIdResponse, Integer numItems, Double amountExpected) {
+        log.info("Disbursement details items: {}", 
getLoansLoanIdResponse.getDisbursementDetails().size());
+        assertEquals(numItems, 
getLoansLoanIdResponse.getDisbursementDetails().size());
+        Double amount = Double.valueOf("0.0");
+        for (GetLoansLoanIdDisbursementDetails disbursementDetails : 
getLoansLoanIdResponse.getDisbursementDetails()) {
+            amount = amount + disbursementDetails.getPrincipal();
+            log.info("Disbursement details with principal {} {}", 
disbursementDetails.getExpectedDisbursementDate(),
+                    disbursementDetails.getPrincipal());
+        }
+        assertEquals(amountExpected, amount);
+    }
+
     public Long applyChargebackTransaction(final Integer loanId, final Long 
transactionId, final String amount,
             final Integer paymentTypeIdx, ResponseSpecification responseSpec) {
         List<GetPaymentTypesResponse> paymentTypeList = 
PaymentTypeHelper.getSystemPaymentType(this.requestSpec, this.responseSpec);

Reply via email to