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/07/08 12:45:14 UTC
[fineract] branch develop updated: FINERACT-1657 Allow schedule approved/submitted multi non-tranche loans
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 16aafdf95 FINERACT-1657 Allow schedule approved/submitted multi non-tranche loans
16aafdf95 is described below
commit 16aafdf95bf92c7685ad4e2e1cf7150d18eee072
Author: John Woodlock <jo...@gmail.com>
AuthorDate: Sun Jul 3 16:14:49 2022 +0100
FINERACT-1657 Allow schedule approved/submitted multi non-tranche loans
---
.../domain/AbstractLoanScheduleGenerator.java | 58 ++++++++++++++--------
...rancheMultipleDisbursementsIntegrationTest.java | 39 +++++++++++++++
2 files changed, 77 insertions(+), 20 deletions(-)
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
index c72bb2b7f..1465baaf4 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/AbstractLoanScheduleGenerator.java
@@ -1906,27 +1906,40 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
private BigDecimal getDisbursementAmount(final LoanApplicationTerms loanApplicationTerms, LocalDate disbursementDate,
final Collection<LoanScheduleModelPeriod> periods, final BigDecimal chargesDueAtTimeOfDisbursement,
final Map<LocalDate, Money> disurseDetail, final boolean excludePastUndisbursed) {
+
+ // this method relates to multi-disbursement loans
BigDecimal principal = BigDecimal.ZERO;
- MonetaryCurrency currency = loanApplicationTerms.getPrincipal().getCurrency();
- for (DisbursementData disbursementData : loanApplicationTerms.getDisbursementDatas()) {
- if (disbursementData.disbursementDate().equals(disbursementDate)) {
- final LoanScheduleModelDisbursementPeriod disbursementPeriod = LoanScheduleModelDisbursementPeriod.disbursement(
- disbursementData.disbursementDate(), Money.of(currency, disbursementData.amount()), chargesDueAtTimeOfDisbursement);
- periods.add(disbursementPeriod);
- principal = principal.add(disbursementData.amount());
- } else if (!excludePastUndisbursed || disbursementData.isDisbursed()
- || !disbursementData.disbursementDate().isBefore(DateUtils.getBusinessLocalDate())) {
- /*
- * JW: sums up amounts by disbursal date in case of side-effect issues. Original assumed that there were
- * no duplicate disbursal dates and 'put' each amount into the map keyed by date
- */
- Money prevsum = disurseDetail.get(disbursementData.disbursementDate());
- BigDecimal sumToNow = BigDecimal.ZERO;
- if (prevsum != null) {
- sumToNow = prevsum.getAmount();
+ if (loanApplicationTerms.getDisbursementDatas().size() == 0) {
+ // non tranche loans have no disbursement data entries in submitted and approved status
+ // the appropriate approved amount or applied for amount is used to show a proposed schedule
+ if (loanApplicationTerms.getApprovedPrincipal().getAmount().compareTo(BigDecimal.ZERO) > 0) {
+ principal = loanApplicationTerms.getApprovedPrincipal().getAmount();
+ } else {
+ principal = loanApplicationTerms.getPrincipal().getAmount();
+ }
+ } else {
+ MonetaryCurrency currency = loanApplicationTerms.getPrincipal().getCurrency();
+ for (DisbursementData disbursementData : loanApplicationTerms.getDisbursementDatas()) {
+ if (disbursementData.disbursementDate().equals(disbursementDate)) {
+ final LoanScheduleModelDisbursementPeriod disbursementPeriod = LoanScheduleModelDisbursementPeriod.disbursement(
+ disbursementData.disbursementDate(), Money.of(currency, disbursementData.amount()),
+ chargesDueAtTimeOfDisbursement);
+ periods.add(disbursementPeriod);
+ principal = principal.add(disbursementData.amount());
+ } else if (!excludePastUndisbursed || disbursementData.isDisbursed()
+ || !disbursementData.disbursementDate().isBefore(DateUtils.getLocalDateOfTenant())) {
+ /*
+ * JW: sums up amounts by disbursal date in case of side-effect issues. Original assumed that there
+ * were no duplicate disbursal dates and 'put' each amount into the map keyed by date
+ */
+ Money prevsum = disurseDetail.get(disbursementData.disbursementDate());
+ BigDecimal sumToNow = BigDecimal.ZERO;
+ if (prevsum != null) {
+ sumToNow = prevsum.getAmount();
+ }
+ sumToNow = sumToNow.add(disbursementData.amount());
+ disurseDetail.put(disbursementData.disbursementDate(), Money.of(currency, sumToNow));
}
- sumToNow = sumToNow.add(disbursementData.amount());
- disurseDetail.put(disbursementData.disbursementDate(), Money.of(currency, sumToNow));
}
}
return principal;
@@ -1937,7 +1950,12 @@ public abstract class AbstractLoanScheduleGenerator implements LoanScheduleGener
Collection<LoanScheduleModelPeriod> periods = null;
if (loanApplicationTerms.isMultiDisburseLoan()) {
- periods = new ArrayList<>(numberOfRepayments + loanApplicationTerms.getDisbursementDatas().size());
+ int multiDisbursalTrancheEntries = loanApplicationTerms.getDisbursementDatas().size();
+ if (multiDisbursalTrancheEntries == 0) {
+ // will be zero for non-tranche multi-disbursal loan when submitted or approved
+ multiDisbursalTrancheEntries = 1;
+ }
+ periods = new ArrayList<>(numberOfRepayments + multiDisbursalTrancheEntries);
} else {
periods = new ArrayList<>(numberOfRepayments + 1);
final LoanScheduleModelDisbursementPeriod disbursementPeriod = LoanScheduleModelDisbursementPeriod
diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanNonTrancheMultipleDisbursementsIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanNonTrancheMultipleDisbursementsIntegrationTest.java
index fecca0c2b..a33f7402c 100644
--- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanNonTrancheMultipleDisbursementsIntegrationTest.java
+++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanNonTrancheMultipleDisbursementsIntegrationTest.java
@@ -203,4 +203,43 @@ public class ClientLoanNonTrancheMultipleDisbursementsIntegrationTest {
}
+ @Test
+ public void checkThatNonTrancheMultiDisbursalsCreateAScheduleOnSubmitAndApprovalTest() {
+ this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
+
+ final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
+ ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
+
+ /***
+ * Create loan product allowing non-tranche multiple disbursals with interest recalculation
+ */
+ boolean isInterestRecalculationEnabled = true;
+ final Integer loanProductID = createLoanProduct(isInterestRecalculationEnabled);
+ Assertions.assertNotNull(loanProductID);
+
+ /***
+ * Apply for loan application and verify loan status
+ */
+ final String savingsId = null;
+ String submitDate = "01 January 2022";
+ Integer repaymentsNo = 3;
+ final Integer loanID = applyForLoanApplication(clientID, loanProductID, savingsId, APPLIED_FOR_PRINCIPAL, submitDate,
+ repaymentsNo.toString());
+ Assertions.assertNotNull(loanID);
+ HashMap loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
+ LoanStatusChecker.verifyLoanIsPending(loanStatusHashMap);
+ ArrayList<HashMap> loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+ Integer loanScheduleLineCount = loanSchedule.size() - 1; // exclude disbursement line
+ Assertions.assertEquals(repaymentsNo, loanScheduleLineCount);
+
+ LOG.info("-----------------------------------APPROVE LOAN-----------------------------------------");
+ final Float approved = 9000.00f;
+ loanStatusHashMap = this.loanTransactionHelper.approveLoanWithApproveAmount(submitDate, null, approved.toString(), loanID, null);
+ LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
+ LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
+ loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
+ loanScheduleLineCount = loanSchedule.size() - 1;
+ Assertions.assertEquals(repaymentsNo, loanScheduleLineCount);
+
+ }
}