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 d15fc994e FINERACT-1724-Accrual-reversal-multiple-disbursement
d15fc994e is described below
commit d15fc994e37734822215d34bec62e178d731a59e
Author: Ruchi Dhamankar <[email protected]>
AuthorDate: Mon May 8 21:59:36 2023 +0530
FINERACT-1724-Accrual-reversal-multiple-disbursement
---
.../portfolio/loanaccount/domain/Loan.java | 6 +-
.../LoanAccrualTransactionReversalTest.java | 285 +++++++++++++++++++++
.../LoanRescheduleOnDecliningBalanceLoanTest.java | 55 +++-
.../integrationtests/SchedulerJobsTestResults.java | 30 ++-
4 files changed, 370 insertions(+), 6 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 3773ff3b5..ecef2f2a4 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
@@ -1335,13 +1335,14 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
if
(installment.getFeeChargesCharged(getCurrency()).isLessThan(fee)
||
installment.getInterestCharged(getCurrency()).isLessThan(interest)
||
installment.getPenaltyChargesCharged(getCurrency()).isLessThan(penality)
- ||
(getAccruedTill().isEqual(loanTransaction.getTransactionDate())
+ || (isInterestBearing() &&
getAccruedTill().isEqual(loanTransaction.getTransactionDate())
&&
!installment.getDueDate().isEqual(getAccruedTill()))) {
interest =
interest.minus(loanTransaction.getInterestPortion(getCurrency()));
fee =
fee.minus(loanTransaction.getFeeChargesPortion(getCurrency()));
penality =
penality.minus(loanTransaction.getPenaltyChargesPortion(getCurrency()));
loanTransaction.reverse();
}
+
}
}
installment.updateAccrualPortion(interest, fee, penality);
@@ -5339,8 +5340,7 @@ public class Loan extends
AbstractAuditableWithUTCDateTimeCustom {
}
public boolean isInterestBearing() {
- return
getLoanRepaymentScheduleDetail().isInterestRecalculationEnabled()
- &&
BigDecimal.ZERO.compareTo(getLoanRepaymentScheduleDetail().getAnnualNominalInterestRate())
< 0;
+ return
BigDecimal.ZERO.compareTo(getLoanRepaymentScheduleDetail().getAnnualNominalInterestRate())
< 0;
}
public LocalDate getExpectedMaturityDate() {
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionReversalTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionReversalTest.java
new file mode 100644
index 000000000..e0fabe178
--- /dev/null
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccrualTransactionReversalTest.java
@@ -0,0 +1,285 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.integrationtests;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import io.restassured.builder.RequestSpecBuilder;
+import io.restassured.builder.ResponseSpecBuilder;
+import io.restassured.http.ContentType;
+import io.restassured.specification.RequestSpecification;
+import io.restassured.specification.ResponseSpecification;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.UUID;
+import org.apache.fineract.client.models.GetDelinquencyBucketsResponse;
+import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
+import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
+import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
+import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
+import org.apache.fineract.integrationtests.common.BusinessDateHelper;
+import org.apache.fineract.integrationtests.common.ClientHelper;
+import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
+import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.accounting.Account;
+import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
+import
org.apache.fineract.integrationtests.common.accounting.PeriodicAccrualAccountingHelper;
+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.LoanTestLifecycleExtension;
+import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
+import
org.apache.fineract.integrationtests.common.products.DelinquencyBucketsHelper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+@ExtendWith(LoanTestLifecycleExtension.class)
+public class LoanAccrualTransactionReversalTest {
+
+ private ResponseSpecification responseSpec;
+ private RequestSpecification requestSpec;
+ private LoanTransactionHelper loanTransactionHelper;
+ private ClientHelper clientHelper;
+ private DateTimeFormatter dateFormatter = new
DateTimeFormatterBuilder().appendPattern("dd MMMM yyyy").toFormatter();
+ private PeriodicAccrualAccountingHelper periodicAccrualAccountingHelper;
+ private AccountHelper accountHelper;
+
+ @BeforeEach
+ public void setup() {
+ Utils.initializeRESTAssured();
+ this.requestSpec = new
RequestSpecBuilder().setContentType(ContentType.JSON).build();
+ this.requestSpec.header("Authorization", "Basic " +
Utils.loginIntoServerAndGetBase64EncodedAuthenticationKey());
+ this.responseSpec = new
ResponseSpecBuilder().expectStatusCode(200).build();
+ this.loanTransactionHelper = new
LoanTransactionHelper(this.requestSpec, this.responseSpec);
+ this.clientHelper = new ClientHelper(this.requestSpec,
this.responseSpec);
+ this.periodicAccrualAccountingHelper = new
PeriodicAccrualAccountingHelper(this.requestSpec, this.responseSpec);
+ this.accountHelper = new AccountHelper(this.requestSpec,
this.responseSpec);
+ }
+
+ @Test
+ public void
testNoAccrualTransactionReversalForMultipleDisbursementWithChargeForLoanAccountWithNoInterestBearingSchedulePeriodicAccrual()
{
+
+ // Accounts for periodic accrual
+ final Account assetAccount = this.accountHelper.createAssetAccount();
+ final Account incomeAccount = this.accountHelper.createIncomeAccount();
+ final Account expenseAccount =
this.accountHelper.createExpenseAccount();
+ final Account overpaymentAccount =
this.accountHelper.createLiabilityAccount();
+
+ // Loan ExternalId
+ String loanExternalIdStr = UUID.randomUUID().toString();
+
+ // 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(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
+ final GetLoanProductsProductIdResponse getLoanProductsProductResponse
= createLoanProductWithMultipleDisbursement(
+ loanTransactionHelper, delinquencyBucketId, assetAccount,
incomeAccount, expenseAccount, overpaymentAccount);
+ assertNotNull(getLoanProductsProductResponse);
+
+ final Integer loanId = createLoanAccount(clientId,
getLoanProductsProductResponse.getId(), loanExternalIdStr);
+ // 1st disbursement
+ loanTransactionHelper.disburseLoanWithTransactionAmount("03 September
2022", loanId, "100");
+ // 2nd disbursement
+ loanTransactionHelper.disburseLoanWithTransactionAmount("04 September
2022", loanId, "300");
+
+ // Add Charge
+ Integer penalty = ChargesHelper.createCharges(requestSpec,
responseSpec,
+
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT,
"10", true));
+
+ LocalDate targetDate = LocalDate.of(2022, 9, 4);
+ final String penaltyCharge1AddedDate =
dateFormatter.format(targetDate);
+
+ Integer penalty1LoanChargeId =
this.loanTransactionHelper.addChargesForLoan(loanId,
+
LoanTransactionHelper.getSpecifiedDueDateChargesForLoanAsJSON(String.valueOf(penalty),
penaltyCharge1AddedDate, "10"));
+
+ // Run accrual till charge date
+
this.periodicAccrualAccountingHelper.runPeriodicAccrualAccounting(penaltyCharge1AddedDate);
+
+ // verify accrual transaction created
+ checkAccrualTransaction(targetDate, 0.0f, 0.0f, 10.0f, loanId);
+
+ // 3rd disbursement
+ loanTransactionHelper.disburseLoanWithTransactionAmount("05 September
2022", loanId, "600");
+
+ // verify accrual transaction exists with same date,amount and is not
reversed by regeneration of repayment
+ // schedule
+ checkAccrualTransaction(targetDate, 0.0f, 0.0f, 10.0f, loanId);
+
+ }
+
+ @Test
+ public void
testLastAccrualTransactionReversalRecalculationForLoanAccountWithInterestBearingScheduleWithDecliningBalance()
{
+
+ try {
+ // Set business date
+ LocalDate currentDate = LocalDate.of(2022, 05, 8);
+ final String accrualRunTillDate =
dateFormatter.format(currentDate);
+
+ GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec,
responseSpec, Boolean.TRUE);
+ BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec,
BusinessDateType.BUSINESS_DATE, currentDate);
+
+ // Accounts oof periodic accrual
+ final Account assetAccount =
this.accountHelper.createAssetAccount();
+ final Account incomeAccount =
this.accountHelper.createIncomeAccount();
+ final Account expenseAccount =
this.accountHelper.createExpenseAccount();
+ final Account overpaymentAccount =
this.accountHelper.createLiabilityAccount();
+
+ // Loan ExternalId
+ String loanExternalIdStr = UUID.randomUUID().toString();
+
+ // Client and Loan account creation
+
+ final Integer clientId =
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
+
+ // create loan product
+ final GetLoanProductsProductIdResponse
getLoanProductsProductResponse =
createLoanProductWithInterestRecalculation(assetAccount,
+ incomeAccount, expenseAccount, overpaymentAccount);
+ assertNotNull(getLoanProductsProductResponse);
+ // create loan account
+ final Integer loanId =
createLoanAccountWithInterestRecalculation(clientId,
getLoanProductsProductResponse.getId(),
+ loanExternalIdStr);
+ // run accruals till business date
+
this.periodicAccrualAccountingHelper.runPeriodicAccrualAccounting(accrualRunTillDate);
+ // check amount for last accrual on business date
+ checkAccrualTransaction(currentDate, 0.82f, 0.0f, 0.0f, loanId);
+ // make repayment on due date
+ final PostLoansLoanIdTransactionsResponse repaymentTransaction =
loanTransactionHelper.makeLoanRepayment(loanExternalIdStr,
+ new PostLoansLoanIdTransactionsRequest().dateFormat("dd
MMMM yyyy").transactionDate("5 February 2022").locale("en")
+ .transactionAmount(106.57));
+ // check previous accrual is reversed and new accrual created for
same date and different amount.
+ checkAccrualTransaction(currentDate, 0.71f, 0.0f, 0.0f, loanId);
+ } finally {
+ GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec,
responseSpec, Boolean.FALSE);
+ }
+
+ }
+
+ private Integer createLoanAccountWithInterestRecalculation(final Integer
clientID, final Long loanProductID, final String externalId) {
+
+ final String loanApplicationJSON = new
LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("12")
+
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
+
.withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments().withInterestCalculationPeriodTypeAsDays()
+
.withInterestRatePerPeriod("12").withInterestTypeAsDecliningBalance().withPrincipalGrace("2").withInterestGrace("2")
+ .withExpectedDisbursementDate("05 January
2022").withSubmittedOnDate("05 January 2022").withLoanType("individual")
+ .withExternalId(externalId).build(clientID.toString(),
loanProductID.toString(), null);
+
+ final Integer loanId =
loanTransactionHelper.getLoanId(loanApplicationJSON);
+ loanTransactionHelper.approveLoan("05 January 2022", "1000", loanId,
null);
+ loanTransactionHelper.disburseLoanWithNetDisbursalAmount("05 January
2022", loanId, "1000");
+ return loanId;
+ }
+
+ private GetLoanProductsProductIdResponse
createLoanProductWithInterestRecalculation(final Account... accounts) {
+
+ final String interestRecalculationCompoundingMethod =
LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE;
+ final String rescheduleStrategyMethod =
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS;
+ final String recalculationRestFrequencyType =
LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_DAILY;
+ final String recalculationRestFrequencyInterval = "0";
+ final String preCloseInterestCalculationStrategy =
LoanProductTestBuilder.INTEREST_APPLICABLE_STRATEGY_ON_PRE_CLOSE_DATE;
+ final String recalculationCompoundingFrequencyType = null;
+ final String recalculationCompoundingFrequencyInterval = null;
+ final Integer recalculationCompoundingFrequencyOnDayType = null;
+ final Integer recalculationCompoundingFrequencyDayOfWeekType = null;
+ final Integer recalculationRestFrequencyOnDayType = null;
+ final Integer recalculationRestFrequencyDayOfWeekType = null;
+
+ final String loanProductJSON = new
LoanProductTestBuilder().withPrincipal("1000").withNumberOfRepayments("12")
+
.withinterestRatePerPeriod("12").withInterestRateFrequencyTypeAsYear().withInterestTypeAsDecliningBalance()
+ .withInterestCalculationPeriodTypeAsDays()
+
.withInterestRecalculationDetails(interestRecalculationCompoundingMethod,
rescheduleStrategyMethod,
+ preCloseInterestCalculationStrategy)
+
.withInterestRecalculationRestFrequencyDetails(recalculationRestFrequencyType,
recalculationRestFrequencyInterval,
+ recalculationRestFrequencyOnDayType,
recalculationRestFrequencyDayOfWeekType)
+
.withInterestRecalculationCompoundingFrequencyDetails(recalculationCompoundingFrequencyType,
+ recalculationCompoundingFrequencyInterval,
recalculationCompoundingFrequencyOnDayType,
+ recalculationCompoundingFrequencyDayOfWeekType)
+ .withAccountingRulePeriodicAccrual(accounts).build(null);
+
+ final Integer loanProductId =
this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+ return loanTransactionHelper.getLoanProduct(loanProductId);
+ }
+
+ private GetLoanProductsProductIdResponse
createLoanProductWithMultipleDisbursement(final LoanTransactionHelper
loanTransactionHelper,
+ final Integer delinquencyBucketId, final Account... accounts) {
+
+ final HashMap<String, Object> loanProductMap = new
LoanProductTestBuilder().withPrincipal("1000").withRepaymentTypeAsMonth()
+
.withRepaymentAfterEvery("1").withNumberOfRepayments("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("0")
+
.withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsDecliningBalance()
+
.withAccountingRulePeriodicAccrual(accounts).withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withDaysInMonth("30")
+ .withDaysInYear("365").withMoratorium("0",
"0").withMultiDisburse().withDisallowExpectedDisbursements(true)
+ .build(null, delinquencyBucketId);
+ final Integer loanProductId =
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
+ return loanTransactionHelper.getLoanProduct(loanProductId);
+ }
+
+ private Integer createLoanAccount(final Integer clientID, final Long
loanProductID, final String externalId) {
+
+ String loanApplicationJSON = new
LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("1")
+
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("1").withRepaymentEveryAfter("1")
+
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance()
+
.withAmortizationTypeAsEqualPrincipalPayments().withInterestCalculationPeriodTypeSameAsRepaymentPeriod()
+ .withExpectedDisbursementDate("03 September
2022").withSubmittedOnDate("01 September 2022").withLoanType("individual")
+ .withExternalId(externalId).build(clientID.toString(),
loanProductID.toString(), null);
+
+ final Integer loanId =
loanTransactionHelper.getLoanId(loanApplicationJSON);
+ loanTransactionHelper.approveLoan("02 September 2022", "1000", loanId,
null);
+ return loanId;
+ }
+
+ private void checkAccrualTransaction(final LocalDate transactionDate,
final Float interestPortion, final Float feePortion,
+ final Float penaltyPortion, final Integer loanID) {
+
+ ArrayList<HashMap> transactions = (ArrayList<HashMap>)
loanTransactionHelper.getLoanTransactions(this.requestSpec,
+ this.responseSpec, loanID);
+ boolean isTransactionFound = false;
+ for (int i = 0; i < transactions.size(); i++) {
+ HashMap transactionType = (HashMap)
transactions.get(i).get("type");
+ boolean isAccrualTransaction = (Boolean)
transactionType.get("accrual");
+
+ if (isAccrualTransaction) {
+ ArrayList<Integer> accrualEntryDateAsArray =
(ArrayList<Integer>) transactions.get(i).get("date");
+ LocalDate accrualEntryDate =
LocalDate.of(accrualEntryDateAsArray.get(0), accrualEntryDateAsArray.get(1),
+ accrualEntryDateAsArray.get(2));
+
+ if (transactionDate.isEqual(accrualEntryDate)) {
+ isTransactionFound = true;
+ assertEquals(interestPortion,
Float.valueOf(String.valueOf(transactions.get(i).get("interestPortion"))),
+ "Mismatch in transaction amounts");
+ assertEquals(feePortion,
Float.valueOf(String.valueOf(transactions.get(i).get("feeChargesPortion"))),
+ "Mismatch in transaction amounts");
+ assertEquals(penaltyPortion,
Float.valueOf(String.valueOf(transactions.get(i).get("penaltyChargesPortion"))),
+ "Mismatch in transaction amounts");
+ break;
+ }
+ }
+ }
+ assertTrue(isTransactionFound, "No Accrual entries are posted");
+ }
+
+}
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java
index 8618a7fbf..058e1ba08 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanRescheduleOnDecliningBalanceLoanTest.java
@@ -97,6 +97,16 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
this.enableConfig();
}
+ /**
+ * Creates the client, loan product, and loan entities
+ **/
+ private void createRequiredEntitiesNoInterest() {
+ this.createClientEntity();
+ this.createLoanProductEntityNoInterest();
+ this.createLoanEntityNoInterest();
+ this.enableConfig();
+ }
+
/**
* Creates the client, loan product, and loan entities
**/
@@ -131,6 +141,20 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
LOG.info("Successfully created loan product (ID:{}) ",
this.loanProductId);
}
+ /**
+ * create a new loan product
+ **/
+ private void createLoanProductEntityNoInterest() {
+ LOG.info("-------------------------------- - CREATING LOAN PRODUCT
------------------------------------------");
+
+ final String loanProductJSON = new
LoanProductTestBuilder().withPrincipal(loanPrincipalAmount)
+
.withNumberOfRepayments(numberOfRepayments).withinterestRatePerPeriod("0").withInterestRateFrequencyTypeAsYear()
+ .withInterestCalculationPeriodTypeAsDays().build(null);
+ this.loanProductId =
this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+ LOG.info("Successfully created loan product(ID:{}) ",
this.loanProductId);
+
+ }
+
private void createLoanProductWithInterestRecalculation() {
LOG.info(
"---------------------------------CREATING LOAN PRODUCT WITH
RECALULATION ENABLED ------------------------------------------");
@@ -193,6 +217,35 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
this.disburseLoan(this.dateString);
}
+ /**
+ * submit a new loan application, approve and disburse the loan
+ **/
+ private void createLoanEntityNoInterest() {
+ LOG.info("---------------------------------NEW LOAN
APPLICATION------------------------------------------");
+
+ List<HashMap> collaterals = new ArrayList<>();
+ final Integer collateralId =
CollateralManagementHelper.createCollateralProduct(this.requestSpec,
this.responseSpec);
+ Assertions.assertNotNull(collateralId);
+ final Integer clientCollateralId =
CollateralManagementHelper.createClientCollateral(this.requestSpec,
this.responseSpec,
+ this.clientId.toString(), collateralId);
+ Assertions.assertNotNull(clientCollateralId);
+ addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
+
+ final String loanApplicationJSON = new
LoanApplicationTestBuilder().withPrincipal(loanPrincipalAmount)
+
.withLoanTermFrequency(numberOfRepayments).withLoanTermFrequencyAsMonths().withNumberOfRepayments(numberOfRepayments)
+
.withRepaymentEveryAfter("1").withRepaymentFrequencyTypeAsMonths().withAmortizationTypeAsEqualInstallments()
+
.withInterestCalculationPeriodTypeAsDays().withInterestRatePerPeriod("0").withSubmittedOnDate(dateString)
+
.withExpectedDisbursementDate(dateString).withCollaterals(collaterals).withPrincipalGrace("2").withInterestGrace("2")
+ .build(this.clientId.toString(),
this.loanProductId.toString(), null);
+
+ this.loanId =
this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+
+ LOG.info("Sucessfully created loan (ID: {} )", this.loanId);
+
+ this.approveLoanApplication(this.dateString);
+ this.disburseLoan(this.dateString);
+ }
+
private void addCollaterals(List<HashMap> collaterals, Integer
collateralId, BigDecimal quantity) {
collaterals.add(collaterals(collateralId, quantity));
}
@@ -253,7 +306,7 @@ public class LoanRescheduleOnDecliningBalanceLoanTest {
@Test
public void testCreateLoanRescheduleRequestFailIfLoanIsChargedOff() {
// create all required entities
- this.createRequiredEntities();
+ this.createRequiredEntitiesNoInterest();
this.createLoanRescheduleRequestWhichFailsAsLoanIdChargedOff();
}
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
index f13d40620..a94cfdc37 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SchedulerJobsTestResults.java
@@ -623,10 +623,10 @@ public class SchedulerJobsTestResults {
Integer overdueFeeChargeId = ChargesHelper.createCharges(requestSpec,
responseSpec, ChargesHelper.getLoanOverdueFeeJSON());
Assertions.assertNotNull(overdueFeeChargeId);
- final Integer loanProductID =
createLoanProduct(overdueFeeChargeId.toString());
+ final Integer loanProductID =
createLoanProductNoInterest(overdueFeeChargeId.toString());
Assertions.assertNotNull(loanProductID);
- final Integer loanID = applyForLoanApplication(clientID.toString(),
loanProductID.toString(), null, "10 January 2020");
+ final Integer loanID =
applyForLoanApplicationNoInterest(clientID.toString(),
loanProductID.toString(), null, "10 January 2020");
Assertions.assertNotNull(loanID);
HashMap loanStatusHashMap =
LoanStatusChecker.getStatusOfLoan(requestSpec, responseSpec, loanID);
@@ -1183,6 +1183,13 @@ public class SchedulerJobsTestResults {
return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
}
+ private Integer createLoanProductNoInterest(final String chargeId) {
+ final String loanProductJSON = new
LoanProductTestBuilder().withPrincipal("15,000.00").withNumberOfRepayments("4")
+
.withRepaymentAfterEvery("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("0")
+ .withAmortizationTypeAsEqualInstallments().build(chargeId);
+ return this.loanTransactionHelper.getLoanProductId(loanProductJSON);
+ }
+
private Integer createLoanProductWithPeriodicAccrual(final String
chargeId) {
final Account assetAccount = this.accountHelper.createAssetAccount();
final Account assetFeeAndPenaltyAccount =
this.accountHelper.createAssetAccount();
@@ -1228,6 +1235,25 @@ public class SchedulerJobsTestResults {
return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
}
+ private Integer applyForLoanApplicationNoInterest(final String clientID,
final String loanProductID, final String savingsID,
+ final String date) {
+
+ List<HashMap> collaterals = new ArrayList<>();
+ final Integer collateralId =
CollateralManagementHelper.createCollateralProduct(this.requestSpec,
this.responseSpec);
+ Assertions.assertNotNull(collateralId);
+ final Integer clientCollateralId =
CollateralManagementHelper.createClientCollateral(this.requestSpec,
this.responseSpec, clientID,
+ collateralId);
+ Assertions.assertNotNull(clientCollateralId);
+ addCollaterals(collaterals, clientCollateralId, BigDecimal.valueOf(1));
+
+ final String loanApplicationJSON = new
LoanApplicationTestBuilder().withPrincipal("15,000.00").withLoanTermFrequency("4")
+
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("4").withRepaymentEveryAfter("1")
+
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("0").withAmortizationTypeAsEqualInstallments()
+
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod().withExpectedDisbursementDate(date).withSubmittedOnDate(date)
+ .withCollaterals(collaterals).build(clientID, loanProductID,
savingsID);
+ return this.loanTransactionHelper.getLoanId(loanApplicationJSON);
+ }
+
private Integer createFixedDepositProduct(final String validFrom, final
String validTo) {
FixedDepositProductHelper fixedDepositProductHelper = new
FixedDepositProductHelper(requestSpec, responseSpec);
final String fixedDepositProductJSON =
fixedDepositProductHelper.withPeriodRangeChart().build(validFrom, validTo);