MIFOSX-1631 : added constrains for charges with interest recalculation

This commit is contained in:
Pramod Nuthakki
2014-10-31 23:43:53 +05:30
parent c7cd28c340
commit 784c180154
6 changed files with 189 additions and 23 deletions
@@ -3230,6 +3230,101 @@ public class ClientLoanIntegrationTest {
LoanStatusChecker.verifyLoanAccountIsClosed(loanStatusHashMap);
}
@Test
public void testLoanScheduleWithInterestRecalculation_WITH_REST_SAME_AS_REPAYMENT_INTEREST_COMPOUND_NONE_STRATEGY_REDUCE_EMI_WITH_INSTALLMENT_CHARGE() {
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
Calendar todaysDate = Calendar.getInstance();
todaysDate.add(Calendar.DAY_OF_MONTH, -14);
final String LOAN_DISBURSEMENT_DATE = dateFormat.format(todaysDate.getTime());
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
final Integer loanProductID = createLoanProductWithInterestRecalculation(LoanProductTestBuilder.MIFOS_STANDARD_STRATEGY,
LoanProductTestBuilder.RECALCULATION_COMPOUNDING_METHOD_NONE,
LoanProductTestBuilder.RECALCULATION_STRATEGY_REDUCE_EMI_AMOUN,
LoanProductTestBuilder.RECALCULATION_FREQUENCY_TYPE_SAME_AS_REPAYMENT_PERIOD, "0", null, null);
List<HashMap> charges = new ArrayList<HashMap>();
Integer installmentCharge = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanInstallmentJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "10", false));
addCharges(charges, installmentCharge, "10", null);
final Integer loanID = applyForLoanApplicationForInterestRecalculation(clientID, loanProductID, LOAN_DISBURSEMENT_DATE, null,
LoanApplicationTestBuilder.MIFOS_STANDARD_STRATEGY, charges);
Assert.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);
List<Map<String, Object>> expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "4.62", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2494.22", "34.69", "3.47", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.73", "23.18", "2.32", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2517.29", "11.62", "1.16", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
System.out.println("-----------------------------------APPROVE LOAN-----------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.approveLoan(LOAN_DISBURSEMENT_DATE, loanID);
LoanStatusChecker.verifyLoanIsApproved(loanStatusHashMap);
LoanStatusChecker.verifyLoanIsWaitingForDisbursal(loanStatusHashMap);
System.out.println("-------------------------------DISBURSE LOAN-------------------------------------------");
loanStatusHashMap = this.loanTransactionHelper.disburseLoan(LOAN_DISBURSEMENT_DATE, loanID);
LoanStatusChecker.verifyLoanIsActive(loanStatusHashMap);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "4.62", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2482.76", "46.15", "4.62", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.67", "23.24", "2.32", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2528.81", "11.67", "1.17", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
todaysDate = Calendar.getInstance();
todaysDate.add(Calendar.DAY_OF_MONTH, -7);
final String LOAN_FIRST_REPAYMENT_DATE = dateFormat.format(todaysDate.getTime());
Float totalDueForCurrentPeriod = (Float) loanSchedule.get(1).get("totalDueForPeriod");
this.loanTransactionHelper.makeRepayment(LOAN_FIRST_REPAYMENT_DATE, totalDueForCurrentPeriod, loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "4.62", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2494.22", "34.69", "3.47", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.73", "23.18", "2.32", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2517.29", "11.62", "1.16", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
Float earlyPayment = new Float("4000");
todaysDate = Calendar.getInstance();
todaysDate.add(Calendar.DAY_OF_MONTH, -5);
final String LOAN_SECOND_REPAYMENT_DATE = dateFormat.format(todaysDate.getTime());
this.loanTransactionHelper.makeRepayment(LOAN_SECOND_REPAYMENT_DATE, earlyPayment, loanID);
loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(this.requestSpec, this.responseSpec, loanID);
expectedvalues = new ArrayList<>();
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "4.62", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "3961.84", "34.69", "3.47", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "1773.61", "16.41", "1.64", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "1781.79", "8.22", "0.82", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
HashMap prepayDetail = this.loanTransactionHelper.getPrepayAmount(this.requestSpec, this.responseSpec, loanID);
String prepayAmount = String.valueOf(prepayDetail.get("amount"));
todaysDate = Calendar.getInstance();
String LOAN_REPAYMENT_DATE = dateFormat.format(todaysDate.getTime());
this.loanTransactionHelper.makeRepayment(LOAN_REPAYMENT_DATE, new Float(prepayAmount), loanID);
loanStatusHashMap = LoanStatusChecker.getStatusOfLoan(this.requestSpec, this.responseSpec, loanID);
LoanStatusChecker.verifyLoanAccountIsClosed(loanStatusHashMap);
}
@Test
public void testLoanScheduleWithInterestRecalculation_WITH_REST_DAILY_INTEREST_COMPOUND_INTEREST_STRATEGY_REDUCE_NUMBER_OF_INSTALLMENTS() {
this.loanTransactionHelper = new LoanTransactionHelper(this.requestSpec, this.responseSpec);
@@ -3359,11 +3454,11 @@ public class ClientLoanIntegrationTest {
List<HashMap> charges = new ArrayList<>(2);
Integer flat = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_FLAT, "100", false));
Integer interestPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_INTEREST, "1", false));
Integer principalPercentage = ChargesHelper.createCharges(requestSpec, responseSpec,
ChargesHelper.getLoanSpecifiedDueDateJSON(ChargesHelper.CHARGE_CALCULATION_TYPE_PERCENTAGE_AMOUNT, "2", false));
addCharges(charges, flat, "100", LOAN_FLAT_CHARGE_DATE);
addCharges(charges, interestPercentage, "10", LOAN_INTEREST_CHARGE_DATE);
addCharges(charges, principalPercentage, "2", LOAN_INTEREST_CHARGE_DATE);
final Integer clientID = ClientHelper.createClient(this.requestSpec, this.responseSpec);
ClientHelper.verifyClientCreatedOnServer(this.requestSpec, this.responseSpec, clientID);
@@ -3384,7 +3479,7 @@ public class ClientLoanIntegrationTest {
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "100.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2494.22", "34.69", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.73", "23.18", "11.56", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.73", "23.18", "200", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2517.29", "11.62", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
@@ -3402,7 +3497,7 @@ public class ClientLoanIntegrationTest {
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "100.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2490.75", "38.16", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.71", "23.2", "11.91", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.71", "23.2", "200", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2520.78", "11.63", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
@@ -3418,7 +3513,7 @@ public class ClientLoanIntegrationTest {
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "100.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2494.22", "34.69", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.73", "23.18", "11.56", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2505.73", "23.18", "200", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2517.29", "11.62", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
@@ -3433,7 +3528,7 @@ public class ClientLoanIntegrationTest {
todaysDate = Calendar.getInstance();
addRepaymentValues(expectedvalues, todaysDate, -1, "2482.76", "46.15", "100.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "5100", "27.96", "0.0", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "0", "11.16", "9.64", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "0", "11.16", "200", "0.0");
addRepaymentValues(expectedvalues, todaysDate, 1, "2417.24", "11.16", "0.0", "0.0");
verifyLoanRepaymentSchedule(loanSchedule, expectedvalues);
@@ -28,6 +28,10 @@ public interface LoanApiConstants {
public static final String principalDisbursedParameterName = "transactionAmount";
public static final String ALREADY_DISBURSED = "can.not.change.disbursement.date";
public static final String LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_INTEREST_CALCULATION_TYPE= "loancharge.with.calculation.type.interest.not.allowed";
public static final String LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_PRINCIPAL_CALCULATION_TYPE= "loancharge.with.calculation.type.principal.not.allowed";
// Interest recalculation related
public static final String isInterestRecalculationEnabledParameterName = "isInterestRecalculationEnabled";
@@ -4377,7 +4377,8 @@ public class Loan extends AbstractPersistable<Long> {
if (!loanCharge.isDueAtDisbursement()) {
updateOverdueScheduleInstallment(loanCharge);
if (loanCharge.getDueLocalDate() == null || (!lastRepaymentDate.isBefore(loanCharge.getDueLocalDate()))) {
if (!loanCharge.isWaived() && !lastTransactionDate.isAfter(loanCharge.getDueLocalDate())) {
if (!loanCharge.isWaived()
&& (loanCharge.getDueLocalDate() == null || !lastTransactionDate.isAfter(loanCharge.getDueLocalDate()))) {
recalculateLoanCharge(loanCharge, generatorDTO.getPenaltyWaitPeriod());
loanCharge.updateWaivedAmount(getCurrency());
}
@@ -25,6 +25,7 @@ import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.portfolio.accountdetails.domain.AccountType;
import org.mifosplatform.portfolio.loanaccount.api.LoanApiConstants;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
import org.mifosplatform.portfolio.loanproduct.LoanProductConstants;
import org.mifosplatform.portfolio.loanproduct.domain.InterestMethod;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
@@ -836,11 +837,53 @@ public final class LoanApplicationCommandFromApiJsonHelper {
}
public void validateRecalcuationFrequency(final LocalDate recalculationFrequencyDate, final LocalDate expectedDisbursementDate) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
public void validateRecalcuationFrequency(final LocalDate recalculationFrequencyDate, final LocalDate expectedDisbursementDate,
final List<ApiParameterError> dataValidationErrors) {
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
baseDataValidator.reset().parameter(LoanProductConstants.recalculationRestFrequencyDateParamName).value(recalculationFrequencyDate)
.notNull().validateDateBeforeOrEqual(expectedDisbursementDate);
}
public void validateLoanCharges(final Set<LoanCharge> charges, final List<ApiParameterError> dataValidationErrors) {
if (charges == null) { return; }
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan");
for (LoanCharge loanCharge : charges) {
String errorcode = null;
switch (loanCharge.getChargeCalculation()) {
case PERCENT_OF_AMOUNT:
if (loanCharge.isInstalmentFee()) {
errorcode = "installment." + LoanApiConstants.LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_PRINCIPAL_CALCULATION_TYPE;
}
break;
case PERCENT_OF_AMOUNT_AND_INTEREST:
if (loanCharge.isInstalmentFee()) {
errorcode = "installment." + LoanApiConstants.LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_PRINCIPAL_CALCULATION_TYPE;
} else if (loanCharge.isSpecifiedDueDate()) {
errorcode = "specific." + LoanApiConstants.LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_INTEREST_CALCULATION_TYPE;
}
break;
case PERCENT_OF_INTEREST:
if (loanCharge.isSpecifiedDueDate()) {
errorcode = "specific." + LoanApiConstants.LOAN_CHARGE_CAN_NOT_BE_ADDED_WITH_INTEREST_CALCULATION_TYPE;
}
break;
default:
break;
}
if (errorcode != null) {
baseDataValidator.reset().parameter("charges").failWithCode(errorcode);
}
}
}
public void validateLoanForInterestRecalculation(final LocalDate recalculationFrequencyDate, final LocalDate expectedDisbursementDate,
final Set<LoanCharge> charges) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
validateRecalcuationFrequency(recalculationFrequencyDate, expectedDisbursementDate, dataValidationErrors);
validateLoanCharges(charges, dataValidationErrors);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
@@ -216,8 +216,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final LocalDate recalculationFrequencyDate = this.fromJsonHelper.extractLocalDateNamed(
LoanProductConstants.recalculationRestFrequencyDateParamName, command.parsedJson());
if (!newLoanApplication.loanInterestRecalculationDetails().getRestFrequencyType().isSameAsRepayment()) {
this.fromApiJsonDeserializer.validateRecalcuationFrequency(recalculationFrequencyDate,
newLoanApplication.getExpectedDisbursedOnLocalDate());
this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(recalculationFrequencyDate,
newLoanApplication.getExpectedDisbursedOnLocalDate(), newLoanApplication.charges());
}
createAndPersistCalendarInstanceForInterestRecalculation(newLoanApplication);
}
@@ -624,8 +624,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
recalculationFrequencyDate = this.fromJsonHelper.extractLocalDateNamed(
LoanProductConstants.recalculationRestFrequencyDateParamName, command.parsedJson());
if (!existingLoanApplication.loanInterestRecalculationDetails().getRestFrequencyType().isSameAsRepayment()) {
this.fromApiJsonDeserializer.validateRecalcuationFrequency(recalculationFrequencyDate,
existingLoanApplication.getExpectedDisbursedOnLocalDate());
this.fromApiJsonDeserializer.validateLoanForInterestRecalculation(recalculationFrequencyDate,
existingLoanApplication.getExpectedDisbursedOnLocalDate(), existingLoanApplication.charges());
}
}
@@ -10,6 +10,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
@@ -120,6 +121,7 @@ import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleM
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.LoanScheduleModelPeriod;
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.ScheduledDateGenerator;
import org.mifosplatform.portfolio.loanaccount.loanschedule.service.LoanScheduleHistoryWritePlatformService;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanApplicationCommandFromApiJsonHelper;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanEventApiJsonValidator;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanproduct.data.LoanOverdueDTO;
@@ -178,6 +180,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
private final CalendarRepository calendarRepository;
private final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository;
private final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService;
private final LoanApplicationCommandFromApiJsonHelper loanApplicationCommandFromApiJsonHelper;
@Autowired
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -199,7 +202,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final FromJsonHelper fromApiJsonHelper, final AccountTransferRepository accountTransferRepository,
final CalendarRepository calendarRepository,
final LoanRepaymentScheduleInstallmentRepository repaymentScheduleInstallmentRepository,
final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService) {
final LoanScheduleHistoryWritePlatformService loanScheduleHistoryWritePlatformService,
final LoanApplicationCommandFromApiJsonHelper loanApplicationCommandFromApiJsonHelper) {
this.context = context;
this.loanEventApiJsonValidator = loanEventApiJsonValidator;
this.loanAssembler = loanAssembler;
@@ -229,6 +233,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
this.calendarRepository = calendarRepository;
this.repaymentScheduleInstallmentRepository = repaymentScheduleInstallmentRepository;
this.loanScheduleHistoryWritePlatformService = loanScheduleHistoryWritePlatformService;
this.loanApplicationCommandFromApiJsonHelper = loanApplicationCommandFromApiJsonHelper;
}
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
@@ -1179,14 +1184,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final LoanCharge loanCharge = LoanCharge.createNewFromJson(loan, chargeDefinition, command);
if (chargeDefinition.isOverdueInstallment()) {
final String defaultUserMessage = "Installment charge cannot be added to the loan.";
throw new LoanChargeCannotBeAddedException("loanCharge", "overdue.charge", defaultUserMessage, null, chargeDefinition.getName());
} else if(loanCharge.getDueLocalDate() != null && loanCharge.getDueLocalDate().isBefore(loan.getLastUserTransactionForChargeCalc())){
final String defaultUserMessage = "charge after last transaction date can not be added to loan.";
throw new LoanChargeCannotBeAddedException("loanCharge", "date.is.after.last.transaction.date", defaultUserMessage, null, chargeDefinition.getName());
}
validateAddLoanCharge(loan, chargeDefinition, loanCharge);
final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
final List<Long> existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds());
@@ -1217,6 +1215,31 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
.build();
}
private void validateAddLoanCharge(final Loan loan, final Charge chargeDefinition, final LoanCharge loanCharge) {
if (chargeDefinition.isOverdueInstallment()) {
final String defaultUserMessage = "Installment charge cannot be added to the loan.";
throw new LoanChargeCannotBeAddedException("loanCharge", "overdue.charge", defaultUserMessage, null, chargeDefinition.getName());
} else if (loanCharge.getDueLocalDate() != null
&& loanCharge.getDueLocalDate().isBefore(loan.getLastUserTransactionForChargeCalc())) {
final String defaultUserMessage = "charge with date before last transaction date can not be added to loan.";
throw new LoanChargeCannotBeAddedException("loanCharge", "date.is.before.last.transaction.date", defaultUserMessage, null,
chargeDefinition.getName());
} else if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
if (loanCharge.isInstalmentFee() && loan.status().isActive()) {
final String defaultUserMessage = "installment charge addition not allowed after disbursement";
throw new LoanChargeCannotBeAddedException("loanCharge", "installment.charge", defaultUserMessage, null,
chargeDefinition.getName());
}
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final Set<LoanCharge> loanCharges = new HashSet<>(1);
loanCharges.add(loanCharge);
this.loanApplicationCommandFromApiJsonHelper.validateLoanCharges(loanCharges, dataValidationErrors);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
}
public void runScheduleRecalculation(Loan loan) {
if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
CalendarInstance restCalendarInstance = calendarInstanceRepository.findCalendarInstaneByEntityId(