blob: 74b017d1ca3c85f41f1da2c47a51438c77f3c6fe [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.floatingrates.serialization;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.portfolio.floatingrates.domain.FloatingRate;
import org.apache.fineract.portfolio.floatingrates.domain.FloatingRateRepository;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public class FloatingRateDataValidator {
private final Set<String> supportedParametersForFloatingRates = new HashSet<>(
Arrays.asList("name", "isBaseLendingRate", "isActive",
"ratePeriods"));
private final Set<String> supportedParametersForFloatingRatePeriods = new HashSet<>(
Arrays.asList("fromDate", "interestRate",
"isDifferentialToBaseLendingRate", "locale", "dateFormat"));
private final FromJsonHelper fromApiJsonHelper;
private final FloatingRateRepository floatingRateRepository;
@Autowired
public FloatingRateDataValidator(final FromJsonHelper fromApiJsonHelper,
final FloatingRateRepository floatingRateRepository) {
this.fromApiJsonHelper = fromApiJsonHelper;
this.floatingRateRepository = floatingRateRepository;
}
public void validateForCreate(String json) {
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
this.supportedParametersForFloatingRates);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
dataValidationErrors).resource("floatingrate");
final JsonElement element = this.fromApiJsonHelper.parse(json);
final String name = this.fromApiJsonHelper.extractStringNamed("name",
element);
baseDataValidator.reset().parameter("name").value(name).notBlank()
.notExceedingLengthOf(200);
Boolean isBaseLendingRate = null;
if (this.fromApiJsonHelper
.parameterExists("isBaseLendingRate", element)) {
isBaseLendingRate = this.fromApiJsonHelper
.extractBooleanNamed("isBaseLendingRate", element);
baseDataValidator.reset().parameter("isBaseLendingRate")
.value(isBaseLendingRate).notNull();
if (isBaseLendingRate == null) {
baseDataValidator.reset().parameter("isBaseLendingRate")
.trueOrFalseRequired(false);
} else if (isBaseLendingRate) {
FloatingRate baseLendingRate = this.floatingRateRepository
.retrieveBaseLendingRate();
if (baseLendingRate != null) {
baseDataValidator
.reset()
.parameter("isBaseLendingRate")
.value(isBaseLendingRate)
.failWithCode("baselendingrate.duplicate",
"Base Lending Rate already exists");
}
}
}
if (this.fromApiJsonHelper.parameterExists("isActive", element)) {
final Boolean isActive = this.fromApiJsonHelper
.extractBooleanNamed("isActive", element);
if (isActive == null) {
baseDataValidator.reset().parameter("isActive")
.trueOrFalseRequired(false);
}
}
if(isBaseLendingRate == null){
isBaseLendingRate = false;
}
validateRatePeriods(baseDataValidator, element, isBaseLendingRate, false);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void validateRatePeriods(DataValidatorBuilder baseDataValidator,
JsonElement element, boolean isBaseLendingRate, boolean isBLRModifiedAsNonBLR) {
if (this.fromApiJsonHelper.parameterExists("ratePeriods", element)) {
final JsonArray ratePeriods = this.fromApiJsonHelper
.extractJsonArrayNamed("ratePeriods", element);
baseDataValidator.reset().parameter("ratePeriods")
.value(ratePeriods).notBlank().jsonArrayNotEmpty();
if (ratePeriods != null) {
List<LocalDate> fromDates = new ArrayList<>();
for (int i = 0; i < ratePeriods.size(); i++) {
final JsonElement ratePeriod = ratePeriods.get(i);
this.fromApiJsonHelper.checkForUnsupportedParameters(
ratePeriod.getAsJsonObject(),
this.supportedParametersForFloatingRatePeriods);
final LocalDate fromDate = this.fromApiJsonHelper
.extractLocalDateNamed("fromDate", ratePeriod);
baseDataValidator
.reset()
.parameter("fromDate")
.parameterAtIndexArray("fromDate", i + 1)
.value(fromDate)
.notBlank()
.validateDateAfter(
DateUtils.getLocalDateOfTenant()
.plusDays(1));
if (fromDate != null) {
fromDates.add(fromDate);
}
final BigDecimal interestRatePerPeriod = this.fromApiJsonHelper
.extractBigDecimalWithLocaleNamed("interestRate",
ratePeriod);
baseDataValidator.reset().parameter("interestRate")
.parameterAtIndexArray("interestRate", i + 1)
.value(interestRatePerPeriod).notNull()
.zeroOrPositiveAmount();
if (this.fromApiJsonHelper.parameterExists(
"isDifferentialToBaseLendingRate", ratePeriod)) {
final Boolean isDifferentialToBaseLendingRate = this.fromApiJsonHelper
.extractBooleanNamed(
"isDifferentialToBaseLendingRate",
ratePeriod);
if (isDifferentialToBaseLendingRate == null) {
baseDataValidator
.reset()
.parameter(
"isDifferentialToBaseLendingRate")
.parameterAtIndexArray(
"isDifferentialToBaseLendingRate",
i + 1).trueOrFalseRequired(false);
} else if (isDifferentialToBaseLendingRate) {
FloatingRate baseLendingRate = this.floatingRateRepository
.retrieveBaseLendingRate();
if (baseLendingRate == null || isBLRModifiedAsNonBLR) {
baseDataValidator
.reset()
.parameter(
"isDifferentialToBaseLendingRate")
.parameterAtIndexArray(
"isDifferentialToBaseLendingRate",
i + 1)
.value(isDifferentialToBaseLendingRate)
.failWithCode(
"no.baselending.rate.defined",
"Base Lending Rate doesn't exists");
}
if(isBaseLendingRate){
baseDataValidator
.reset()
.parameter(
"isDifferentialToBaseLendingRate")
.parameterAtIndexArray(
"isDifferentialToBaseLendingRate",
i + 1)
.value(isDifferentialToBaseLendingRate)
.failWithCode(
"cannot.be.true.for.baselendingrate",
"isDifferentialToBaseLendingRate cannot be true for floating rate marked as Base Lending Rate.");
}
}
}
}
Set<LocalDate> uniqueFromDates = new HashSet<>(fromDates);
if (fromDates.size() != uniqueFromDates.size()) {
baseDataValidator
.reset()
.parameter("fromDate")
.failWithCode("multiple.same.date",
"More than one entry in ratePeriods have same fromDate.");
}
}
}
}
public void validateForUpdate(String json,
FloatingRate floatingRateForUpdate) {
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
this.supportedParametersForFloatingRates);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
dataValidationErrors).resource("floatingrate");
final JsonElement element = this.fromApiJsonHelper.parse(json);
if (this.fromApiJsonHelper.parameterExists("name", element)) {
final String name = this.fromApiJsonHelper.extractStringNamed(
"name", element);
baseDataValidator.reset().parameter("name").value(name).notBlank()
.notExceedingLengthOf(200);
}
Boolean isBaseLendingRate = null;
Boolean isBLRModifiedAsNonBLR = false;
FloatingRate baseLendingRate = this.floatingRateRepository
.retrieveBaseLendingRate();
if (this.fromApiJsonHelper
.parameterExists("isBaseLendingRate", element)) {
isBaseLendingRate = this.fromApiJsonHelper
.extractBooleanNamed("isBaseLendingRate", element);
baseDataValidator.reset().parameter("isBaseLendingRate")
.value(isBaseLendingRate).notNull();
if (isBaseLendingRate == null) {
baseDataValidator.reset().parameter("isBaseLendingRate")
.trueOrFalseRequired(false);
} else if (isBaseLendingRate) {
if (baseLendingRate != null
&& baseLendingRate.getId() != floatingRateForUpdate
.getId()) {
baseDataValidator
.reset()
.parameter("isBaseLendingRate")
.value(isBaseLendingRate)
.failWithCode("baselendingrate.duplicate",
"Base Lending Rate already exists");
}
}
}
Boolean isActive = null;
if (this.fromApiJsonHelper.parameterExists("isActive", element)) {
isActive = this.fromApiJsonHelper
.extractBooleanNamed("isActive", element);
if (isActive == null) {
baseDataValidator.reset().parameter("isActive")
.trueOrFalseRequired(false);
}
}
if(isBaseLendingRate == null){
isBaseLendingRate = floatingRateForUpdate.isBaseLendingRate();
}
if(isActive == null){
isActive = floatingRateForUpdate.isActive();
}
if(baseLendingRate != null
&& baseLendingRate.getId() == floatingRateForUpdate
.getId()){
if(!isBaseLendingRate || !isActive){
isBLRModifiedAsNonBLR = true;
}
}
if(isBLRModifiedAsNonBLR){
Collection<FloatingRate> floatingRates = this.floatingRateRepository.retrieveFloatingRatesLinkedToBLR();
if(floatingRates != null && floatingRates.size() > 0){
baseDataValidator
.reset()
.parameter("isBaseLendingRate")
.value(isBaseLendingRate)
.failWithCode("cannot.be.marked.non.baselendingrate",
"There are floating rates linked to this Base Lending Rate, cannot be marked as non-Base Lending Rate.");
}
}
validateRatePeriods(baseDataValidator, element, isBaseLendingRate, isBLRModifiedAsNonBLR);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(
final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
}
}