blob: 552c2fc59e18a52af1846d80e43ad38b9dd2af7f [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.account.data;
import static org.apache.fineract.portfolio.account.AccountDetailConstants.fromAccountTypeParamName;
import static org.apache.fineract.portfolio.account.AccountDetailConstants.toAccountTypeParamName;
import static org.apache.fineract.portfolio.account.AccountDetailConstants.transferTypeParamName;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.MonthDay;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
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.account.AccountDetailConstants;
import org.apache.fineract.portfolio.account.PortfolioAccountType;
import org.apache.fineract.portfolio.account.api.StandingInstructionApiConstants;
import org.apache.fineract.portfolio.account.domain.AccountTransferRecurrenceType;
import org.apache.fineract.portfolio.account.domain.AccountTransferType;
import org.apache.fineract.portfolio.account.domain.StandingInstructionType;
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class StandingInstructionDataValidator {
private final FromJsonHelper fromApiJsonHelper;
private final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator;
private static final Set<String> CREATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(AccountDetailConstants.localeParamName,
AccountDetailConstants.dateFormatParamName, AccountDetailConstants.fromOfficeIdParamName,
AccountDetailConstants.fromClientIdParamName, AccountDetailConstants.fromAccountTypeParamName,
AccountDetailConstants.fromAccountIdParamName, AccountDetailConstants.toOfficeIdParamName,
AccountDetailConstants.toClientIdParamName, AccountDetailConstants.toAccountTypeParamName,
AccountDetailConstants.toAccountIdParamName, AccountDetailConstants.transferTypeParamName,
StandingInstructionApiConstants.priorityParamName, StandingInstructionApiConstants.instructionTypeParamName,
StandingInstructionApiConstants.statusParamName, StandingInstructionApiConstants.amountParamName,
StandingInstructionApiConstants.validFromParamName, StandingInstructionApiConstants.validTillParamName,
StandingInstructionApiConstants.recurrenceTypeParamName, StandingInstructionApiConstants.recurrenceFrequencyParamName,
StandingInstructionApiConstants.recurrenceIntervalParamName, StandingInstructionApiConstants.recurrenceOnMonthDayParamName,
StandingInstructionApiConstants.nameParamName, StandingInstructionApiConstants.monthDayFormatParamName));
private static final Set<String> UPDATE_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(AccountDetailConstants.localeParamName,
AccountDetailConstants.dateFormatParamName, StandingInstructionApiConstants.priorityParamName,
StandingInstructionApiConstants.instructionTypeParamName, StandingInstructionApiConstants.statusParamName,
StandingInstructionApiConstants.amountParamName, StandingInstructionApiConstants.validFromParamName,
StandingInstructionApiConstants.validTillParamName, StandingInstructionApiConstants.recurrenceTypeParamName,
StandingInstructionApiConstants.recurrenceFrequencyParamName, StandingInstructionApiConstants.recurrenceIntervalParamName,
StandingInstructionApiConstants.recurrenceOnMonthDayParamName, StandingInstructionApiConstants.monthDayFormatParamName));
@Autowired
public StandingInstructionDataValidator(final FromJsonHelper fromApiJsonHelper,
final AccountTransfersDetailDataValidator accountTransfersDetailDataValidator) {
this.fromApiJsonHelper = fromApiJsonHelper;
this.accountTransfersDetailDataValidator = accountTransfersDetailDataValidator;
}
public void validateForCreate(final JsonCommand command) {
final String json = command.json();
if (StringUtils.isBlank(json)) {
throw new InvalidJsonException();
}
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, CREATE_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
this.accountTransfersDetailDataValidator.validate(command, baseDataValidator);
final JsonElement element = command.parsedJson();
final Integer status = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.statusParamName, element,
Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.statusParamName).value(status).notNull().inMinMaxRange(1, 2);
final LocalDate validFrom = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validFromParamName,
element);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validFromParamName).value(validFrom).notNull();
final LocalDate validTill = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validTillParamName,
element);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validTillParamName).value(validTill)
.validateDateAfter(validFrom);
final BigDecimal transferAmount = this.fromApiJsonHelper
.extractBigDecimalWithLocaleNamed(StandingInstructionApiConstants.amountParamName, element);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.amountParamName).value(transferAmount).positiveAmount();
final Integer transferType = this.fromApiJsonHelper.extractIntegerNamed(transferTypeParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(transferTypeParamName).value(transferType).notNull().inMinMaxRange(1, 3);
final Integer priority = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.priorityParamName, element,
Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.priorityParamName).value(priority).notNull().inMinMaxRange(1,
4);
final Integer standingInstructionType = this.fromApiJsonHelper
.extractIntegerNamed(StandingInstructionApiConstants.instructionTypeParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.instructionTypeParamName).value(standingInstructionType)
.notNull().inMinMaxRange(1, 2);
final Integer recurrenceType = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.recurrenceTypeParamName,
element, Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceTypeParamName).value(recurrenceType).notNull()
.inMinMaxRange(1, 2);
boolean isPeriodic = false;
if (recurrenceType != null) {
isPeriodic = AccountTransferRecurrenceType.fromInt(recurrenceType).isPeriodicRecurrence();
}
final Integer recurrenceFrequency = this.fromApiJsonHelper
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceFrequencyParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceFrequencyParamName).value(recurrenceFrequency)
.inMinMaxRange(0, 3);
if (recurrenceFrequency != null) {
PeriodFrequencyType frequencyType = PeriodFrequencyType.fromInt(recurrenceFrequency);
if (frequencyType.isMonthly() || frequencyType.isYearly()) {
final MonthDay monthDay = this.fromApiJsonHelper
.extractMonthDayNamed(StandingInstructionApiConstants.recurrenceOnMonthDayParamName, element);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceOnMonthDayParamName).value(monthDay)
.notNull();
}
}
final Integer recurrenceInterval = this.fromApiJsonHelper
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceIntervalParamName, element, Locale.getDefault());
if (isPeriodic) {
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceIntervalParamName).value(recurrenceInterval)
.notNull();
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceFrequencyParamName).value(recurrenceFrequency)
.notNull();
}
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceIntervalParamName).value(recurrenceInterval)
.integerGreaterThanZero();
final String name = this.fromApiJsonHelper.extractStringNamed(StandingInstructionApiConstants.nameParamName, element);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.nameParamName).value(name).notNull();
final Integer toAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(toAccountTypeParamName, element);
if (toAccountType != null && PortfolioAccountType.fromInt(toAccountType).isSavingsAccount()) {
baseDataValidator.reset().parameter(StandingInstructionApiConstants.instructionTypeParamName).value(standingInstructionType)
.notNull().inMinMaxRange(1, 1);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceTypeParamName).value(recurrenceType).notNull()
.inMinMaxRange(1, 1);
}
if (standingInstructionType != null && StandingInstructionType.fromInt(standingInstructionType).isFixedAmoutTransfer()) {
baseDataValidator.reset().parameter(StandingInstructionApiConstants.amountParamName).value(transferAmount).notNull();
}
String errorCode = null;
AccountTransferType accountTransferType = AccountTransferType.fromInt(transferType);
final Integer fromAccountType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(fromAccountTypeParamName, element);
if (fromAccountType != null && toAccountType != null) {
PortfolioAccountType fromPortfolioAccountType = PortfolioAccountType.fromInt(fromAccountType);
PortfolioAccountType toPortfolioAccountType = PortfolioAccountType.fromInt(toAccountType);
if (accountTransferType.isAccountTransfer()
&& (fromPortfolioAccountType.isLoanAccount() || toPortfolioAccountType.isLoanAccount())) {
errorCode = "not.account.transfer";
} else if (accountTransferType.isLoanRepayment()
&& (fromPortfolioAccountType.isLoanAccount() || toPortfolioAccountType.isSavingsAccount())) {
errorCode = "not.loan.repayment";
}
if (errorCode != null) {
baseDataValidator.reset().parameter(transferTypeParamName).failWithCode(errorCode);
}
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateForUpdate(final JsonCommand command) {
final String json = command.json();
if (StringUtils.isBlank(json)) {
throw new InvalidJsonException();
}
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, UPDATE_REQUEST_DATA_PARAMETERS);
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
.resource(StandingInstructionApiConstants.STANDING_INSTRUCTION_RESOURCE_NAME);
final JsonElement element = command.parsedJson();
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.validFromParamName, element)) {
final LocalDate validFrom = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validFromParamName,
element);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validFromParamName).value(validFrom).notNull();
}
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.validTillParamName, element)) {
final LocalDate validTill = this.fromApiJsonHelper.extractLocalDateNamed(StandingInstructionApiConstants.validTillParamName,
element);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.validTillParamName).value(validTill).notNull();
}
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.amountParamName, element)) {
final BigDecimal transferAmount = this.fromApiJsonHelper
.extractBigDecimalWithLocaleNamed(StandingInstructionApiConstants.amountParamName, element);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.amountParamName).value(transferAmount).positiveAmount();
}
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.statusParamName, element)) {
final Integer status = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.statusParamName, element,
Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.statusParamName).value(status).notNull().inMinMaxRange(1,
2);
}
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.priorityParamName, element)) {
final Integer priority = this.fromApiJsonHelper.extractIntegerNamed(StandingInstructionApiConstants.priorityParamName, element,
Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.priorityParamName).value(priority).notNull()
.inMinMaxRange(1, 4);
}
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.instructionTypeParamName, element)) {
final Integer standingInstructionType = this.fromApiJsonHelper
.extractIntegerNamed(StandingInstructionApiConstants.instructionTypeParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.instructionTypeParamName).value(standingInstructionType)
.notNull().inMinMaxRange(1, 2);
}
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.recurrenceTypeParamName, element)) {
final Integer recurrenceType = this.fromApiJsonHelper
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceTypeParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceTypeParamName).value(recurrenceType).notNull()
.inMinMaxRange(1, 2);
}
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.recurrenceFrequencyParamName, element)) {
final Integer recurrenceFrequency = this.fromApiJsonHelper
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceFrequencyParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceFrequencyParamName).value(recurrenceFrequency)
.inMinMaxRange(0, 3);
}
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.recurrenceIntervalParamName, element)) {
final Integer recurrenceInterval = this.fromApiJsonHelper
.extractIntegerNamed(StandingInstructionApiConstants.recurrenceIntervalParamName, element, Locale.getDefault());
baseDataValidator.reset().parameter(StandingInstructionApiConstants.recurrenceIntervalParamName).value(recurrenceInterval)
.integerGreaterThanZero();
}
if (this.fromApiJsonHelper.parameterExists(StandingInstructionApiConstants.nameParamName, element)) {
final String name = this.fromApiJsonHelper.extractStringNamed(StandingInstructionApiConstants.nameParamName, element);
baseDataValidator.reset().parameter(StandingInstructionApiConstants.nameParamName).value(name).notNull();
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(dataValidationErrors);
}
}
}