FINERACT-2181: Loan disbursement amount exceed loan principal amount when we have Capitalized Income
This commit is contained in:
committed by
Adam Saghy
parent
0d8d6671a1
commit
060cdb5685
+4
-2
@@ -35,9 +35,10 @@ public final class LoanDisbursementValidator {
|
|||||||
|
|
||||||
public void compareDisbursedToApprovedOrProposedPrincipal(final Loan loan, final BigDecimal disbursedAmount,
|
public void compareDisbursedToApprovedOrProposedPrincipal(final Loan loan, final BigDecimal disbursedAmount,
|
||||||
final BigDecimal totalDisbursed) {
|
final BigDecimal totalDisbursed) {
|
||||||
|
final BigDecimal capitalizedIncome = loan.getSummary().getTotalCapitalizedIncome();
|
||||||
if (loan.loanProduct().isDisallowExpectedDisbursements() && loan.loanProduct().isAllowApprovedDisbursedAmountsOverApplied()) {
|
if (loan.loanProduct().isDisallowExpectedDisbursements() && loan.loanProduct().isAllowApprovedDisbursedAmountsOverApplied()) {
|
||||||
final BigDecimal maxDisbursedAmount = loanApplicationValidator.getOverAppliedMax(loan);
|
final BigDecimal maxDisbursedAmount = loanApplicationValidator.getOverAppliedMax(loan);
|
||||||
if (totalDisbursed.compareTo(maxDisbursedAmount) > 0) {
|
if (totalDisbursed.add(capitalizedIncome).compareTo(maxDisbursedAmount) > 0) {
|
||||||
final String errorMessage = String.format(
|
final String errorMessage = String.format(
|
||||||
"Loan disbursal amount can't be greater than maximum applied loan amount calculation. "
|
"Loan disbursal amount can't be greater than maximum applied loan amount calculation. "
|
||||||
+ "Total disbursed amount: %s Maximum disbursal amount: %s",
|
+ "Total disbursed amount: %s Maximum disbursal amount: %s",
|
||||||
@@ -47,7 +48,8 @@ public final class LoanDisbursementValidator {
|
|||||||
maxDisbursedAmount);
|
maxDisbursedAmount);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (totalDisbursed.compareTo(loan.getApprovedPrincipal()) > 0) {
|
if ((totalDisbursed.compareTo(loan.getApprovedPrincipal()) > 0)
|
||||||
|
|| (totalDisbursed.add(capitalizedIncome).compareTo(loan.getApprovedPrincipal()) > 0)) {
|
||||||
final String errorMsg = "Loan can't be disbursed,disburse amount is exceeding approved principal ";
|
final String errorMsg = "Loan can't be disbursed,disburse amount is exceeding approved principal ";
|
||||||
throw new LoanDisbursalException(errorMsg, "disburse.amount.must.be.less.than.approved.principal", totalDisbursed,
|
throw new LoanDisbursalException(errorMsg, "disburse.amount.must.be.less.than.approved.principal", totalDisbursed,
|
||||||
loan.getApprovedPrincipal());
|
loan.getApprovedPrincipal());
|
||||||
|
|||||||
+4
-1
@@ -106,6 +106,7 @@ public final class LoanTransactionValidatorImpl implements LoanTransactionValida
|
|||||||
private final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService;
|
private final EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService;
|
||||||
private final CalendarInstanceRepository calendarInstanceRepository;
|
private final CalendarInstanceRepository calendarInstanceRepository;
|
||||||
private final LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator;
|
private final LoanDownPaymentTransactionValidator loanDownPaymentTransactionValidator;
|
||||||
|
private final LoanDisbursementValidator loanDisbursementValidator;
|
||||||
|
|
||||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
if (!dataValidationErrors.isEmpty()) {
|
||||||
@@ -157,6 +158,9 @@ public final class LoanTransactionValidatorImpl implements LoanTransactionValida
|
|||||||
validateLoanClientIsActive(loan);
|
validateLoanClientIsActive(loan);
|
||||||
validateLoanGroupIsActive(loan);
|
validateLoanGroupIsActive(loan);
|
||||||
|
|
||||||
|
final BigDecimal disbursedAmount = loan.getDisbursedAmount();
|
||||||
|
loanDisbursementValidator.compareDisbursedToApprovedOrProposedPrincipal(loan, principal, disbursedAmount);
|
||||||
|
|
||||||
if (loan.isChargedOff()) {
|
if (loan.isChargedOff()) {
|
||||||
throw new GeneralPlatformDomainRuleException("error.msg.loan.disbursal.not.allowed.on.charged.off",
|
throw new GeneralPlatformDomainRuleException("error.msg.loan.disbursal.not.allowed.on.charged.off",
|
||||||
"Loan: " + loan.getId() + " disbursement is not allowed on charged-off loan.");
|
"Loan: " + loan.getId() + " disbursement is not allowed on charged-off loan.");
|
||||||
@@ -173,7 +177,6 @@ public final class LoanTransactionValidatorImpl implements LoanTransactionValida
|
|||||||
baseDataValidator.getDataValidationErrors().add(error);
|
baseDataValidator.getDataValidationErrors().add(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
final BigDecimal disbursedAmount = loan.getDisbursedAmount();
|
|
||||||
final Set<LoanCollateralManagement> loanCollateralManagements = loan.getLoanCollateralManagements();
|
final Set<LoanCollateralManagement> loanCollateralManagements = loan.getLoanCollateralManagements();
|
||||||
|
|
||||||
if ((loanCollateralManagements != null && !loanCollateralManagements.isEmpty()) && loan.getLoanType().isIndividualAccount()) {
|
if ((loanCollateralManagements != null && !loanCollateralManagements.isEmpty()) && loan.getLoanType().isIndividualAccount()) {
|
||||||
|
|||||||
+33
@@ -27,6 +27,7 @@ import org.apache.fineract.client.models.PostClientsResponse;
|
|||||||
import org.apache.fineract.client.models.PostLoanProductsRequest;
|
import org.apache.fineract.client.models.PostLoanProductsRequest;
|
||||||
import org.apache.fineract.client.models.PostLoanProductsResponse;
|
import org.apache.fineract.client.models.PostLoanProductsResponse;
|
||||||
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
|
||||||
|
import org.apache.fineract.client.util.CallFailedRuntimeException;
|
||||||
import org.apache.fineract.integrationtests.common.BusinessStepHelper;
|
import org.apache.fineract.integrationtests.common.BusinessStepHelper;
|
||||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
@@ -102,6 +103,38 @@ public class LoanCapitalizedIncomeTest extends BaseLoanIntegrationTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoanDisbursementWithCapitalizedIncome() {
|
||||||
|
final AtomicReference<Long> loanIdRef = new AtomicReference<>();
|
||||||
|
final AtomicReference<Long> capitalizedIncomeIdRef = new AtomicReference<>();
|
||||||
|
|
||||||
|
final PostClientsResponse client = clientHelper.createClient(ClientHelper.defaultClientCreationRequest());
|
||||||
|
|
||||||
|
final PostLoanProductsResponse loanProductsResponse = loanProductHelper
|
||||||
|
.createLoanProduct(create4IProgressive().enableIncomeCapitalization(true)
|
||||||
|
.capitalizedIncomeCalculationType(PostLoanProductsRequest.CapitalizedIncomeCalculationTypeEnum.FLAT)
|
||||||
|
.capitalizedIncomeStrategy(PostLoanProductsRequest.CapitalizedIncomeStrategyEnum.EQUAL_AMORTIZATION)
|
||||||
|
.deferredIncomeLiabilityAccountId(deferredIncomeLiabilityAccount.getAccountID().longValue())
|
||||||
|
.incomeFromCapitalizationAccountId(feeIncomeAccount.getAccountID().longValue())
|
||||||
|
.capitalizedIncomeType(PostLoanProductsRequest.CapitalizedIncomeTypeEnum.FEE).overAppliedNumber(3));
|
||||||
|
|
||||||
|
runAt("1 April 2024", () -> {
|
||||||
|
Long loanId = applyAndApproveProgressiveLoan(client.getClientId(), loanProductsResponse.getResourceId(), "1 January 2024",
|
||||||
|
500.0, 7.0, 3, null);
|
||||||
|
loanIdRef.set(loanId);
|
||||||
|
|
||||||
|
disburseLoan(loanId, BigDecimal.valueOf(300), "1 January 2024");
|
||||||
|
PostLoansLoanIdTransactionsResponse capitalizedIncomeResponse = loanTransactionHelper.addCapitalizedIncome(loanId,
|
||||||
|
"1 January 2024", 50.0);
|
||||||
|
|
||||||
|
CallFailedRuntimeException callFailedRuntimeException = Assertions.assertThrows(CallFailedRuntimeException.class,
|
||||||
|
() -> disburseLoan(loanId, BigDecimal.valueOf(200), "1 February 2024"));
|
||||||
|
|
||||||
|
Assertions.assertTrue(callFailedRuntimeException.getMessage()
|
||||||
|
.contains("Loan disbursal amount can't be greater than maximum applied loan amount calculation"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLoanCapitalizedIncomeAdjustment() {
|
public void testLoanCapitalizedIncomeAdjustment() {
|
||||||
final AtomicReference<Long> loanIdRef = new AtomicReference<>();
|
final AtomicReference<Long> loanIdRef = new AtomicReference<>();
|
||||||
|
|||||||
Reference in New Issue
Block a user