Allow multi-disbursements without setting up expected tranche details (#2129)
This commit is contained in:
+7
-1
@@ -109,7 +109,6 @@ public interface LoanProductConstants {
|
||||
BigDecimal DEFAULT_PRINCIPAL_THRESHOLD_FOR_SINGLE_DISBURSE_LOAN = BigDecimal.valueOf(0);
|
||||
// Fixed installment configuration related
|
||||
String canDefineEmiAmountParamName = "canDefineInstallmentAmount";
|
||||
String installmentAmountInMultiplesOfParamName = "installmentAmountInMultiplesOf";
|
||||
String fixedPrincipalPercentagePerInstallmentParamName = "fixedPrincipalPercentagePerInstallment";
|
||||
|
||||
// Loan Configurable Attributes
|
||||
@@ -136,4 +135,11 @@ public interface LoanProductConstants {
|
||||
|
||||
String RATES_PARAM_NAME = "rates";
|
||||
|
||||
// Multiple disbursement related
|
||||
String installmentAmountInMultiplesOfParamName = "installmentAmountInMultiplesOf";
|
||||
String DISALLOW_EXPECTED_DISBURSEMENTS = "disallowExpectedDisbursements";
|
||||
String ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED = "allowApprovedDisbursedAmountsOverApplied";
|
||||
String OVER_APPLIED_CALCULATION_TYPE = "overAppliedCalculationType";
|
||||
String OVER_APPLIED_NUMBER = "overAppliedNumber";
|
||||
|
||||
}
|
||||
|
||||
+129
-2
@@ -24,6 +24,7 @@ import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@@ -64,6 +65,7 @@ import org.apache.fineract.portfolio.floatingrates.domain.FloatingRate;
|
||||
import org.apache.fineract.portfolio.fund.domain.Fund;
|
||||
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.AprCalculator;
|
||||
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductGeneralRuleException;
|
||||
import org.apache.fineract.portfolio.rate.domain.Rate;
|
||||
|
||||
/**
|
||||
@@ -361,6 +363,20 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
BigDecimal fixedPrincipalPercentagePerInstallment = command
|
||||
.bigDecimalValueOfParameterNamed(LoanProductConstants.fixedPrincipalPercentagePerInstallmentParamName);
|
||||
|
||||
final boolean disallowExpectedDisbursements = command.parameterExists(LoanProductConstants.DISALLOW_EXPECTED_DISBURSEMENTS)
|
||||
? command.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.DISALLOW_EXPECTED_DISBURSEMENTS)
|
||||
: false;
|
||||
|
||||
final boolean allowApprovedDisbursedAmountsOverApplied = command
|
||||
.parameterExists(LoanProductConstants.ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED)
|
||||
? command.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED)
|
||||
: false;
|
||||
|
||||
final String overAppliedCalculationType = command
|
||||
.stringValueOfParameterNamedAllowingNull(LoanProductConstants.OVER_APPLIED_CALCULATION_TYPE);
|
||||
|
||||
final Integer overAppliedNumber = command.integerValueOfParameterNamed(LoanProductConstants.OVER_APPLIED_NUMBER);
|
||||
|
||||
return new LoanProduct(fund, loanTransactionProcessingStrategy, name, shortName, description, currency, principal, minPrincipal,
|
||||
maxPrincipal, interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType,
|
||||
annualInterestRate, interestMethod, interestCalculationPeriodMethod, allowPartialPeriodInterestCalcualtion, repaymentEvery,
|
||||
@@ -375,7 +391,8 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
floatingRate, interestRateDifferential, minDifferentialLendingRate, maxDifferentialLendingRate,
|
||||
defaultDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed,
|
||||
minimumGapBetweenInstallments, maximumGapBetweenInstallments, syncExpectedWithDisbursementDate, canUseForTopup,
|
||||
isEqualAmortization, productRates, fixedPrincipalPercentagePerInstallment);
|
||||
isEqualAmortization, productRates, fixedPrincipalPercentagePerInstallment, disallowExpectedDisbursements,
|
||||
allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber);
|
||||
|
||||
}
|
||||
|
||||
@@ -610,7 +627,9 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
Boolean isFloatingInterestRateCalculationAllowed, final Boolean isVariableInstallmentsAllowed,
|
||||
final Integer minimumGapBetweenInstallments, final Integer maximumGapBetweenInstallments,
|
||||
final boolean syncExpectedWithDisbursementDate, final boolean canUseForTopup, final boolean isEqualAmortization,
|
||||
final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment) {
|
||||
final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment, final boolean disallowExpectedDisbursements,
|
||||
final boolean allowApprovedDisbursedAmountsOverApplied, final String overAppliedCalculationType,
|
||||
final Integer overAppliedNumber) {
|
||||
this.fund = fund;
|
||||
this.transactionProcessingStrategy = transactionProcessingStrategy;
|
||||
this.name = name.trim();
|
||||
@@ -689,9 +708,68 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
this.canUseForTopup = canUseForTopup;
|
||||
this.fixedPrincipalPercentagePerInstallment = fixedPrincipalPercentagePerInstallment;
|
||||
|
||||
this.disallowExpectedDisbursements = disallowExpectedDisbursements;
|
||||
this.allowApprovedDisbursedAmountsOverApplied = allowApprovedDisbursedAmountsOverApplied;
|
||||
this.overAppliedCalculationType = overAppliedCalculationType;
|
||||
this.overAppliedNumber = overAppliedNumber;
|
||||
|
||||
if (rates != null) {
|
||||
this.rates = rates;
|
||||
}
|
||||
validateLoanProductPreSave();
|
||||
}
|
||||
|
||||
public void validateLoanProductPreSave() {
|
||||
|
||||
if (this.disallowExpectedDisbursements) {
|
||||
if (!this.isMultiDisburseLoan()) {
|
||||
throw new LoanProductGeneralRuleException("allowMultipleDisbursals.not.set.disallowExpectedDisbursements.cant.be.set",
|
||||
"Allow Multiple Disbursals Not Set - Disallow Expected Disbursals Can't Be Set");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.allowApprovedDisbursedAmountsOverApplied) {
|
||||
if (!this.disallowExpectedDisbursements) {
|
||||
throw new LoanProductGeneralRuleException(
|
||||
"disallowExpectedDisbursements.not.set.allowApprovedDisbursedAmountsOverApplied.cant.be.set",
|
||||
"Disallow Expected Disbursals Not Set - Allow Approved / Disbursed Amounts Over Applied Can't Be Set");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.overAppliedCalculationType == null || this.overAppliedCalculationType.isEmpty()) {
|
||||
if (this.allowApprovedDisbursedAmountsOverApplied) {
|
||||
throw new LoanProductGeneralRuleException(
|
||||
"allowApprovedDisbursedAmountsOverApplied.is.set.overAppliedCalculationType.is.mandatory",
|
||||
"Allow Approved / Disbursed Amounts Over Applied is Set - Over Applied Calculation Type is Mandatory");
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!this.allowApprovedDisbursedAmountsOverApplied) {
|
||||
throw new LoanProductGeneralRuleException(
|
||||
"allowApprovedDisbursedAmountsOverApplied.is.not.set.overAppliedCalculationType.cant.be.entered",
|
||||
"Allow Approved / Disbursed Amounts Over Applied is Not Set - Over Applied Calculation Type Can't Be Entered");
|
||||
}
|
||||
|
||||
List<String> overAppliedCalculationTypeAllowedValues = Arrays.asList("percentage", "flat");
|
||||
if (!overAppliedCalculationTypeAllowedValues.contains(this.overAppliedCalculationType)) {
|
||||
throw new LoanProductGeneralRuleException("overAppliedCalculationType.must.be.percentage.or.flat",
|
||||
"Over Applied Calculation Type Must Be 'percentage' or 'flat'");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.overAppliedNumber != null) {
|
||||
if (!this.allowApprovedDisbursedAmountsOverApplied) {
|
||||
throw new LoanProductGeneralRuleException(
|
||||
"allowApprovedDisbursedAmountsOverApplied.is.not.set.overAppliedNumber.cant.be.entered",
|
||||
"Allow Approved / Disbursed Amounts Over Applied is Not Set - Over Applied Number Can't Be Entered");
|
||||
}
|
||||
} else {
|
||||
if (this.allowApprovedDisbursedAmountsOverApplied) {
|
||||
throw new LoanProductGeneralRuleException("allowApprovedDisbursedAmountsOverApplied.is.set.overAppliedNumber.is.mandatory",
|
||||
"Allow Approved / Disbursed Amounts Over Applied is Set - Over Applied Number is Mandatory");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public MonetaryCurrency getCurrency() {
|
||||
@@ -1116,6 +1194,34 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
this.fixedPrincipalPercentagePerInstallment = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(LoanProductConstants.DISALLOW_EXPECTED_DISBURSEMENTS,
|
||||
this.disallowExpectedDisbursements)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.DISALLOW_EXPECTED_DISBURSEMENTS);
|
||||
actualChanges.put(LoanProductConstants.DISALLOW_EXPECTED_DISBURSEMENTS, newValue);
|
||||
this.disallowExpectedDisbursements = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(LoanProductConstants.ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED,
|
||||
this.allowApprovedDisbursedAmountsOverApplied)) {
|
||||
final boolean newValue = command
|
||||
.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED);
|
||||
actualChanges.put(LoanProductConstants.ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED, newValue);
|
||||
this.allowApprovedDisbursedAmountsOverApplied = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInStringParameterNamed(LoanProductConstants.OVER_APPLIED_CALCULATION_TYPE, this.overAppliedCalculationType)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(LoanProductConstants.OVER_APPLIED_CALCULATION_TYPE);
|
||||
actualChanges.put(LoanProductConstants.OVER_APPLIED_CALCULATION_TYPE, newValue);
|
||||
this.overAppliedCalculationType = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(LoanProductConstants.OVER_APPLIED_NUMBER, this.overAppliedNumber)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(LoanProductConstants.OVER_APPLIED_NUMBER);
|
||||
actualChanges.put(LoanProductConstants.OVER_APPLIED_NUMBER, newValue);
|
||||
actualChanges.put("locale", localeAsInput);
|
||||
this.overAppliedNumber = newValue;
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
@@ -1481,4 +1587,25 @@ public class LoanProduct extends AbstractPersistableCustom {
|
||||
public Integer getOverAppliedNumber() {
|
||||
return overAppliedNumber;
|
||||
}
|
||||
|
||||
public void setDisallowExpectedDisbursements(boolean disallowExpectedDisbursements) {
|
||||
this.disallowExpectedDisbursements = disallowExpectedDisbursements;
|
||||
}
|
||||
|
||||
public void setAllowApprovedDisbursedAmountsOverApplied(boolean allowApprovedDisbursedAmountsOverApplied) {
|
||||
this.allowApprovedDisbursedAmountsOverApplied = allowApprovedDisbursedAmountsOverApplied;
|
||||
}
|
||||
|
||||
public void setOverAppliedCalculationType(String overAppliedCalculationType) {
|
||||
this.overAppliedCalculationType = overAppliedCalculationType;
|
||||
}
|
||||
|
||||
public void setOverAppliedNumber(Integer overAppliedNumber) {
|
||||
this.overAppliedNumber = overAppliedNumber;
|
||||
}
|
||||
|
||||
public void setLoanProducTrancheDetails(LoanProductTrancheDetails loanProducTrancheDetails) {
|
||||
this.loanProducTrancheDetails = loanProducTrancheDetails;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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.portfolio.loanproduct.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when lending strategy mismatch occurs
|
||||
*/
|
||||
public class LoanProductGeneralRuleException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public LoanProductGeneralRuleException(String errorMsg, String errorMsgEnglish) {
|
||||
super("error.msg." + errorMsg, errorMsgEnglish);
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -109,7 +109,9 @@ public final class LoanProductDataValidator {
|
||||
LoanProductConstants.recalculationRestFrequencyOnDayParamName,
|
||||
LoanProductConstants.isCompoundingToBePostedAsTransactionParamName, LoanProductConstants.allowCompoundingOnEodParamName,
|
||||
LoanProductConstants.CAN_USE_FOR_TOPUP, LoanProductConstants.IS_EQUAL_AMORTIZATION_PARAM, LoanProductConstants.RATES_PARAM_NAME,
|
||||
LoanProductConstants.fixedPrincipalPercentagePerInstallmentParamName));
|
||||
LoanProductConstants.fixedPrincipalPercentagePerInstallmentParamName, LoanProductConstants.DISALLOW_EXPECTED_DISBURSEMENTS,
|
||||
LoanProductConstants.ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED, LoanProductConstants.OVER_APPLIED_CALCULATION_TYPE,
|
||||
LoanProductConstants.OVER_APPLIED_NUMBER));
|
||||
|
||||
private static final String[] supportedloanConfigurableAttributes = { LoanProductConstants.amortizationTypeParamName,
|
||||
LoanProductConstants.interestTypeParamName, LoanProductConstants.transactionProcessingStrategyIdParamName,
|
||||
@@ -753,6 +755,7 @@ public final class LoanProductDataValidator {
|
||||
baseDataValidator.reset().parameter("interestType").value(interestType).ignoreIfNull()
|
||||
.integerSameAsNumber(InterestMethod.DECLINING_BALANCE.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void validateInterestRecalculationParams(final JsonElement element, final DataValidatorBuilder baseDataValidator,
|
||||
|
||||
+1
@@ -252,6 +252,7 @@ public class LoanProductWritePlatformServiceJpaRepositoryImpl implements LoanPro
|
||||
}
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
product.validateLoanProductPreSave();
|
||||
this.loanProductRepository.saveAndFlush(product);
|
||||
}
|
||||
|
||||
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* 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.portfolio.loanproduct.domain;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import org.apache.fineract.portfolio.loanproduct.exception.LoanProductGeneralRuleException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class LoanProductTest {
|
||||
|
||||
@Test
|
||||
public void shouldThrowExceptionWhenAllowMultipleDisbursalsFalseAndDisallowExpectedDisbursementsIsTrue() {
|
||||
|
||||
LoanProduct lp = stubLoanProduct(false);
|
||||
lp.setDisallowExpectedDisbursements(true);
|
||||
|
||||
LoanProductGeneralRuleException expectedEx = assertThrows(LoanProductGeneralRuleException.class,
|
||||
() -> lp.validateLoanProductPreSave());
|
||||
|
||||
assertThat(expectedEx.getGlobalisationMessageCode(),
|
||||
is("error.msg.allowMultipleDisbursals.not.set.disallowExpectedDisbursements.cant.be.set"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowExceptionWhenDisallowExpectedDisbursementIsFalseAndAllowApprovedDisbursedAmountsOverAppliedIsTrue() {
|
||||
|
||||
LoanProduct lp = stubLoanProduct(true);
|
||||
lp.setDisallowExpectedDisbursements(false);
|
||||
lp.setAllowApprovedDisbursedAmountsOverApplied(true);
|
||||
|
||||
LoanProductGeneralRuleException expectedEx = assertThrows(LoanProductGeneralRuleException.class,
|
||||
() -> lp.validateLoanProductPreSave());
|
||||
|
||||
assertThat(expectedEx.getGlobalisationMessageCode(),
|
||||
is("error.msg.disallowExpectedDisbursements.not.set.allowApprovedDisbursedAmountsOverApplied.cant.be.set"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowExceptionWhenAllowApprovedDisbursedAmountsOverAppliedIsTrueAndAppliedCalculationTypeIsNull() {
|
||||
|
||||
LoanProduct lp = stubLoanProduct(true);
|
||||
lp.setDisallowExpectedDisbursements(true);
|
||||
lp.setAllowApprovedDisbursedAmountsOverApplied(true);
|
||||
lp.setOverAppliedCalculationType(null);
|
||||
|
||||
LoanProductGeneralRuleException expectedEx = assertThrows(LoanProductGeneralRuleException.class,
|
||||
() -> lp.validateLoanProductPreSave());
|
||||
|
||||
assertThat(expectedEx.getGlobalisationMessageCode(),
|
||||
is("error.msg.allowApprovedDisbursedAmountsOverApplied.is.set.overAppliedCalculationType.is.mandatory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowExceptionWhenAllowApprovedDisbursedAmountsOverAppliedIsTrueAndAppliedCalculationTypeIsEmpty() {
|
||||
|
||||
LoanProduct lp = stubLoanProduct(true);
|
||||
lp.setDisallowExpectedDisbursements(true);
|
||||
lp.setAllowApprovedDisbursedAmountsOverApplied(true);
|
||||
lp.setOverAppliedCalculationType("");
|
||||
|
||||
LoanProductGeneralRuleException expectedEx = assertThrows(LoanProductGeneralRuleException.class,
|
||||
() -> lp.validateLoanProductPreSave());
|
||||
|
||||
assertThat(expectedEx.getGlobalisationMessageCode(),
|
||||
is("error.msg.allowApprovedDisbursedAmountsOverApplied.is.set.overAppliedCalculationType.is.mandatory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowExceptionWhenAllowApprovedDisbursedAmountsOverAppliedIsFalseAndAppliedCalculationTypeIsNotEmpty() {
|
||||
|
||||
LoanProduct lp = stubLoanProduct(true);
|
||||
lp.setDisallowExpectedDisbursements(true);
|
||||
lp.setAllowApprovedDisbursedAmountsOverApplied(false);
|
||||
lp.setOverAppliedCalculationType("flat");
|
||||
|
||||
LoanProductGeneralRuleException expectedEx = assertThrows(LoanProductGeneralRuleException.class,
|
||||
() -> lp.validateLoanProductPreSave());
|
||||
|
||||
assertThat(expectedEx.getGlobalisationMessageCode(),
|
||||
is("error.msg.allowApprovedDisbursedAmountsOverApplied.is.not.set.overAppliedCalculationType.cant.be.entered"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowExceptionWhenOverAppliedCalculationTypeNotValid() {
|
||||
|
||||
LoanProduct lp = stubLoanProduct(true);
|
||||
lp.setDisallowExpectedDisbursements(true);
|
||||
lp.setAllowApprovedDisbursedAmountsOverApplied(true);
|
||||
lp.setOverAppliedCalculationType("notflat");
|
||||
|
||||
LoanProductGeneralRuleException expectedEx = assertThrows(LoanProductGeneralRuleException.class,
|
||||
() -> lp.validateLoanProductPreSave());
|
||||
|
||||
assertThat(expectedEx.getGlobalisationMessageCode(), is("error.msg.overAppliedCalculationType.must.be.percentage.or.flat"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowExceptionWhenAllowApprovedDisbursedAmountsOverAppliedIsTrueAndAppliedCalculationNumberIsNull() {
|
||||
|
||||
LoanProduct lp = stubLoanProduct(true);
|
||||
lp.setDisallowExpectedDisbursements(true);
|
||||
lp.setAllowApprovedDisbursedAmountsOverApplied(true);
|
||||
lp.setOverAppliedCalculationType("flat");
|
||||
lp.setOverAppliedNumber(null);
|
||||
|
||||
LoanProductGeneralRuleException expectedEx = assertThrows(LoanProductGeneralRuleException.class,
|
||||
() -> lp.validateLoanProductPreSave());
|
||||
|
||||
assertThat(expectedEx.getGlobalisationMessageCode(),
|
||||
is("error.msg.allowApprovedDisbursedAmountsOverApplied.is.set.overAppliedNumber.is.mandatory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowExceptionWhenAllowApprovedDisbursedAmountsOverAppliedIsFalseAndAppliedCalculationNumberIsNotNull() {
|
||||
|
||||
LoanProduct lp = stubLoanProduct(true);
|
||||
lp.setDisallowExpectedDisbursements(true);
|
||||
lp.setAllowApprovedDisbursedAmountsOverApplied(false);
|
||||
lp.setOverAppliedNumber(80);
|
||||
|
||||
LoanProductGeneralRuleException expectedEx = assertThrows(LoanProductGeneralRuleException.class,
|
||||
() -> lp.validateLoanProductPreSave());
|
||||
|
||||
assertThat(expectedEx.getGlobalisationMessageCode(),
|
||||
is("error.msg.allowApprovedDisbursedAmountsOverApplied.is.not.set.overAppliedNumber.cant.be.entered"));
|
||||
}
|
||||
|
||||
private LoanProduct stubLoanProduct(boolean allowMultipleDisbursals) {
|
||||
LoanProduct lp = new LoanProduct();
|
||||
lp.setLoanProducTrancheDetails(new LoanProductTrancheDetails(allowMultipleDisbursals, null, null));
|
||||
return lp;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user