blob: f0f9a7537bbe0d22beff7e5212b4c6a685a81617 [file] [log] [blame]
/**
* 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.loanaccount.serialization;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
import org.apache.fineract.portfolio.loanproduct.LoanProductConstants;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public final class CalculateLoanScheduleQueryFromApiJsonHelper {
/**
* The parameters supported for this command.
*/
final Set<String> supportedParameters = new HashSet<>(Arrays.asList("id", "clientId", "groupId", "loanType", "calendarId", "productId",
"accountNo", "externalId", "fundId", "loanOfficerId", "loanPurposeId", "transactionProcessingStrategyId", "principal",
"inArrearsTolerance", "interestRatePerPeriod", "repaymentEvery", "numberOfRepayments", "loanTermFrequency",
"loanTermFrequencyType", "repaymentFrequencyType", "amortizationType", "interestType", "interestCalculationPeriodType",
LoanProductConstants.allowPartialPeriodInterestCalcualtionParamName, "interestRateFrequencyType", "expectedDisbursementDate",
"repaymentsStartingFromDate", "graceOnPrincipalPayment", "graceOnInterestPayment", "graceOnInterestCharged",
"interestChargedFromDate", "submittedOnDate", "submittedOnNote", "locale", "dateFormat", "charges", "collateral",
"syncDisbursementWithMeeting", "linkAccountId", LoanApiConstants.disbursementDataParameterName,
LoanApiConstants.emiAmountParameterName, LoanApiConstants.maxOutstandingBalanceParameterName,
LoanProductConstants.graceOnArrearsAgeingParameterName, LoanProductConstants.recalculationRestFrequencyDateParamName,
"createStandingInstructionAtDisbursement", LoanApiConstants.isFloatingInterestRateParameterName,
LoanApiConstants.interestRateDifferentialParameterName));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public CalculateLoanScheduleQueryFromApiJsonHelper(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validate(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, this.supportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final JsonElement element = this.fromApiJsonHelper.parse(json);
final String loanTermFrequencyParameterName = "loanTermFrequency";
final Integer loanTermFrequency = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(loanTermFrequencyParameterName, element);
final String loanTermFrequencyTypeParameterName = "loanTermFrequencyType";
final Integer loanTermFrequencyType = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(loanTermFrequencyTypeParameterName,
element);
final String numberOfRepaymentsParameterName = "numberOfRepayments";
final Integer numberOfRepayments = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(numberOfRepaymentsParameterName, element);
final String repaymentEveryParameterName = "repaymentEvery";
final Integer repaymentEvery = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(repaymentEveryParameterName, element);
final String repaymentEveryFrequencyTypeParameterName = "repaymentFrequencyType";
final Integer repaymentEveryType = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(repaymentEveryFrequencyTypeParameterName,
element);
// FIXME - KW - this constraint doesnt really need to be here. should be
// possible to express loan term as say 12 months whilst also saying
// - that the repayment structure is 6 repayments every bi-monthly.
validateSelectedPeriodFrequencyTypeIsTheSame(dataValidationErrors, loanTermFrequency, loanTermFrequencyType, numberOfRepayments,
repaymentEvery, repaymentEveryType);
final String expectedDisbursementDateParameterName = "expectedDisbursementDate";
final LocalDate expectedDisbursementDate = this.fromApiJsonHelper.extractLocalDateNamed(expectedDisbursementDateParameterName,
element);
LocalDate repaymentsStartingFromDate = null;
final String repaymentsStartingFromDateParameterName = "repaymentsStartingFromDate";
if (this.fromApiJsonHelper.parameterExists(repaymentsStartingFromDateParameterName, element)) {
repaymentsStartingFromDate = this.fromApiJsonHelper.extractLocalDateNamed(repaymentsStartingFromDateParameterName, element);
}
validateRepaymentsStartingFromDateIsAfterDisbursementDate(dataValidationErrors, expectedDisbursementDate,
repaymentsStartingFromDate);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
public void validateSelectedPeriodFrequencyTypeIsTheSame(final List<ApiParameterError> dataValidationErrors,
final Integer loanTermFrequency, final Integer loanTermFrequencyType, final Integer numberOfRepayments,
final Integer repaymentEvery, final Integer repaymentEveryType) {
if (loanTermFrequencyType != null && !loanTermFrequencyType.equals(repaymentEveryType)) {
final ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.loan.loanTermFrequencyType.not.the.same.as.repaymentFrequencyType",
"The parameters loanTermFrequencyType and repaymentFrequencyType must be the same.", "loanTermFrequencyType",
loanTermFrequencyType, repaymentEveryType);
dataValidationErrors.add(error);
} else {
if (loanTermFrequency != null && repaymentEvery != null && numberOfRepayments != null) {
final int suggestsedLoanTerm = repaymentEvery * numberOfRepayments;
if (loanTermFrequency.intValue() < suggestsedLoanTerm) {
final ApiParameterError error = ApiParameterError
.parameterError(
"validation.msg.loan.loanTermFrequency.less.than.repayment.structure.suggests",
"The parameter loanTermFrequency is less than the suggest loan term as indicated by numberOfRepayments and repaymentEvery.",
"loanTermFrequency", loanTermFrequency, numberOfRepayments, repaymentEvery);
dataValidationErrors.add(error);
}
}
}
}
private void validateRepaymentsStartingFromDateIsAfterDisbursementDate(final List<ApiParameterError> dataValidationErrors,
final LocalDate expectedDisbursementDate, final LocalDate repaymentsStartingFromDate) {
if (expectedDisbursementDate != null) {
if (repaymentsStartingFromDate != null && expectedDisbursementDate.isAfter(repaymentsStartingFromDate)) {
final ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.loan.expectedDisbursementDate.cannot.be.after.first.repayment.date",
"The parameter expectedDisbursementDate has a date which falls after the date for repaymentsStartingFromDate.",
"expectedDisbursementDate", expectedDisbursementDate, repaymentsStartingFromDate);
dataValidationErrors.add(error);
}
}
}
}