FINERACT-1932: Fineract modularization - fineract-savings
This commit is contained in:
committed by
Adam Saghy
parent
1f00bb6d33
commit
02cf6749af
-241
@@ -1,241 +0,0 @@
|
||||
/**
|
||||
* 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.accounting.producttoaccountmapping.service;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.CashAccountsForSavings;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SavingProductAccountingParams;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountRepository;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountRepositoryWrapper;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccountType;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.PortfolioProductType;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.domain.ProductToGLAccountMappingRepository;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.paymenttype.domain.PaymentTypeRepositoryWrapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMappingHelper {
|
||||
|
||||
public SavingsProductToGLAccountMappingHelper(final GLAccountRepository glAccountRepository,
|
||||
final ProductToGLAccountMappingRepository glAccountMappingRepository, final FromJsonHelper fromApiJsonHelper,
|
||||
final ChargeRepositoryWrapper chargeRepositoryWrapper, final GLAccountRepositoryWrapper accountRepositoryWrapper,
|
||||
final PaymentTypeRepositoryWrapper paymentTypeRepositoryWrapper) {
|
||||
super(glAccountRepository, glAccountMappingRepository, fromApiJsonHelper, chargeRepositoryWrapper, accountRepositoryWrapper,
|
||||
paymentTypeRepositoryWrapper);
|
||||
}
|
||||
|
||||
/***
|
||||
* Set of abstractions for saving Saving Products to GL Account Mappings
|
||||
***/
|
||||
|
||||
public void saveSavingsToAssetAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.ASSET, PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void saveSavingsToIncomeAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.INCOME, PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void saveSavingsToExpenseAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.EXPENSE, PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void saveSavingsToLiabilityAccountMapping(final JsonElement element, final String paramName, final Long productId,
|
||||
final int placeHolderTypeId) {
|
||||
saveProductToAccountMapping(element, paramName, productId, placeHolderTypeId, GLAccountType.LIABILITY, PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
/***
|
||||
* Set of abstractions for merging Savings Products to GL Account Mappings
|
||||
***/
|
||||
|
||||
public void mergeSavingsToAssetAccountMappingChanges(final JsonElement element, final String paramName, final Long productId,
|
||||
final int accountTypeId, final String accountTypeName, final Map<String, Object> changes) {
|
||||
mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes, GLAccountType.ASSET,
|
||||
PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void mergeSavingsToIncomeAccountMappingChanges(final JsonElement element, final String paramName, final Long productId,
|
||||
final int accountTypeId, final String accountTypeName, final Map<String, Object> changes) {
|
||||
mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes, GLAccountType.INCOME,
|
||||
PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void mergeSavingsToExpenseAccountMappingChanges(final JsonElement element, final String paramName, final Long productId,
|
||||
final int accountTypeId, final String accountTypeName, final Map<String, Object> changes) {
|
||||
mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes, GLAccountType.EXPENSE,
|
||||
PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void mergeSavingsToLiabilityAccountMappingChanges(final JsonElement element, final String paramName, final Long productId,
|
||||
final int accountTypeId, final String accountTypeName, final Map<String, Object> changes) {
|
||||
mergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, accountTypeName, changes, GLAccountType.LIABILITY,
|
||||
PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void createOrmergeSavingsToLiabilityAccountMappingChanges(final JsonElement element, final String paramName,
|
||||
final Long productId, final int accountTypeId, final Map<String, Object> changes) {
|
||||
createOrmergeProductToAccountMappingChanges(element, paramName, productId, accountTypeId, changes, GLAccountType.LIABILITY,
|
||||
PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
/*** Abstractions for payments channel related to savings products ***/
|
||||
|
||||
public void savePaymentChannelToFundSourceMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
savePaymentChannelToFundSourceMappings(command, element, productId, changes, PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void updatePaymentChannelToFundSourceMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
updatePaymentChannelToFundSourceMappings(command, element, productId, changes, PortfolioProductType.SAVING);
|
||||
}
|
||||
|
||||
public void saveChargesToIncomeAccountMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
// save both fee and penalty charges
|
||||
saveChargesToGLAccountMappings(command, element, productId, changes, PortfolioProductType.SAVING, true);
|
||||
saveChargesToGLAccountMappings(command, element, productId, changes, PortfolioProductType.SAVING, false);
|
||||
}
|
||||
|
||||
public void updateChargesToIncomeAccountMappings(final JsonCommand command, final JsonElement element, final Long productId,
|
||||
final Map<String, Object> changes) {
|
||||
// update both fee and penalty charges
|
||||
updateChargeToIncomeAccountMappings(command, element, productId, changes, PortfolioProductType.SAVING, true);
|
||||
updateChargeToIncomeAccountMappings(command, element, productId, changes, PortfolioProductType.SAVING, false);
|
||||
}
|
||||
|
||||
public Map<String, Object> populateChangesForNewSavingsProductToGLAccountMappingCreation(final JsonElement element,
|
||||
final AccountingRuleType accountingRuleType) {
|
||||
final Map<String, Object> changes = new HashMap<>();
|
||||
|
||||
final Long savingsReferenceId = this.fromApiJsonHelper.extractLongNamed(SavingProductAccountingParams.SAVINGS_REFERENCE.getValue(),
|
||||
element);
|
||||
final Long incomeFromFeesId = this.fromApiJsonHelper.extractLongNamed(SavingProductAccountingParams.INCOME_FROM_FEES.getValue(),
|
||||
element);
|
||||
final Long incomeFromPenaltiesId = this.fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue(), element);
|
||||
final Long interestOnSavingsId = this.fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.INTEREST_ON_SAVINGS.getValue(), element);
|
||||
final Long savingsControlId = this.fromApiJsonHelper.extractLongNamed(SavingProductAccountingParams.SAVINGS_CONTROL.getValue(),
|
||||
element);
|
||||
final Long transfersInSuspenseAccountId = this.fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), element);
|
||||
final Long overdraftControlId = this.fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), element);
|
||||
final Long incomeFromInterest = this.fromApiJsonHelper
|
||||
.extractLongNamed(SavingProductAccountingParams.INCOME_FROM_INTEREST.getValue(), element);
|
||||
final Long writeOffId = this.fromApiJsonHelper.extractLongNamed(SavingProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(),
|
||||
element);
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
case CASH_BASED:
|
||||
changes.put(SavingProductAccountingParams.SAVINGS_CONTROL.getValue(), savingsControlId);
|
||||
changes.put(SavingProductAccountingParams.SAVINGS_REFERENCE.getValue(), savingsReferenceId);
|
||||
changes.put(SavingProductAccountingParams.INTEREST_ON_SAVINGS.getValue(), interestOnSavingsId);
|
||||
changes.put(SavingProductAccountingParams.INCOME_FROM_FEES.getValue(), incomeFromFeesId);
|
||||
changes.put(SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue(), incomeFromPenaltiesId);
|
||||
changes.put(SavingProductAccountingParams.TRANSFERS_SUSPENSE.getValue(), transfersInSuspenseAccountId);
|
||||
changes.put(SavingProductAccountingParams.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), overdraftControlId);
|
||||
changes.put(SavingProductAccountingParams.INCOME_FROM_INTEREST.getValue(), incomeFromInterest);
|
||||
changes.put(SavingProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(), writeOffId);
|
||||
break;
|
||||
case ACCRUAL_PERIODIC:
|
||||
break;
|
||||
case ACCRUAL_UPFRONT:
|
||||
break;
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Examines and updates each account mapping for given loan product with changes passed in from the Json element
|
||||
*
|
||||
* @param savingsProductId
|
||||
* @param changes
|
||||
* @param element
|
||||
* @param accountingRuleType
|
||||
*/
|
||||
public void handleChangesToSavingsProductToGLAccountMappings(final Long savingsProductId, final Map<String, Object> changes,
|
||||
final JsonElement element, final AccountingRuleType accountingRuleType) {
|
||||
switch (accountingRuleType) {
|
||||
case NONE:
|
||||
break;
|
||||
case CASH_BASED:
|
||||
// asset
|
||||
mergeSavingsToAssetAccountMappingChanges(element, SavingProductAccountingParams.SAVINGS_REFERENCE.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.SAVINGS_REFERENCE.getValue(),
|
||||
CashAccountsForSavings.SAVINGS_REFERENCE.toString(), changes);
|
||||
|
||||
mergeSavingsToAssetAccountMappingChanges(element, SavingProductAccountingParams.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
|
||||
CashAccountsForSavings.OVERDRAFT_PORTFOLIO_CONTROL.toString(), changes);
|
||||
|
||||
// income
|
||||
mergeSavingsToIncomeAccountMappingChanges(element, SavingProductAccountingParams.INCOME_FROM_FEES.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.INCOME_FROM_FEES.getValue(),
|
||||
CashAccountsForSavings.INCOME_FROM_FEES.toString(), changes);
|
||||
|
||||
mergeSavingsToIncomeAccountMappingChanges(element, SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.INCOME_FROM_PENALTIES.getValue(),
|
||||
CashAccountsForSavings.INCOME_FROM_PENALTIES.toString(), changes);
|
||||
|
||||
mergeSavingsToIncomeAccountMappingChanges(element, SavingProductAccountingParams.INCOME_FROM_INTEREST.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.INCOME_FROM_INTEREST.getValue(),
|
||||
CashAccountsForSavings.INCOME_FROM_INTEREST.toString(), changes);
|
||||
|
||||
// expenses
|
||||
mergeSavingsToExpenseAccountMappingChanges(element, SavingProductAccountingParams.INTEREST_ON_SAVINGS.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.INTEREST_ON_SAVINGS.getValue(),
|
||||
CashAccountsForSavings.INTEREST_ON_SAVINGS.toString(), changes);
|
||||
mergeSavingsToExpenseAccountMappingChanges(element, SavingProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.LOSSES_WRITTEN_OFF.getValue(),
|
||||
CashAccountsForSavings.LOSSES_WRITTEN_OFF.toString(), changes);
|
||||
|
||||
// liability
|
||||
mergeSavingsToLiabilityAccountMappingChanges(element, SavingProductAccountingParams.SAVINGS_CONTROL.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.SAVINGS_CONTROL.getValue(),
|
||||
CashAccountsForSavings.SAVINGS_CONTROL.toString(), changes);
|
||||
mergeSavingsToLiabilityAccountMappingChanges(element, SavingProductAccountingParams.TRANSFERS_SUSPENSE.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.TRANSFERS_SUSPENSE.getValue(),
|
||||
CashAccountsForSavings.TRANSFERS_SUSPENSE.toString(), changes);
|
||||
createOrmergeSavingsToLiabilityAccountMappingChanges(element, SavingProductAccountingParams.ESCHEAT_LIABILITY.getValue(),
|
||||
savingsProductId, CashAccountsForSavings.ESCHEAT_LIABILITY.getValue(), changes);
|
||||
break;
|
||||
case ACCRUAL_PERIODIC:
|
||||
break;
|
||||
case ACCRUAL_UPFRONT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteSavingsProductToGLAccountMapping(final Long savingsProductId) {
|
||||
deleteProductToGLAccountMapping(savingsProductId, PortfolioProductType.SAVING);
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.api;
|
||||
|
||||
/**
|
||||
* Created by Cieyou on 2/26/14.
|
||||
*/
|
||||
public final class DataTableApiConstant {
|
||||
|
||||
private DataTableApiConstant() {
|
||||
|
||||
}
|
||||
|
||||
public static final Integer CATEGORY_PPI = 200;
|
||||
public static final Integer CATEGORY_DEFAULT = 100;
|
||||
|
||||
public static final String categoryParamName = "category";
|
||||
public static final String localParamName = "locale";
|
||||
public static final String DATATABLE_RESOURCE_NAME = "dataTables";
|
||||
|
||||
public static final String CREATEDAT_FIELD_NAME = "created_at";
|
||||
public static final String UPDATEDAT_FIELD_NAME = "updated_at";
|
||||
|
||||
// associationParameters
|
||||
public static final String allAssociateParamName = "all";
|
||||
public static final String repaymentScheduleAssociateParamName = "repaymentSchedule";
|
||||
public static final String originalScheduleAssociateParamName = "originalSchedule";
|
||||
public static final String transactionsAssociateParamName = "transactions";
|
||||
public static final String chargesAssociateParamName = "charges";
|
||||
public static final String guarantorsAssociateParamName = "guarantors";
|
||||
public static final String collateralAssociateParamName = "collateral";
|
||||
public static final String notesAssociateParamName = "notes";
|
||||
public static final String linkedAccountAssociateParamName = "linkedAccount";
|
||||
public static final String multiDisburseDetailsAssociateParamName = "multiDisburseDetails";
|
||||
public static final String futureScheduleAssociateParamName = "futureSchedule";
|
||||
public static final String meetingAssociateParamName = "meeting";
|
||||
public static final String emiAmountVariationsAssociateParamName = "emiAmountVariations";
|
||||
public static final String collectionAssociateParamName = "collection";
|
||||
|
||||
public static final String TABLE_COLUMN_CODE_MAPPINGS = "x_table_column_code_mappings";
|
||||
public static final String TABLE_REGISTERED_TABLE = "x_registered_table";
|
||||
public static final String TABLE_FIELD_ID = "id";
|
||||
|
||||
public static final String API_PARAM_COLUMNS = "columns";
|
||||
public static final String API_PARAM_CHANGECOLUMNS = "changeColumns";
|
||||
public static final String API_PARAM_ADDCOLUMNS = "addColumns";
|
||||
public static final String API_PARAM_DROPCOLUMNS = "dropColumns";
|
||||
public static final String API_PARAM_DATATABLE_NAME = "datatableName";
|
||||
public static final String API_PARAM_APPTABLE_NAME = "apptableName";
|
||||
public static final String API_PARAM_SUBTYPE = "entitySubType";
|
||||
public static final String API_PARAM_MULTIROW = "multiRow";
|
||||
|
||||
public static final String API_FIELD_NAME = "name";
|
||||
public static final String API_FIELD_NEWNAME = "newName";
|
||||
public static final String API_FIELD_TYPE = "type";
|
||||
public static final String API_FIELD_LENGTH = "length";
|
||||
public static final String API_FIELD_MANDATORY = "mandatory";
|
||||
public static final String API_FIELD_UNIQUE = "unique";
|
||||
public static final String API_FIELD_INDEXED = "indexed";
|
||||
public static final String API_FIELD_AFTER = "after";
|
||||
public static final String API_FIELD_CODE = "code";
|
||||
public static final String API_FIELD_NEWCODE = "newCode";
|
||||
|
||||
public static final String API_FIELD_TYPE_STRING = "string";
|
||||
public static final String API_FIELD_TYPE_NUMBER = "number";
|
||||
public static final String API_FIELD_TYPE_BOOLEAN = "boolean";
|
||||
public static final String API_FIELD_TYPE_DECIMAL = "decimal";
|
||||
public static final String API_FIELD_TYPE_DATE = "date";
|
||||
public static final String API_FIELD_TYPE_DATETIME = "datetime";
|
||||
public static final String API_FIELD_TYPE_TIMESTAMP = "timestamp";
|
||||
public static final String API_FIELD_TYPE_TEXT = "text";
|
||||
public static final String API_FIELD_TYPE_JSON = "json";
|
||||
public static final String API_FIELD_TYPE_DROPDOWN = "dropdown";
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
import static org.apache.fineract.portfolio.search.SearchConstants.API_PARAM_COLUMN;
|
||||
import static org.apache.fineract.portfolio.search.SearchConstants.API_PARAM_FILTERS;
|
||||
import static org.apache.fineract.portfolio.search.SearchConstants.API_PARAM_OPERATOR;
|
||||
import static org.apache.fineract.portfolio.search.SearchConstants.API_PARAM_QUERY;
|
||||
import static org.apache.fineract.portfolio.search.SearchConstants.API_PARAM_RESULTCOLUMNS;
|
||||
import static org.apache.fineract.portfolio.search.SearchConstants.API_PARAM_TABLE;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
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.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant;
|
||||
import org.apache.fineract.portfolio.search.data.AdvancedQueryData;
|
||||
import org.apache.fineract.portfolio.search.data.AdvancedQueryRequest;
|
||||
import org.apache.fineract.portfolio.search.data.ColumnFilterData;
|
||||
import org.apache.fineract.portfolio.search.data.FilterData;
|
||||
import org.apache.fineract.portfolio.search.data.TableQueryData;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class DataTableValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private static final Set<String> SUPPORTED_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(DataTableApiConstant.categoryParamName, DataTableApiConstant.localParamName));
|
||||
|
||||
@Autowired
|
||||
public DataTableValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public void validateDataTableRegistration(final String json) {
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(DataTableApiConstant.DATATABLE_RESOURCE_NAME);
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(DataTableApiConstant.categoryParamName, element)) {
|
||||
|
||||
final Integer category = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(DataTableApiConstant.categoryParamName, element);
|
||||
Object[] objectArray = new Integer[] { DataTableApiConstant.CATEGORY_PPI, DataTableApiConstant.CATEGORY_DEFAULT };
|
||||
baseDataValidator.reset().parameter(DataTableApiConstant.categoryParamName).value(category).isOneOfTheseValues(objectArray);
|
||||
}
|
||||
|
||||
baseDataValidator.throwValidationErrors();
|
||||
}
|
||||
|
||||
public void validateTableSearch(@NotNull AdvancedQueryRequest queryRequest) {
|
||||
final List<ApiParameterError> errors = new ArrayList<>();
|
||||
final DataValidatorBuilder validator = new DataValidatorBuilder(errors).resource(DataTableApiConstant.DATATABLE_RESOURCE_NAME);
|
||||
AdvancedQueryData baseQuery = queryRequest.getBaseQuery();
|
||||
if (baseQuery != null) {
|
||||
validateQueryData(baseQuery, validator);
|
||||
}
|
||||
List<TableQueryData> datatableQueries = queryRequest.getDatatableQueries();
|
||||
if (datatableQueries != null) {
|
||||
for (TableQueryData datatableQuery : datatableQueries) {
|
||||
validator.reset().parameter(API_PARAM_TABLE).value(datatableQuery.getTable()).notBlank();
|
||||
AdvancedQueryData queryData = datatableQuery.getQuery();
|
||||
validator.reset().parameter(API_PARAM_QUERY).value(queryData).notBlank();
|
||||
if (queryData != null) {
|
||||
validateQueryData(queryData, validator);
|
||||
}
|
||||
}
|
||||
}
|
||||
validator.throwValidationErrors();
|
||||
}
|
||||
|
||||
public void validateTableSearch(@NotNull AdvancedQueryData queryData) {
|
||||
final DataValidatorBuilder validator = new DataValidatorBuilder(new ArrayList<>())
|
||||
.resource(DataTableApiConstant.DATATABLE_RESOURCE_NAME);
|
||||
validateQueryData(queryData, validator);
|
||||
validator.throwValidationErrors();
|
||||
}
|
||||
|
||||
private void validateQueryData(@NotNull AdvancedQueryData queryData, @NotNull DataValidatorBuilder validator) {
|
||||
List<ColumnFilterData> columnFilters = queryData.getColumnFilters();
|
||||
if (columnFilters != null) {
|
||||
for (ColumnFilterData columnFilter : columnFilters) {
|
||||
validator.reset().parameter(API_PARAM_COLUMN).value(columnFilter.getColumn()).notNull();
|
||||
List<FilterData> filters = columnFilter.getFilters();
|
||||
validator.reset().parameter(API_PARAM_FILTERS).value(filters == null ? null : filters.toArray()).notNull().arrayNotEmpty();
|
||||
if (filters != null) {
|
||||
for (FilterData filter : filters) {
|
||||
validator.reset().parameter(API_PARAM_OPERATOR).value(filter.getOperator()).notNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
List<String> resultColumns = queryData.getResultColumns();
|
||||
if (resultColumns != null) {
|
||||
for (String resultColumn : resultColumns) {
|
||||
validator.reset().parameter(API_PARAM_RESULTCOLUMNS).value(resultColumn).notBlank();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class DatatableCheckStatusData implements Serializable {
|
||||
|
||||
private final String name;
|
||||
private final int code;
|
||||
|
||||
public DatatableCheckStatusData(final String name, final int code) {
|
||||
this.name = name;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class DatatableChecksData implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3113568562509206452L;
|
||||
private final String entity;
|
||||
private final String dataTableName;
|
||||
|
||||
public DatatableChecksData(final String entity, final String dataTableName) {
|
||||
this.entity = entity;
|
||||
this.dataTableName = dataTableName;
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
/**
|
||||
* Immutable data object for role data.
|
||||
*/
|
||||
public class EntityDataTableChecksData implements Serializable {
|
||||
|
||||
private final long id;
|
||||
private final String entity;
|
||||
private final EnumOptionData status;
|
||||
private final String datatableName;
|
||||
private final boolean systemDefined;
|
||||
private final Long order;
|
||||
private final Long productId;
|
||||
private final String productName;
|
||||
|
||||
public EntityDataTableChecksData(final long id, final String entity, final EnumOptionData status, final String datatableName,
|
||||
final boolean systemDefined, final Long loanProductId, final String productName) {
|
||||
this.id = id;
|
||||
this.entity = entity;
|
||||
this.status = status;
|
||||
this.datatableName = datatableName;
|
||||
this.systemDefined = systemDefined;
|
||||
this.order = id;
|
||||
this.productId = loanProductId;
|
||||
this.productName = productName;
|
||||
}
|
||||
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
import static org.apache.fineract.infrastructure.dataqueries.data.StatusEnum.ACTIVATE;
|
||||
import static org.apache.fineract.infrastructure.dataqueries.data.StatusEnum.APPROVE;
|
||||
import static org.apache.fineract.infrastructure.dataqueries.data.StatusEnum.CLOSE;
|
||||
import static org.apache.fineract.infrastructure.dataqueries.data.StatusEnum.CREATE;
|
||||
import static org.apache.fineract.infrastructure.dataqueries.data.StatusEnum.DISBURSE;
|
||||
import static org.apache.fineract.infrastructure.dataqueries.data.StatusEnum.REJECTED;
|
||||
import static org.apache.fineract.infrastructure.dataqueries.data.StatusEnum.WITHDRAWN;
|
||||
import static org.apache.fineract.infrastructure.dataqueries.data.StatusEnum.WRITE_OFF;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public enum EntityTables {
|
||||
|
||||
CLIENT("m_client", "client_id", "id", CREATE, ACTIVATE, CLOSE), //
|
||||
GROUP("m_group", "group_id", "id", CREATE, ACTIVATE, CLOSE), //
|
||||
CENTER("m_center", "m_group", "center_id", "id"), //
|
||||
OFFICE("m_office", "office_id", "id"), //
|
||||
LOAN_PRODUCT("m_product_loan", "product_loan_id", "id"), //
|
||||
LOAN("m_loan", "loan_id", "id", CREATE, APPROVE, DISBURSE, WITHDRAWN, REJECTED, WRITE_OFF), //
|
||||
SAVINGS_PRODUCT("m_savings_product", "savings_product_id", "id"), //
|
||||
SAVINGS("m_savings_account", "savings_account_id", "id", CREATE, APPROVE, ACTIVATE, WITHDRAWN, REJECTED, CLOSE), //
|
||||
SAVINGS_TRANSACTION("m_savings_account_transaction", "savings_transaction_id", "id"), //
|
||||
SHARE_PRODUCT("m_share_product", "share_product_id", "id"), //
|
||||
;
|
||||
|
||||
public static final EntityTables[] VALUES = values();
|
||||
|
||||
private static final List<String> ENTITY_NAMES = Arrays.stream(VALUES).map(EntityTables::getName).toList();
|
||||
|
||||
private static final Map<String, EntityTables> BY_ENTITY_NAME = Arrays.stream(VALUES)
|
||||
.collect(Collectors.toMap(EntityTables::getName, e -> e));
|
||||
|
||||
@NotNull
|
||||
private final String name;
|
||||
@NotNull
|
||||
private final String apptableName;
|
||||
|
||||
@NotNull
|
||||
private final String foreignKeyColumnNameOnDatatable;
|
||||
@NotNull
|
||||
private final String refColumn; // referenced column name on apptable
|
||||
|
||||
private final ImmutableList<StatusEnum> checkStatuses;
|
||||
|
||||
EntityTables(@NotNull String name, @NotNull String apptableName, @NotNull String foreignKeyColumnNameOnDatatable,
|
||||
@NotNull String refColumn, StatusEnum... statuses) {
|
||||
this.name = name;
|
||||
this.apptableName = apptableName;
|
||||
this.foreignKeyColumnNameOnDatatable = foreignKeyColumnNameOnDatatable;
|
||||
this.refColumn = refColumn;
|
||||
this.checkStatuses = statuses == null ? ImmutableList.of() : ImmutableList.copyOf(statuses);
|
||||
}
|
||||
|
||||
EntityTables(@NotNull String name, @NotNull String foreignKeyColumnNameOnDatatable, @NotNull String refColumn, StatusEnum... statuses) {
|
||||
this(name, name, foreignKeyColumnNameOnDatatable, refColumn, statuses);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getApptableName() {
|
||||
return apptableName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getForeignKeyColumnNameOnDatatable() {
|
||||
return this.foreignKeyColumnNameOnDatatable;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getRefColumn() {
|
||||
return refColumn;
|
||||
}
|
||||
|
||||
public List<StatusEnum> getCheckStatuses() {
|
||||
return checkStatuses;
|
||||
}
|
||||
|
||||
public boolean hasCheck() {
|
||||
return checkStatuses != null && !checkStatuses.isEmpty();
|
||||
}
|
||||
|
||||
public static List<String> getEntityNames() {
|
||||
return ENTITY_NAMES;
|
||||
}
|
||||
|
||||
public static EntityTables fromEntityName(String name) {
|
||||
return name == null ? null : BY_ENTITY_NAME.get(name.toLowerCase());
|
||||
}
|
||||
|
||||
public static String getForeignKeyColumnNameOnDatatable(String name) {
|
||||
EntityTables entityTable = fromEntityName(name);
|
||||
return entityTable == null ? null : entityTable.getForeignKeyColumnNameOnDatatable();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<StatusEnum> getCheckStatuses(String name) {
|
||||
EntityTables entityTable = fromEntityName(name);
|
||||
return entityTable == null ? List.of() : entityTable.getCheckStatuses();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<Integer> getCheckStatusCodes(String name) {
|
||||
return getCheckStatuses(name).stream().map(StatusEnum::getCode).toList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<EntityTables> getFiltered(Predicate<EntityTables> filter) {
|
||||
return Arrays.stream(VALUES).filter(filter).toList();
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.service.database.JdbcJavaType;
|
||||
|
||||
/**
|
||||
* Immutable data object for generic resultset data.
|
||||
*/
|
||||
public final class GenericResultsetData {
|
||||
|
||||
private final List<ResultsetColumnHeaderData> columnHeaders;
|
||||
private final List<ResultsetRowData> data;
|
||||
|
||||
public GenericResultsetData(final List<ResultsetColumnHeaderData> columnHeaders, final List<ResultsetRowData> resultsetDataRows) {
|
||||
this.columnHeaders = columnHeaders;
|
||||
this.data = resultsetDataRows;
|
||||
}
|
||||
|
||||
public List<ResultsetColumnHeaderData> getColumnHeaders() {
|
||||
return this.columnHeaders;
|
||||
}
|
||||
|
||||
public List<ResultsetRowData> getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public JdbcJavaType getColTypeOfColumnNamed(final String columnName) {
|
||||
for (final ResultsetColumnHeaderData columnHeader : this.columnHeaders) {
|
||||
if (columnHeader.isNamed(columnName)) {
|
||||
return columnHeader.getColumnType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasNoEntries() {
|
||||
return this.data.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasEntries() {
|
||||
return !hasNoEntries();
|
||||
}
|
||||
|
||||
public boolean hasMoreThanOneEntry() {
|
||||
return this.data.size() > 1;
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ReportData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final String reportName;
|
||||
@SuppressWarnings("unused")
|
||||
private final String reportType;
|
||||
@SuppressWarnings("unused")
|
||||
private final String reportSubType;
|
||||
@SuppressWarnings("unused")
|
||||
private final String reportCategory;
|
||||
@SuppressWarnings("unused")
|
||||
private final String description;
|
||||
@SuppressWarnings("unused")
|
||||
private final String reportSql;
|
||||
@SuppressWarnings("unused")
|
||||
private final Boolean coreReport;
|
||||
@SuppressWarnings("unused")
|
||||
private final Boolean useReport;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<ReportParameterData> reportParameters;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private List<String> allowedReportTypes;
|
||||
@SuppressWarnings("unused")
|
||||
private List<String> allowedReportSubTypes;
|
||||
@SuppressWarnings("unused")
|
||||
private Collection<ReportParameterData> allowedParameters;
|
||||
|
||||
public ReportData(final Long id, final String reportName, final String reportType, final String reportSubType,
|
||||
final String reportCategory, final String description, final String reportSql, final Boolean coreReport,
|
||||
final Boolean useReport, final Collection<ReportParameterData> reportParameters) {
|
||||
this.id = id;
|
||||
this.reportName = reportName;
|
||||
this.reportType = reportType;
|
||||
this.reportSubType = reportSubType;
|
||||
this.reportCategory = reportCategory;
|
||||
this.description = description;
|
||||
this.reportParameters = reportParameters;
|
||||
this.reportSql = reportSql;
|
||||
this.coreReport = coreReport;
|
||||
this.useReport = useReport;
|
||||
this.allowedReportTypes = null;
|
||||
this.allowedReportSubTypes = null;
|
||||
this.allowedParameters = null;
|
||||
}
|
||||
|
||||
public ReportData() {
|
||||
this.id = null;
|
||||
this.reportName = null;
|
||||
this.reportType = null;
|
||||
this.reportSubType = null;
|
||||
this.reportCategory = null;
|
||||
this.description = null;
|
||||
this.reportParameters = null;
|
||||
this.reportSql = null;
|
||||
this.coreReport = null;
|
||||
this.useReport = null;
|
||||
this.allowedReportTypes = null;
|
||||
this.allowedReportSubTypes = null;
|
||||
this.allowedParameters = null;
|
||||
}
|
||||
|
||||
public void appendedTemplate(final Collection<ReportParameterData> allowedParameters, final Collection<String> allowedReportTypes) {
|
||||
|
||||
final List<String> reportTypes = new ArrayList<>();
|
||||
reportTypes.addAll(allowedReportTypes);
|
||||
this.allowedReportTypes = reportTypes;
|
||||
|
||||
final List<String> reportSubTypes = new ArrayList<>();
|
||||
reportSubTypes.add("Bar");
|
||||
reportSubTypes.add("Pie");
|
||||
this.allowedReportSubTypes = reportSubTypes;
|
||||
|
||||
this.allowedParameters = allowedParameters;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+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.infrastructure.dataqueries.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
public class ReportExportType implements Serializable {
|
||||
|
||||
private final String key;
|
||||
private final String queryParameter;
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
/* used to show list of parameters used by a report and also for getting a list of parameters available (the reportParameterName is left null */
|
||||
public final class ReportParameterData {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final Long id;
|
||||
@SuppressWarnings("unused")
|
||||
private final Long parameterId;
|
||||
@SuppressWarnings("unused")
|
||||
private final String parameterName;
|
||||
@SuppressWarnings("unused")
|
||||
private final String reportParameterName;
|
||||
|
||||
public ReportParameterData(final Long id, final Long parameterId, final String reportParameterName, final String parameterName) {
|
||||
this.id = id;
|
||||
this.parameterId = parameterId;
|
||||
this.parameterName = parameterName;
|
||||
this.reportParameterName = reportParameterName;
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
public final class ReportParameterJoinData {
|
||||
|
||||
private final Long reportId;
|
||||
private final String reportName;
|
||||
private final String reportType;
|
||||
private final String reportSubType;
|
||||
private final String reportCategory;
|
||||
private final String description;
|
||||
private final String reportSql;
|
||||
private final Boolean coreReport;
|
||||
private final Boolean useReport;
|
||||
|
||||
private final Long reportParameterId;
|
||||
private final Long parameterId;
|
||||
private final String reportParameterName;
|
||||
private final String parameterName;
|
||||
|
||||
public ReportParameterJoinData(final Long reportId, final String reportName, final String reportType, final String reportSubType,
|
||||
final String reportCategory, final String description, final String reportSql, final Boolean coreReport,
|
||||
final Boolean useReport, final Long reportParameterId, final Long parameterId, final String reportParameterName,
|
||||
final String parameterName) {
|
||||
this.reportId = reportId;
|
||||
this.reportName = reportName;
|
||||
this.reportType = reportType;
|
||||
this.reportSubType = reportSubType;
|
||||
this.reportCategory = reportCategory;
|
||||
this.description = description;
|
||||
this.reportSql = reportSql;
|
||||
this.coreReport = coreReport;
|
||||
this.useReport = useReport;
|
||||
this.reportParameterId = reportParameterId;
|
||||
this.parameterId = parameterId;
|
||||
this.reportParameterName = reportParameterName;
|
||||
this.parameterName = parameterName;
|
||||
}
|
||||
|
||||
public Long getReportId() {
|
||||
return this.reportId;
|
||||
}
|
||||
|
||||
public String getReportName() {
|
||||
return this.reportName;
|
||||
}
|
||||
|
||||
public String getReportType() {
|
||||
return this.reportType;
|
||||
}
|
||||
|
||||
public String getReportSubType() {
|
||||
return this.reportSubType;
|
||||
}
|
||||
|
||||
public String getReportCategory() {
|
||||
return this.reportCategory;
|
||||
}
|
||||
|
||||
public String getReportSql() {
|
||||
return this.reportSql;
|
||||
}
|
||||
|
||||
public Boolean getCoreReport() {
|
||||
return this.coreReport;
|
||||
}
|
||||
|
||||
public Boolean getUseReport() {
|
||||
return this.useReport;
|
||||
}
|
||||
|
||||
public Long getReportParameterId() {
|
||||
return this.reportParameterId;
|
||||
}
|
||||
|
||||
public Long getParameterId() {
|
||||
return this.parameterId;
|
||||
}
|
||||
|
||||
public String getReportParameterName() {
|
||||
return this.reportParameterName;
|
||||
}
|
||||
|
||||
public String getParameterName() {
|
||||
return this.parameterName;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return this.description;
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class ResultsetRowData {
|
||||
|
||||
private final List<Object> row;
|
||||
|
||||
public static ResultsetRowData create(final List<Object> rowValues) {
|
||||
return new ResultsetRowData(rowValues);
|
||||
}
|
||||
|
||||
private ResultsetRowData(final List<Object> rowValues) {
|
||||
this.row = rowValues;
|
||||
}
|
||||
|
||||
public List<Object> getRow() {
|
||||
return this.row;
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public enum StatusEnum {
|
||||
|
||||
CREATE("create", 100), APPROVE("approve", 200), ACTIVATE("activate", 300), WITHDRAWN("withdraw", 400), REJECTED("reject", 500), CLOSE(
|
||||
"close", 600), WRITE_OFF("write off", 601), RESCHEDULE("reschedule", 602), OVERPAY("overpay", 700), DISBURSE("disburse", 800);
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Integer code;
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
StatusEnum(String name, Integer code) {
|
||||
|
||||
this.name = name;
|
||||
this.code = code;
|
||||
|
||||
}
|
||||
|
||||
public static List<DatatableCheckStatusData> getStatusList() {
|
||||
|
||||
List<DatatableCheckStatusData> data = new ArrayList<DatatableCheckStatusData>();
|
||||
|
||||
for (StatusEnum status : StatusEnum.values()) {
|
||||
data.add(new DatatableCheckStatusData(status.name, status.code));
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
public static StatusEnum fromInt(final Integer code) {
|
||||
StatusEnum ret = null;
|
||||
switch (code) {
|
||||
case 100:
|
||||
ret = StatusEnum.CREATE;
|
||||
break;
|
||||
case 200:
|
||||
ret = StatusEnum.APPROVE;
|
||||
break;
|
||||
case 300:
|
||||
ret = StatusEnum.ACTIVATE;
|
||||
break;
|
||||
case 400:
|
||||
ret = StatusEnum.WITHDRAWN;
|
||||
break;
|
||||
case 500:
|
||||
ret = StatusEnum.REJECTED;
|
||||
break;
|
||||
case 600:
|
||||
ret = StatusEnum.CLOSE;
|
||||
break;
|
||||
case 601:
|
||||
ret = StatusEnum.WRITE_OFF;
|
||||
break;
|
||||
case 602:
|
||||
ret = StatusEnum.RESCHEDULE;
|
||||
break;
|
||||
case 700:
|
||||
ret = StatusEnum.OVERPAY;
|
||||
break;
|
||||
case 800:
|
||||
ret = StatusEnum.DISBURSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static EnumOptionData statusTypeEnum(final Integer id) {
|
||||
return statusType(StatusEnum.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData statusType(final StatusEnum statusType) {
|
||||
final EnumOptionData optionData = new EnumOptionData(statusType.getCode().longValue(), statusType.name(), statusType.name());
|
||||
return optionData;
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.service;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
|
||||
|
||||
public interface GenericDataService {
|
||||
|
||||
GenericResultsetData fillGenericResultSet(String sql);
|
||||
|
||||
List<ResultsetColumnHeaderData> fillResultsetColumnHeaders(String tableName);
|
||||
|
||||
List<ResultsetRowData> fillResultsetRowData(String sql, List<ResultsetColumnHeaderData> columnHeaders);
|
||||
|
||||
String generateJsonFromGenericResultsetData(GenericResultsetData grs);
|
||||
|
||||
String replace(String str, String pattern, String replace);
|
||||
|
||||
String wrapSQL(String sql);
|
||||
|
||||
boolean isExplicitlyUnique(String tableName, String columnName);
|
||||
|
||||
boolean isExplicitlyIndexed(String tableName, String columnName);
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* 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.infrastructure.dataqueries.service;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.service.PagedLocalRequest;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.GenericResultsetData;
|
||||
import org.apache.fineract.portfolio.search.data.AdvancedQueryData;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
public interface ReadWriteNonCoreDataService {
|
||||
|
||||
List<DatatableData> retrieveDatatableNames(String appTable);
|
||||
|
||||
DatatableData retrieveDatatable(String datatable);
|
||||
|
||||
@PreAuthorize(value = "hasAnyAuthority('ALL_FUNCTIONS', 'REGISTER_DATATABLE')")
|
||||
void registerDatatable(JsonCommand command);
|
||||
|
||||
@PreAuthorize(value = "hasAnyAuthority('ALL_FUNCTIONS', 'REGISTER_DATATABLE')")
|
||||
void registerDatatable(String dataTableName, String applicationTableName, String entitySubType);
|
||||
|
||||
@PreAuthorize(value = "hasAnyAuthority('ALL_FUNCTIONS', 'REGISTER_DATATABLE')")
|
||||
void registerDatatable(JsonCommand command, String permissionTable);
|
||||
|
||||
@PreAuthorize(value = "hasAnyAuthority('ALL_FUNCTIONS', 'DEREGISTER_DATATABLE')")
|
||||
void deregisterDatatable(String datatable);
|
||||
|
||||
GenericResultsetData retrieveDataTableGenericResultSet(String datatable, Long appTableId, String order, Long id);
|
||||
|
||||
CommandProcessingResult createDatatable(JsonCommand command);
|
||||
|
||||
void updateDatatable(String datatableName, JsonCommand command);
|
||||
|
||||
void deleteDatatable(String datatableName);
|
||||
|
||||
CommandProcessingResult createNewDatatableEntry(String datatable, Long appTableId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult createNewDatatableEntry(String datatable, Long appTableId, String json);
|
||||
|
||||
CommandProcessingResult createPPIEntry(String datatable, Long appTableId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult updateDatatableEntryOneToOne(String datatable, Long appTableId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult updateDatatableEntryOneToMany(String datatable, Long appTableId, Long datatableId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult deleteDatatableEntries(String datatable, Long appTableId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult deleteDatatableEntry(String datatable, Long appTableId, Long datatableId, JsonCommand command);
|
||||
|
||||
String getTableName(String Url);
|
||||
|
||||
String getDataTableName(String Url);
|
||||
|
||||
Long countDatatableEntries(String datatableName, Long appTableId, String foreignKeyColumn);
|
||||
|
||||
List<JsonObject> queryDataTable(@NotNull String datatable, @NotNull String columnName, String columnValue,
|
||||
@NotNull String resultColumns);
|
||||
|
||||
Page<JsonObject> queryDataTableAdvanced(@NotNull String datatable, @NotNull PagedLocalRequest<AdvancedQueryData> pagedRequest);
|
||||
|
||||
boolean buildDataQueryEmbedded(@NotNull EntityTables entityTable, @NotNull String datatable, @NotNull AdvancedQueryData request,
|
||||
@NotNull List<String> selectColumns, @NotNull StringBuilder select, @NotNull StringBuilder from, @NotNull StringBuilder where,
|
||||
@NotNull List<Object> params, String mainAlias, String alias, String dateFormat, String dateTimeFormat, Locale locale);
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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.organisation.monetary.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when currency mismatch occurs
|
||||
*/
|
||||
public class InvalidCurrencyException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public InvalidCurrencyException(final String entity, final String postFix, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super("error.msg." + entity + "." + postFix + ".invalid.currency", defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* 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.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class ChargeCannotBeAppliedToException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeCannotBeAppliedToException(final String postFix, final String defaultUserMessage, final Object... defaultUserMessageArgs) {
|
||||
|
||||
super("error.msg.charge.cannot.be.applied.to" + postFix, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* 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.collectionsheet;
|
||||
|
||||
public final class CollectionSheetConstants {
|
||||
|
||||
private CollectionSheetConstants() {
|
||||
|
||||
}
|
||||
|
||||
public static final String COLLECTIONSHEET_RESOURCE_NAME = "collectionsheet";
|
||||
|
||||
public static final String localeParamName = "locale";
|
||||
public static final String dateFormatParamName = "dateFormat";
|
||||
|
||||
public static final String transactionDateParamName = "transactionDate";
|
||||
public static final String actualDisbursementDateParamName = "actualDisbursementDate";
|
||||
public static final String bulkRepaymentTransactionsParamName = "bulkRepaymentTransactions";
|
||||
public static final String bulkDisbursementTransactionsParamName = "bulkDisbursementTransactions";
|
||||
public static final String bulkSavingsDueTransactionsParamName = "bulkSavingsDueTransactions";
|
||||
public static final String noteParamName = "note";
|
||||
public static final String calendarIdParamName = "calendarId";
|
||||
public static final String officeIdParamName = "officeId";
|
||||
public static final String staffIdParamName = "staffId";
|
||||
public static final String isTransactionDateOnNonMeetingDateParamName = "isTransactionDateOnNonMeetingDate";
|
||||
|
||||
// attendance parameters
|
||||
public static final String clientsAttendanceParamName = "clientsAttendance";
|
||||
public static final String clientIdParamName = "clientId";
|
||||
public static final String attendanceTypeParamName = "attendanceType";
|
||||
|
||||
public static final String loanIdParamName = "loanId";
|
||||
public static final String savingsIdParamName = "savingsId";
|
||||
public static final String transactionAmountParamName = "transactionAmount";
|
||||
public static final String depositAccountTypeParamName = "depositAccountType";
|
||||
}
|
||||
Executable
+81
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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.common.domain;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public enum ConditionType {
|
||||
|
||||
INVALID(0, "ConditionType.invalid"), //
|
||||
LESSTHAN(1, "ConditionType.lessthan"), //
|
||||
EQUAL(2, "ConditionType.equal"), //
|
||||
// TODO: fix typo "GREATERTHAN"
|
||||
GRETERTHAN(3, "ConditionType.greterthan"), //
|
||||
NOT_EQUAL(4, "ConditionType.notequal");//
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
public static ConditionType fromInt(final Integer v) {
|
||||
if (v == null) {
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
switch (v) {
|
||||
case 1:
|
||||
return LESSTHAN;
|
||||
case 2:
|
||||
return EQUAL;
|
||||
case 3:
|
||||
return GRETERTHAN;
|
||||
case 4:
|
||||
return NOT_EQUAL;
|
||||
default:
|
||||
return INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
ConditionType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replace("_", " ");
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
// TODO: why not just use the enum values... just more boilerplate code here!!
|
||||
public boolean isInvalid() {
|
||||
return ConditionType.INVALID.getValue().equals(this.value);
|
||||
}
|
||||
|
||||
// TODO: do we really need this?!?
|
||||
public static Object[] integerValues() {
|
||||
return Arrays.stream(values()).filter(value -> !INVALID.equals(value)).map(value -> value.value).toList().toArray();
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* 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.common.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.common.domain.ConditionType;
|
||||
import org.apache.fineract.portfolio.common.domain.DaysInMonthType;
|
||||
import org.apache.fineract.portfolio.common.domain.DaysInYearType;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
|
||||
public final class CommonEnumerations {
|
||||
|
||||
private CommonEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static final String DAYS_IN_MONTH_TYPE = "daysInMonthType";
|
||||
public static final String DAYS_IN_YEAR_TYPE = "daysInYearType";
|
||||
|
||||
public static EnumOptionData commonEnumueration(final String typeName, final int id) {
|
||||
EnumOptionData enumData = null;
|
||||
if (typeName.equals(DAYS_IN_MONTH_TYPE)) {
|
||||
enumData = daysInMonthType(id);
|
||||
} else if (typeName.equals(DAYS_IN_YEAR_TYPE)) {
|
||||
enumData = daysInYearType(id);
|
||||
}
|
||||
return enumData;
|
||||
}
|
||||
|
||||
public static EnumOptionData termFrequencyType(final int id, final String codePrefix) {
|
||||
return termFrequencyType(PeriodFrequencyType.fromInt(id), codePrefix);
|
||||
}
|
||||
|
||||
public static EnumOptionData termFrequencyType(final PeriodFrequencyType type, final String codePrefix) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case DAYS:
|
||||
optionData = new EnumOptionData(PeriodFrequencyType.DAYS.getValue().longValue(),
|
||||
codePrefix + PeriodFrequencyType.DAYS.getCode(), "Days");
|
||||
break;
|
||||
case WEEKS:
|
||||
optionData = new EnumOptionData(PeriodFrequencyType.WEEKS.getValue().longValue(),
|
||||
codePrefix + PeriodFrequencyType.WEEKS.getCode(), "Weeks");
|
||||
break;
|
||||
case MONTHS:
|
||||
optionData = new EnumOptionData(PeriodFrequencyType.MONTHS.getValue().longValue(),
|
||||
codePrefix + PeriodFrequencyType.MONTHS.getCode(), "Months");
|
||||
break;
|
||||
case YEARS:
|
||||
optionData = new EnumOptionData(PeriodFrequencyType.YEARS.getValue().longValue(),
|
||||
codePrefix + PeriodFrequencyType.YEARS.getCode(), "Years");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(PeriodFrequencyType.INVALID.getValue().longValue(), PeriodFrequencyType.INVALID.getCode(),
|
||||
"Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData conditionType(final int id, final String codePrefix) {
|
||||
return conditionType(ConditionType.fromInt(id), codePrefix);
|
||||
}
|
||||
|
||||
public static EnumOptionData conditionType(final ConditionType type, final String codePrefix) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case EQUAL:
|
||||
optionData = new EnumOptionData(ConditionType.EQUAL.getValue().longValue(), codePrefix + ConditionType.EQUAL.getCode(),
|
||||
"equal");
|
||||
break;
|
||||
case NOT_EQUAL:
|
||||
optionData = new EnumOptionData(ConditionType.NOT_EQUAL.getValue().longValue(),
|
||||
codePrefix + ConditionType.NOT_EQUAL.getCode(), "notEqual");
|
||||
break;
|
||||
case GRETERTHAN:
|
||||
optionData = new EnumOptionData(ConditionType.GRETERTHAN.getValue().longValue(),
|
||||
codePrefix + ConditionType.GRETERTHAN.getCode(), "greterthan");
|
||||
break;
|
||||
case LESSTHAN:
|
||||
optionData = new EnumOptionData(ConditionType.LESSTHAN.getValue().longValue(),
|
||||
codePrefix + ConditionType.LESSTHAN.getCode(), "lessthan");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ConditionType.INVALID.getValue().longValue(), ConditionType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static List<EnumOptionData> conditionType(final ConditionType[] conditionTypes, final String codePrefix) {
|
||||
final List<EnumOptionData> optionDatas = new ArrayList<>();
|
||||
for (final ConditionType conditionType : conditionTypes) {
|
||||
if (!conditionType.isInvalid()) {
|
||||
optionDatas.add(conditionType(conditionType, codePrefix));
|
||||
}
|
||||
}
|
||||
return optionDatas;
|
||||
}
|
||||
|
||||
public static EnumOptionData daysInMonthType(final int id) {
|
||||
return daysInMonthType(DaysInMonthType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData daysInMonthType(final DaysInMonthType type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case ACTUAL:
|
||||
optionData = new EnumOptionData(DaysInMonthType.ACTUAL.getValue().longValue(), DaysInMonthType.ACTUAL.getCode(), "Actual");
|
||||
break;
|
||||
case DAYS_30:
|
||||
optionData = new EnumOptionData(DaysInMonthType.DAYS_30.getValue().longValue(), DaysInMonthType.DAYS_30.getCode(),
|
||||
"30 Days");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(DaysInMonthType.INVALID.getValue().longValue(), DaysInMonthType.INVALID.getCode(),
|
||||
"Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData daysInYearType(final int id) {
|
||||
return daysInYearType(DaysInYearType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData daysInYearType(final DaysInYearType type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case ACTUAL:
|
||||
optionData = new EnumOptionData(DaysInYearType.ACTUAL.getValue().longValue(), DaysInYearType.ACTUAL.getCode(), "Actual");
|
||||
break;
|
||||
case DAYS_360:
|
||||
optionData = new EnumOptionData(DaysInYearType.DAYS_360.getValue().longValue(), DaysInYearType.DAYS_360.getCode(),
|
||||
"360 Days");
|
||||
break;
|
||||
case DAYS_364:
|
||||
optionData = new EnumOptionData(DaysInYearType.DAYS_364.getValue().longValue(), DaysInYearType.DAYS_364.getCode(),
|
||||
"364 Days");
|
||||
break;
|
||||
case DAYS_365:
|
||||
optionData = new EnumOptionData(DaysInYearType.DAYS_365.getValue().longValue(), DaysInYearType.DAYS_365.getCode(),
|
||||
"365 Days");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(DaysInYearType.INVALID.getValue().longValue(), DaysInYearType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* 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.domain;
|
||||
|
||||
/**
|
||||
* Enum representation of loan status states.
|
||||
*/
|
||||
public enum LoanStatus {
|
||||
|
||||
INVALID(0, "loanStatusType.invalid"), //
|
||||
SUBMITTED_AND_PENDING_APPROVAL(100, "loanStatusType.submitted.and.pending.approval"), //
|
||||
APPROVED(200, "loanStatusType.approved"), //
|
||||
ACTIVE(300, "loanStatusType.active"), //
|
||||
TRANSFER_IN_PROGRESS(303, "loanStatusType.transfer.in.progress"), //
|
||||
TRANSFER_ON_HOLD(304, "loanStatusType.transfer.on.hold"), //
|
||||
WITHDRAWN_BY_CLIENT(400, "loanStatusType.withdrawn.by.client"), //
|
||||
REJECTED(500, "loanStatusType.rejected"), //
|
||||
CLOSED_OBLIGATIONS_MET(600, "loanStatusType.closed.obligations.met"), //
|
||||
CLOSED_WRITTEN_OFF(601, "loanStatusType.closed.written.off"), //
|
||||
CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT(602, "loanStatusType.closed.reschedule.outstanding.amount"), //
|
||||
OVERPAID(700, "loanStatusType.overpaid");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
public static LoanStatus fromInt(final Integer statusValue) {
|
||||
|
||||
LoanStatus enumeration = LoanStatus.INVALID;
|
||||
switch (statusValue) {
|
||||
case 100:
|
||||
enumeration = LoanStatus.SUBMITTED_AND_PENDING_APPROVAL;
|
||||
break;
|
||||
case 200:
|
||||
enumeration = LoanStatus.APPROVED;
|
||||
break;
|
||||
case 300:
|
||||
enumeration = LoanStatus.ACTIVE;
|
||||
break;
|
||||
case 303:
|
||||
enumeration = LoanStatus.TRANSFER_IN_PROGRESS;
|
||||
break;
|
||||
case 304:
|
||||
enumeration = LoanStatus.TRANSFER_ON_HOLD;
|
||||
break;
|
||||
case 400:
|
||||
enumeration = LoanStatus.WITHDRAWN_BY_CLIENT;
|
||||
break;
|
||||
case 500:
|
||||
enumeration = LoanStatus.REJECTED;
|
||||
break;
|
||||
case 600:
|
||||
enumeration = LoanStatus.CLOSED_OBLIGATIONS_MET;
|
||||
break;
|
||||
case 601:
|
||||
enumeration = LoanStatus.CLOSED_WRITTEN_OFF;
|
||||
break;
|
||||
case 602:
|
||||
enumeration = LoanStatus.CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT;
|
||||
break;
|
||||
case 700:
|
||||
enumeration = LoanStatus.OVERPAID;
|
||||
break;
|
||||
}
|
||||
return enumeration;
|
||||
}
|
||||
|
||||
LoanStatus(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public boolean hasStateOf(final LoanStatus state) {
|
||||
return this.value.equals(state.getValue());
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public boolean isSubmittedAndPendingApproval() {
|
||||
return this.value.equals(LoanStatus.SUBMITTED_AND_PENDING_APPROVAL.getValue());
|
||||
}
|
||||
|
||||
public boolean isApproved() {
|
||||
return this.value.equals(LoanStatus.APPROVED.getValue());
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.value.equals(LoanStatus.ACTIVE.getValue());
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return isClosedObligationsMet() || isClosedWrittenOff() || isClosedWithOutsandingAmountMarkedForReschedule();
|
||||
}
|
||||
|
||||
public boolean isClosedObligationsMet() {
|
||||
return this.value.equals(LoanStatus.CLOSED_OBLIGATIONS_MET.getValue());
|
||||
}
|
||||
|
||||
public boolean isClosedWrittenOff() {
|
||||
return this.value.equals(LoanStatus.CLOSED_WRITTEN_OFF.getValue());
|
||||
}
|
||||
|
||||
public boolean isClosedWithOutsandingAmountMarkedForReschedule() {
|
||||
return this.value.equals(LoanStatus.CLOSED_RESCHEDULE_OUTSTANDING_AMOUNT.getValue());
|
||||
}
|
||||
|
||||
public boolean isWithdrawnByClient() {
|
||||
return this.value.equals(LoanStatus.WITHDRAWN_BY_CLIENT.getValue());
|
||||
}
|
||||
|
||||
public boolean isRejected() {
|
||||
return this.value.equals(LoanStatus.REJECTED.getValue());
|
||||
}
|
||||
|
||||
public boolean isActiveOrAwaitingApprovalOrDisbursal() {
|
||||
return isApproved() || isSubmittedAndPendingApproval() || isActive();
|
||||
}
|
||||
|
||||
public boolean isTransferInProgress() {
|
||||
return this.value.equals(LoanStatus.TRANSFER_IN_PROGRESS.getValue());
|
||||
}
|
||||
|
||||
public boolean isTransferOnHold() {
|
||||
return this.value.equals(LoanStatus.TRANSFER_ON_HOLD.getValue());
|
||||
}
|
||||
|
||||
public boolean isUnderTransfer() {
|
||||
return isTransferInProgress() || isTransferOnHold();
|
||||
}
|
||||
|
||||
public boolean isOverpaid() {
|
||||
return this.value.equals(LoanStatus.OVERPAID.getValue());
|
||||
}
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* 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.search;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class SearchConstants {
|
||||
|
||||
public static final String API_PARAM_RESULTCOLUMNS = "resultColumns";
|
||||
public static final String API_PARAM_COLUMN_FILTERS = "columnFilters";
|
||||
public static final String API_PARAM_COLUMN = "column";
|
||||
public static final String API_PARAM_FILTERS = "filters";
|
||||
public static final String API_PARAM_OPERATOR = "operator";
|
||||
public static final String API_PARAM_VALUES = "values";
|
||||
public static final String API_PARAM_TABLE = "table";
|
||||
public static final String API_PARAM_QUERY = "query";
|
||||
public static final String API_PARAM_DATE_FORMAT = "dateFormat";
|
||||
public static final String API_PARAM_DATETIME_FORMAT = "dateTimeFormat";
|
||||
public static final String API_PARAM_LOCALE = "locale";
|
||||
|
||||
private SearchConstants() {}
|
||||
|
||||
public enum SearchResponseParameters {
|
||||
|
||||
ENTITY_ID("entityId"), ENTITY_ACCOUNT_NO("entityAccountNo"), ENTITY_EXTERNAL_ID("entityExternalId"), ENTITY_NAME(
|
||||
"entityName"), ENTITY_TYPE("entityType"), PARENT_ID(
|
||||
"parentId"), PARENT_NAME("parentName"), ENTITY_MOBILE_NO("entityMobileNo"), ENTITY_STATUS("entityStatus");
|
||||
|
||||
private final String value;
|
||||
|
||||
SearchResponseParameters(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final Set<String> values = new HashSet<>();
|
||||
|
||||
static {
|
||||
for (final SearchResponseParameters param : SearchResponseParameters.values()) {
|
||||
values.add(param.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
public enum SearchSupportedParameters {
|
||||
|
||||
QUERY("query"), RESOURCE("resource"), EXACTMATCH("exactMatch");
|
||||
|
||||
private final String value;
|
||||
|
||||
SearchSupportedParameters(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final Set<String> values = new HashSet<>();
|
||||
|
||||
static {
|
||||
for (final SearchSupportedParameters param : SearchSupportedParameters.values()) {
|
||||
values.add(param.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
public enum SearchSupportedResources {
|
||||
|
||||
CLIENTS("clients"), GROUPS("groups"), LOANS("loans"), SAVINGS("savings"), SHARES("shares"), CLIENTIDENTIFIERS("clientIdentifiers");
|
||||
|
||||
private final String value;
|
||||
|
||||
SearchSupportedResources(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final Set<String> values = new HashSet<>();
|
||||
|
||||
static {
|
||||
for (final SearchSupportedResources param : SearchSupportedResources.values()) {
|
||||
values.add(param.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
public enum SearchLoanDate {
|
||||
|
||||
APPROVAL_DATE("approvalDate"), CREATED_DATE("createdDate"), DISBURSAL_DATE("disbursalDate");
|
||||
|
||||
private final String value;
|
||||
|
||||
SearchLoanDate(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final Set<String> values = new HashSet<>();
|
||||
|
||||
static {
|
||||
for (final SearchLoanDate param : SearchLoanDate.values()) {
|
||||
values.add(param.value);
|
||||
}
|
||||
}
|
||||
|
||||
public static Set<String> getAllValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().toString().replaceAll("_", " ");
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
+322
@@ -0,0 +1,322 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
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.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.lang3.StringUtils;
|
||||
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.infrastructure.security.utils.SQLInjectionValidator;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AdHocQueryDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private static final Set<String> AD_HOC_SEARCH_QUERY_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(
|
||||
AdHocQuerySearchConstants.entitiesParamName, AdHocQuerySearchConstants.loanStatusParamName,
|
||||
AdHocQuerySearchConstants.loanProductsParamName, AdHocQuerySearchConstants.officesParamName,
|
||||
AdHocQuerySearchConstants.loanDateOptionParamName, AdHocQuerySearchConstants.loanFromDateParamName,
|
||||
AdHocQuerySearchConstants.loanToDateParamName, AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName,
|
||||
AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName,
|
||||
AdHocQuerySearchConstants.minOutStandingAmountPercentageParamName,
|
||||
AdHocQuerySearchConstants.maxOutStandingAmountPercentageParamName,
|
||||
AdHocQuerySearchConstants.outStandingAmountPercentageParamName, AdHocQuerySearchConstants.includeOutstandingAmountParamName,
|
||||
AdHocQuerySearchConstants.outstandingAmountConditionParamName, AdHocQuerySearchConstants.minOutstandingAmountParamName,
|
||||
AdHocQuerySearchConstants.maxOutstandingAmountParamName, AdHocQuerySearchConstants.outstandingAmountParamName,
|
||||
AdHocQuerySearchConstants.localeParamName, AdHocQuerySearchConstants.dateFormatParamName));
|
||||
|
||||
private static final Set<String> AD_HOC_SEARCH_QUERY_CONDITIONS = new HashSet<>(Arrays.asList("between", "<=", ">=", "<", ">", "="));
|
||||
|
||||
private static final Object[] loanDateOptions = { AdHocQuerySearchConstants.approvalDateOption,
|
||||
AdHocQuerySearchConstants.createDateOption, AdHocQuerySearchConstants.disbursalDateOption };
|
||||
|
||||
private static final Object[] loanStatusOptions = { AdHocQuerySearchConstants.allLoanStatusOption,
|
||||
AdHocQuerySearchConstants.activeLoanStatusOption, AdHocQuerySearchConstants.overpaidLoanStatusOption,
|
||||
AdHocQuerySearchConstants.arrearsLoanStatusOption, AdHocQuerySearchConstants.closedLoanStatusOption,
|
||||
AdHocQuerySearchConstants.writeoffLoanStatusOption };
|
||||
|
||||
@Autowired
|
||||
public AdHocQueryDataValidator(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public void validateAdHocQueryParameters(final String json) {
|
||||
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, AD_HOC_SEARCH_QUERY_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(AdHocQuerySearchConstants.AD_HOC_SEARCH_QUERY_RESOURCE_NAME);
|
||||
|
||||
final String[] entities = this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.entitiesParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.entitiesParamName).value(entities).arrayNotEmpty();
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanStatusParamName, element)) {
|
||||
final String[] loanStatus = this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.loanStatusParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanStatusParamName).value(loanStatus).arrayNotEmpty();
|
||||
if (loanStatus != null && loanStatus.length > 0) {
|
||||
for (String status : loanStatus) {
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanStatusParamName).value(status)
|
||||
.isOneOfTheseValues(loanStatusOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanProductsParamName, element)) {
|
||||
final String[] loanProducts = this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.loanProductsParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanProductsParamName).value(loanProducts).arrayNotEmpty();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.officesParamName, element)) {
|
||||
final String[] offices = this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.officesParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.officesParamName).value(offices).arrayNotEmpty();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanDateOptionParamName, element)) {
|
||||
final String loanDateOption = this.fromApiJsonHelper.extractStringNamed(AdHocQuerySearchConstants.loanDateOptionParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanDateOptionParamName).value(loanDateOption)
|
||||
.isOneOfTheseValues(loanDateOptions);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanFromDateParamName, element)) {
|
||||
final LocalDate loanFromDate = this.fromApiJsonHelper.extractLocalDateNamed(AdHocQuerySearchConstants.loanFromDateParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanFromDateParamName).value(loanFromDate).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanToDateParamName, element)) {
|
||||
final LocalDate loanToDate = this.fromApiJsonHelper.extractLocalDateNamed(AdHocQuerySearchConstants.loanToDateParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.loanToDateParamName).value(loanToDate).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName, element)) {
|
||||
final boolean includeOutStandingAmountPercentage = this.fromApiJsonHelper
|
||||
.extractBooleanNamed(AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName)
|
||||
.value(includeOutStandingAmountPercentage).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName, element)) {
|
||||
final String outStandingAmountPercentageCondition = this.fromApiJsonHelper
|
||||
.extractStringNamed(AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName)
|
||||
.value(outStandingAmountPercentageCondition).isNotOneOfTheseValues(AD_HOC_SEARCH_QUERY_CONDITIONS);
|
||||
if (outStandingAmountPercentageCondition.equals("between")) {
|
||||
final BigDecimal minOutStandingAmountPercentage = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.minOutStandingAmountPercentageParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.minOutStandingAmountPercentageParamName)
|
||||
.value(minOutStandingAmountPercentage).notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
final BigDecimal maxOutStandingAmountPercentage = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.maxOutStandingAmountPercentageParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.maxOutStandingAmountPercentageParamName)
|
||||
.value(maxOutStandingAmountPercentage).notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
baseDataValidator.reset().compareMinAndMaxOfTwoBigDecmimalNos(minOutStandingAmountPercentage,
|
||||
maxOutStandingAmountPercentage);
|
||||
} else {
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outStandingAmountPercentageParamName, element)) {
|
||||
final BigDecimal outStandingAmountPercentage = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.outStandingAmountPercentageParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.outStandingAmountPercentageParamName)
|
||||
.value(outStandingAmountPercentage).notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.includeOutstandingAmountParamName, element)) {
|
||||
final Boolean includeOutstandingAmountParamName = this.fromApiJsonHelper
|
||||
.extractBooleanNamed(AdHocQuerySearchConstants.includeOutstandingAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.includeOutstandingAmountParamName)
|
||||
.value(includeOutstandingAmountParamName).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outstandingAmountConditionParamName, element)) {
|
||||
final String outstandingAmountCondition = this.fromApiJsonHelper
|
||||
.extractStringNamed(AdHocQuerySearchConstants.outstandingAmountConditionParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.outstandingAmountConditionParamName)
|
||||
.value(outstandingAmountCondition).isNotOneOfTheseValues(AD_HOC_SEARCH_QUERY_CONDITIONS);
|
||||
if (outstandingAmountCondition.equals("between")) {
|
||||
final BigDecimal minOutstandingAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.minOutstandingAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.minOutstandingAmountParamName).value(minOutstandingAmount)
|
||||
.notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
final BigDecimal maxOutstandingAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.maxOutstandingAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.maxOutstandingAmountParamName).value(maxOutstandingAmount)
|
||||
.notNull().notLessThanMin(BigDecimal.ZERO);
|
||||
baseDataValidator.reset().compareMinAndMaxOfTwoBigDecmimalNos(minOutstandingAmount, maxOutstandingAmount);
|
||||
} else {
|
||||
final BigDecimal outstandingAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.outstandingAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(AdHocQuerySearchConstants.outstandingAmountParamName).value(outstandingAmount).notNull()
|
||||
.notLessThanMin(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public AdHocQuerySearchConditions retrieveSearchConditions(String json) {
|
||||
|
||||
validateAdHocQueryParameters(json);
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
List<String> loanStatus = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanStatusParamName, element)) {
|
||||
loanStatus = Arrays.asList(this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.loanStatusParamName, element));
|
||||
}
|
||||
|
||||
List<Long> loanProducts = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanProductsParamName, element)) {
|
||||
loanProducts = extractLongValuesList(
|
||||
Arrays.asList(this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.loanProductsParamName, element)));
|
||||
}
|
||||
|
||||
List<Long> offices = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.officesParamName, element)) {
|
||||
offices = extractLongValuesList(
|
||||
Arrays.asList(this.fromApiJsonHelper.extractArrayNamed(AdHocQuerySearchConstants.officesParamName, element)));
|
||||
}
|
||||
|
||||
String loanDateOption = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanDateOptionParamName, element)) {
|
||||
loanDateOption = this.fromApiJsonHelper.extractStringNamed(AdHocQuerySearchConstants.loanDateOptionParamName, element);
|
||||
SQLInjectionValidator.validateSQLInput(loanDateOption);
|
||||
}
|
||||
|
||||
LocalDate loanFromDate = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanFromDateParamName, element)) {
|
||||
loanFromDate = this.fromApiJsonHelper.extractLocalDateNamed(AdHocQuerySearchConstants.loanFromDateParamName, element);
|
||||
}
|
||||
|
||||
LocalDate loanToDate = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.loanToDateParamName, element)) {
|
||||
loanToDate = this.fromApiJsonHelper.extractLocalDateNamed(AdHocQuerySearchConstants.loanToDateParamName, element);
|
||||
}
|
||||
|
||||
Boolean includeOutStandingAmountPercentage = false;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName, element)) {
|
||||
includeOutStandingAmountPercentage = this.fromApiJsonHelper
|
||||
.extractBooleanNamed(AdHocQuerySearchConstants.includeOutStandingAmountPercentageParamName, element);
|
||||
}
|
||||
|
||||
String outStandingAmountPercentageCondition = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName, element)) {
|
||||
outStandingAmountPercentageCondition = this.fromApiJsonHelper
|
||||
.extractStringNamed(AdHocQuerySearchConstants.outStandingAmountPercentageConditionParamName, element);
|
||||
SQLInjectionValidator.validateSQLInput(outStandingAmountPercentageCondition);
|
||||
}
|
||||
|
||||
BigDecimal minOutStandingAmountPercentage = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.minOutStandingAmountPercentageParamName, element)) {
|
||||
minOutStandingAmountPercentage = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.minOutStandingAmountPercentageParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal maxOutStandingAmountPercentage = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.maxOutStandingAmountPercentageParamName, element)) {
|
||||
maxOutStandingAmountPercentage = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.maxOutStandingAmountPercentageParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal outStandingAmountPercentage = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outStandingAmountPercentageParamName, element)) {
|
||||
outStandingAmountPercentage = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.outStandingAmountPercentageParamName, element);
|
||||
}
|
||||
|
||||
Boolean includeOutstandingAmountParamName = false;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.includeOutstandingAmountParamName, element)) {
|
||||
includeOutstandingAmountParamName = this.fromApiJsonHelper
|
||||
.extractBooleanNamed(AdHocQuerySearchConstants.includeOutstandingAmountParamName, element);
|
||||
}
|
||||
|
||||
String outstandingAmountCondition = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outstandingAmountConditionParamName, element)) {
|
||||
outstandingAmountCondition = this.fromApiJsonHelper
|
||||
.extractStringNamed(AdHocQuerySearchConstants.outstandingAmountConditionParamName, element);
|
||||
SQLInjectionValidator.validateSQLInput(outstandingAmountCondition);
|
||||
}
|
||||
|
||||
BigDecimal minOutstandingAmount = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.minOutstandingAmountParamName, element)) {
|
||||
minOutstandingAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.minOutstandingAmountParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal maxOutstandingAmount = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.maxOutstandingAmountParamName, element)) {
|
||||
maxOutstandingAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.maxOutstandingAmountParamName, element);
|
||||
}
|
||||
|
||||
BigDecimal outstandingAmount = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(AdHocQuerySearchConstants.outstandingAmountParamName, element)) {
|
||||
outstandingAmount = this.fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(AdHocQuerySearchConstants.outstandingAmountParamName, element);
|
||||
}
|
||||
|
||||
return AdHocQuerySearchConditions.instance(loanStatus, loanProducts, offices, loanDateOption, loanFromDate, loanToDate,
|
||||
includeOutStandingAmountPercentage, outStandingAmountPercentageCondition, minOutStandingAmountPercentage,
|
||||
maxOutStandingAmountPercentage, outStandingAmountPercentage, includeOutstandingAmountParamName, outstandingAmountCondition,
|
||||
minOutstandingAmount, maxOutstandingAmount, outstandingAmount);
|
||||
|
||||
}
|
||||
|
||||
private List<Long> extractLongValuesList(List<String> listTobeConverted) {
|
||||
List<Long> tempList = new ArrayList<>();
|
||||
for (String temp : listTobeConverted) {
|
||||
tempList.add(Long.valueOf(temp));
|
||||
}
|
||||
return tempList;
|
||||
}
|
||||
|
||||
}
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.loanaccount.domain.LoanStatus;
|
||||
|
||||
public class AdHocQuerySearchConditions {
|
||||
|
||||
private final List<String> loanStatus;
|
||||
private final List<Long> loanProducts;
|
||||
private final List<Long> offices;
|
||||
private final String loanDateOption;
|
||||
private final LocalDate loanFromDate;
|
||||
private final LocalDate loanToDate;
|
||||
private final Boolean includeOutStandingAmountPercentage;
|
||||
private final String outStandingAmountPercentageCondition;
|
||||
private final BigDecimal minOutStandingAmountPercentage;
|
||||
private final BigDecimal maxOutStandingAmountPercentage;
|
||||
private final BigDecimal outStandingAmountPercentage;
|
||||
private final Boolean includeOutstandingAmount;
|
||||
private final String outstandingAmountCondition;
|
||||
private final BigDecimal minOutstandingAmount;
|
||||
private final BigDecimal maxOutstandingAmount;
|
||||
private final BigDecimal outstandingAmount;
|
||||
|
||||
public static AdHocQuerySearchConditions instance(final List<String> loanStatus, final List<Long> loanProducts,
|
||||
final List<Long> offices, final String loanDateOption, final LocalDate loanFromDate, final LocalDate loanToDate,
|
||||
final Boolean includeOutStandingAmountPercentage, final String outStandingAmountPercentageCondition,
|
||||
final BigDecimal minOutStandingAmountPercentage, final BigDecimal maxOutStandingAmountPercentage,
|
||||
final BigDecimal outStandingAmountPercentage, final Boolean includeOutstandingAmountParamName,
|
||||
final String outstandingAmountCondition, final BigDecimal minOutstandingAmount, final BigDecimal maxOutstandingAmount,
|
||||
final BigDecimal outstandingAmount) {
|
||||
|
||||
return new AdHocQuerySearchConditions(loanStatus, loanProducts, offices, loanDateOption, loanFromDate, loanToDate,
|
||||
includeOutStandingAmountPercentage, outStandingAmountPercentageCondition, minOutStandingAmountPercentage,
|
||||
maxOutStandingAmountPercentage, outStandingAmountPercentage, includeOutstandingAmountParamName, outstandingAmountCondition,
|
||||
minOutstandingAmount, maxOutstandingAmount, outstandingAmount);
|
||||
|
||||
}
|
||||
|
||||
public AdHocQuerySearchConditions(final List<String> loanStatus, final List<Long> loanProducts, final List<Long> offices,
|
||||
final String loanDateOption, final LocalDate loanFromDate, final LocalDate loanToDate,
|
||||
final Boolean includeOutStandingAmountPercentage, final String outStandingAmountPercentageCondition,
|
||||
final BigDecimal minOutStandingAmountPercentage, final BigDecimal maxOutStandingAmountPercentage,
|
||||
final BigDecimal outStandingAmountPercentage, final Boolean includeOutstandingAmount, final String outstandingAmountCondition,
|
||||
final BigDecimal minOutstandingAmount, final BigDecimal maxOutstandingAmount, final BigDecimal outstandingAmount) {
|
||||
|
||||
this.loanStatus = loanStatus;
|
||||
this.loanProducts = loanProducts;
|
||||
this.offices = offices;
|
||||
this.loanDateOption = loanDateOption;
|
||||
this.loanFromDate = loanFromDate;
|
||||
this.loanToDate = loanToDate;
|
||||
this.includeOutStandingAmountPercentage = includeOutStandingAmountPercentage;
|
||||
this.outStandingAmountPercentageCondition = outStandingAmountPercentageCondition;
|
||||
this.minOutStandingAmountPercentage = minOutStandingAmountPercentage;
|
||||
this.maxOutStandingAmountPercentage = maxOutStandingAmountPercentage;
|
||||
this.outStandingAmountPercentage = outStandingAmountPercentage;
|
||||
this.includeOutstandingAmount = includeOutstandingAmount;
|
||||
this.outstandingAmountCondition = outstandingAmountCondition;
|
||||
this.minOutstandingAmount = minOutstandingAmount;
|
||||
this.maxOutstandingAmount = maxOutstandingAmount;
|
||||
this.outstandingAmount = outstandingAmount;
|
||||
|
||||
}
|
||||
|
||||
public List<String> getLoanStatus() {
|
||||
return getStatusVluesFromStatusCodes();
|
||||
}
|
||||
|
||||
private List<String> getStatusVluesFromStatusCodes() {
|
||||
List<String> loanStatusValues = new ArrayList<>();
|
||||
if (this.loanStatus != null) {
|
||||
for (String statusCode : this.loanStatus) {
|
||||
|
||||
if (statusCode.equalsIgnoreCase("active")) {
|
||||
loanStatusValues.add(LoanStatus.ACTIVE.getValue().toString());
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("overpaid")) {
|
||||
loanStatusValues.add(LoanStatus.OVERPAID.getValue().toString());
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("closed")) {
|
||||
loanStatusValues.add(LoanStatus.CLOSED_OBLIGATIONS_MET.getValue().toString());
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("writeoff")) {
|
||||
loanStatusValues.add(LoanStatus.CLOSED_WRITTEN_OFF.getValue().toString());
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("arrears")) {
|
||||
// TODO - No status code is there for loans which are in
|
||||
// active bad standing
|
||||
}
|
||||
|
||||
if (statusCode.equalsIgnoreCase("all")) {
|
||||
loanStatusValues.add("all");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loanStatusValues;
|
||||
}
|
||||
|
||||
public List<Long> getLoanProducts() {
|
||||
return this.loanProducts;
|
||||
}
|
||||
|
||||
public List<Long> getOffices() {
|
||||
return this.offices;
|
||||
}
|
||||
|
||||
public String getLoanDateOption() {
|
||||
return this.loanDateOption;
|
||||
}
|
||||
|
||||
public LocalDate getLoanFromDate() {
|
||||
return this.loanFromDate;
|
||||
}
|
||||
|
||||
public LocalDate getLoanToDate() {
|
||||
return this.loanToDate;
|
||||
}
|
||||
|
||||
public Boolean getIncludeOutStandingAmountPercentage() {
|
||||
return this.includeOutStandingAmountPercentage;
|
||||
}
|
||||
|
||||
public String getOutStandingAmountPercentageCondition() {
|
||||
return this.outStandingAmountPercentageCondition;
|
||||
}
|
||||
|
||||
public BigDecimal getMinOutStandingAmountPercentage() {
|
||||
return this.minOutStandingAmountPercentage;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxOutStandingAmountPercentage() {
|
||||
return this.maxOutStandingAmountPercentage;
|
||||
}
|
||||
|
||||
public BigDecimal getOutStandingAmountPercentage() {
|
||||
return this.outStandingAmountPercentage;
|
||||
}
|
||||
|
||||
public Boolean getIncludeOutstandingAmount() {
|
||||
return this.includeOutstandingAmount;
|
||||
}
|
||||
|
||||
public String getOutstandingAmountCondition() {
|
||||
return this.outstandingAmountCondition;
|
||||
}
|
||||
|
||||
public BigDecimal getMinOutstandingAmount() {
|
||||
return this.minOutstandingAmount;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxOutstandingAmount() {
|
||||
return this.maxOutstandingAmount;
|
||||
}
|
||||
|
||||
public BigDecimal getOutstandingAmount() {
|
||||
return this.outstandingAmount;
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public interface AdHocQuerySearchConstants {
|
||||
|
||||
String AD_HOC_SEARCH_QUERY_RESOURCE_NAME = "adHocQuery";
|
||||
|
||||
String localeParamName = "locale";
|
||||
String dateFormatParamName = "dateFormat";
|
||||
String entitiesParamName = "entities";
|
||||
String loanStatusParamName = "loanStatus";
|
||||
String loanProductsParamName = "loanProducts";
|
||||
String officesParamName = "offices";
|
||||
String loanDateOptionParamName = "loanDateOption";
|
||||
String loanFromDateParamName = "loanFromDate";
|
||||
String loanToDateParamName = "loanToDate";
|
||||
String includeOutStandingAmountPercentageParamName = "includeOutStandingAmountPercentage";
|
||||
String outStandingAmountPercentageConditionParamName = "outStandingAmountPercentageCondition";
|
||||
String minOutStandingAmountPercentageParamName = "minOutStandingAmountPercentage";
|
||||
String maxOutStandingAmountPercentageParamName = "maxOutStandingAmountPercentage";
|
||||
String outStandingAmountPercentageParamName = "outStandingAmountPercentage";
|
||||
String includeOutstandingAmountParamName = "includeOutstandingAmount";
|
||||
String outstandingAmountConditionParamName = "outstandingAmountCondition";
|
||||
String minOutstandingAmountParamName = "minOutstandingAmount";
|
||||
String maxOutstandingAmountParamName = "maxOutstandingAmount";
|
||||
String outstandingAmountParamName = "outstandingAmount";
|
||||
|
||||
String approvalDateOption = "approvalDate";
|
||||
String createDateOption = "createdDate";
|
||||
String disbursalDateOption = "disbursalDate";
|
||||
|
||||
String allLoanStatusOption = "all";
|
||||
String activeLoanStatusOption = "active";
|
||||
String overpaidLoanStatusOption = "overpaid";
|
||||
String arrearsLoanStatusOption = "arrears";
|
||||
String closedLoanStatusOption = "closed";
|
||||
String writeoffLoanStatusOption = "writeoff";
|
||||
|
||||
List<Object> entityTypeOptions = List.copyOf(Arrays.asList("clients", "groups", "loans", "clientIdentifiers"));
|
||||
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Immutable data object representing datatable data.
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public final class AdvancedQueryData implements Serializable {
|
||||
|
||||
private List<ColumnFilterData> columnFilters;
|
||||
|
||||
private List<String> resultColumns;
|
||||
|
||||
public List<ColumnFilterData> getNonNullFilters() {
|
||||
return columnFilters == null ? new ArrayList<>() : columnFilters;
|
||||
}
|
||||
|
||||
public boolean hasFilter() {
|
||||
return columnFilters != null && !columnFilters.isEmpty();
|
||||
}
|
||||
|
||||
public List<String> getNonNullResultColumns() {
|
||||
return resultColumns == null ? new ArrayList<>() : resultColumns;
|
||||
}
|
||||
|
||||
public boolean hasResultColumn() {
|
||||
return resultColumns != null && !resultColumns.isEmpty();
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Immutable data object representing datatable data.
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public final class AdvancedQueryRequest implements Serializable {
|
||||
|
||||
private AdvancedQueryData baseQuery;
|
||||
|
||||
private List<TableQueryData> datatableQueries;
|
||||
|
||||
public boolean hasFilter() {
|
||||
return (baseQuery != null && baseQuery.hasFilter())
|
||||
|| (datatableQueries != null && datatableQueries.stream().anyMatch(TableQueryData::hasFilter));
|
||||
}
|
||||
|
||||
public boolean hasResultColumn() {
|
||||
return (baseQuery != null && baseQuery.hasResultColumn())
|
||||
|| (datatableQueries != null && datatableQueries.stream().anyMatch(TableQueryData::hasResultColumn));
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.service.database.SqlOperator;
|
||||
|
||||
/**
|
||||
* Immutable data object representing datatable data.
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public final class ColumnFilterData implements Serializable {
|
||||
|
||||
private String column;
|
||||
|
||||
private List<FilterData> filters;
|
||||
|
||||
public static ColumnFilterData eq(String column, String value) {
|
||||
return new ColumnFilterData(column, List.of(FilterData.eq(value)));
|
||||
}
|
||||
|
||||
public static ColumnFilterData btw(String column, String value1, String value2) {
|
||||
return new ColumnFilterData(column, List.of(FilterData.btw(value1, value2)));
|
||||
}
|
||||
|
||||
public static ColumnFilterData create(String column, SqlOperator op, String... values) {
|
||||
return new ColumnFilterData(column, List.of(FilterData.create(op, values)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import static org.apache.fineract.infrastructure.core.service.database.SqlOperator.BTW;
|
||||
import static org.apache.fineract.infrastructure.core.service.database.SqlOperator.EQ;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.service.database.SqlOperator;
|
||||
|
||||
/**
|
||||
* Immutable data object representing datatable data.
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public final class FilterData implements Serializable {
|
||||
|
||||
private SqlOperator operator;
|
||||
|
||||
private List<String> values;
|
||||
|
||||
static FilterData eq(String value) {
|
||||
return new FilterData(EQ, List.of(value));
|
||||
}
|
||||
|
||||
static FilterData btw(String value1, String value2) {
|
||||
return new FilterData(BTW, List.of(value1, value2));
|
||||
}
|
||||
|
||||
static FilterData create(SqlOperator op, String... values) {
|
||||
return new FilterData(op, List.of(values));
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import org.apache.fineract.portfolio.search.SearchConstants.SearchSupportedResources;
|
||||
|
||||
public class SearchConditions {
|
||||
|
||||
private final String searchQuery;
|
||||
private final String searchResource;
|
||||
private final Boolean clientSearch;
|
||||
private final Boolean groupSearch;
|
||||
private final Boolean loanSeach;
|
||||
private final Boolean savingSeach;
|
||||
private final Boolean shareSeach;
|
||||
private final Boolean clientIdentifierSearch;
|
||||
private Boolean exactMatch;
|
||||
|
||||
public SearchConditions(final String searchQueryParam, final String searchResource, Boolean exactMatch) {
|
||||
this.searchQuery = searchQueryParam;
|
||||
this.searchResource = searchResource;
|
||||
this.exactMatch = exactMatch;
|
||||
this.clientSearch = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTS.name().toLowerCase());
|
||||
this.groupSearch = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.GROUPS.name().toLowerCase());
|
||||
this.loanSeach = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.LOANS.name().toLowerCase());
|
||||
this.savingSeach = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.SAVINGS.name().toLowerCase());
|
||||
this.shareSeach = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.SHARES.name().toLowerCase());
|
||||
this.clientIdentifierSearch = null == searchResource
|
||||
|| searchResource.toLowerCase().contains(SearchSupportedResources.CLIENTIDENTIFIERS.name().toLowerCase());
|
||||
}
|
||||
|
||||
public SearchConditions(final String searchQueryParam, final String searchResource, final Boolean clientSearch,
|
||||
final Boolean groupSearch, final Boolean loanSeach, final Boolean savingSeach, final Boolean shareSeach,
|
||||
final Boolean clientIdentifierSearch, Boolean exactMatch) {
|
||||
this.searchQuery = searchQueryParam;
|
||||
this.searchResource = searchResource;
|
||||
this.clientSearch = clientSearch;
|
||||
this.groupSearch = groupSearch;
|
||||
this.loanSeach = loanSeach;
|
||||
this.savingSeach = savingSeach;
|
||||
this.shareSeach = shareSeach;
|
||||
this.clientIdentifierSearch = clientIdentifierSearch;
|
||||
this.exactMatch = exactMatch;
|
||||
}
|
||||
|
||||
public String getSearchQuery() {
|
||||
return this.searchQuery;
|
||||
}
|
||||
|
||||
public String getSearchResource() {
|
||||
return this.searchResource;
|
||||
}
|
||||
|
||||
public Boolean getExactMatch() {
|
||||
return this.exactMatch;
|
||||
}
|
||||
|
||||
public Boolean isClientSearch() {
|
||||
return this.clientSearch;
|
||||
}
|
||||
|
||||
public Boolean isGroupSearch() {
|
||||
return this.groupSearch;
|
||||
}
|
||||
|
||||
public Boolean isLoanSeach() {
|
||||
return this.loanSeach;
|
||||
}
|
||||
|
||||
public Boolean isSavingSeach() {
|
||||
return this.savingSeach;
|
||||
}
|
||||
|
||||
public Boolean isShareSeach() {
|
||||
return this.shareSeach;
|
||||
}
|
||||
|
||||
public Boolean isClientIdentifierSearch() {
|
||||
return this.clientIdentifierSearch;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public class SearchData {
|
||||
|
||||
private final Long entityId;
|
||||
private final String entityAccountNo;
|
||||
private final String entityExternalId;
|
||||
private final String entityName;
|
||||
private final String entityType;
|
||||
private final Long parentId;
|
||||
private final String parentName;
|
||||
private final String entityMobileNo;
|
||||
private final EnumOptionData entityStatus;
|
||||
private final String parentType;
|
||||
private final String subEntityType;
|
||||
|
||||
public SearchData(final Long entityId, final String entityAccountNo, final String entityExternalId, final String entityName,
|
||||
final String entityType, final Long parentId, final String parentName, final String parentType, final String entityMobileNo,
|
||||
final EnumOptionData entityStatus, final String subEntityType) {
|
||||
|
||||
this.entityId = entityId;
|
||||
this.entityAccountNo = entityAccountNo;
|
||||
this.entityExternalId = entityExternalId;
|
||||
this.entityName = entityName;
|
||||
this.entityType = entityType;
|
||||
this.parentId = parentId;
|
||||
this.parentName = parentName;
|
||||
this.parentType = parentType;
|
||||
this.entityMobileNo = entityMobileNo;
|
||||
this.entityStatus = entityStatus;
|
||||
this.subEntityType = subEntityType;
|
||||
}
|
||||
|
||||
public Long getEntityId() {
|
||||
return this.entityId;
|
||||
}
|
||||
|
||||
public String getEntityAccountNo() {
|
||||
return this.entityAccountNo;
|
||||
}
|
||||
|
||||
public String getEntityExternalId() {
|
||||
return this.entityExternalId;
|
||||
}
|
||||
|
||||
public String getEntityName() {
|
||||
return this.entityName;
|
||||
}
|
||||
|
||||
public String getEntityType() {
|
||||
return this.entityType;
|
||||
}
|
||||
|
||||
public Long getParentId() {
|
||||
return this.parentId;
|
||||
}
|
||||
|
||||
public String getParentName() {
|
||||
return this.parentName;
|
||||
}
|
||||
|
||||
public String getParentType() {
|
||||
return this.parentType;
|
||||
}
|
||||
|
||||
public String getEntityMobileNo() {
|
||||
return this.entityMobileNo;
|
||||
}
|
||||
|
||||
public EnumOptionData getEntityStatus() {
|
||||
return this.entityStatus;
|
||||
}
|
||||
|
||||
public String getSubEntityType() {
|
||||
return this.subEntityType;
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Immutable data object representing datatable data.
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public final class TableQueryData implements Serializable {
|
||||
|
||||
private String table;
|
||||
|
||||
private AdvancedQueryData query;
|
||||
|
||||
public boolean hasFilter() {
|
||||
return query != null && query.hasFilter();
|
||||
}
|
||||
|
||||
public boolean hasResultColumn() {
|
||||
return query != null && query.hasResultColumn();
|
||||
}
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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.search.data;
|
||||
|
||||
import static org.apache.fineract.portfolio.search.service.SearchUtil.DEFAULT_PAGE_SIZE;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Locale;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.MathUtil;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
@Getter
|
||||
public class TransactionSearchRequest {
|
||||
|
||||
private Long accountId;
|
||||
private LocalDate fromDate;
|
||||
private LocalDate toDate;
|
||||
private LocalDate fromSubmittedDate;
|
||||
private LocalDate toSubmittedDate;
|
||||
private BigDecimal fromAmount;
|
||||
private BigDecimal toAmount;
|
||||
private String[] types;
|
||||
private Boolean credit;
|
||||
private Boolean debit;
|
||||
|
||||
private PageRequest pageable;
|
||||
|
||||
public TransactionSearchRequest accountId(Long accountId) {
|
||||
this.accountId = accountId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest fromDate(String fromDate, String dateFormat, Locale locale) {
|
||||
this.fromDate = fromDate == null ? null : DateUtils.parseLocalDate(fromDate, dateFormat, locale);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest toDate(String toDate, String dateFormat, Locale locale) {
|
||||
this.toDate = toDate == null ? null : DateUtils.parseLocalDate(toDate, dateFormat, locale);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest fromSubmittedDate(String fromSubmittedDate, String dateFormat, Locale locale) {
|
||||
this.fromSubmittedDate = fromSubmittedDate == null ? null : DateUtils.parseLocalDate(fromSubmittedDate, dateFormat, locale);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest toSubmittedDate(String toSubmittedDate, String dateFormat, Locale locale) {
|
||||
this.toSubmittedDate = toSubmittedDate == null ? null : DateUtils.parseLocalDate(toSubmittedDate, dateFormat, locale);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest fromAmount(BigDecimal fromAmount) {
|
||||
this.fromAmount = fromAmount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest toAmount(BigDecimal toAmount) {
|
||||
this.toAmount = toAmount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest types(String types) {
|
||||
this.types = types == null ? null : types.split(",");
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest credit(Boolean credit) {
|
||||
this.credit = credit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest debit(Boolean debit) {
|
||||
this.debit = debit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionSearchRequest pageable(Integer offset, Integer limit, String orderByProps, Sort.Direction direction) {
|
||||
offset = MathUtil.nullToDefault(offset, 0);
|
||||
limit = MathUtil.nullToDefault(limit, DEFAULT_PAGE_SIZE);
|
||||
String[] properties = Strings.isEmpty(orderByProps) ? null : orderByProps.split(",");
|
||||
this.pageable = properties == null ? PageRequest.of(offset, limit) : PageRequest.of(offset, limit, direction, properties);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+321
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* 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.search.service;
|
||||
|
||||
import static java.util.Locale.ENGLISH;
|
||||
import static org.apache.fineract.infrastructure.core.data.ApiParameterError.parameterErrorWithValue;
|
||||
import static org.apache.fineract.infrastructure.core.service.DateUtils.DEFAULT_DATETIME_FORMAT;
|
||||
import static org.apache.fineract.infrastructure.core.service.DateUtils.DEFAULT_DATE_FORMAT;
|
||||
import static org.apache.fineract.infrastructure.dataqueries.api.DataTableApiConstant.API_FIELD_MANDATORY;
|
||||
import static org.apache.fineract.portfolio.search.SearchConstants.API_PARAM_COLUMN;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Date;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.JsonParserHelper;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
|
||||
import org.apache.fineract.infrastructure.core.service.database.JdbcJavaType;
|
||||
import org.apache.fineract.infrastructure.core.service.database.SqlOperator;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.ResultsetColumnHeaderData;
|
||||
import org.apache.fineract.infrastructure.security.utils.SQLInjectionValidator;
|
||||
import org.apache.fineract.portfolio.search.data.ColumnFilterData;
|
||||
import org.apache.fineract.portfolio.search.data.FilterData;
|
||||
import org.springframework.jdbc.support.rowset.SqlRowSet;
|
||||
|
||||
public final class SearchUtil {
|
||||
|
||||
public static final int DEFAULT_PAGE_SIZE = 50;
|
||||
|
||||
private static final JsonParserHelper helper = new JsonParserHelper();
|
||||
|
||||
private SearchUtil() {}
|
||||
|
||||
@NotNull
|
||||
public static Map<String, ResultsetColumnHeaderData> mapHeadersToName(@NotNull Collection<ResultsetColumnHeaderData> columnHeaders) {
|
||||
return columnHeaders.stream().collect(Collectors.toMap(ResultsetColumnHeaderData::getColumnName, e -> e));
|
||||
}
|
||||
|
||||
public static ResultsetColumnHeaderData findFiltered(@NotNull Collection<ResultsetColumnHeaderData> columnHeaders,
|
||||
@NotNull Predicate<ResultsetColumnHeaderData> filter) {
|
||||
return columnHeaders.stream().filter(filter).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static ResultsetColumnHeaderData getFiltered(@NotNull Collection<ResultsetColumnHeaderData> columnHeaders,
|
||||
@NotNull Predicate<ResultsetColumnHeaderData> filter) {
|
||||
ResultsetColumnHeaderData filtered = findFiltered(columnHeaders, filter);
|
||||
if (filtered == null) {
|
||||
throw new PlatformDataIntegrityException("error.msg.column.not.exists", "Column filtered does not exist");
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public static void extractJsonResult(@NotNull SqlRowSet rowSet, @NotNull List<String> selectColumns,
|
||||
@NotNull List<String> resultColumns, @NotNull List<JsonObject> results) {
|
||||
JsonObject json = new JsonObject();
|
||||
for (int i = 0; i < selectColumns.size(); i++) {
|
||||
Object rowValue = rowSet.getObject(selectColumns.get(i));
|
||||
if (rowValue != null) {
|
||||
String rCol = resultColumns.get(i);
|
||||
if (rowValue instanceof Character) {
|
||||
json.addProperty(rCol, (Character) rowValue);
|
||||
} else if (rowValue instanceof Number) {
|
||||
json.addProperty(rCol, new BigDecimal(rowValue.toString()));
|
||||
} else if (rowValue instanceof Boolean) {
|
||||
json.addProperty(rCol, (Boolean) rowValue);
|
||||
} else if (rowValue instanceof LocalDateTime) {
|
||||
json.addProperty(rCol, DateUtils.format((LocalDateTime) rowValue));
|
||||
} else if (rowValue instanceof Timestamp) {
|
||||
json.addProperty(rCol, DateUtils.format(((Timestamp) rowValue).toLocalDateTime()));
|
||||
} else if (rowValue instanceof LocalDate) {
|
||||
json.addProperty(rCol, DateUtils.format((LocalDate) rowValue));
|
||||
} else if (rowValue instanceof Date) {
|
||||
json.addProperty(rCol, DateUtils.format(((Date) rowValue).toLocalDate()));
|
||||
} else {
|
||||
json.addProperty(rCol, rowValue.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (json.size() > 0) {
|
||||
results.add(json);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<String> validateToJdbcColumnNames(List<String> columns, Map<String, ResultsetColumnHeaderData> headersByName,
|
||||
boolean allowEmpty) {
|
||||
List<ResultsetColumnHeaderData> columnHeaders = validateToJdbcColumns(columns, headersByName, allowEmpty);
|
||||
return columnHeaders.stream().map(e -> e == null ? null : e.getColumnName()).toList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<ResultsetColumnHeaderData> validateToJdbcColumns(List<String> columns,
|
||||
Map<String, ResultsetColumnHeaderData> headersByName, boolean allowEmpty) {
|
||||
final List<ApiParameterError> errors = new ArrayList<>();
|
||||
|
||||
List<ResultsetColumnHeaderData> result = new ArrayList<>();
|
||||
if (columns == null || columns.isEmpty()) {
|
||||
if (!allowEmpty) {
|
||||
errors.add(parameterErrorWithValue("error.msg.columns.empty", "Columns list is empty", API_PARAM_COLUMN, null));
|
||||
}
|
||||
} else {
|
||||
columns.forEach(rcn -> result.add(validateToJdbcColumnImpl(rcn, headersByName, errors, allowEmpty)));
|
||||
}
|
||||
if (!errors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(errors);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String validateToJdbcColumnName(String column, Map<String, ResultsetColumnHeaderData> headersByName, boolean allowEmpty) {
|
||||
ResultsetColumnHeaderData columnHeader = validateToJdbcColumn(column, headersByName, allowEmpty);
|
||||
return columnHeader == null ? null : columnHeader.getColumnName();
|
||||
}
|
||||
|
||||
public static ResultsetColumnHeaderData validateToJdbcColumn(String column,
|
||||
@NotNull Map<String, ResultsetColumnHeaderData> headersByName, boolean allowEmpty) {
|
||||
final List<ApiParameterError> errors = new ArrayList<>();
|
||||
ResultsetColumnHeaderData columnHeader = validateToJdbcColumnImpl(column, headersByName, errors, allowEmpty);
|
||||
if (!errors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(errors);
|
||||
}
|
||||
return columnHeader;
|
||||
}
|
||||
|
||||
private static ResultsetColumnHeaderData validateToJdbcColumnImpl(String column,
|
||||
@NotNull Map<String, ResultsetColumnHeaderData> headersByName, @NotNull List<ApiParameterError> errors, boolean allowEmpty) {
|
||||
if (!allowEmpty && column == null) {
|
||||
errors.add(parameterErrorWithValue("error.msg.column.empty", "Column filter is empty", API_PARAM_COLUMN, null));
|
||||
}
|
||||
if (column == null) {
|
||||
return null;
|
||||
}
|
||||
Collection<ResultsetColumnHeaderData> columnHeaders = headersByName.values();
|
||||
ResultsetColumnHeaderData columnHeader;
|
||||
if ((columnHeader = findFiltered(columnHeaders, e -> e.isNamed(column))) == null
|
||||
&& (columnHeader = findFiltered(columnHeaders, e -> e.isNamed(column.replaceAll(" ", "_")))) == null
|
||||
&& (columnHeader = findFiltered(columnHeaders, e -> e.isNamed(camelToSnake(column.replaceAll(" ", ""))))) == null) {
|
||||
errors.add(parameterErrorWithValue("error.msg.invalid.column", "Column not exist in database", API_PARAM_COLUMN, column));
|
||||
}
|
||||
return columnHeader;
|
||||
}
|
||||
|
||||
public static boolean buildQueryCondition(List<ColumnFilterData> columnFilters, @NotNull StringBuilder where,
|
||||
@NotNull List<Object> params, String alias, Map<String, ResultsetColumnHeaderData> headersByName, String dateFormat,
|
||||
String dateTimeFormat, Locale locale, boolean embedded, @NotNull DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
if (columnFilters == null) {
|
||||
return false;
|
||||
}
|
||||
boolean added = false;
|
||||
int isize = columnFilters.size();
|
||||
for (int i = 0; i < isize; i++) {
|
||||
boolean addedFilter = buildFilterCondition(columnFilters.get(i), where, params, alias, headersByName, dateFormat,
|
||||
dateTimeFormat, locale, embedded, sqlGenerator);
|
||||
if (addedFilter && i < isize - 1) {
|
||||
where.append(" AND ");
|
||||
}
|
||||
added |= addedFilter;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public static boolean buildFilterCondition(ColumnFilterData columnFilter, @NotNull StringBuilder where, @NotNull List<Object> params,
|
||||
String alias, Map<String, ResultsetColumnHeaderData> headersByName, String dateFormat, String dateTimeFormat, Locale locale,
|
||||
boolean embedded, @NotNull DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
String columnName = columnFilter.getColumn();
|
||||
List<FilterData> filters = columnFilter.getFilters();
|
||||
int size = filters.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (!embedded && where.isEmpty()) {
|
||||
where.append(" WHERE ");
|
||||
}
|
||||
ResultsetColumnHeaderData columnHeader = validateToJdbcColumn(columnName, headersByName, false);
|
||||
|
||||
FilterData filter = filters.get(i);
|
||||
SqlOperator operator = filter.getOperator();
|
||||
List<String> values = filter.getValues();
|
||||
List<Object> objectValues = values == null ? null
|
||||
: values.stream()
|
||||
.map(e -> parseJdbcColumnValue(columnHeader, e, dateFormat, dateTimeFormat, locale, false, sqlGenerator))
|
||||
.toList();
|
||||
|
||||
buildCondition(columnHeader.getColumnName(), columnHeader.getColumnType(), operator, objectValues, where, params, alias,
|
||||
sqlGenerator);
|
||||
if (i < size - 1) {
|
||||
where.append(" AND ");
|
||||
}
|
||||
}
|
||||
return size > 0;
|
||||
}
|
||||
|
||||
public static void buildCondition(@NotNull String definition, JdbcJavaType columnType, @NotNull SqlOperator operator,
|
||||
List<Object> values, @NotNull StringBuilder where, @NotNull List<Object> params, String alias,
|
||||
@NotNull DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
int paramCount = values == null ? 0 : values.size();
|
||||
where.append(operator.formatPlaceholder(sqlGenerator, definition, paramCount, alias));
|
||||
if (values != null) {
|
||||
params.addAll(values);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object parseJdbcColumnValue(@NotNull ResultsetColumnHeaderData columnHeader, String columnValue, String dateFormat,
|
||||
String dateTimeFormat, Locale locale, boolean strict, @NotNull DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
return columnHeader.getColumnType().toJdbcValue(sqlGenerator.getDialect(),
|
||||
parseColumnValue(columnHeader, columnValue, dateFormat, dateTimeFormat, locale, strict, sqlGenerator), false);
|
||||
}
|
||||
|
||||
public static Object parseColumnValue(@NotNull ResultsetColumnHeaderData columnHeader, String columnValue, String dateFormat,
|
||||
String dateTimeFormat, Locale locale, boolean strict, @NotNull DatabaseSpecificSQLGenerator sqlGenerator) {
|
||||
JdbcJavaType colType = columnHeader.getColumnType();
|
||||
if (!colType.isStringType() || !columnHeader.isMandatory()) {
|
||||
columnValue = StringUtils.trimToNull(columnValue);
|
||||
}
|
||||
String errorCode = "validation.msg.validation.errors.exist";
|
||||
String errorMsg = "Validation errors exist.";
|
||||
if (columnValue == null && columnHeader.isMandatory()) {
|
||||
ApiParameterError error = ApiParameterError.parameterError("error.msg.column.mandatory", API_FIELD_MANDATORY,
|
||||
columnHeader.getColumnName());
|
||||
throw new PlatformApiDataValidationException(errorCode, errorMsg, List.of(error));
|
||||
}
|
||||
if (StringUtils.isEmpty(columnValue)) {
|
||||
return columnValue;
|
||||
}
|
||||
if (strict) {
|
||||
SQLInjectionValidator.validateDynamicQuery(columnValue);
|
||||
}
|
||||
|
||||
if (columnHeader.hasColumnValues()) {
|
||||
if (columnHeader.isCodeValueDisplayType()) {
|
||||
if (!columnHeader.isColumnValueAllowed(columnValue)) {
|
||||
ApiParameterError error = ApiParameterError.parameterError("error.msg.invalid.columnValue",
|
||||
"Value not found in Allowed Value list", columnHeader.getColumnName(), columnValue);
|
||||
throw new PlatformApiDataValidationException(errorCode, errorMsg, List.of(error));
|
||||
}
|
||||
return columnValue;
|
||||
} else if (columnHeader.isCodeLookupDisplayType()) {
|
||||
final Integer codeLookup = Integer.valueOf(columnValue);
|
||||
if (!columnHeader.isColumnCodeAllowed(codeLookup)) {
|
||||
ApiParameterError error = ApiParameterError.parameterError("error.msg.invalid.columnValue",
|
||||
"Value not found in Allowed Value list", columnHeader.getColumnName(), columnValue);
|
||||
throw new PlatformApiDataValidationException(errorCode, errorMsg, List.of(error));
|
||||
}
|
||||
return codeLookup;
|
||||
} else {
|
||||
throw new PlatformDataIntegrityException("error.msg.invalid.columnType.", "Code: " + columnHeader.getColumnName()
|
||||
+ " - Invalid Type " + colType.getJdbcName(sqlGenerator.getDialect()) + " (neither varchar nor int)");
|
||||
}
|
||||
}
|
||||
locale = locale == null ? ENGLISH : locale;
|
||||
if (colType.isDateType()) {
|
||||
String format = dateFormat == null ? DEFAULT_DATE_FORMAT : dateFormat;
|
||||
return JsonParserHelper.convertFrom(columnValue, columnHeader.getColumnName(), format, locale);
|
||||
}
|
||||
if (colType.isDateTimeType()) {
|
||||
String format = dateTimeFormat == null ? DEFAULT_DATETIME_FORMAT : dateTimeFormat;
|
||||
return JsonParserHelper.convertDateTimeFrom(columnValue, columnHeader.getColumnName(), format, locale);
|
||||
}
|
||||
if (colType.isAnyIntegerType()) {
|
||||
return helper.convertToInteger(columnValue, columnHeader.getColumnName(), locale);
|
||||
}
|
||||
if (colType.isDecimalType()) {
|
||||
return helper.convertFrom(columnValue, columnHeader.getColumnName(), locale);
|
||||
}
|
||||
if (colType.isBooleanType()) {
|
||||
final Boolean boolValue = BooleanUtils.toBooleanObject(columnValue);
|
||||
if (boolValue == null) {
|
||||
ApiParameterError error = ApiParameterError.parameterError("validation.msg.invalid.boolean.format",
|
||||
"The parameter " + columnHeader.getColumnName() + " has value: " + columnValue + " which is invalid boolean value.",
|
||||
columnHeader.getColumnName(), columnValue);
|
||||
throw new PlatformApiDataValidationException(errorCode, errorMsg, List.of(error));
|
||||
}
|
||||
return boolValue;
|
||||
}
|
||||
if (colType.isStringType()) {
|
||||
if (columnHeader.getColumnLength() > 0 && columnValue.length() > columnHeader.getColumnLength()) {
|
||||
ApiParameterError error = ApiParameterError.parameterError("validation.msg.datatable.entry.column.exceeds.maxlength",
|
||||
"The column `" + columnHeader.getColumnName() + "` exceeds its defined max-length ", columnHeader.getColumnName(),
|
||||
columnValue);
|
||||
throw new PlatformApiDataValidationException(errorCode, errorMsg, List.of(error));
|
||||
}
|
||||
}
|
||||
return columnValue;
|
||||
}
|
||||
|
||||
public static String camelToSnake(final String camelStr) {
|
||||
return camelStr == null ? null
|
||||
: camelStr.replaceAll("([A-Z]+)([A-Z][a-z])", "$1_$2").replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.tax.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface TaxComponentRepository extends JpaRepository<TaxComponent, Long>, JpaSpecificationExecutor<TaxComponent> {
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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.tax.domain;
|
||||
|
||||
import org.apache.fineract.portfolio.tax.exception.TaxComponentNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class TaxComponentRepositoryWrapper {
|
||||
|
||||
private final TaxComponentRepository repository;
|
||||
|
||||
@Autowired
|
||||
public TaxComponentRepositoryWrapper(final TaxComponentRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public TaxComponent findOneWithNotFoundDetection(final Long id) {
|
||||
return this.repository.findById(id).orElseThrow(() -> new TaxComponentNotFoundException(id));
|
||||
}
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.tax.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface TaxGroupRepository extends JpaRepository<TaxGroup, Long>, JpaSpecificationExecutor<TaxGroup> {
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 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.tax.domain;
|
||||
|
||||
import org.apache.fineract.portfolio.tax.exception.TaxGroupNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class TaxGroupRepositoryWrapper {
|
||||
|
||||
private final TaxGroupRepository repository;
|
||||
|
||||
@Autowired
|
||||
public TaxGroupRepositoryWrapper(final TaxGroupRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public TaxGroup findOneWithNotFoundDetection(final Long id) {
|
||||
return this.repository.findById(id).orElseThrow(() -> new TaxGroupNotFoundException(id));
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.tax.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class TaxComponentNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public TaxComponentNotFoundException(final Long id) {
|
||||
super("error.msg.tax.component.id.invalid", "tax component with identifier " + id + " does not exist", id);
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.tax.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
|
||||
public class TaxGroupNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public TaxGroupNotFoundException(final Long id) {
|
||||
super("error.msg.tax.group.id.invalid", "tax group with identifier " + id + " does not exist", id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* 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.tax.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxComponentData;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupMappingsData;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxComponent;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroupMappings;
|
||||
|
||||
public final class TaxUtils {
|
||||
|
||||
private TaxUtils() {
|
||||
|
||||
}
|
||||
|
||||
public static Map<TaxComponent, BigDecimal> splitTax(final BigDecimal amount, final LocalDate date,
|
||||
final Set<TaxGroupMappings> taxGroupMappings, final int scale) {
|
||||
Map<TaxComponent, BigDecimal> map = new HashMap<>(3);
|
||||
if (amount != null) {
|
||||
final double amountVal = amount.doubleValue();
|
||||
double cent_percentage = Double.parseDouble("100.0");
|
||||
for (TaxGroupMappings groupMappings : taxGroupMappings) {
|
||||
if (groupMappings.occursOnDayFromAndUpToAndIncluding(date)) {
|
||||
TaxComponent component = groupMappings.getTaxComponent();
|
||||
BigDecimal percentage = component.getApplicablePercentage(date);
|
||||
if (percentage != null) {
|
||||
double percentageVal = percentage.doubleValue();
|
||||
double tax = amountVal * percentageVal / cent_percentage;
|
||||
map.put(component, BigDecimal.valueOf(tax).setScale(scale, MoneyHelper.getRoundingMode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static Map<TaxComponentData, BigDecimal> splitTaxData(final BigDecimal amount, final LocalDate date,
|
||||
final Set<TaxGroupMappingsData> taxGroupMappings, final int scale) {
|
||||
Map<TaxComponentData, BigDecimal> map = new HashMap<>(3);
|
||||
if (amount != null) {
|
||||
final double amountVal = amount.doubleValue();
|
||||
double cent_percentage = Double.parseDouble("100.0");
|
||||
for (TaxGroupMappingsData groupMappings : taxGroupMappings) {
|
||||
if (groupMappings.occursOnDayFromAndUpToAndIncluding(date)) {
|
||||
TaxComponentData component = groupMappings.getTaxComponent();
|
||||
BigDecimal percentage = component.getApplicablePercentage(date);
|
||||
if (percentage != null) {
|
||||
double percentageVal = percentage.doubleValue();
|
||||
double tax = amountVal * percentageVal / cent_percentage;
|
||||
map.put(component, BigDecimal.valueOf(tax).setScale(scale, MoneyHelper.getRoundingMode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static BigDecimal incomeAmount(final BigDecimal amount, final LocalDate date, final Set<TaxGroupMappings> taxGroupMappings,
|
||||
final int scale) {
|
||||
Map<TaxComponent, BigDecimal> map = splitTax(amount, date, taxGroupMappings, scale);
|
||||
return incomeAmount(amount, map);
|
||||
}
|
||||
|
||||
public static BigDecimal incomeAmount(final BigDecimal amount, final Map<TaxComponent, BigDecimal> map) {
|
||||
BigDecimal totalTax = totalTaxAmount(map);
|
||||
return amount.subtract(totalTax);
|
||||
}
|
||||
|
||||
public static BigDecimal totalTaxAmount(final Map<TaxComponent, BigDecimal> map) {
|
||||
BigDecimal totalTax = BigDecimal.ZERO;
|
||||
for (BigDecimal tax : map.values()) {
|
||||
totalTax = totalTax.add(tax);
|
||||
}
|
||||
return totalTax;
|
||||
}
|
||||
|
||||
public static BigDecimal totalTaxDataAmount(final Map<TaxComponentData, BigDecimal> map) {
|
||||
BigDecimal totalTax = BigDecimal.ZERO;
|
||||
for (BigDecimal tax : map.values()) {
|
||||
totalTax = totalTax.add(tax);
|
||||
}
|
||||
return totalTax;
|
||||
}
|
||||
|
||||
public static BigDecimal addTax(final BigDecimal amount, final LocalDate date, final List<TaxGroupMappings> taxGroupMappings,
|
||||
final int scale) {
|
||||
BigDecimal totalAmount = null;
|
||||
if (amount != null && amount.compareTo(BigDecimal.ZERO) > 0) {
|
||||
double percentageVal = 0;
|
||||
double amountVal = amount.doubleValue();
|
||||
double cent_percentage = Double.parseDouble("100.0");
|
||||
for (TaxGroupMappings groupMappings : taxGroupMappings) {
|
||||
if (groupMappings.occursOnDayFromAndUpToAndIncluding(date)) {
|
||||
TaxComponent component = groupMappings.getTaxComponent();
|
||||
BigDecimal percentage = component.getApplicablePercentage(date);
|
||||
if (percentage != null) {
|
||||
percentageVal = percentageVal + percentage.doubleValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
double total = amountVal * cent_percentage / (cent_percentage - percentageVal);
|
||||
totalAmount = BigDecimal.valueOf(total).setScale(scale, MoneyHelper.getRoundingMode());
|
||||
}
|
||||
return totalAmount;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user