FINERACT-1724: Approval limit calculation modification

This commit is contained in:
abraham.menyhart
2023-07-05 16:19:21 +02:00
committed by Adam Saghy
parent 1cb1372e68
commit 28747fecd1
4 changed files with 106 additions and 4 deletions
@@ -2668,8 +2668,11 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom {
if (this.loanProduct().isDisallowExpectedDisbursements() && this.loanProduct().isAllowApprovedDisbursedAmountsOverApplied()) {
BigDecimal maxDisbursedAmount = getOverAppliedMax();
if (disbursedAmount.compareTo(maxDisbursedAmount) > 0) {
final String errorMessage = "Loan disbursal amount can't be greater than maximum applied loan amount calculation.";
if (totalDisbursed.compareTo(maxDisbursedAmount) > 0) {
final String errorMessage = String.format(
"Loan disbursal amount can't be greater than maximum applied loan amount calculation. "
+ "Total disbursed amount: %s Maximum disbursal amount: %s",
totalDisbursed.stripTrailingZeros().toPlainString(), maxDisbursedAmount.stripTrailingZeros().toPlainString());
throw new InvalidLoanStateTransitionException("disbursal",
"amount.can't.be.greater.than.maximum.applied.loan.amount.calculation", errorMessage, disbursedAmount,
maxDisbursedAmount);
@@ -18,6 +18,8 @@
*/
package org.apache.fineract.integrationtests;
import static java.lang.Double.parseDouble;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -36,6 +38,7 @@ import java.util.List;
import java.util.Locale;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
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;
@@ -316,6 +319,89 @@ public class LoanDisbursementDetailsIntegrationTest {
log.info("-----------MULTI DISBURSAL LOAN EQUAL INSTALLMENTS SUCCESSFULLY-------");
}
@Test
public void disburseLoanWithExceededOverAppliedAmountFails() {
final String operationDate = "01 January 2014";
final String principal = "1000";
final String firstDisbursedPrincipal = "900";
final String secondDisbursedPrincipal = "1101";
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, operationDate);
log.info("-----------------CLIENT CREATED WITH ID------------------- {}", clientId);
final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments() //
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
.withInterestTypeAsDecliningBalance() //
.withMultiDisburse() //
.withDisallowExpectedDisbursements(true) //
.build(null);
log.info("Product {}", loanProductJSON);
final Integer loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
log.info("------------------LOAN PRODUCT CREATED WITH ID----------- {}", loanProductId);
final Integer loanId = applyForMultiTrancheLoanApplication(clientId.toString(), loanProductId.toString(), principal, operationDate);
log.info("-------------------LOAN CREATED WITH loanId----------------- {}", loanId);
this.loanTransactionHelper.approveLoanWithApproveAmount(operationDate, expectedDisbursementDate, principal, loanId, null);
log.info("-------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY-------");
GetLoansLoanIdResponse getLoansLoanIdResponse = this.loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse);
this.loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, loanId, firstDisbursedPrincipal);
log.info("-------------------MULTI DISBURSAL LOAN DISBURSED SUCCESSFULLY-------");
loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, loanId, secondDisbursedPrincipal,
overAppliedAmountFailedResponseSpec());
log.info("-------------------MULTI DISBURSAL LOAN DISBURSEMENT FAILED-------");
}
@Test
public void disburseLoanWithExceededOverAppliedAmountSucceed() {
final String operationDate = "01 January 2014";
final String principal = "1000";
final String firstDisbursedPrincipal = "900";
final String secondDisbursedPrincipal = "1100";
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec, operationDate);
log.info("-----------------CLIENT CREATED WITH ID------------------- {}", clientId);
final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments() //
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
.withInterestTypeAsDecliningBalance() //
.withMultiDisburse() //
.withDisallowExpectedDisbursements(true) //
.build(null);
log.info("Product {}", loanProductJSON);
final Integer loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
log.info("------------------LOAN PRODUCT CREATED WITH ID----------- {}", loanProductId);
final Integer loanId = applyForMultiTrancheLoanApplication(clientId.toString(), loanProductId.toString(), principal, operationDate);
log.info("-------------------LOAN CREATED WITH loanId----------------- {}", loanId);
this.loanTransactionHelper.approveLoanWithApproveAmount(operationDate, expectedDisbursementDate, principal, loanId, null);
log.info("-------------------MULTI DISBURSAL LOAN APPROVED SUCCESSFULLY-------");
GetLoansLoanIdResponse getLoansLoanIdResponse = this.loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId);
assertNotNull(getLoansLoanIdResponse);
this.loanTransactionHelper.printRepaymentSchedule(getLoansLoanIdResponse);
loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, loanId, firstDisbursedPrincipal);
log.info("-------------------MULTI DISBURSAL LOAN DISBURSED SUCCESSFULLY-FIRST-------");
loanTransactionHelper.disburseLoanWithTransactionAmount(operationDate, loanId, secondDisbursedPrincipal);
log.info("-------------------MULTI DISBURSAL LOAN DISBURSED SUCCESSFULLY-SECOND-------");
double disbursementPrincipalSum = this.loanTransactionHelper.getLoan(requestSpec, responseSpec, loanId).getDisbursementDetails()
.stream().map(GetLoansLoanIdDisbursementDetails::getPrincipal).mapToDouble(p -> p).sum();
assertEquals(parseDouble(firstDisbursedPrincipal) + parseDouble(secondDisbursedPrincipal), disbursementPrincipalSum);
}
@Test
public void createApproveAndValidateMultiDisburseLoan() throws ParseException {
@@ -599,4 +685,11 @@ public class LoanDisbursementDetailsIntegrationTest {
}
}
}
private ResponseSpecification overAppliedAmountFailedResponseSpec() {
return new ResponseSpecBuilder().expectBody("userMessageGlobalisationCode", equalTo("validation.msg.domain.rule.violation"))
.expectBody("errors[0].userMessageGlobalisationCode",
equalTo("error.msg.loan.disbursal.amount.can't.be.greater.than.maximum.applied.loan.amount.calculation"))
.expectStatusCode(403).build();
}
}
@@ -435,8 +435,8 @@ public class LoanProductTestBuilder {
return this;
}
public LoanProductTestBuilder withDisallowExpectedDisbursements(boolean disallowExpectectedDisbursements) {
this.disallowExpectedDisbursements = disallowExpectectedDisbursements;
public LoanProductTestBuilder withDisallowExpectedDisbursements(boolean disallowExpectedDisbursements) {
this.disallowExpectedDisbursements = disallowExpectedDisbursements;
if (this.disallowExpectedDisbursements) {
this.allowApprovedDisbursedAmountsOverApplied = true;
this.overAppliedCalculationType = "percentage";
@@ -356,6 +356,12 @@ public class LoanTransactionHelper extends IntegrationTest {
getDisburseLoanAsJSON(date, transactionAmount, null, externalId), "");
}
public Object disburseLoanWithTransactionAmount(final String date, final Integer loanID, final String transactionAmount,
ResponseSpecification responseSpec) {
return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_COMMAND, loanID),
getDisburseLoanAsJSON(date, transactionAmount, null), responseSpec);
}
public HashMap disburseLoanWithTransactionAmount(final String date, final Integer loanID, final String transactionAmount) {
return performLoanTransaction(createLoanOperationURL(DISBURSE_LOAN_COMMAND, loanID),
getDisburseLoanAsJSON(date, transactionAmount, null));