update current product code and RD code
This commit is contained in:
@@ -0,0 +1 @@
|
||||
{"sessionId":"0fda6e48-a79d-4980-a9ee-31a6d5f735e1","pid":15548,"acquiredAt":1776168814856}
|
||||
@@ -49,7 +49,7 @@
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 \"%CLAUDE_PROJECT_DIR%/.claude/hooks/post-tool-call.py\""
|
||||
"command": "python3 \"$CLAUDE_PROJECT_DIR/.claude/hooks/post-tool-call.py\""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ buildscript {
|
||||
'fineract-loan-origination',
|
||||
'fineract-loan',
|
||||
'fineract-savings',
|
||||
'fineract-current-product',
|
||||
'fineract-report',
|
||||
'fineract-mix',
|
||||
'integration-tests',
|
||||
|
||||
+8
@@ -115,6 +115,14 @@ public interface ChargeReadPlatformService {
|
||||
/** Retrieve savings account charges **/
|
||||
List<ChargeData> retrieveSavingsAccountApplicableCharges(Long savingsId);
|
||||
|
||||
/**
|
||||
* Returns all charges applicable for a given current product
|
||||
*
|
||||
* @param currentProductId
|
||||
* @return
|
||||
*/
|
||||
List<ChargeData> retrieveCurrentProductCharges(Long currentProductId);
|
||||
|
||||
/**
|
||||
* Returns charge definitions which are applicable for shares
|
||||
*/
|
||||
|
||||
+12
@@ -28,6 +28,10 @@ public class SavingsApiConstants {
|
||||
public static final String YES_NO = "YesNo";
|
||||
public static final String SAVINGS_PRODUCT_ACCOUNT_TYPE = "SavingsProductAccountType";
|
||||
public static final String SAVINGS_PRODUCT_CUSTOMER_SEGMENT = "SavingsProductCustomerSegment";
|
||||
public static final String CURRENT_PRODUCT_ACCOUNT_TYPE = "CurrentProductAccountType";
|
||||
public static final String CURRENT_PRODUCT_CUSTOMER_SEGMENT = "CurrentProductCustomerSegment";
|
||||
public static final String RD_PRODUCT_ACCOUNT_TYPE = "RecurringDepositProductAccountType";
|
||||
public static final String RD_PRODUCT_CUSTOMER_SEGMENT = "RecurringDepositProductCustomerSegment";
|
||||
public static final String PERIOD_FREQUENCY = "PeriodFrequency";
|
||||
public static final String INTEREST_CALCULATION_TYPE_OPTION = "InterestCalculationTypeOption";
|
||||
|
||||
@@ -268,4 +272,12 @@ public class SavingsApiConstants {
|
||||
// Additional custom fields
|
||||
public static final String balanceFrequencyParamName = "balanceFrequency";
|
||||
public static final String accountClosedZeroBalanceInDayClosingParamName = "accountClosedZeroBalanceInDayClosing";
|
||||
|
||||
// Current Product — new UI fields
|
||||
public static final String balanceSwapOptionParamName = "balanceSwapOption";
|
||||
public static final String msmeParamName = "msme";
|
||||
public static final String autoDebitFacilityParamName = "autoDebitFacility";
|
||||
public static final String avgBalanceCalcPeriodParamName = "avgBalanceCalcPeriod";
|
||||
public static final String validForPeriodParamName = "validForPeriod";
|
||||
public static final String odAccountClosedZeroBalanceInDayClosingParamName = "odAccountClosedZeroBalanceInDayClosing";
|
||||
}
|
||||
|
||||
+16
@@ -142,10 +142,19 @@ public final class SavingsProductData implements Serializable {
|
||||
@Getter @Setter private String balanceFrequency;
|
||||
@Getter @Setter private Boolean accountClosedZeroBalanceInDayClosing;
|
||||
|
||||
// New current product fields
|
||||
@Getter @Setter private Boolean balanceSwapOption;
|
||||
@Getter @Setter private Boolean msme;
|
||||
@Getter @Setter private Boolean autoDebitFacility;
|
||||
@Getter @Setter private String avgBalanceCalcPeriod;
|
||||
@Getter @Setter private String validForPeriod;
|
||||
@Getter @Setter private Boolean odAccountClosedZeroBalanceInDayClosing;
|
||||
|
||||
// Complex objects wrapped as Maps/Lists so Jackson converts them into the exact JSON your UI expects
|
||||
@Getter @Setter private Map<String, Object> accountFacilityConfig;
|
||||
@Getter @Setter private Collection<Map<String, Object>> accountFacilityLimits;
|
||||
@Getter @Setter private Map<String, Object> depositLimitKyc;
|
||||
@Getter @Setter private Map<String, List<Map<String, Object>>> otherGlMappingsMap;
|
||||
|
||||
public static SavingsProductData template(final CurrencyData currency, final EnumOptionData interestCompoundingPeriodType,
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
@@ -358,6 +367,13 @@ public final class SavingsProductData implements Serializable {
|
||||
target.setEnableLockinPeriod(source.getEnableLockinPeriod());
|
||||
target.setBalanceFrequency(source.getBalanceFrequency());
|
||||
target.setAccountClosedZeroBalanceInDayClosing(source.getAccountClosedZeroBalanceInDayClosing());
|
||||
target.setBalanceSwapOption(source.getBalanceSwapOption());
|
||||
target.setMsme(source.getMsme());
|
||||
target.setAutoDebitFacility(source.getAutoDebitFacility());
|
||||
target.setAvgBalanceCalcPeriod(source.getAvgBalanceCalcPeriod());
|
||||
target.setValidForPeriod(source.getValidForPeriod());
|
||||
target.setOdAccountClosedZeroBalanceInDayClosing(source.getOdAccountClosedZeroBalanceInDayClosing());
|
||||
target.setOtherGlMappingsMap(source.getOtherGlMappingsMap());
|
||||
target.setAccountFacilityConfig(source.getAccountFacilityConfig());
|
||||
target.setAccountFacilityLimits(source.getAccountFacilityLimits());
|
||||
target.setDepositLimitKyc(source.getDepositLimitKyc());
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
description = 'Fineract Current Product'
|
||||
|
||||
compileJava {
|
||||
dependsOn ':fineract-avro-schemas:buildJavaSdk'
|
||||
}
|
||||
|
||||
configurations {
|
||||
providedRuntime // needed for Spring Boot executable WAR
|
||||
providedCompile
|
||||
compile() {
|
||||
exclude module: 'hibernate-entitymanager'
|
||||
exclude module: 'hibernate-validator'
|
||||
exclude module: 'activation'
|
||||
exclude module: 'bcmail-jdk14'
|
||||
exclude module: 'bcprov-jdk14'
|
||||
exclude module: 'bctsp-jdk14'
|
||||
exclude module: 'c3p0'
|
||||
exclude module: 'stax-api'
|
||||
exclude module: 'jaxb-api'
|
||||
exclude module: 'jaxb-impl'
|
||||
exclude module: 'jboss-logging'
|
||||
exclude module: 'itext-rtf'
|
||||
exclude module: 'classworlds'
|
||||
}
|
||||
runtime
|
||||
}
|
||||
|
||||
apply from: 'dependencies.gradle'
|
||||
|
||||
// If we are running Gradle within Eclipse to enhance classes with OpenJPA,
|
||||
// set the classes directory to point to Eclipse's default build directory
|
||||
if (project.hasProperty('env') && project.getProperty('env') == 'eclipse') {
|
||||
sourceSets.main.java.outputDir = new File(rootProject.projectDir, "fineract-current-product/bin/main")
|
||||
}
|
||||
|
||||
eclipse {
|
||||
project {
|
||||
buildCommand([ LaunchConfigHandle: "<project>/.externalToolBuilders/OpenJPA Enhance Builder.launch" ], 'org.eclipse.ui.externaltools.ExternalToolBuilder')
|
||||
}
|
||||
}
|
||||
|
||||
if (!(project.hasProperty('env') && project.getProperty('env') == 'dev')) {
|
||||
sourceSets {
|
||||
test {
|
||||
java {
|
||||
exclude '**/core/boot/tests/**'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
dependencies {
|
||||
// Never use "compile" scope, but make all dependencies either 'implementation', 'runtimeOnly' or 'testCompile'.
|
||||
|
||||
implementation(project(path: ':fineract-core'))
|
||||
implementation(project(path: ':fineract-accounting'))
|
||||
implementation(project(path: ':fineract-charge'))
|
||||
implementation(project(path: ':fineract-tax'))
|
||||
implementation(project(path: ':fineract-savings'))
|
||||
|
||||
implementation(
|
||||
'org.springframework.boot:spring-boot-starter-web',
|
||||
'org.springframework.boot:spring-boot-starter-security',
|
||||
'jakarta.ws.rs:jakarta.ws.rs-api',
|
||||
|
||||
'com.google.guava:guava',
|
||||
'com.google.code.gson:gson',
|
||||
|
||||
'org.apache.commons:commons-lang3',
|
||||
|
||||
'com.jayway.jsonpath:json-path',
|
||||
|
||||
'com.github.spotbugs:spotbugs-annotations',
|
||||
'io.swagger.core.v3:swagger-annotations-jakarta',
|
||||
|
||||
'org.mapstruct:mapstruct',
|
||||
)
|
||||
compileOnly 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.mapstruct:mapstruct-processor'
|
||||
implementation ('org.springframework.boot:spring-boot-starter-data-jpa') {
|
||||
exclude group: 'org.hibernate'
|
||||
}
|
||||
implementation('org.eclipse.persistence:org.eclipse.persistence.jpa') {
|
||||
exclude group: 'org.eclipse.persistence', module: 'jakarta.persistence'
|
||||
}
|
||||
testImplementation( 'io.github.classgraph:classgraph' )
|
||||
testImplementation ('org.springframework.boot:spring-boot-starter-test') {
|
||||
exclude group: 'com.jayway.jsonpath', module: 'json-path'
|
||||
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
|
||||
exclude group: 'jakarta.activation'
|
||||
exclude group: 'javax.activation'
|
||||
exclude group: 'org.skyscreamer'
|
||||
}
|
||||
testImplementation ('org.mockito:mockito-inline')
|
||||
}
|
||||
+460
@@ -0,0 +1,460 @@
|
||||
/**
|
||||
* 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.currentproduct.data;
|
||||
|
||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.CURRENT_PRODUCT_RESOURCE_NAME;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToDormancyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToEscheatParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToInactiveParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.feeAmountParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.feeOnMonthDayParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.inMultiplesOfParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.maxAllowedLienLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minOverdraftForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateOverdraftParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNameParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.MonthDay;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.accounting.common.AccountingConstants.SavingProductAccountingParams;
|
||||
import org.apache.fineract.accounting.common.AccountingValidations;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProduct;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsProductAccountingDataValidator;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CurrentProductDataValidator {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
private final SavingsProductAccountingDataValidator savingsProductAccountingDataValidator;
|
||||
|
||||
private static final Set<String> CURRENT_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(
|
||||
SavingsApiConstants.localeParamName, SavingsApiConstants.dateFormatParamName,
|
||||
SavingsApiConstants.monthDayFormatParamName, nameParamName, shortNameParamName,
|
||||
descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName, inMultiplesOfParamName,
|
||||
nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName,
|
||||
interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
|
||||
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||
SavingsApiConstants.withdrawalFeeAmountParamName, SavingsApiConstants.withdrawalFeeTypeParamName,
|
||||
withdrawalFeeForTransfersParamName, feeAmountParamName, feeOnMonthDayParamName,
|
||||
SavingsApiConstants.accountingRuleParamName, SavingsApiConstants.chargesParamName,
|
||||
SavingsApiConstants.otherGlMappingsParamName,
|
||||
SavingProductAccountingParams.INCOME_FROM_FEES.getValue(),
|
||||
SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue(),
|
||||
SavingProductAccountingParams.INTEREST_ON_SAVINGS.getValue(),
|
||||
SavingProductAccountingParams.PENALTIES_RECEIVABLE.getValue(),
|
||||
SavingProductAccountingParams.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(),
|
||||
SavingProductAccountingParams.SAVINGS_CONTROL.getValue(),
|
||||
SavingProductAccountingParams.TRANSFERS_SUSPENSE.getValue(),
|
||||
SavingProductAccountingParams.SAVINGS_REFERENCE.getValue(),
|
||||
SavingProductAccountingParams.FEE_INCOME_ACCOUNT_MAPPING.getValue(),
|
||||
SavingProductAccountingParams.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(),
|
||||
SavingProductAccountingParams.FEES_RECEIVABLE.getValue(),
|
||||
SavingProductAccountingParams.INTEREST_PAYABLE.getValue(),
|
||||
SavingProductAccountingParams.OVERDRAFT_PORTFOLIO_CONTROL.getValue(),
|
||||
SavingProductAccountingParams.LOSSES_WRITTEN_OFF.getValue(),
|
||||
SavingProductAccountingParams.INCOME_FROM_INTEREST.getValue(),
|
||||
SavingProductAccountingParams.ESCHEAT_LIABILITY.getValue(),
|
||||
SavingProductAccountingParams.INTEREST_RECEIVABLE.getValue(),
|
||||
isDormancyTrackingActiveParamName, daysToDormancyParamName, daysToInactiveParamName,
|
||||
daysToEscheatParamName, allowOverdraftParamName, overdraftLimitParamName,
|
||||
nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
|
||||
SavingsApiConstants.minRequiredBalanceParamName, SavingsApiConstants.enforceMinRequiredBalanceParamName,
|
||||
SavingsApiConstants.maxAllowedLienLimitParamName, SavingsApiConstants.lienAllowedParamName,
|
||||
minBalanceForInterestCalculationParamName, withHoldTaxParamName, taxGroupIdParamName,
|
||||
SavingsApiConstants.accountTypeParamName, SavingsApiConstants.customerSegmentParamName,
|
||||
SavingsApiConstants.productCodeParamName, SavingsApiConstants.effectiveDateParamName,
|
||||
SavingsApiConstants.effectiveToParamName, SavingsApiConstants.endDateParamName,
|
||||
SavingsApiConstants.introducerRequiredParamName, SavingsApiConstants.shareLinkingEnabledParamName,
|
||||
SavingsApiConstants.nominationFacilityParamName, SavingsApiConstants.dormancyAlertParamName,
|
||||
SavingsApiConstants.interestCalculateSelectorParamName, SavingsApiConstants.averagePeriodParamName,
|
||||
SavingsApiConstants.autoPostParamName, SavingsApiConstants.frequencyFixDayParamName,
|
||||
SavingsApiConstants.lastInterestDateParamName, SavingsApiConstants.enableLockinPeriodParamName,
|
||||
SavingsApiConstants.accountFacilityConfigParamName, SavingsApiConstants.accountFacilityLimitsParamName,
|
||||
SavingsApiConstants.depositLimitKycParamName,
|
||||
SavingsApiConstants.balanceFrequencyParamName, SavingsApiConstants.accountClosedZeroBalanceInDayClosingParamName,
|
||||
SavingsApiConstants.balanceSwapOptionParamName, SavingsApiConstants.msmeParamName,
|
||||
SavingsApiConstants.autoDebitFacilityParamName, SavingsApiConstants.avgBalanceCalcPeriodParamName,
|
||||
SavingsApiConstants.validForPeriodParamName, SavingsApiConstants.odAccountClosedZeroBalanceInDayClosingParamName));
|
||||
|
||||
public void validateForCreate(final String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, CURRENT_PRODUCT_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(CURRENT_PRODUCT_RESOURCE_NAME);
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(nameParamName, element);
|
||||
baseDataValidator.reset().parameter(nameParamName).value(name).notBlank().notExceedingLengthOf(100);
|
||||
|
||||
final String shortName = this.fromApiJsonHelper.extractStringNamed(shortNameParamName, element);
|
||||
baseDataValidator.reset().parameter(shortNameParamName).value(shortName).notBlank().notExceedingLengthOf(4);
|
||||
|
||||
final String currencyCode = this.fromApiJsonHelper.extractStringNamed(currencyCodeParamName, element);
|
||||
baseDataValidator.reset().parameter(currencyCodeParamName).value(currencyCode).notBlank();
|
||||
|
||||
final Integer digitsAfterDecimal = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(digitsAfterDecimalParamName, element);
|
||||
baseDataValidator.reset().parameter(digitsAfterDecimalParamName).value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(inMultiplesOfParamName, element)) {
|
||||
final Integer inMultiplesOf = this.fromApiJsonHelper.extractIntegerNamed(inMultiplesOfParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(inMultiplesOfParamName).value(inMultiplesOf).ignoreIfNull().integerZeroOrGreater();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(nominalAnnualInterestRateParamName, element)) {
|
||||
final BigDecimal nominalAnnualInterestRate = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
|
||||
baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(nominalAnnualInterestRate).zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(interestCompoundingPeriodTypeParamName, element)) {
|
||||
final Integer interestCompoundingPeriodType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCompoundingPeriodTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType)
|
||||
.isOneOfTheseValues(SavingsCompoundingInterestPeriodType.integerValues());
|
||||
}
|
||||
|
||||
final Integer interestPostingPeriodType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestPostingPeriodTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(interestPostingPeriodTypeParamName).value(interestPostingPeriodType).notNull()
|
||||
.isOneOfTheseValues(SavingsPostingInterestPeriodType.integerValues());
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(interestCalculationTypeParamName, element)) {
|
||||
final Integer interestCalculationType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(interestCalculationTypeParamName).value(interestCalculationType).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(interestCalculationDaysInYearTypeParamName, element)) {
|
||||
final Integer interestCalculationDaysInYearType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationDaysInYearTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(interestCalculationDaysInYearTypeParamName).value(interestCalculationDaysInYearType)
|
||||
.isOneOfTheseValues(SavingsInterestCalculationDaysInYearType.integerValues());
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(descriptionParamName, element)) {
|
||||
final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
|
||||
baseDataValidator.reset().parameter(descriptionParamName).value(description).ignoreIfNull().notExceedingLengthOf(500);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
|
||||
final BigDecimal minOpeningBalance = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minRequiredOpeningBalanceParamName, element);
|
||||
baseDataValidator.reset().parameter(minRequiredOpeningBalanceParamName).value(minOpeningBalance).zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
||||
final Integer lockinPeriodFrequency = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).integerZeroOrGreater();
|
||||
if (lockinPeriodFrequency != null) {
|
||||
final Integer lockinPeriodFrequencyType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(lockinPeriodFrequencyTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).notNull().inMinMaxRange(0, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyTypeParamName, element)) {
|
||||
final Integer lockinPeriodFrequencyType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(lockinPeriodFrequencyTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(0, 3);
|
||||
if (lockinPeriodFrequencyType != null) {
|
||||
final Integer lockinPeriodFrequency = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).notNull().integerZeroOrGreater();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) {
|
||||
final Boolean isWithdrawalFeeApplicableForTransfers = this.fromApiJsonHelper.extractBooleanNamed(withdrawalFeeForTransfersParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeForTransfersParamName).value(isWithdrawalFeeApplicableForTransfers).ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
// dormancy
|
||||
Boolean isDormancyActive = this.fromApiJsonHelper.extractBooleanNamed(isDormancyTrackingActiveParamName, element);
|
||||
if (isDormancyActive == null) {
|
||||
isDormancyActive = false;
|
||||
}
|
||||
if (isDormancyActive) {
|
||||
final Long daysToInact = this.fromApiJsonHelper.extractLongNamed(daysToInactiveParamName, element);
|
||||
baseDataValidator.reset().parameter(daysToInactiveParamName).value(daysToInact).notNull().longGreaterThanZero();
|
||||
final Long daysToDor = this.fromApiJsonHelper.extractLongNamed(daysToDormancyParamName, element);
|
||||
baseDataValidator.reset().parameter(daysToDormancyParamName).value(daysToDor).notNull().longGreaterThanZero();
|
||||
final Long daysToEsc = this.fromApiJsonHelper.extractLongNamed(daysToEscheatParamName, element);
|
||||
baseDataValidator.reset().parameter(daysToEscheatParamName).value(daysToEsc).notNull().longGreaterThanZero();
|
||||
if (null != daysToInact && null != daysToDor && null != daysToEsc) {
|
||||
baseDataValidator.reset().parameter(daysToDormancyParamName).value(daysToDor).longGreaterThanNumber(daysToInact);
|
||||
baseDataValidator.reset().parameter(daysToEscheatParamName).value(daysToEsc).longGreaterThanNumber(daysToDor);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(SavingsApiConstants.effectiveToParamName, element)
|
||||
&& this.fromApiJsonHelper.parameterExists(SavingsApiConstants.effectiveDateParamName, element)) {
|
||||
final java.time.LocalDate effectiveDate = this.fromApiJsonHelper.extractLocalDateNamed(SavingsApiConstants.effectiveDateParamName, element);
|
||||
final java.time.LocalDate effectiveTo = this.fromApiJsonHelper.extractLocalDateNamed(SavingsApiConstants.effectiveToParamName, element);
|
||||
if (effectiveDate != null && effectiveTo != null && effectiveTo.isBefore(effectiveDate)) {
|
||||
baseDataValidator.reset().parameter(SavingsApiConstants.effectiveToParamName).value(effectiveTo)
|
||||
.failWithCode("error.msg.effectiveto.cannot.be.before.effectivedate");
|
||||
}
|
||||
}
|
||||
|
||||
final Integer accountingRuleType = this.fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
||||
|
||||
if (AccountingValidations.isCashBasedAccounting(accountingRuleType)
|
||||
|| AccountingValidations.isAccrualPeriodicBasedAccounting(accountingRuleType)) {
|
||||
savingsProductAccountingDataValidator.evaluateProductAccountingData(accountingRuleType, isDormancyActive, element,
|
||||
baseDataValidator, DepositAccountType.SAVINGS_DEPOSIT, true);
|
||||
}
|
||||
|
||||
validateOverdraftParams(baseDataValidator, element);
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(minBalanceForInterestCalculationParamName, element)) {
|
||||
final BigDecimal minBalanceForInterestCalculation = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minBalanceForInterestCalculationParamName, element);
|
||||
baseDataValidator.reset().parameter(minBalanceForInterestCalculationParamName).value(minBalanceForInterestCalculation).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
validateTaxWithHoldingParams(baseDataValidator, element, true);
|
||||
validateLienParams(baseDataValidator, element);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateForUpdate(final String json, final CurrentProduct product) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, CURRENT_PRODUCT_REQUEST_DATA_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(CURRENT_PRODUCT_RESOURCE_NAME);
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(nameParamName, element)) {
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(nameParamName, element);
|
||||
baseDataValidator.reset().parameter(nameParamName).value(name).notBlank().notExceedingLengthOf(100);
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(shortNameParamName, element)) {
|
||||
final String shortName = this.fromApiJsonHelper.extractStringNamed(shortNameParamName, element);
|
||||
baseDataValidator.reset().parameter(shortNameParamName).value(shortName).notBlank().notExceedingLengthOf(4);
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(descriptionParamName, element)) {
|
||||
final String description = this.fromApiJsonHelper.extractStringNamed(descriptionParamName, element);
|
||||
baseDataValidator.reset().parameter(descriptionParamName).value(description).notBlank().notExceedingLengthOf(500);
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(currencyCodeParamName, element)) {
|
||||
final String currencyCode = this.fromApiJsonHelper.extractStringNamed(currencyCodeParamName, element);
|
||||
baseDataValidator.reset().parameter(currencyCodeParamName).value(currencyCode).notBlank();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(digitsAfterDecimalParamName, element)) {
|
||||
final Integer digitsAfterDecimal = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(digitsAfterDecimalParamName, element);
|
||||
baseDataValidator.reset().parameter(digitsAfterDecimalParamName).value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(inMultiplesOfParamName, element)) {
|
||||
final Integer inMultiplesOf = this.fromApiJsonHelper.extractIntegerNamed(inMultiplesOfParamName, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(inMultiplesOfParamName).value(inMultiplesOf).ignoreIfNull().integerZeroOrGreater();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(nominalAnnualInterestRateParamName, element)) {
|
||||
final BigDecimal interestRate = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
|
||||
baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(interestRate).notNull().zeroOrPositiveAmount();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(interestCompoundingPeriodTypeParamName, element)) {
|
||||
final Integer interestCompoundingPeriodType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCompoundingPeriodTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(interestCompoundingPeriodTypeParamName).value(interestCompoundingPeriodType).notNull()
|
||||
.isOneOfTheseValues(SavingsCompoundingInterestPeriodType.integerValues());
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(interestCalculationTypeParamName, element)) {
|
||||
final Integer interestCalculationType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(interestCalculationTypeParamName).value(interestCalculationType).notNull().inMinMaxRange(1, 2);
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(interestCalculationDaysInYearTypeParamName, element)) {
|
||||
final Integer interestCalculationDaysInYearType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationDaysInYearTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(interestCalculationDaysInYearTypeParamName).value(interestCalculationDaysInYearType).notNull().isOneOfTheseValues(360, 365);
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(minRequiredOpeningBalanceParamName, element)) {
|
||||
final BigDecimal minOpeningBalance = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minRequiredOpeningBalanceParamName, element);
|
||||
baseDataValidator.reset().parameter(minRequiredOpeningBalanceParamName).value(minOpeningBalance).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyParamName, element)) {
|
||||
final Integer lockinPeriodFrequency = this.fromApiJsonHelper.extractIntegerWithLocaleNamed(lockinPeriodFrequencyParamName, element);
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyParamName).value(lockinPeriodFrequency).ignoreIfNull().integerZeroOrGreater();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(lockinPeriodFrequencyTypeParamName, element)) {
|
||||
final Integer lockinPeriodFrequencyType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(lockinPeriodFrequencyTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(0, 3);
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) {
|
||||
final Boolean isWithdrawalFeeApplicableForTransfers = this.fromApiJsonHelper.extractBooleanNamed(withdrawalFeeForTransfersParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeForTransfersParamName).value(isWithdrawalFeeApplicableForTransfers).ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
|
||||
Integer accountingRuleType = product.getAccountingType();
|
||||
if (this.fromApiJsonHelper.parameterExists("accountingRule", element)) {
|
||||
accountingRuleType = this.fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
|
||||
}
|
||||
|
||||
final Boolean isDormancyActive = this.fromApiJsonHelper.parameterExists(isDormancyTrackingActiveParamName, element)
|
||||
? this.fromApiJsonHelper.extractBooleanNamed(isDormancyTrackingActiveParamName, element)
|
||||
: product.isDormancyTrackingActive();
|
||||
|
||||
if (AccountingValidations.isCashBasedAccounting(accountingRuleType)
|
||||
|| AccountingValidations.isAccrualPeriodicBasedAccounting(accountingRuleType)) {
|
||||
savingsProductAccountingDataValidator.evaluateProductAccountingData(accountingRuleType, isDormancyActive, element,
|
||||
baseDataValidator, DepositAccountType.SAVINGS_DEPOSIT, false);
|
||||
}
|
||||
|
||||
if (null != isDormancyActive && isDormancyActive) {
|
||||
final Long daysToInact = this.fromApiJsonHelper.parameterExists(daysToInactiveParamName, element)
|
||||
? this.fromApiJsonHelper.extractLongNamed(daysToInactiveParamName, element)
|
||||
: product.getDaysToInactive();
|
||||
baseDataValidator.reset().parameter(daysToInactiveParamName).value(daysToInact).notNull().longGreaterThanZero();
|
||||
final Long daysToDor = this.fromApiJsonHelper.parameterExists(daysToDormancyParamName, element)
|
||||
? this.fromApiJsonHelper.extractLongNamed(daysToDormancyParamName, element)
|
||||
: product.getDaysToDormancy();
|
||||
baseDataValidator.reset().parameter(daysToDormancyParamName).value(daysToDor).notNull().longGreaterThanZero();
|
||||
final Long daysToEsc = this.fromApiJsonHelper.parameterExists(daysToEscheatParamName, element)
|
||||
? this.fromApiJsonHelper.extractLongNamed(daysToEscheatParamName, element)
|
||||
: product.getDaysToEscheat();
|
||||
baseDataValidator.reset().parameter(daysToEscheatParamName).value(daysToEsc).notNull().longGreaterThanZero();
|
||||
if (null != daysToInact && null != daysToDor && null != daysToEsc) {
|
||||
baseDataValidator.reset().parameter(daysToDormancyParamName).value(daysToDor).longGreaterThanNumber(daysToInact);
|
||||
baseDataValidator.reset().parameter(daysToEscheatParamName).value(daysToEsc).longGreaterThanNumber(daysToDor);
|
||||
}
|
||||
}
|
||||
|
||||
validateOverdraftParams(baseDataValidator, element);
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(minBalanceForInterestCalculationParamName, element)) {
|
||||
final BigDecimal minBalanceForInterestCalculation = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minBalanceForInterestCalculationParamName, element);
|
||||
baseDataValidator.reset().parameter(minBalanceForInterestCalculationParamName).value(minBalanceForInterestCalculation).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
|
||||
validateTaxWithHoldingParams(baseDataValidator, element, false);
|
||||
validateLienParams(baseDataValidator, element);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateOverdraftParams(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
if (this.fromApiJsonHelper.parameterExists(allowOverdraftParamName, element)) {
|
||||
final Boolean allowOverdraft = this.fromApiJsonHelper.extractBooleanNamed(allowOverdraftParamName, element);
|
||||
baseDataValidator.reset().parameter(allowOverdraftParamName).value(allowOverdraft).ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(overdraftLimitParamName, element)) {
|
||||
final BigDecimal overdraftLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(overdraftLimitParamName, element);
|
||||
baseDataValidator.reset().parameter(overdraftLimitParamName).value(overdraftLimit).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(nominalAnnualInterestRateOverdraftParamName, element)) {
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateOverdraftParamName, element);
|
||||
baseDataValidator.reset().parameter(nominalAnnualInterestRateOverdraftParamName).value(nominalAnnualInterestRateOverdraft).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(minOverdraftForInterestCalculationParamName, element)) {
|
||||
final BigDecimal minOverdraftForInterestCalculation = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(minOverdraftForInterestCalculationParamName, element);
|
||||
baseDataValidator.reset().parameter(minOverdraftForInterestCalculationParamName).value(minOverdraftForInterestCalculation).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLienParams(final DataValidatorBuilder baseDataValidator, final JsonElement element) {
|
||||
if (this.fromApiJsonHelper.parameterExists(lienAllowedParamName, element)) {
|
||||
final Boolean lienAllowed = this.fromApiJsonHelper.extractBooleanNamed(lienAllowedParamName, element);
|
||||
baseDataValidator.reset().parameter(lienAllowedParamName).value(lienAllowed).ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(maxAllowedLienLimitParamName, element)) {
|
||||
final BigDecimal maxAllowedLienLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxAllowedLienLimitParamName, element);
|
||||
baseDataValidator.reset().parameter(maxAllowedLienLimitParamName).value(maxAllowedLienLimit).ignoreIfNull().zeroOrPositiveAmount();
|
||||
}
|
||||
if (BooleanUtils.isTrue(this.fromApiJsonHelper.extractBooleanNamed(lienAllowedParamName, element))
|
||||
&& BooleanUtils.isTrue(this.fromApiJsonHelper.extractBooleanNamed(allowOverdraftParamName, element))) {
|
||||
final BigDecimal maxAllowedLienLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(maxAllowedLienLimitParamName, element);
|
||||
final BigDecimal overdraftLimit = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(overdraftLimitParamName, element);
|
||||
if (overdraftLimit.compareTo(maxAllowedLienLimit) > 0) {
|
||||
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("Overdraft.limit.can.not.be.greater.than.lien.limit");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void validateTaxWithHoldingParams(final DataValidatorBuilder baseDataValidator, final JsonElement element, final boolean isCreate) {
|
||||
if (this.fromApiJsonHelper.parameterExists(withHoldTaxParamName, element)) {
|
||||
final String withHoldTax = this.fromApiJsonHelper.extractStringNamed(withHoldTaxParamName, element);
|
||||
baseDataValidator.reset().parameter(withHoldTaxParamName).value(withHoldTax).ignoreIfNull().validateForBooleanValue();
|
||||
}
|
||||
Boolean withHoldTax = this.fromApiJsonHelper.extractBooleanNamed(withHoldTaxParamName, element);
|
||||
if (withHoldTax == null) {
|
||||
withHoldTax = false;
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(taxGroupIdParamName, element)) {
|
||||
final Long taxGroupId = this.fromApiJsonHelper.extractLongNamed(taxGroupIdParamName, element);
|
||||
baseDataValidator.reset().parameter(taxGroupIdParamName).value(taxGroupId).ignoreIfNull().longGreaterThanZero();
|
||||
if (withHoldTax) {
|
||||
baseDataValidator.reset().parameter(taxGroupIdParamName).value(taxGroupId).notBlank();
|
||||
}
|
||||
} else if (withHoldTax && isCreate) {
|
||||
final Long taxGroupId = null;
|
||||
baseDataValidator.reset().parameter(taxGroupIdParamName).value(taxGroupId).notBlank();
|
||||
}
|
||||
}
|
||||
}
|
||||
+868
@@ -0,0 +1,868 @@
|
||||
/**
|
||||
* 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.currentproduct.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToDormancyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToEscheatParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToInactiveParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enforceMinRequiredBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.inMultiplesOfParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.localeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.maxAllowedLienLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minOverdraftForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateOverdraftParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.otherGlMappingsParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNameParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.customerSegmentParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.productCodeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveToParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.endDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.introducerRequiredParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shareLinkingEnabledParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominationFacilityParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.dormancyAlertParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculateSelectorParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.averagePeriodParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoPostParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.frequencyFixDayParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lastInterestDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enableLockinPeriodParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.balanceSwapOptionParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.msmeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoDebitFacilityParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.avgBalanceCalcPeriodParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.validForPeriodParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.odAccountClosedZeroBalanceInDayClosingParamName;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embedded;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.domain.Money;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_current_product", uniqueConstraints = {
|
||||
@UniqueConstraint(columnNames = { "name" }, name = "cp_unq_name"),
|
||||
@UniqueConstraint(columnNames = { "short_name" }, name = "cp_unq_short_name") })
|
||||
public class CurrentProduct extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@Column(name = "name", nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
@Column(name = "short_name", nullable = false, unique = true)
|
||||
private String shortName;
|
||||
|
||||
@Column(name = "description", length = 500, nullable = false)
|
||||
private String description;
|
||||
|
||||
@Embedded
|
||||
private MonetaryCurrency currency;
|
||||
|
||||
@Column(name = "nominal_annual_interest_rate", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal nominalAnnualInterestRate;
|
||||
|
||||
@Column(name = "interest_compounding_period_enum", nullable = false)
|
||||
private Integer interestCompoundingPeriodType;
|
||||
|
||||
@Column(name = "interest_posting_period_enum", nullable = false)
|
||||
private Integer interestPostingPeriodType;
|
||||
|
||||
@Column(name = "interest_calculation_type_enum", nullable = false)
|
||||
private Integer interestCalculationType;
|
||||
|
||||
@Column(name = "interest_calculation_days_in_year_type_enum", nullable = false)
|
||||
private Integer interestCalculationDaysInYearType;
|
||||
|
||||
@Column(name = "min_required_opening_balance", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minRequiredOpeningBalance;
|
||||
|
||||
@Column(name = "lockin_period_frequency", nullable = true)
|
||||
private Integer lockinPeriodFrequency;
|
||||
|
||||
@Column(name = "lockin_period_frequency_enum", nullable = true)
|
||||
private Integer lockinPeriodFrequencyType;
|
||||
|
||||
@Column(name = "accounting_type", nullable = false)
|
||||
private Integer accountingRule;
|
||||
|
||||
@Column(name = "withdrawal_fee_for_transfer")
|
||||
private boolean withdrawalFeeApplicableForTransfer;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "m_current_product_charge",
|
||||
joinColumns = @JoinColumn(name = "current_product_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "charge_id"))
|
||||
private Set<Charge> charges;
|
||||
|
||||
@Column(name = "allow_overdraft")
|
||||
private boolean allowOverdraft;
|
||||
|
||||
@Column(name = "overdraft_limit", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal overdraftLimit;
|
||||
|
||||
@Column(name = "nominal_annual_interest_rate_overdraft", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal nominalAnnualInterestRateOverdraft;
|
||||
|
||||
@Column(name = "min_overdraft_for_interest_calculation", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minOverdraftForInterestCalculation;
|
||||
|
||||
@Column(name = "enforce_min_required_balance")
|
||||
private boolean enforceMinRequiredBalance;
|
||||
|
||||
@Column(name = "min_required_balance", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minRequiredBalance;
|
||||
|
||||
@Column(name = "is_lien_allowed", nullable = false)
|
||||
private boolean lienAllowed;
|
||||
|
||||
@Column(name = "max_allowed_lien_limit", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal maxAllowedLienLimit;
|
||||
|
||||
@Column(name = "min_balance_for_interest_calculation", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minBalanceForInterestCalculation;
|
||||
|
||||
@Column(name = "withhold_tax", nullable = false)
|
||||
private boolean withHoldTax;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "tax_group_id")
|
||||
private TaxGroup taxGroup;
|
||||
|
||||
@Column(name = "is_dormancy_tracking_active")
|
||||
private Boolean isDormancyTrackingActive;
|
||||
|
||||
@Column(name = "days_to_inactive")
|
||||
private Long daysToInactive;
|
||||
|
||||
@Column(name = "days_to_dormancy")
|
||||
private Long daysToDormancy;
|
||||
|
||||
@Column(name = "days_to_escheat")
|
||||
private Long daysToEscheat;
|
||||
|
||||
@Lob
|
||||
@Column(name = "other_gl_mappings")
|
||||
private String otherGlMappings;
|
||||
|
||||
// Enhanced fields
|
||||
@Column(name = "account_type", length = 50)
|
||||
private String accountType;
|
||||
|
||||
@Column(name = "customer_segment", length = 50)
|
||||
private String customerSegment;
|
||||
|
||||
@Column(name = "product_code", length = 20, unique = true)
|
||||
private String productCode;
|
||||
|
||||
@Column(name = "effective_date")
|
||||
private LocalDate effectiveDate;
|
||||
|
||||
@Column(name = "effective_to")
|
||||
private LocalDate effectiveTo;
|
||||
|
||||
@Column(name = "end_date")
|
||||
private LocalDate endDate;
|
||||
|
||||
@Column(name = "introducer_required")
|
||||
private boolean introducerRequired = false;
|
||||
|
||||
@Column(name = "share_linking_enabled")
|
||||
private boolean shareLinkingEnabled = false;
|
||||
|
||||
@Column(name = "nomination_facility")
|
||||
private boolean nominationFacility = false;
|
||||
|
||||
@Column(name = "dormancy_alert")
|
||||
private boolean dormancyAlert = false;
|
||||
|
||||
@Column(name = "interest_calculate_selector")
|
||||
private Integer interestCalculateSelector;
|
||||
|
||||
@Column(name = "average_period", length = 20)
|
||||
private String averagePeriod;
|
||||
|
||||
@Column(name = "auto_post")
|
||||
private boolean autoPost = false;
|
||||
|
||||
@Column(name = "frequency_fix_day")
|
||||
private Integer frequencyFixDay;
|
||||
|
||||
@Column(name = "last_interest_date")
|
||||
private LocalDate lastInterestDate;
|
||||
|
||||
@Column(name = "enable_lockin_period")
|
||||
private boolean enableLockinPeriod = false;
|
||||
|
||||
@Column(name = "balance_frequency", length = 50)
|
||||
private String balanceFrequency;
|
||||
|
||||
@Column(name = "account_closed_zero_balance_in_day_closing")
|
||||
private Boolean accountClosedZeroBalanceInDayClosing = false;
|
||||
|
||||
// New UI fields (Currency step)
|
||||
@Column(name = "balance_swap_option")
|
||||
private boolean balanceSwapOption = false;
|
||||
|
||||
@Column(name = "msme")
|
||||
private boolean msme = false;
|
||||
|
||||
@Column(name = "auto_debit_facility")
|
||||
private boolean autoDebitFacility = false;
|
||||
|
||||
// New UI fields (OD section)
|
||||
@Column(name = "avg_balance_calc_period", length = 10)
|
||||
private String avgBalanceCalcPeriod;
|
||||
|
||||
@Column(name = "valid_for_period", length = 10)
|
||||
private String validForPeriod;
|
||||
|
||||
@Column(name = "od_account_closed_zero_balance_in_day_closing")
|
||||
private boolean odAccountClosedZeroBalanceInDayClosing = false;
|
||||
|
||||
@OneToOne(cascade = CascadeType.ALL, mappedBy = "currentProduct", orphanRemoval = true)
|
||||
private CurrentProductFacilityConfig facilityConfig;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "currentProduct", orphanRemoval = true)
|
||||
private Set<CurrentProductFacilityLimit> facilityLimits = new HashSet<>();
|
||||
|
||||
@OneToOne(cascade = CascadeType.ALL, mappedBy = "currentProduct", orphanRemoval = true)
|
||||
private CurrentProductDepositLimitKyc depositLimitKyc;
|
||||
|
||||
public static CurrentProduct createNew(final String name, final String shortName, final String description,
|
||||
final MonetaryCurrency currency, final BigDecimal interestRate,
|
||||
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType,
|
||||
final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType,
|
||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
||||
final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType,
|
||||
final Set<Charge> charges, final boolean allowOverdraft, final BigDecimal overdraftLimit,
|
||||
final boolean enforceMinRequiredBalance, final BigDecimal minRequiredBalance,
|
||||
final boolean lienAllowed, final BigDecimal maxAllowedLienLimit,
|
||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroup taxGroup,
|
||||
final String otherGlMappings, final Boolean isDormancyTrackingActive, final Long daysToInactive,
|
||||
final Long daysToDormancy, final Long daysToEscheat) {
|
||||
|
||||
return new CurrentProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit,
|
||||
enforceMinRequiredBalance, minRequiredBalance, lienAllowed, maxAllowedLienLimit,
|
||||
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation,
|
||||
withHoldTax, taxGroup, otherGlMappings, isDormancyTrackingActive, daysToInactive, daysToDormancy,
|
||||
daysToEscheat);
|
||||
}
|
||||
|
||||
protected CurrentProduct() {
|
||||
this.name = null;
|
||||
this.description = null;
|
||||
}
|
||||
|
||||
private CurrentProduct(final String name, final String shortName, final String description,
|
||||
final MonetaryCurrency currency, final BigDecimal interestRate,
|
||||
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||
final SavingsPostingInterestPeriodType interestPostingPeriodType,
|
||||
final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType,
|
||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
||||
final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType,
|
||||
final Set<Charge> charges, final boolean allowOverdraft, final BigDecimal overdraftLimit,
|
||||
final boolean enforceMinRequiredBalance, final BigDecimal minRequiredBalance,
|
||||
final boolean lienAllowed, final BigDecimal maxAllowedLienLimit,
|
||||
final BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
|
||||
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroup taxGroup,
|
||||
final String otherGlMappings, final Boolean isDormancyTrackingActive, final Long daysToInactive,
|
||||
final Long daysToDormancy, final Long daysToEscheat) {
|
||||
|
||||
this.name = name;
|
||||
this.shortName = shortName;
|
||||
this.description = description;
|
||||
this.currency = currency;
|
||||
this.nominalAnnualInterestRate = interestRate;
|
||||
this.interestCompoundingPeriodType = interestCompoundingPeriodType.getValue();
|
||||
this.interestPostingPeriodType = interestPostingPeriodType.getValue();
|
||||
this.interestCalculationType = interestCalculationType.getValue();
|
||||
this.interestCalculationDaysInYearType = interestCalculationDaysInYearType.getValue();
|
||||
|
||||
if (minRequiredOpeningBalance != null) {
|
||||
this.minRequiredOpeningBalance = Money.of(currency, minRequiredOpeningBalance).getAmount();
|
||||
}
|
||||
|
||||
this.lockinPeriodFrequency = lockinPeriodFrequency;
|
||||
if (lockinPeriodFrequency != null && lockinPeriodFrequencyType != null) {
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType.getValue();
|
||||
}
|
||||
|
||||
this.withdrawalFeeApplicableForTransfer = withdrawalFeeApplicableForTransfer;
|
||||
|
||||
if (accountingRuleType != null) {
|
||||
this.accountingRule = accountingRuleType.getValue();
|
||||
}
|
||||
|
||||
if (charges != null) {
|
||||
this.charges = charges;
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
|
||||
this.allowOverdraft = allowOverdraft;
|
||||
this.overdraftLimit = overdraftLimit;
|
||||
this.nominalAnnualInterestRateOverdraft = nominalAnnualInterestRateOverdraft;
|
||||
this.minOverdraftForInterestCalculation = minOverdraftForInterestCalculation;
|
||||
|
||||
ensureOverdraftLimitsSetForOverdraftAccounts();
|
||||
|
||||
this.enforceMinRequiredBalance = enforceMinRequiredBalance;
|
||||
this.minRequiredBalance = minRequiredBalance;
|
||||
this.lienAllowed = lienAllowed;
|
||||
this.maxAllowedLienLimit = maxAllowedLienLimit;
|
||||
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
|
||||
this.withHoldTax = withHoldTax;
|
||||
this.taxGroup = taxGroup;
|
||||
this.otherGlMappings = otherGlMappings;
|
||||
|
||||
this.isDormancyTrackingActive = isDormancyTrackingActive == null ? Boolean.FALSE : isDormancyTrackingActive;
|
||||
this.daysToInactive = daysToInactive;
|
||||
this.daysToDormancy = daysToDormancy;
|
||||
this.daysToEscheat = daysToEscheat;
|
||||
}
|
||||
|
||||
private void ensureOverdraftLimitsSetForOverdraftAccounts() {
|
||||
if (this.allowOverdraft) {
|
||||
this.overdraftLimit = this.overdraftLimit == null ? BigDecimal.ZERO : this.overdraftLimit;
|
||||
this.nominalAnnualInterestRateOverdraft = this.nominalAnnualInterestRateOverdraft == null ? BigDecimal.ZERO
|
||||
: this.nominalAnnualInterestRateOverdraft;
|
||||
this.minOverdraftForInterestCalculation = this.minOverdraftForInterestCalculation == null ? BigDecimal.ZERO
|
||||
: this.minOverdraftForInterestCalculation;
|
||||
}
|
||||
}
|
||||
|
||||
private void validateLockinDetails() {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource("currentproduct");
|
||||
if (this.lockinPeriodFrequency == null) {
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(this.lockinPeriodFrequencyType)
|
||||
.ignoreIfNull().inMinMaxRange(0, 3);
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public MonetaryCurrency currency() {
|
||||
return this.currency.copy();
|
||||
}
|
||||
|
||||
public BigDecimal nominalAnnualInterestRate() {
|
||||
return this.nominalAnnualInterestRate;
|
||||
}
|
||||
|
||||
public Integer getAccountingType() {
|
||||
return this.accountingRule;
|
||||
}
|
||||
|
||||
public boolean withHoldTax() {
|
||||
return this.withHoldTax;
|
||||
}
|
||||
|
||||
public TaxGroup getTaxGroup() {
|
||||
return this.taxGroup;
|
||||
}
|
||||
|
||||
public void setTaxGroup(final TaxGroup taxGroup) {
|
||||
this.taxGroup = taxGroup;
|
||||
}
|
||||
|
||||
public CurrentProductFacilityConfig getFacilityConfig() {
|
||||
return this.facilityConfig;
|
||||
}
|
||||
|
||||
public void setFacilityConfig(CurrentProductFacilityConfig facilityConfig) {
|
||||
this.facilityConfig = facilityConfig;
|
||||
}
|
||||
|
||||
public Set<CurrentProductFacilityLimit> getFacilityLimits() {
|
||||
return this.facilityLimits;
|
||||
}
|
||||
|
||||
public void setFacilityLimits(Set<CurrentProductFacilityLimit> facilityLimits) {
|
||||
this.facilityLimits = facilityLimits;
|
||||
}
|
||||
|
||||
public CurrentProductDepositLimitKyc getDepositLimitKyc() {
|
||||
return this.depositLimitKyc;
|
||||
}
|
||||
|
||||
public void setDepositLimitKyc(CurrentProductDepositLimitKyc depositLimitKyc) {
|
||||
this.depositLimitKyc = depositLimitKyc;
|
||||
}
|
||||
|
||||
public boolean update(final Set<Charge> newCharges) {
|
||||
if (newCharges == null) {
|
||||
return false;
|
||||
}
|
||||
final Set<Charge> currentSetOfCharges = this.charges == null ? new HashSet<>() : this.charges;
|
||||
if (!currentSetOfCharges.equals(newCharges)) {
|
||||
this.charges = newCharges;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(10);
|
||||
final String localeAsInput = command.locale();
|
||||
|
||||
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(nameParamName);
|
||||
actualChanges.put(nameParamName, newValue);
|
||||
this.name = newValue;
|
||||
}
|
||||
if (command.isChangeInStringParameterNamed(shortNameParamName, this.shortName)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(shortNameParamName);
|
||||
actualChanges.put(shortNameParamName, newValue);
|
||||
this.shortName = newValue;
|
||||
}
|
||||
if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
|
||||
actualChanges.put(descriptionParamName, newValue);
|
||||
this.description = newValue;
|
||||
}
|
||||
|
||||
Integer digitsAfterDecimal = this.currency.getDigitsAfterDecimal();
|
||||
if (command.isChangeInIntegerParameterNamed(digitsAfterDecimalParamName, digitsAfterDecimal)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(digitsAfterDecimalParamName);
|
||||
actualChanges.put(digitsAfterDecimalParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
digitsAfterDecimal = newValue;
|
||||
this.currency = new MonetaryCurrency(this.currency.getCode(), digitsAfterDecimal, this.currency.getInMultiplesOf());
|
||||
}
|
||||
|
||||
String currencyCode = this.currency.getCode();
|
||||
if (command.isChangeInStringParameterNamed(currencyCodeParamName, currencyCode)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(currencyCodeParamName);
|
||||
actualChanges.put(currencyCodeParamName, newValue);
|
||||
currencyCode = newValue;
|
||||
this.currency = new MonetaryCurrency(currencyCode, this.currency.getDigitsAfterDecimal(), this.currency.getInMultiplesOf());
|
||||
}
|
||||
|
||||
Integer inMultiplesOf = this.currency.getInMultiplesOf();
|
||||
if (command.isChangeInIntegerParameterNamed(inMultiplesOfParamName, inMultiplesOf)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(inMultiplesOfParamName);
|
||||
actualChanges.put(inMultiplesOfParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
inMultiplesOf = newValue;
|
||||
this.currency = new MonetaryCurrency(this.currency.getCode(), this.currency.getDigitsAfterDecimal(), inMultiplesOf);
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamed(nominalAnnualInterestRateParamName, this.nominalAnnualInterestRate)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
|
||||
actualChanges.put(nominalAnnualInterestRateParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.nominalAnnualInterestRate = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(interestCompoundingPeriodTypeParamName, this.interestCompoundingPeriodType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
|
||||
actualChanges.put(interestCompoundingPeriodTypeParamName, newValue);
|
||||
this.interestCompoundingPeriodType = SavingsCompoundingInterestPeriodType.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(interestPostingPeriodTypeParamName, this.interestPostingPeriodType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(interestPostingPeriodTypeParamName);
|
||||
actualChanges.put(interestPostingPeriodTypeParamName, newValue);
|
||||
this.interestPostingPeriodType = SavingsPostingInterestPeriodType.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(interestCalculationTypeParamName, this.interestCalculationType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(interestCalculationTypeParamName);
|
||||
actualChanges.put(interestCalculationTypeParamName, newValue);
|
||||
this.interestCalculationType = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(interestCalculationDaysInYearTypeParamName, this.interestCalculationDaysInYearType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(interestCalculationDaysInYearTypeParamName);
|
||||
actualChanges.put(interestCalculationDaysInYearTypeParamName, newValue);
|
||||
this.interestCalculationDaysInYearType = SavingsInterestCalculationDaysInYearType.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minRequiredOpeningBalanceParamName, this.minRequiredOpeningBalance)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredOpeningBalanceParamName);
|
||||
actualChanges.put(minRequiredOpeningBalanceParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.minRequiredOpeningBalance = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamedDefaultingZeroToNull(lockinPeriodFrequencyParamName, this.lockinPeriodFrequency)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamedDefaultToNullIfZero(lockinPeriodFrequencyParamName);
|
||||
actualChanges.put(lockinPeriodFrequencyParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.lockinPeriodFrequency = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(lockinPeriodFrequencyTypeParamName, this.lockinPeriodFrequencyType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
|
||||
actualChanges.put(lockinPeriodFrequencyTypeParamName, newValue);
|
||||
this.lockinPeriodFrequencyType = newValue != null ? SavingsPeriodFrequencyType.fromInt(newValue).getValue() : newValue;
|
||||
}
|
||||
|
||||
if (this.lockinPeriodFrequency == null) {
|
||||
this.lockinPeriodFrequencyType = null;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(withdrawalFeeForTransfersParamName, this.withdrawalFeeApplicableForTransfer)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(withdrawalFeeForTransfersParamName);
|
||||
actualChanges.put(withdrawalFeeForTransfersParamName, newValue);
|
||||
this.withdrawalFeeApplicableForTransfer = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(accountingRuleParamName, this.accountingRule)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(accountingRuleParamName);
|
||||
actualChanges.put(accountingRuleParamName, newValue);
|
||||
this.accountingRule = newValue;
|
||||
}
|
||||
|
||||
if (command.hasParameter(chargesParamName)) {
|
||||
final JsonArray jsonArray = command.arrayOfParameterNamed(chargesParamName);
|
||||
if (jsonArray != null) {
|
||||
actualChanges.put(chargesParamName, command.jsonFragment(chargesParamName));
|
||||
}
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(allowOverdraftParamName, this.allowOverdraft)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftParamName);
|
||||
actualChanges.put(allowOverdraftParamName, newValue);
|
||||
this.allowOverdraft = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(overdraftLimitParamName, this.overdraftLimit)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(overdraftLimitParamName);
|
||||
actualChanges.put(overdraftLimitParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.overdraftLimit = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(nominalAnnualInterestRateOverdraftParamName, this.nominalAnnualInterestRateOverdraft)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(nominalAnnualInterestRateOverdraftParamName);
|
||||
actualChanges.put(nominalAnnualInterestRateOverdraftParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.nominalAnnualInterestRateOverdraft = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minOverdraftForInterestCalculationParamName, this.minOverdraftForInterestCalculation)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minOverdraftForInterestCalculationParamName);
|
||||
actualChanges.put(minOverdraftForInterestCalculationParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.minOverdraftForInterestCalculation = newValue;
|
||||
}
|
||||
|
||||
if (!this.allowOverdraft) {
|
||||
this.overdraftLimit = null;
|
||||
this.nominalAnnualInterestRateOverdraft = null;
|
||||
this.minOverdraftForInterestCalculation = null;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(enforceMinRequiredBalanceParamName, this.enforceMinRequiredBalance)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(enforceMinRequiredBalanceParamName);
|
||||
actualChanges.put(enforceMinRequiredBalanceParamName, newValue);
|
||||
this.enforceMinRequiredBalance = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minRequiredBalanceParamName, this.minRequiredBalance)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredBalanceParamName);
|
||||
actualChanges.put(minRequiredBalanceParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.minRequiredBalance = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(lienAllowedParamName, this.lienAllowed)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(lienAllowedParamName);
|
||||
actualChanges.put(lienAllowedParamName, newValue);
|
||||
this.lienAllowed = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(maxAllowedLienLimitParamName, this.maxAllowedLienLimit)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(maxAllowedLienLimitParamName);
|
||||
actualChanges.put(maxAllowedLienLimitParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.maxAllowedLienLimit = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minBalanceForInterestCalculationParamName, this.minBalanceForInterestCalculation)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minBalanceForInterestCalculationParamName);
|
||||
actualChanges.put(minBalanceForInterestCalculationParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.minBalanceForInterestCalculation = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(withHoldTaxParamName, this.withHoldTax)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(withHoldTaxParamName);
|
||||
actualChanges.put(withHoldTaxParamName, newValue);
|
||||
this.withHoldTax = newValue;
|
||||
}
|
||||
|
||||
if (this.withHoldTax) {
|
||||
if (this.taxGroup == null || command.isChangeInLongParameterNamed(taxGroupIdParamName, this.taxGroup.getId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(taxGroupIdParamName);
|
||||
actualChanges.put(taxGroupIdParamName, newValue);
|
||||
}
|
||||
} else {
|
||||
this.taxGroup = null;
|
||||
}
|
||||
|
||||
if (command.hasParameter(otherGlMappingsParamName)) {
|
||||
final String newValue = command.hasParameter(otherGlMappingsParamName) ? command.jsonFragment(otherGlMappingsParamName) : null;
|
||||
actualChanges.put(otherGlMappingsParamName, newValue);
|
||||
this.otherGlMappings = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInBooleanParameterNamed(isDormancyTrackingActiveParamName, this.isDormancyTrackingActive)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(isDormancyTrackingActiveParamName);
|
||||
actualChanges.put(isDormancyTrackingActiveParamName, newValue);
|
||||
this.isDormancyTrackingActive = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(daysToInactiveParamName, this.daysToInactive)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(daysToInactiveParamName);
|
||||
actualChanges.put(daysToInactiveParamName, newValue);
|
||||
this.daysToInactive = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(daysToDormancyParamName, this.daysToDormancy)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(daysToDormancyParamName);
|
||||
actualChanges.put(daysToDormancyParamName, newValue);
|
||||
this.daysToDormancy = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(daysToEscheatParamName, this.daysToEscheat)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(daysToEscheatParamName);
|
||||
actualChanges.put(daysToEscheatParamName, newValue);
|
||||
this.daysToEscheat = newValue;
|
||||
}
|
||||
|
||||
// Enhanced fields
|
||||
if (command.isChangeInStringParameterNamed(accountTypeParamName, this.accountType)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(accountTypeParamName);
|
||||
actualChanges.put(accountTypeParamName, newValue);
|
||||
this.accountType = newValue;
|
||||
}
|
||||
if (command.isChangeInStringParameterNamed(customerSegmentParamName, this.customerSegment)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(customerSegmentParamName);
|
||||
actualChanges.put(customerSegmentParamName, newValue);
|
||||
this.customerSegment = newValue;
|
||||
}
|
||||
if (command.isChangeInStringParameterNamed(productCodeParamName, this.productCode)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(productCodeParamName);
|
||||
actualChanges.put(productCodeParamName, newValue);
|
||||
this.productCode = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(introducerRequiredParamName, this.introducerRequired)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(introducerRequiredParamName);
|
||||
actualChanges.put(introducerRequiredParamName, newValue);
|
||||
this.introducerRequired = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(shareLinkingEnabledParamName, this.shareLinkingEnabled)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(shareLinkingEnabledParamName);
|
||||
actualChanges.put(shareLinkingEnabledParamName, newValue);
|
||||
this.shareLinkingEnabled = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(nominationFacilityParamName, this.nominationFacility)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(nominationFacilityParamName);
|
||||
actualChanges.put(nominationFacilityParamName, newValue);
|
||||
this.nominationFacility = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(dormancyAlertParamName, this.dormancyAlert)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(dormancyAlertParamName);
|
||||
actualChanges.put(dormancyAlertParamName, newValue);
|
||||
this.dormancyAlert = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(autoPostParamName, this.autoPost)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(autoPostParamName);
|
||||
actualChanges.put(autoPostParamName, newValue);
|
||||
this.autoPost = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(enableLockinPeriodParamName, this.enableLockinPeriod)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(enableLockinPeriodParamName);
|
||||
actualChanges.put(enableLockinPeriodParamName, newValue);
|
||||
this.enableLockinPeriod = newValue;
|
||||
}
|
||||
|
||||
// New currency-step fields
|
||||
if (command.isChangeInBooleanParameterNamed(balanceSwapOptionParamName, this.balanceSwapOption)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(balanceSwapOptionParamName);
|
||||
actualChanges.put(balanceSwapOptionParamName, newValue);
|
||||
this.balanceSwapOption = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(msmeParamName, this.msme)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(msmeParamName);
|
||||
actualChanges.put(msmeParamName, newValue);
|
||||
this.msme = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(autoDebitFacilityParamName, this.autoDebitFacility)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(autoDebitFacilityParamName);
|
||||
actualChanges.put(autoDebitFacilityParamName, newValue);
|
||||
this.autoDebitFacility = newValue;
|
||||
}
|
||||
|
||||
// New OD-section fields
|
||||
if (command.isChangeInStringParameterNamed(avgBalanceCalcPeriodParamName, this.avgBalanceCalcPeriod)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(avgBalanceCalcPeriodParamName);
|
||||
actualChanges.put(avgBalanceCalcPeriodParamName, newValue);
|
||||
this.avgBalanceCalcPeriod = newValue;
|
||||
}
|
||||
if (command.isChangeInStringParameterNamed(validForPeriodParamName, this.validForPeriod)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(validForPeriodParamName);
|
||||
actualChanges.put(validForPeriodParamName, newValue);
|
||||
this.validForPeriod = newValue;
|
||||
}
|
||||
if (command.isChangeInBooleanParameterNamed(odAccountClosedZeroBalanceInDayClosingParamName, this.odAccountClosedZeroBalanceInDayClosing)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(odAccountClosedZeroBalanceInDayClosingParamName);
|
||||
actualChanges.put(odAccountClosedZeroBalanceInDayClosingParamName, newValue);
|
||||
this.odAccountClosedZeroBalanceInDayClosing = newValue;
|
||||
}
|
||||
// Clear OD-specific fields when overdraft is disabled
|
||||
if (!this.allowOverdraft) {
|
||||
this.avgBalanceCalcPeriod = null;
|
||||
this.validForPeriod = null;
|
||||
this.odAccountClosedZeroBalanceInDayClosing = false;
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
// Dormancy/misc getters needed by validator
|
||||
public Boolean isDormancyTrackingActive() { return this.isDormancyTrackingActive; }
|
||||
public Long getDaysToInactive() { return this.daysToInactive; }
|
||||
public Long getDaysToDormancy() { return this.daysToDormancy; }
|
||||
public Long getDaysToEscheat() { return this.daysToEscheat; }
|
||||
|
||||
// Getters and setters for enhanced fields
|
||||
public String getAccountType() { return accountType; }
|
||||
public void setAccountType(String accountType) { this.accountType = accountType; }
|
||||
public String getCustomerSegment() { return customerSegment; }
|
||||
public void setCustomerSegment(String customerSegment) { this.customerSegment = customerSegment; }
|
||||
public String getProductCode() { return productCode; }
|
||||
public void setProductCode(String productCode) { this.productCode = productCode; }
|
||||
public LocalDate getEffectiveDate() { return effectiveDate; }
|
||||
public void setEffectiveDate(LocalDate effectiveDate) { this.effectiveDate = effectiveDate; }
|
||||
public LocalDate getEffectiveTo() { return effectiveTo; }
|
||||
public void setEffectiveTo(LocalDate effectiveTo) { this.effectiveTo = effectiveTo; }
|
||||
public LocalDate getEndDate() { return endDate; }
|
||||
public void setEndDate(LocalDate endDate) { this.endDate = endDate; }
|
||||
public boolean isIntroducerRequired() { return introducerRequired; }
|
||||
public void setIntroducerRequired(boolean introducerRequired) { this.introducerRequired = introducerRequired; }
|
||||
public boolean isShareLinkingEnabled() { return shareLinkingEnabled; }
|
||||
public void setShareLinkingEnabled(boolean shareLinkingEnabled) { this.shareLinkingEnabled = shareLinkingEnabled; }
|
||||
public boolean isNominationFacility() { return nominationFacility; }
|
||||
public void setNominationFacility(boolean nominationFacility) { this.nominationFacility = nominationFacility; }
|
||||
public boolean isDormancyAlert() { return dormancyAlert; }
|
||||
public void setDormancyAlert(boolean dormancyAlert) { this.dormancyAlert = dormancyAlert; }
|
||||
public Integer getInterestCalculateSelector() { return interestCalculateSelector; }
|
||||
public void setInterestCalculateSelector(Integer interestCalculateSelector) { this.interestCalculateSelector = interestCalculateSelector; }
|
||||
public String getAveragePeriod() { return averagePeriod; }
|
||||
public void setAveragePeriod(String averagePeriod) { this.averagePeriod = averagePeriod; }
|
||||
public boolean isAutoPost() { return autoPost; }
|
||||
public void setAutoPost(boolean autoPost) { this.autoPost = autoPost; }
|
||||
public Integer getFrequencyFixDay() { return frequencyFixDay; }
|
||||
public void setFrequencyFixDay(Integer frequencyFixDay) { this.frequencyFixDay = frequencyFixDay; }
|
||||
public LocalDate getLastInterestDate() { return lastInterestDate; }
|
||||
public void setLastInterestDate(LocalDate lastInterestDate) { this.lastInterestDate = lastInterestDate; }
|
||||
public boolean isEnableLockinPeriod() { return enableLockinPeriod; }
|
||||
public void setEnableLockinPeriod(boolean enableLockinPeriod) { this.enableLockinPeriod = enableLockinPeriod; }
|
||||
public String getBalanceFrequency() { return balanceFrequency; }
|
||||
public void setBalanceFrequency(String balanceFrequency) { this.balanceFrequency = balanceFrequency; }
|
||||
public Boolean getAccountClosedZeroBalanceInDayClosing() { return accountClosedZeroBalanceInDayClosing; }
|
||||
public void setAccountClosedZeroBalanceInDayClosing(Boolean val) { this.accountClosedZeroBalanceInDayClosing = val; }
|
||||
|
||||
// New field getters/setters
|
||||
public boolean isBalanceSwapOption() { return balanceSwapOption; }
|
||||
public void setBalanceSwapOption(boolean balanceSwapOption) { this.balanceSwapOption = balanceSwapOption; }
|
||||
public boolean isMsme() { return msme; }
|
||||
public void setMsme(boolean msme) { this.msme = msme; }
|
||||
public boolean isAutoDebitFacility() { return autoDebitFacility; }
|
||||
public void setAutoDebitFacility(boolean autoDebitFacility) { this.autoDebitFacility = autoDebitFacility; }
|
||||
public String getAvgBalanceCalcPeriod() { return avgBalanceCalcPeriod; }
|
||||
public void setAvgBalanceCalcPeriod(String avgBalanceCalcPeriod) { this.avgBalanceCalcPeriod = avgBalanceCalcPeriod; }
|
||||
public String getValidForPeriod() { return validForPeriod; }
|
||||
public void setValidForPeriod(String validForPeriod) { this.validForPeriod = validForPeriod; }
|
||||
public boolean isOdAccountClosedZeroBalanceInDayClosing() { return odAccountClosedZeroBalanceInDayClosing; }
|
||||
public void setOdAccountClosedZeroBalanceInDayClosing(boolean val) { this.odAccountClosedZeroBalanceInDayClosing = val; }
|
||||
}
|
||||
+429
@@ -0,0 +1,429 @@
|
||||
/**
|
||||
* 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.currentproduct.domain;
|
||||
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountFacilityConfigParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountFacilityLimitsParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoPostParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.averagePeriodParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.customerSegmentParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToDormancyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToEscheatParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToInactiveParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.depositLimitKycParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.descriptionParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.dormancyAlertParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveToParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enableLockinPeriodParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.balanceSwapOptionParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.msmeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoDebitFacilityParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.avgBalanceCalcPeriodParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.validForPeriodParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.odAccountClosedZeroBalanceInDayClosingParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.endDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enforceMinRequiredBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.frequencyFixDayParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.idParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.inMultiplesOfParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculateSelectorParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestPostingPeriodTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.introducerRequiredParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.isDormancyTrackingActiveParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lastInterestDateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lienAllowedParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.maxAllowedLienLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minBalanceForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minOverdraftForInterestCalculationParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nameParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominationFacilityParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateOverdraftParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.otherGlMappingsParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.productCodeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shareLinkingEnabledParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNameParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.accounting.common.AccountingRuleType;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.apache.fineract.organisation.monetary.exception.InvalidCurrencyException;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeCannotBeAppliedToException;
|
||||
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroup;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroupRepositoryWrapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CurrentProductAssembler {
|
||||
|
||||
private final ChargeRepositoryWrapper chargeRepository;
|
||||
private final TaxGroupRepositoryWrapper taxGroupRepository;
|
||||
|
||||
@Autowired
|
||||
public CurrentProductAssembler(final ChargeRepositoryWrapper chargeRepository,
|
||||
final TaxGroupRepositoryWrapper taxGroupRepository) {
|
||||
this.chargeRepository = chargeRepository;
|
||||
this.taxGroupRepository = taxGroupRepository;
|
||||
}
|
||||
|
||||
public CurrentProduct assemble(final JsonCommand command) {
|
||||
|
||||
final String name = command.stringValueOfParameterNamed(nameParamName);
|
||||
final String shortName = command.stringValueOfParameterNamed(shortNameParamName);
|
||||
final String description = command.stringValueOfParameterNamedAllowingNull(descriptionParamName);
|
||||
|
||||
final String currencyCode = command.stringValueOfParameterNamed(currencyCodeParamName);
|
||||
final Integer digitsAfterDecimal = command.integerValueOfParameterNamed(digitsAfterDecimalParamName);
|
||||
final Integer inMultiplesOf = command.integerValueOfParameterNamed(inMultiplesOfParamName);
|
||||
final MonetaryCurrency currency = new MonetaryCurrency(currencyCode, digitsAfterDecimal, inMultiplesOf);
|
||||
|
||||
BigDecimal interestRate = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateParamName);
|
||||
if (interestRate == null) {
|
||||
interestRate = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
SavingsCompoundingInterestPeriodType interestCompoundingPeriodType = SavingsCompoundingInterestPeriodType.DAILY;
|
||||
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
|
||||
if (interestPeriodTypeValue != null) {
|
||||
interestCompoundingPeriodType = SavingsCompoundingInterestPeriodType.fromInt(interestPeriodTypeValue);
|
||||
}
|
||||
|
||||
SavingsPostingInterestPeriodType interestPostingPeriodType = null;
|
||||
final Integer interestPostingPeriodTypeValue = command.integerValueOfParameterNamed(interestPostingPeriodTypeParamName);
|
||||
if (interestPostingPeriodTypeValue != null) {
|
||||
interestPostingPeriodType = SavingsPostingInterestPeriodType.fromInt(interestPostingPeriodTypeValue);
|
||||
}
|
||||
|
||||
SavingsInterestCalculationType interestCalculationType = SavingsInterestCalculationType.DAILY_BALANCE;
|
||||
final Integer interestCalculationTypeValue = command.integerValueOfParameterNamed(interestCalculationTypeParamName);
|
||||
if (interestCalculationTypeValue != null) {
|
||||
interestCalculationType = SavingsInterestCalculationType.fromInt(interestCalculationTypeValue);
|
||||
}
|
||||
|
||||
SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType = SavingsInterestCalculationDaysInYearType.DAYS_365;
|
||||
final Integer interestCalculationDaysInYearTypeValue = command.integerValueOfParameterNamed(interestCalculationDaysInYearTypeParamName);
|
||||
if (interestCalculationDaysInYearTypeValue != null) {
|
||||
interestCalculationDaysInYearType = SavingsInterestCalculationDaysInYearType.fromInt(interestCalculationDaysInYearTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal minRequiredOpeningBalance = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredOpeningBalanceParamName);
|
||||
|
||||
final Integer lockinPeriodFrequency = command.integerValueOfParameterNamedDefaultToNullIfZero(lockinPeriodFrequencyParamName);
|
||||
SavingsPeriodFrequencyType lockinPeriodFrequencyType = null;
|
||||
final Integer lockinPeriodFrequencyTypeValue = command.integerValueOfParameterNamed(lockinPeriodFrequencyTypeParamName);
|
||||
if (lockinPeriodFrequencyTypeValue != null) {
|
||||
lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
|
||||
}
|
||||
|
||||
boolean isWithdrawalFeeApplicableForTransfer = false;
|
||||
if (command.parameterExists(withdrawalFeeForTransfersParamName)) {
|
||||
isWithdrawalFeeApplicableForTransfer = command.booleanPrimitiveValueOfParameterNamed(withdrawalFeeForTransfersParamName);
|
||||
}
|
||||
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule"));
|
||||
|
||||
final Set<Charge> charges = assembleListOfCurrentProductCharges(command, currencyCode);
|
||||
|
||||
boolean allowOverdraft = false;
|
||||
if (command.parameterExists(allowOverdraftParamName)) {
|
||||
allowOverdraft = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftParamName);
|
||||
}
|
||||
|
||||
BigDecimal overdraftLimit = BigDecimal.ZERO;
|
||||
if (command.parameterExists(overdraftLimitParamName)) {
|
||||
overdraftLimit = command.bigDecimalValueOfParameterNamed(overdraftLimitParamName);
|
||||
}
|
||||
|
||||
BigDecimal nominalAnnualInterestRateOverdraft = BigDecimal.ZERO;
|
||||
if (command.parameterExists(nominalAnnualInterestRateOverdraftParamName)) {
|
||||
nominalAnnualInterestRateOverdraft = command.bigDecimalValueOfParameterNamed(nominalAnnualInterestRateOverdraftParamName);
|
||||
}
|
||||
|
||||
BigDecimal minOverdraftForInterestCalculation = BigDecimal.ZERO;
|
||||
if (command.parameterExists(minOverdraftForInterestCalculationParamName)) {
|
||||
minOverdraftForInterestCalculation = command.bigDecimalValueOfParameterNamed(minOverdraftForInterestCalculationParamName);
|
||||
}
|
||||
|
||||
boolean enforceMinRequiredBalance = false;
|
||||
if (command.parameterExists(enforceMinRequiredBalanceParamName)) {
|
||||
enforceMinRequiredBalance = command.booleanPrimitiveValueOfParameterNamed(enforceMinRequiredBalanceParamName);
|
||||
}
|
||||
|
||||
BigDecimal minRequiredBalance = BigDecimal.ZERO;
|
||||
if (command.parameterExists(minRequiredBalanceParamName)) {
|
||||
minRequiredBalance = command.bigDecimalValueOfParameterNamed(minRequiredBalanceParamName);
|
||||
}
|
||||
|
||||
boolean lienAllowed = false;
|
||||
if (command.parameterExists(lienAllowedParamName)) {
|
||||
lienAllowed = command.booleanPrimitiveValueOfParameterNamed(lienAllowedParamName);
|
||||
}
|
||||
|
||||
BigDecimal maxAllowedLienLimit = BigDecimal.ZERO;
|
||||
if (command.parameterExists(maxAllowedLienLimitParamName)) {
|
||||
maxAllowedLienLimit = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(maxAllowedLienLimitParamName);
|
||||
}
|
||||
|
||||
final BigDecimal minBalanceForInterestCalculation = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minBalanceForInterestCalculationParamName);
|
||||
|
||||
boolean withHoldTax = command.booleanPrimitiveValueOfParameterNamed(withHoldTaxParamName);
|
||||
final TaxGroup taxGroup = assembleTaxGroup(command);
|
||||
|
||||
final Boolean isDormancyTrackingActive = command.booleanObjectValueOfParameterNamed(isDormancyTrackingActiveParamName);
|
||||
final Long daysToInactive = command.longValueOfParameterNamed(daysToInactiveParamName);
|
||||
final Long daysToDormancy = command.longValueOfParameterNamed(daysToDormancyParamName);
|
||||
final Long daysToEscheat = command.longValueOfParameterNamed(daysToEscheatParamName);
|
||||
final String otherGlMappings = command.hasParameter(otherGlMappingsParamName) ? command.jsonFragment(otherGlMappingsParamName) : null;
|
||||
|
||||
CurrentProduct product = CurrentProduct.createNew(name, shortName, description, currency, interestRate,
|
||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, isWithdrawalFeeApplicableForTransfer, accountingRuleType, charges,
|
||||
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, lienAllowed,
|
||||
maxAllowedLienLimit, minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax, taxGroup, otherGlMappings,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
|
||||
|
||||
// Set enhanced fields
|
||||
if (command.parameterExists(accountTypeParamName)) {
|
||||
product.setAccountType(command.stringValueOfParameterNamed(accountTypeParamName));
|
||||
}
|
||||
if (command.parameterExists(customerSegmentParamName)) {
|
||||
product.setCustomerSegment(command.stringValueOfParameterNamed(customerSegmentParamName));
|
||||
}
|
||||
if (command.parameterExists(productCodeParamName)) {
|
||||
product.setProductCode(command.stringValueOfParameterNamed(productCodeParamName));
|
||||
}
|
||||
if (command.parameterExists(effectiveDateParamName)) {
|
||||
product.setEffectiveDate(command.localDateValueOfParameterNamed(effectiveDateParamName));
|
||||
}
|
||||
if (command.parameterExists(effectiveToParamName)) {
|
||||
product.setEffectiveTo(command.localDateValueOfParameterNamed(effectiveToParamName));
|
||||
}
|
||||
if (command.parameterExists(endDateParamName)) {
|
||||
product.setEndDate(command.localDateValueOfParameterNamed(endDateParamName));
|
||||
}
|
||||
if (command.parameterExists(introducerRequiredParamName)) {
|
||||
product.setIntroducerRequired(command.booleanPrimitiveValueOfParameterNamed(introducerRequiredParamName));
|
||||
}
|
||||
if (command.parameterExists(shareLinkingEnabledParamName)) {
|
||||
product.setShareLinkingEnabled(command.booleanPrimitiveValueOfParameterNamed(shareLinkingEnabledParamName));
|
||||
}
|
||||
if (command.parameterExists(nominationFacilityParamName)) {
|
||||
product.setNominationFacility(command.booleanPrimitiveValueOfParameterNamed(nominationFacilityParamName));
|
||||
}
|
||||
if (command.parameterExists(dormancyAlertParamName)) {
|
||||
product.setDormancyAlert(command.booleanPrimitiveValueOfParameterNamed(dormancyAlertParamName));
|
||||
}
|
||||
if (command.parameterExists(interestCalculateSelectorParamName)) {
|
||||
product.setInterestCalculateSelector(command.integerValueOfParameterNamed(interestCalculateSelectorParamName));
|
||||
}
|
||||
if (command.parameterExists(averagePeriodParamName)) {
|
||||
product.setAveragePeriod(command.stringValueOfParameterNamed(averagePeriodParamName));
|
||||
}
|
||||
if (command.parameterExists(autoPostParamName)) {
|
||||
product.setAutoPost(command.booleanPrimitiveValueOfParameterNamed(autoPostParamName));
|
||||
}
|
||||
if (command.parameterExists(frequencyFixDayParamName)) {
|
||||
product.setFrequencyFixDay(command.integerValueOfParameterNamed(frequencyFixDayParamName));
|
||||
}
|
||||
if (command.parameterExists(lastInterestDateParamName)) {
|
||||
product.setLastInterestDate(command.localDateValueOfParameterNamed(lastInterestDateParamName));
|
||||
}
|
||||
if (command.parameterExists(enableLockinPeriodParamName)) {
|
||||
product.setEnableLockinPeriod(command.booleanPrimitiveValueOfParameterNamed(enableLockinPeriodParamName));
|
||||
}
|
||||
if (command.parameterExists("balanceFrequency")) {
|
||||
product.setBalanceFrequency(command.stringValueOfParameterNamed("balanceFrequency"));
|
||||
}
|
||||
if (command.parameterExists("accountClosedZeroBalanceInDayClosing")) {
|
||||
product.setAccountClosedZeroBalanceInDayClosing(command.booleanObjectValueOfParameterNamed("accountClosedZeroBalanceInDayClosing"));
|
||||
}
|
||||
|
||||
// New currency-step fields
|
||||
if (command.parameterExists(balanceSwapOptionParamName)) {
|
||||
product.setBalanceSwapOption(command.booleanPrimitiveValueOfParameterNamed(balanceSwapOptionParamName));
|
||||
}
|
||||
if (command.parameterExists(msmeParamName)) {
|
||||
product.setMsme(command.booleanPrimitiveValueOfParameterNamed(msmeParamName));
|
||||
}
|
||||
if (command.parameterExists(autoDebitFacilityParamName)) {
|
||||
product.setAutoDebitFacility(command.booleanPrimitiveValueOfParameterNamed(autoDebitFacilityParamName));
|
||||
}
|
||||
|
||||
// New OD-section fields (only set when overdraft is allowed)
|
||||
if (allowOverdraft) {
|
||||
if (command.parameterExists(avgBalanceCalcPeriodParamName)) {
|
||||
product.setAvgBalanceCalcPeriod(command.stringValueOfParameterNamed(avgBalanceCalcPeriodParamName));
|
||||
}
|
||||
if (command.parameterExists(validForPeriodParamName)) {
|
||||
product.setValidForPeriod(command.stringValueOfParameterNamed(validForPeriodParamName));
|
||||
}
|
||||
if (command.parameterExists(odAccountClosedZeroBalanceInDayClosingParamName)) {
|
||||
product.setOdAccountClosedZeroBalanceInDayClosing(command.booleanPrimitiveValueOfParameterNamed(odAccountClosedZeroBalanceInDayClosingParamName));
|
||||
}
|
||||
}
|
||||
|
||||
return product;
|
||||
}
|
||||
|
||||
public Set<Charge> assembleListOfCurrentProductCharges(final JsonCommand command, final String currencyCode) {
|
||||
final Set<Charge> charges = new HashSet<>();
|
||||
if (command.parameterExists(chargesParamName)) {
|
||||
final JsonArray chargesArray = command.arrayOfParameterNamed(chargesParamName);
|
||||
if (chargesArray != null) {
|
||||
for (int i = 0; i < chargesArray.size(); i++) {
|
||||
final JsonObject jsonObject = chargesArray.get(i).getAsJsonObject();
|
||||
if (jsonObject.has(idParamName)) {
|
||||
final Long id = jsonObject.get(idParamName).getAsLong();
|
||||
final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(id);
|
||||
if (!charge.isSavingsCharge()) {
|
||||
final String errorMessage = "Charge with identifier " + charge.getId()
|
||||
+ " cannot be applied to Current product.";
|
||||
throw new ChargeCannotBeAppliedToException("current.product", errorMessage, charge.getId());
|
||||
}
|
||||
if (!currencyCode.equals(charge.getCurrencyCode())) {
|
||||
final String errorMessage = "Charge and Current Product must have the same currency.";
|
||||
throw new InvalidCurrencyException("charge", "attach.to.current.product", errorMessage);
|
||||
}
|
||||
charges.add(charge);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return charges;
|
||||
}
|
||||
|
||||
public TaxGroup assembleTaxGroup(final JsonCommand command) {
|
||||
final Long taxGroupId = command.longValueOfParameterNamed(taxGroupIdParamName);
|
||||
TaxGroup taxGroup = null;
|
||||
if (taxGroupId != null) {
|
||||
taxGroup = this.taxGroupRepository.findOneWithNotFoundDetection(taxGroupId);
|
||||
}
|
||||
return taxGroup;
|
||||
}
|
||||
|
||||
public CurrentProductFacilityConfig assembleAccountFacilityConfig(final JsonCommand command, final CurrentProduct product) {
|
||||
if (!command.hasParameter(accountFacilityConfigParamName)) {
|
||||
return null;
|
||||
}
|
||||
JsonElement facilityConfigElement = command.parsedJson().getAsJsonObject().get(accountFacilityConfigParamName);
|
||||
if (facilityConfigElement == null || facilityConfigElement.isJsonNull()) {
|
||||
return null;
|
||||
}
|
||||
final JsonObject facilityConfigJson = facilityConfigElement.getAsJsonObject();
|
||||
CurrentProductFacilityConfig config = new CurrentProductFacilityConfig(product);
|
||||
config.setAtmFacility(facilityConfigJson.has("atmFacility") ? facilityConfigJson.get("atmFacility").getAsBoolean() : false);
|
||||
config.setAtmWithdrawalFacility(facilityConfigJson.has("atmWithdrawalFacility") ? facilityConfigJson.get("atmWithdrawalFacility").getAsBoolean() : false);
|
||||
config.setUpiFacility(facilityConfigJson.has("upiFacility") ? facilityConfigJson.get("upiFacility").getAsBoolean() : false);
|
||||
config.setPosTransactionsFacility(facilityConfigJson.has("posTransactionsFacility") ? facilityConfigJson.get("posTransactionsFacility").getAsBoolean() : false);
|
||||
config.setChequeBook(facilityConfigJson.has("chequeBook") ? facilityConfigJson.get("chequeBook").getAsBoolean() : false);
|
||||
config.setImpsFacility(facilityConfigJson.has("impsFacility") ? facilityConfigJson.get("impsFacility").getAsBoolean() : false);
|
||||
config.setSmsAlerts(facilityConfigJson.has("smsAlerts") ? facilityConfigJson.get("smsAlerts").getAsBoolean() : false);
|
||||
config.setBbpsFacility(facilityConfigJson.has("bbpsFacility") ? facilityConfigJson.get("bbpsFacility").getAsBoolean() : false);
|
||||
config.setInsuranceCover(facilityConfigJson.has("insuranceCover") ? facilityConfigJson.get("insuranceCover").getAsBoolean() : false);
|
||||
config.setBepgFacility(facilityConfigJson.has("bepgFacility") ? facilityConfigJson.get("bepgFacility").getAsBoolean() : false);
|
||||
config.setNeftFacility(facilityConfigJson.has("neftFacility") ? facilityConfigJson.get("neftFacility").getAsBoolean() : false);
|
||||
config.setRtgsFacility(facilityConfigJson.has("rtgsFacility") ? facilityConfigJson.get("rtgsFacility").getAsBoolean() : false);
|
||||
config.setInterBankTotalCapFacility(facilityConfigJson.has("interBankTotalCapFacility") ? facilityConfigJson.get("interBankTotalCapFacility").getAsBoolean() : false);
|
||||
config.setWithdrawalFacility(facilityConfigJson.has("withdrawalFacility") ? facilityConfigJson.get("withdrawalFacility").getAsBoolean() : false);
|
||||
config.setDepositFacilityKyc(facilityConfigJson.has("depositFacilityKyc") ? facilityConfigJson.get("depositFacilityKyc").getAsBoolean() : false);
|
||||
config.setVirtualDebitCard(facilityConfigJson.has("virtualDebitCard") ? facilityConfigJson.get("virtualDebitCard").getAsBoolean() : false);
|
||||
return config;
|
||||
}
|
||||
|
||||
public Set<CurrentProductFacilityLimit> assembleAccountFacilityLimits(final JsonCommand command, final CurrentProduct product) {
|
||||
final Set<CurrentProductFacilityLimit> limits = new HashSet<>();
|
||||
if (!command.hasParameter(accountFacilityLimitsParamName)) {
|
||||
return limits;
|
||||
}
|
||||
final JsonArray limitsArray = command.arrayOfParameterNamed(accountFacilityLimitsParamName);
|
||||
if (limitsArray == null) {
|
||||
return limits;
|
||||
}
|
||||
for (int i = 0; i < limitsArray.size(); i++) {
|
||||
final JsonObject limitJson = limitsArray.get(i).getAsJsonObject();
|
||||
limits.add(CurrentProductFacilityLimit.create(product,
|
||||
limitJson.has("limitType") ? limitJson.get("limitType").getAsString() : null,
|
||||
limitJson.has("generalLimit") ? limitJson.get("generalLimit").getAsString() : null,
|
||||
limitJson.has("minorAccountLimit") ? limitJson.get("minorAccountLimit").getAsString() : null,
|
||||
limitJson.has("smallSavingLimit") ? limitJson.get("smallSavingLimit").getAsString() : null));
|
||||
}
|
||||
return limits;
|
||||
}
|
||||
|
||||
public CurrentProductDepositLimitKyc assembleDepositLimitKyc(final JsonCommand command, final CurrentProduct product) {
|
||||
if (!command.hasParameter(depositLimitKycParamName)) {
|
||||
return null;
|
||||
}
|
||||
JsonElement kycElement = command.parsedJson().getAsJsonObject().get(depositLimitKycParamName);
|
||||
if (kycElement == null || kycElement.isJsonNull()) {
|
||||
return null;
|
||||
}
|
||||
final JsonObject kycJson = kycElement.getAsJsonObject();
|
||||
CurrentProductDepositLimitKyc kyc = new CurrentProductDepositLimitKyc(product);
|
||||
if (kycJson.has("general")) {
|
||||
final JsonObject generalJson = kycJson.getAsJsonObject("general");
|
||||
kyc.setGeneralKycType(generalJson.has("kycType") ? generalJson.get("kycType").getAsString() : null);
|
||||
kyc.setGeneralLimit(generalJson.has("limit") ? generalJson.get("limit").getAsString() : null);
|
||||
}
|
||||
if (kycJson.has("minor")) {
|
||||
final JsonObject minorJson = kycJson.getAsJsonObject("minor");
|
||||
kyc.setMinorKycType(minorJson.has("kycType") ? minorJson.get("kycType").getAsString() : null);
|
||||
kyc.setMinorLimit(minorJson.has("limit") ? minorJson.get("limit").getAsLong() : null);
|
||||
}
|
||||
if (kycJson.has("smallSaving")) {
|
||||
final JsonObject smallSavingJson = kycJson.getAsJsonObject("smallSaving");
|
||||
kyc.setSmallSavingKycType(smallSavingJson.has("kycType") ? smallSavingJson.get("kycType").getAsString() : null);
|
||||
kyc.setSmallSavingLimit(smallSavingJson.has("limit") ? smallSavingJson.get("limit").getAsLong() : null);
|
||||
}
|
||||
return kyc;
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* 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.currentproduct.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDateTime;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_current_product_deposit_limit_kyc")
|
||||
public class CurrentProductDepositLimitKyc extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "current_product_id", nullable = false)
|
||||
private CurrentProduct currentProduct;
|
||||
|
||||
@Column(name = "general_kyc_type", length = 50)
|
||||
private String generalKycType;
|
||||
|
||||
@Column(name = "general_limit", length = 50)
|
||||
private String generalLimit;
|
||||
|
||||
@Column(name = "minor_kyc_type", length = 50)
|
||||
private String minorKycType;
|
||||
|
||||
@Column(name = "minor_limit")
|
||||
private Long minorLimit;
|
||||
|
||||
@Column(name = "small_saving_kyc_type", length = 50)
|
||||
private String smallSavingKycType;
|
||||
|
||||
@Column(name = "small_saving_limit")
|
||||
private Long smallSavingLimit;
|
||||
|
||||
@Column(name = "created_date", nullable = false)
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
protected CurrentProductDepositLimitKyc() {
|
||||
this.createdDate = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public CurrentProductDepositLimitKyc(CurrentProduct currentProduct) {
|
||||
this();
|
||||
this.currentProduct = currentProduct;
|
||||
}
|
||||
|
||||
public CurrentProduct getCurrentProduct() { return currentProduct; }
|
||||
public void setCurrentProduct(CurrentProduct currentProduct) { this.currentProduct = currentProduct; }
|
||||
public String getGeneralKycType() { return generalKycType; }
|
||||
public void setGeneralKycType(String generalKycType) { this.generalKycType = generalKycType; }
|
||||
public String getGeneralLimit() { return generalLimit; }
|
||||
public void setGeneralLimit(String generalLimit) { this.generalLimit = generalLimit; }
|
||||
public String getMinorKycType() { return minorKycType; }
|
||||
public void setMinorKycType(String minorKycType) { this.minorKycType = minorKycType; }
|
||||
public Long getMinorLimit() { return minorLimit; }
|
||||
public void setMinorLimit(Long minorLimit) { this.minorLimit = minorLimit; }
|
||||
public String getSmallSavingKycType() { return smallSavingKycType; }
|
||||
public void setSmallSavingKycType(String smallSavingKycType) { this.smallSavingKycType = smallSavingKycType; }
|
||||
public Long getSmallSavingLimit() { return smallSavingLimit; }
|
||||
public void setSmallSavingLimit(Long smallSavingLimit) { this.smallSavingLimit = smallSavingLimit; }
|
||||
public LocalDateTime getCreatedDate() { return createdDate; }
|
||||
|
||||
public void updateFrom(CurrentProductDepositLimitKyc other) {
|
||||
this.generalKycType = other.getGeneralKycType();
|
||||
this.generalLimit = other.getGeneralLimit();
|
||||
this.minorKycType = other.getMinorKycType();
|
||||
this.minorLimit = other.getMinorLimit();
|
||||
this.smallSavingKycType = other.getSmallSavingKycType();
|
||||
this.smallSavingLimit = other.getSmallSavingLimit();
|
||||
}
|
||||
}
|
||||
+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.currentproduct.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface CurrentProductDepositLimitKycRepository extends JpaRepository<CurrentProductDepositLimitKyc, Long> {
|
||||
|
||||
CurrentProductDepositLimitKyc findByCurrentProductId(Long currentProductId);
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* 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.currentproduct.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDateTime;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_current_product_facility_config")
|
||||
public class CurrentProductFacilityConfig extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "current_product_id", nullable = false)
|
||||
private CurrentProduct currentProduct;
|
||||
|
||||
@Column(name = "atm_facility")
|
||||
private Boolean atmFacility = false;
|
||||
|
||||
@Column(name = "atm_withdrawal_facility")
|
||||
private Boolean atmWithdrawalFacility = false;
|
||||
|
||||
@Column(name = "upi_facility")
|
||||
private Boolean upiFacility = false;
|
||||
|
||||
@Column(name = "pos_transactions_facility")
|
||||
private Boolean posTransactionsFacility = false;
|
||||
|
||||
@Column(name = "cheque_book")
|
||||
private Boolean chequeBook = false;
|
||||
|
||||
@Column(name = "imps_facility")
|
||||
private Boolean impsFacility = false;
|
||||
|
||||
@Column(name = "sms_alerts")
|
||||
private Boolean smsAlerts = false;
|
||||
|
||||
@Column(name = "bbps_facility")
|
||||
private Boolean bbpsFacility = false;
|
||||
|
||||
@Column(name = "insurance_cover")
|
||||
private Boolean insuranceCover = false;
|
||||
|
||||
@Column(name = "bepg_facility")
|
||||
private Boolean bepgFacility = false;
|
||||
|
||||
@Column(name = "neft_facility")
|
||||
private Boolean neftFacility = false;
|
||||
|
||||
@Column(name = "rtgs_facility")
|
||||
private Boolean rtgsFacility = false;
|
||||
|
||||
@Column(name = "inter_bank_total_cap_facility")
|
||||
private Boolean interBankTotalCapFacility = false;
|
||||
|
||||
@Column(name = "withdrawal_facility")
|
||||
private Boolean withdrawalFacility = false;
|
||||
|
||||
@Column(name = "deposit_facility_kyc")
|
||||
private Boolean depositFacilityKyc = false;
|
||||
|
||||
@Column(name = "virtual_debit_card")
|
||||
private Boolean virtualDebitCard = false;
|
||||
|
||||
@Column(name = "created_date", nullable = false)
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
protected CurrentProductFacilityConfig() {
|
||||
this.createdDate = LocalDateTime.now();
|
||||
}
|
||||
|
||||
public CurrentProductFacilityConfig(CurrentProduct currentProduct) {
|
||||
this();
|
||||
this.currentProduct = currentProduct;
|
||||
}
|
||||
|
||||
public CurrentProduct getCurrentProduct() { return currentProduct; }
|
||||
public void setCurrentProduct(CurrentProduct currentProduct) { this.currentProduct = currentProduct; }
|
||||
|
||||
public Boolean getAtmFacility() { return atmFacility; }
|
||||
public void setAtmFacility(Boolean v) { this.atmFacility = v != null ? v : false; }
|
||||
public Boolean getAtmWithdrawalFacility() { return atmWithdrawalFacility; }
|
||||
public void setAtmWithdrawalFacility(Boolean v) { this.atmWithdrawalFacility = v != null ? v : false; }
|
||||
public Boolean getUpiFacility() { return upiFacility; }
|
||||
public void setUpiFacility(Boolean v) { this.upiFacility = v != null ? v : false; }
|
||||
public Boolean getPosTransactionsFacility() { return posTransactionsFacility; }
|
||||
public void setPosTransactionsFacility(Boolean v) { this.posTransactionsFacility = v != null ? v : false; }
|
||||
public Boolean getChequeBook() { return chequeBook; }
|
||||
public void setChequeBook(Boolean v) { this.chequeBook = v != null ? v : false; }
|
||||
public Boolean getImpsFacility() { return impsFacility; }
|
||||
public void setImpsFacility(Boolean v) { this.impsFacility = v != null ? v : false; }
|
||||
public Boolean getSmsAlerts() { return smsAlerts; }
|
||||
public void setSmsAlerts(Boolean v) { this.smsAlerts = v != null ? v : false; }
|
||||
public Boolean getBbpsFacility() { return bbpsFacility; }
|
||||
public void setBbpsFacility(Boolean v) { this.bbpsFacility = v != null ? v : false; }
|
||||
public Boolean getInsuranceCover() { return insuranceCover; }
|
||||
public void setInsuranceCover(Boolean v) { this.insuranceCover = v != null ? v : false; }
|
||||
public Boolean getBepgFacility() { return bepgFacility; }
|
||||
public void setBepgFacility(Boolean v) { this.bepgFacility = v != null ? v : false; }
|
||||
public Boolean getNeftFacility() { return neftFacility; }
|
||||
public void setNeftFacility(Boolean v) { this.neftFacility = v != null ? v : false; }
|
||||
public Boolean getRtgsFacility() { return rtgsFacility; }
|
||||
public void setRtgsFacility(Boolean v) { this.rtgsFacility = v != null ? v : false; }
|
||||
public Boolean getInterBankTotalCapFacility() { return interBankTotalCapFacility; }
|
||||
public void setInterBankTotalCapFacility(Boolean v) { this.interBankTotalCapFacility = v != null ? v : false; }
|
||||
public Boolean getWithdrawalFacility() { return withdrawalFacility; }
|
||||
public void setWithdrawalFacility(Boolean v) { this.withdrawalFacility = v != null ? v : false; }
|
||||
public Boolean getDepositFacilityKyc() { return depositFacilityKyc; }
|
||||
public void setDepositFacilityKyc(Boolean v) { this.depositFacilityKyc = v != null ? v : false; }
|
||||
public Boolean getVirtualDebitCard() { return virtualDebitCard; }
|
||||
public void setVirtualDebitCard(Boolean v) { this.virtualDebitCard = v != null ? v : false; }
|
||||
public LocalDateTime getCreatedDate() { return createdDate; }
|
||||
|
||||
public void updateFrom(CurrentProductFacilityConfig other) {
|
||||
this.atmFacility = other.getAtmFacility();
|
||||
this.atmWithdrawalFacility = other.getAtmWithdrawalFacility();
|
||||
this.upiFacility = other.getUpiFacility();
|
||||
this.posTransactionsFacility = other.getPosTransactionsFacility();
|
||||
this.chequeBook = other.getChequeBook();
|
||||
this.impsFacility = other.getImpsFacility();
|
||||
this.smsAlerts = other.getSmsAlerts();
|
||||
this.bbpsFacility = other.getBbpsFacility();
|
||||
this.insuranceCover = other.getInsuranceCover();
|
||||
this.bepgFacility = other.getBepgFacility();
|
||||
this.neftFacility = other.getNeftFacility();
|
||||
this.rtgsFacility = other.getRtgsFacility();
|
||||
this.interBankTotalCapFacility = other.getInterBankTotalCapFacility();
|
||||
this.withdrawalFacility = other.getWithdrawalFacility();
|
||||
this.depositFacilityKyc = other.getDepositFacilityKyc();
|
||||
this.virtualDebitCard = other.getVirtualDebitCard();
|
||||
}
|
||||
}
|
||||
+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.currentproduct.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface CurrentProductFacilityConfigRepository extends JpaRepository<CurrentProductFacilityConfig, Long> {
|
||||
|
||||
CurrentProductFacilityConfig findByCurrentProductId(Long currentProductId);
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 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.currentproduct.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDateTime;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_current_product_facility_limits")
|
||||
public class CurrentProductFacilityLimit extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "current_product_id", nullable = false)
|
||||
private CurrentProduct currentProduct;
|
||||
|
||||
@Column(name = "limit_type", length = 100, nullable = false)
|
||||
private String limitType;
|
||||
|
||||
@Column(name = "general_limit", length = 50)
|
||||
private String generalLimit;
|
||||
|
||||
@Column(name = "minor_account_limit", length = 50)
|
||||
private String minorAccountLimit;
|
||||
|
||||
@Column(name = "small_saving_limit", length = 50)
|
||||
private String smallSavingLimit;
|
||||
|
||||
@Column(name = "created_date", nullable = false)
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
protected CurrentProductFacilityLimit() {
|
||||
this.createdDate = LocalDateTime.now();
|
||||
}
|
||||
|
||||
private CurrentProductFacilityLimit(CurrentProduct currentProduct, String limitType,
|
||||
String generalLimit, String minorAccountLimit, String smallSavingLimit) {
|
||||
this();
|
||||
this.currentProduct = currentProduct;
|
||||
this.limitType = limitType;
|
||||
this.generalLimit = generalLimit;
|
||||
this.minorAccountLimit = minorAccountLimit;
|
||||
this.smallSavingLimit = smallSavingLimit;
|
||||
}
|
||||
|
||||
public static CurrentProductFacilityLimit create(CurrentProduct currentProduct, String limitType,
|
||||
String generalLimit, String minorAccountLimit, String smallSavingLimit) {
|
||||
return new CurrentProductFacilityLimit(currentProduct, limitType, generalLimit, minorAccountLimit, smallSavingLimit);
|
||||
}
|
||||
|
||||
public CurrentProduct getCurrentProduct() { return currentProduct; }
|
||||
public void setCurrentProduct(CurrentProduct currentProduct) { this.currentProduct = currentProduct; }
|
||||
public String getLimitType() { return limitType; }
|
||||
public void setLimitType(String limitType) { this.limitType = limitType; }
|
||||
public String getGeneralLimit() { return generalLimit; }
|
||||
public void setGeneralLimit(String generalLimit) { this.generalLimit = generalLimit; }
|
||||
public String getMinorAccountLimit() { return minorAccountLimit; }
|
||||
public void setMinorAccountLimit(String minorAccountLimit) { this.minorAccountLimit = minorAccountLimit; }
|
||||
public String getSmallSavingLimit() { return smallSavingLimit; }
|
||||
public void setSmallSavingLimit(String smallSavingLimit) { this.smallSavingLimit = smallSavingLimit; }
|
||||
public LocalDateTime getCreatedDate() { return createdDate; }
|
||||
}
|
||||
+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.portfolio.currentproduct.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public interface CurrentProductFacilityLimitRepository extends JpaRepository<CurrentProductFacilityLimit, Long> {
|
||||
|
||||
List<CurrentProductFacilityLimit> findByCurrentProductId(Long currentProductId);
|
||||
|
||||
@Transactional
|
||||
void deleteByCurrentProductId(Long currentProductId);
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.currentproduct.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface CurrentProductRepository extends JpaRepository<CurrentProduct, Long>, JpaSpecificationExecutor<CurrentProduct> {
|
||||
}
|
||||
+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.portfolio.currentproduct.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
|
||||
|
||||
public interface CurrentProductReadPlatformService {
|
||||
|
||||
Collection<SavingsProductData> retrieveAll();
|
||||
|
||||
Collection<SavingsProductData> retrieveAllForLookup();
|
||||
|
||||
SavingsProductData retrieveOne(Long productId);
|
||||
}
|
||||
+346
@@ -0,0 +1,346 @@
|
||||
/**
|
||||
* 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.currentproduct.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.common.AccountingEnumerations;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductDepositLimitKyc;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductDepositLimitKycRepository;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityConfig;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityConfigRepository;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityLimit;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityLimitRepository;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
|
||||
import org.apache.fineract.portfolio.savings.exception.SavingsProductNotFoundException;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class CurrentProductReadPlatformServiceImpl implements CurrentProductReadPlatformService {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final CurrentProductFacilityConfigRepository facilityConfigRepository;
|
||||
private final CurrentProductFacilityLimitRepository facilityLimitRepository;
|
||||
private final CurrentProductDepositLimitKycRepository depositLimitKycRepository;
|
||||
|
||||
private final CurrentProductMapper currentProductRowMapper = new CurrentProductMapper();
|
||||
private final CurrentProductLookupMapper currentProductLookupsRowMapper = new CurrentProductLookupMapper();
|
||||
|
||||
private static final Gson GSON = new Gson();
|
||||
private static final Type OTHER_GL_MAPPINGS_TYPE = new TypeToken<Map<String, List<Map<String, Object>>>>() {}.getType();
|
||||
|
||||
@Override
|
||||
public Collection<SavingsProductData> retrieveAll() {
|
||||
this.context.authenticatedUser();
|
||||
final String sql = "select " + this.currentProductRowMapper.schema();
|
||||
return this.jdbcTemplate.query(sql, this.currentProductRowMapper); // NOSONAR
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SavingsProductData> retrieveAllForLookup() {
|
||||
final String sql = "select " + this.currentProductLookupsRowMapper.schema();
|
||||
return this.jdbcTemplate.query(sql, this.currentProductLookupsRowMapper); // NOSONAR
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingsProductData retrieveOne(final Long productId) {
|
||||
try {
|
||||
this.context.authenticatedUser();
|
||||
final String sql = "select " + this.currentProductRowMapper.schema() + " where cp.id = ?";
|
||||
SavingsProductData product = this.jdbcTemplate.queryForObject(sql, this.currentProductRowMapper, // NOSONAR
|
||||
new Object[] { productId });
|
||||
|
||||
if (product != null) {
|
||||
// Fetch Facility Config
|
||||
CurrentProductFacilityConfig facilityConfig = facilityConfigRepository.findByCurrentProductId(productId);
|
||||
if (facilityConfig != null) {
|
||||
Map<String, Object> facilityConfigMap = new HashMap<>();
|
||||
facilityConfigMap.put("atmFacility", facilityConfig.getAtmFacility());
|
||||
facilityConfigMap.put("atmWithdrawalFacility", facilityConfig.getAtmWithdrawalFacility());
|
||||
facilityConfigMap.put("upiFacility", facilityConfig.getUpiFacility());
|
||||
facilityConfigMap.put("posTransactionsFacility", facilityConfig.getPosTransactionsFacility());
|
||||
facilityConfigMap.put("chequeBook", facilityConfig.getChequeBook());
|
||||
facilityConfigMap.put("impsFacility", facilityConfig.getImpsFacility());
|
||||
facilityConfigMap.put("smsAlerts", facilityConfig.getSmsAlerts());
|
||||
facilityConfigMap.put("bbpsFacility", facilityConfig.getBbpsFacility());
|
||||
facilityConfigMap.put("insuranceCover", facilityConfig.getInsuranceCover());
|
||||
facilityConfigMap.put("bepgFacility", facilityConfig.getBepgFacility());
|
||||
facilityConfigMap.put("neftFacility", facilityConfig.getNeftFacility());
|
||||
facilityConfigMap.put("rtgsFacility", facilityConfig.getRtgsFacility());
|
||||
facilityConfigMap.put("interBankTotalCapFacility", facilityConfig.getInterBankTotalCapFacility());
|
||||
facilityConfigMap.put("withdrawalFacility", facilityConfig.getWithdrawalFacility());
|
||||
facilityConfigMap.put("depositFacilityKyc", facilityConfig.getDepositFacilityKyc());
|
||||
facilityConfigMap.put("virtualDebitCard", facilityConfig.getVirtualDebitCard());
|
||||
product.setAccountFacilityConfig(facilityConfigMap);
|
||||
}
|
||||
|
||||
// Fetch Facility Limits
|
||||
List<CurrentProductFacilityLimit> facilityLimits = facilityLimitRepository.findByCurrentProductId(productId);
|
||||
if (facilityLimits != null && !facilityLimits.isEmpty()) {
|
||||
List<Map<String, Object>> limits = facilityLimits.stream().map(limit -> {
|
||||
Map<String, Object> limitMap = new HashMap<>();
|
||||
limitMap.put("limitType", limit.getLimitType());
|
||||
limitMap.put("generalLimit", limit.getGeneralLimit());
|
||||
limitMap.put("minorAccountLimit", limit.getMinorAccountLimit());
|
||||
limitMap.put("smallSavingLimit", limit.getSmallSavingLimit());
|
||||
return limitMap;
|
||||
}).toList();
|
||||
product.setAccountFacilityLimits(limits);
|
||||
}
|
||||
|
||||
// Fetch Deposit Limit KYC
|
||||
CurrentProductDepositLimitKyc depositLimitKyc = depositLimitKycRepository.findByCurrentProductId(productId);
|
||||
if (depositLimitKyc != null) {
|
||||
Map<String, Object> depositLimitKycMap = new HashMap<>();
|
||||
depositLimitKycMap.put("general", Map.of(
|
||||
"kycType", depositLimitKyc.getGeneralKycType() != null ? depositLimitKyc.getGeneralKycType() : "",
|
||||
"limit", depositLimitKyc.getGeneralLimit() != null ? depositLimitKyc.getGeneralLimit() : ""));
|
||||
depositLimitKycMap.put("minor", Map.of(
|
||||
"kycType", depositLimitKyc.getMinorKycType() != null ? depositLimitKyc.getMinorKycType() : "",
|
||||
"limit", depositLimitKyc.getMinorLimit() != null ? depositLimitKyc.getMinorLimit() : 0L));
|
||||
depositLimitKycMap.put("smallSaving", Map.of(
|
||||
"kycType", depositLimitKyc.getSmallSavingKycType() != null ? depositLimitKyc.getSmallSavingKycType() : "",
|
||||
"limit", depositLimitKyc.getSmallSavingLimit() != null ? depositLimitKyc.getSmallSavingLimit() : 0L));
|
||||
product.setDepositLimitKyc(depositLimitKycMap);
|
||||
}
|
||||
}
|
||||
|
||||
return product;
|
||||
} catch (final EmptyResultDataAccessException e) {
|
||||
throw new SavingsProductNotFoundException(productId, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CurrentProductMapper implements RowMapper<SavingsProductData> {
|
||||
|
||||
private final String schemaSql;
|
||||
|
||||
CurrentProductMapper() {
|
||||
final StringBuilder sqlBuilder = new StringBuilder(1000);
|
||||
sqlBuilder.append("cp.id as id, cp.name as name, cp.short_name as shortName, cp.description as description, ");
|
||||
sqlBuilder.append(
|
||||
"cp.currency_code as currencyCode, cp.currency_digits as currencyDigits, cp.currency_multiplesof as inMultiplesOf, ");
|
||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
|
||||
sqlBuilder.append("cp.nominal_annual_interest_rate as nominalAnnualInterestRate, ");
|
||||
sqlBuilder.append("cp.interest_compounding_period_enum as compoundingInterestPeriodType, ");
|
||||
sqlBuilder.append("cp.interest_posting_period_enum as interestPostingPeriodType, ");
|
||||
sqlBuilder.append("cp.interest_calculation_type_enum as interestCalculationType, ");
|
||||
sqlBuilder.append("cp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
|
||||
sqlBuilder.append("cp.min_required_opening_balance as minRequiredOpeningBalance, ");
|
||||
sqlBuilder.append("cp.lockin_period_frequency as lockinPeriodFrequency,");
|
||||
sqlBuilder.append("cp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
sqlBuilder.append("cp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, ");
|
||||
sqlBuilder.append("cp.allow_overdraft as allowOverdraft, ");
|
||||
sqlBuilder.append("cp.overdraft_limit as overdraftLimit, ");
|
||||
sqlBuilder.append("cp.nominal_annual_interest_rate_overdraft as nominalAnnualInterestRateOverdraft, ");
|
||||
sqlBuilder.append("cp.min_overdraft_for_interest_calculation as minOverdraftForInterestCalculation, ");
|
||||
sqlBuilder.append("cp.min_required_balance as minRequiredBalance, ");
|
||||
sqlBuilder.append("cp.enforce_min_required_balance as enforceMinRequiredBalance, ");
|
||||
sqlBuilder.append("cp.max_allowed_lien_limit as maxAllowedLienLimit, ");
|
||||
sqlBuilder.append("cp.is_lien_allowed as lienAllowed, ");
|
||||
sqlBuilder.append("cp.min_balance_for_interest_calculation as minBalanceForInterestCalculation,");
|
||||
sqlBuilder.append("cp.accounting_type as accountingType, ");
|
||||
sqlBuilder.append("cp.withhold_tax as withHoldTax,");
|
||||
sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName, ");
|
||||
sqlBuilder.append("cp.is_dormancy_tracking_active as isDormancyTrackingActive,");
|
||||
sqlBuilder.append("cp.days_to_inactive as daysToInactive,");
|
||||
sqlBuilder.append("cp.days_to_dormancy as daysToDormancy,");
|
||||
sqlBuilder.append("cp.days_to_escheat as daysToEscheat, ");
|
||||
sqlBuilder.append("cp.other_gl_mappings as otherGlMappings, ");
|
||||
|
||||
// Enhanced fields
|
||||
sqlBuilder.append("cp.account_type as accountType, cp.customer_segment as customerSegment, cp.product_code as productCode, ");
|
||||
sqlBuilder.append("cp.effective_date as effectiveDate, cp.effective_to as effectiveTo, cp.end_date as endDate, ");
|
||||
sqlBuilder.append("cp.introducer_required as introducerRequired, cp.share_linking_enabled as shareLinkingEnabled, ");
|
||||
sqlBuilder.append("cp.nomination_facility as nominationFacility, cp.dormancy_alert as dormancyAlert, ");
|
||||
sqlBuilder.append("cp.interest_calculate_selector as interestCalculateSelector, cp.average_period as averagePeriod, ");
|
||||
sqlBuilder.append("cp.auto_post as autoPost, cp.frequency_fix_day as frequencyFixDay, cp.last_interest_date as lastInterestDate, ");
|
||||
sqlBuilder.append("cp.enable_lockin_period as enableLockinPeriod, ");
|
||||
sqlBuilder.append("cp.balance_frequency as balanceFrequency, ");
|
||||
sqlBuilder.append("cp.account_closed_zero_balance_in_day_closing as accountClosedZeroBalanceInDayClosing, ");
|
||||
sqlBuilder.append("cp.balance_swap_option as balanceSwapOption, cp.msme as msme, cp.auto_debit_facility as autoDebitFacility, ");
|
||||
sqlBuilder.append("cp.avg_balance_calc_period as avgBalanceCalcPeriod, cp.valid_for_period as validForPeriod, ");
|
||||
sqlBuilder.append("cp.od_account_closed_zero_balance_in_day_closing as odAccountClosedZeroBalanceInDayClosing ");
|
||||
|
||||
sqlBuilder.append("from m_current_product cp ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = cp.currency_code ");
|
||||
sqlBuilder.append("left join m_tax_group tg on tg.id = cp.tax_group_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingsProductData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long id = rs.getLong("id");
|
||||
final String name = rs.getString("name");
|
||||
final String shortName = rs.getString("shortName");
|
||||
final String description = rs.getString("description");
|
||||
|
||||
final String currencyCode = rs.getString("currencyCode");
|
||||
final String currencyName = rs.getString("currencyName");
|
||||
final String currencyNameCode = rs.getString("currencyNameCode");
|
||||
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
|
||||
final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf, currencyDisplaySymbol,
|
||||
currencyNameCode);
|
||||
|
||||
final BigDecimal nominalAnnualInterestRate = rs.getBigDecimal("nominalAnnualInterestRate");
|
||||
|
||||
final Integer compoundingInterestPeriodTypeValue = JdbcSupport.getInteger(rs, "compoundingInterestPeriodType");
|
||||
final EnumOptionData compoundingInterestPeriodType = SavingsEnumerations
|
||||
.compoundingInterestPeriodType(compoundingInterestPeriodTypeValue);
|
||||
|
||||
final Integer interestPostingPeriodTypeValue = JdbcSupport.getInteger(rs, "interestPostingPeriodType");
|
||||
final EnumOptionData interestPostingPeriodType = SavingsEnumerations.interestPostingPeriodType(interestPostingPeriodTypeValue);
|
||||
|
||||
final Integer interestCalculationTypeValue = JdbcSupport.getInteger(rs, "interestCalculationType");
|
||||
final EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(interestCalculationTypeValue);
|
||||
|
||||
EnumOptionData interestCalculationDaysInYearType = null;
|
||||
final Integer interestCalculationDaysInYearTypeValue = JdbcSupport.getInteger(rs, "interestCalculationDaysInYearType");
|
||||
if (interestCalculationDaysInYearTypeValue != null) {
|
||||
interestCalculationDaysInYearType = SavingsEnumerations
|
||||
.interestCalculationDaysInYearType(interestCalculationDaysInYearTypeValue);
|
||||
}
|
||||
|
||||
final Integer accountingRuleId = JdbcSupport.getInteger(rs, "accountingType");
|
||||
final EnumOptionData accountingRuleType = AccountingEnumerations.accountingRuleType(accountingRuleId);
|
||||
|
||||
final BigDecimal minRequiredOpeningBalance = rs.getBigDecimal("minRequiredOpeningBalance");
|
||||
|
||||
final Integer lockinPeriodFrequency = JdbcSupport.getInteger(rs, "lockinPeriodFrequency");
|
||||
EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final Integer lockinPeriodFrequencyTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodFrequencyType");
|
||||
if (lockinPeriodFrequencyTypeValue != null) {
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodFrequencyTypeValue);
|
||||
}
|
||||
|
||||
final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers");
|
||||
final boolean allowOverdraft = rs.getBoolean("allowOverdraft");
|
||||
final BigDecimal overdraftLimit = rs.getBigDecimal("overdraftLimit");
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft = rs.getBigDecimal("nominalAnnualInterestRateOverdraft");
|
||||
final BigDecimal minOverdraftForInterestCalculation = rs.getBigDecimal("minOverdraftForInterestCalculation");
|
||||
|
||||
final BigDecimal minRequiredBalance = rs.getBigDecimal("minRequiredBalance");
|
||||
final boolean enforceMinRequiredBalance = rs.getBoolean("enforceMinRequiredBalance");
|
||||
final BigDecimal maxAllowedLienLimit = rs.getBigDecimal("maxAllowedLienLimit");
|
||||
final boolean lienAllowed = rs.getBoolean("lienAllowed");
|
||||
final BigDecimal minBalanceForInterestCalculation = rs.getBigDecimal("minBalanceForInterestCalculation");
|
||||
|
||||
final boolean withHoldTax = rs.getBoolean("withHoldTax");
|
||||
final Long taxGroupId = JdbcSupport.getLong(rs, "taxGroupId");
|
||||
final String taxGroupName = rs.getString("taxGroupName");
|
||||
TaxGroupData taxGroupData = null;
|
||||
if (taxGroupId != null) {
|
||||
taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
|
||||
}
|
||||
|
||||
final Boolean isDormancyTrackingActive = rs.getBoolean("isDormancyTrackingActive");
|
||||
final Long daysToInactive = JdbcSupport.getLong(rs, "daysToInactive");
|
||||
final Long daysToDormancy = JdbcSupport.getLong(rs, "daysToDormancy");
|
||||
final Long daysToEscheat = JdbcSupport.getLong(rs, "daysToEscheat");
|
||||
final Map<String, List<Map<String, Object>>> otherGlMappings = parseOtherGlMappings(rs.getString("otherGlMappings"));
|
||||
|
||||
SavingsProductData productData = SavingsProductData.instance(id, name, shortName, description, currency,
|
||||
nominalAnnualInterestRate, compoundingInterestPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeForTransfers, accountingRuleType, allowOverdraft, overdraftLimit, minRequiredBalance,
|
||||
enforceMinRequiredBalance, maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation,
|
||||
nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax, taxGroupData, null, null, null,
|
||||
isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat, null);
|
||||
productData.setOtherGlMappingsMap(otherGlMappings);
|
||||
|
||||
// Populate Enhanced Fields
|
||||
productData.setAccountType(rs.getString("accountType"));
|
||||
productData.setCustomerSegment(rs.getString("customerSegment"));
|
||||
productData.setProductCode(rs.getString("productCode"));
|
||||
productData.setEffectiveDate(JdbcSupport.getLocalDate(rs, "effectiveDate"));
|
||||
productData.setEffectiveTo(JdbcSupport.getLocalDate(rs, "effectiveTo"));
|
||||
productData.setEndDate(JdbcSupport.getLocalDate(rs, "endDate"));
|
||||
productData.setIntroducerRequired(rs.getBoolean("introducerRequired"));
|
||||
productData.setShareLinkingEnabled(rs.getBoolean("shareLinkingEnabled"));
|
||||
productData.setNominationFacility(rs.getBoolean("nominationFacility"));
|
||||
productData.setDormancyAlert(rs.getBoolean("dormancyAlert"));
|
||||
productData.setInterestCalculateSelector(JdbcSupport.getInteger(rs, "interestCalculateSelector"));
|
||||
productData.setAveragePeriod(rs.getString("averagePeriod"));
|
||||
productData.setAutoPost(rs.getBoolean("autoPost"));
|
||||
productData.setFrequencyFixDay(JdbcSupport.getInteger(rs, "frequencyFixDay"));
|
||||
productData.setLastInterestDate(JdbcSupport.getLocalDate(rs, "lastInterestDate"));
|
||||
productData.setEnableLockinPeriod(rs.getBoolean("enableLockinPeriod"));
|
||||
productData.setBalanceFrequency(rs.getString("balanceFrequency"));
|
||||
productData.setAccountClosedZeroBalanceInDayClosing(rs.getBoolean("accountClosedZeroBalanceInDayClosing"));
|
||||
productData.setBalanceSwapOption(rs.getBoolean("balanceSwapOption"));
|
||||
productData.setMsme(rs.getBoolean("msme"));
|
||||
productData.setAutoDebitFacility(rs.getBoolean("autoDebitFacility"));
|
||||
productData.setAvgBalanceCalcPeriod(rs.getString("avgBalanceCalcPeriod"));
|
||||
productData.setValidForPeriod(rs.getString("validForPeriod"));
|
||||
productData.setOdAccountClosedZeroBalanceInDayClosing(rs.getBoolean("odAccountClosedZeroBalanceInDayClosing"));
|
||||
|
||||
return productData;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CurrentProductLookupMapper implements RowMapper<SavingsProductData> {
|
||||
|
||||
public String schema() {
|
||||
return " cp.id as id, cp.name as name from m_current_product cp";
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingsProductData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
final Long id = rs.getLong("id");
|
||||
final String name = rs.getString("name");
|
||||
return SavingsProductData.lookup(id, name);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, List<Map<String, Object>>> parseOtherGlMappings(final String otherGlMappingsJson) {
|
||||
if (otherGlMappingsJson == null || otherGlMappingsJson.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
return GSON.fromJson(otherGlMappingsJson, OTHER_GL_MAPPINGS_TYPE);
|
||||
}
|
||||
}
|
||||
+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.portfolio.currentproduct.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
public interface CurrentProductWritePlatformService {
|
||||
|
||||
CommandProcessingResult create(JsonCommand command);
|
||||
|
||||
CommandProcessingResult update(Long productId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult delete(Long productId);
|
||||
}
|
||||
+267
@@ -0,0 +1,267 @@
|
||||
/**
|
||||
* 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.currentproduct.service;
|
||||
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountingRuleParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.chargesParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
|
||||
|
||||
import jakarta.persistence.PersistenceException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.service.ProductToGLAccountMappingWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.charge.domain.Charge;
|
||||
import org.apache.fineract.portfolio.currentproduct.data.CurrentProductDataValidator;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProduct;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductAssembler;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductDepositLimitKyc;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductDepositLimitKycRepository;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityConfig;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityConfigRepository;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityLimit;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityLimitRepository;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductRepository;
|
||||
import org.apache.fineract.portfolio.savings.DepositsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
import org.apache.fineract.portfolio.savings.exception.SavingsProductNotFoundException;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroup;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class CurrentProductWritePlatformServiceJpaRepositoryImpl implements CurrentProductWritePlatformService {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final CurrentProductRepository currentProductRepository;
|
||||
private final CurrentProductDataValidator fromApiJsonDataValidator;
|
||||
private final CurrentProductAssembler currentProductAssembler;
|
||||
private final ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService;
|
||||
private final CurrentProductFacilityConfigRepository facilityConfigRepository;
|
||||
private final CurrentProductFacilityLimitRepository facilityLimitRepository;
|
||||
private final CurrentProductDepositLimitKycRepository depositLimitKycRepository;
|
||||
|
||||
private void handleDataIntegrityIssues(final JsonCommand command, final Throwable realCause, final Exception dae) {
|
||||
String msgCode = "error.msg." + DepositsApiConstants.CURRENT_PRODUCT_RESOURCE_NAME;
|
||||
String msg = "Unknown data integrity issue with current product.";
|
||||
String param = null;
|
||||
Object[] msgArgs;
|
||||
Throwable checkEx = realCause == null ? dae : realCause;
|
||||
if (checkEx.getMessage().contains("cp_unq_name")) {
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
msgCode += ".duplicate.name";
|
||||
msg = "Current product with name `" + name + "` already exists";
|
||||
param = "name";
|
||||
msgArgs = new Object[] { name, dae };
|
||||
} else if (checkEx.getMessage().contains("cp_unq_short_name")) {
|
||||
final String shortName = command.stringValueOfParameterNamed("shortName");
|
||||
msgCode += ".duplicate.short.name";
|
||||
msg = "Current product with short name `" + shortName + "` already exists";
|
||||
param = "shortName";
|
||||
msgArgs = new Object[] { shortName, dae };
|
||||
} else if (checkEx.getMessage().contains("cp_unq_product_code")) {
|
||||
final String productCode = command.stringValueOfParameterNamed("productCode");
|
||||
msgCode += ".duplicate.product.code";
|
||||
msg = "Current product with product code `" + productCode + "` already exists";
|
||||
param = "productCode";
|
||||
msgArgs = new Object[] { productCode, dae };
|
||||
} else {
|
||||
msgCode += ".unknown.data.integrity.issue";
|
||||
msg = "Unknown data integrity issue with current product. Details: " + checkEx.getMessage();
|
||||
msgArgs = new Object[] { dae };
|
||||
}
|
||||
log.error("Error occured.", dae);
|
||||
throw ErrorHandler.getMappable(dae, msgCode, msg, param, msgArgs);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult create(final JsonCommand command) {
|
||||
try {
|
||||
this.fromApiJsonDataValidator.validateForCreate(command.json());
|
||||
|
||||
final CurrentProduct product = this.currentProductAssembler.assemble(command);
|
||||
|
||||
final CurrentProductFacilityConfig facilityConfig =
|
||||
this.currentProductAssembler.assembleAccountFacilityConfig(command, product);
|
||||
final Set<CurrentProductFacilityLimit> facilityLimits =
|
||||
this.currentProductAssembler.assembleAccountFacilityLimits(command, product);
|
||||
final CurrentProductDepositLimitKyc depositLimitKyc =
|
||||
this.currentProductAssembler.assembleDepositLimitKyc(command, product);
|
||||
|
||||
this.currentProductRepository.saveAndFlush(product);
|
||||
|
||||
if (facilityConfig != null) {
|
||||
this.facilityConfigRepository.saveAndFlush(facilityConfig);
|
||||
}
|
||||
|
||||
if (!facilityLimits.isEmpty()) {
|
||||
this.facilityLimitRepository.saveAll(facilityLimits);
|
||||
}
|
||||
|
||||
if (depositLimitKyc != null) {
|
||||
this.depositLimitKycRepository.saveAndFlush(depositLimitKyc);
|
||||
}
|
||||
|
||||
this.accountMappingWritePlatformService.createSavingProductToGLAccountMapping(product.getId(), command,
|
||||
DepositAccountType.SAVINGS_DEPOSIT);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(product.getId()) //
|
||||
.build();
|
||||
} catch (final DataAccessException e) {
|
||||
handleDataIntegrityIssues(command, e.getMostSpecificCause(), e);
|
||||
return CommandProcessingResult.empty();
|
||||
} catch (final PersistenceException dve) {
|
||||
handleDataIntegrityIssues(command, ExceptionUtils.getRootCause(dve.getCause()), dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult update(final Long productId, final JsonCommand command) {
|
||||
try {
|
||||
this.context.authenticatedUser();
|
||||
final CurrentProduct product = this.currentProductRepository.findById(productId)
|
||||
.orElseThrow(() -> new SavingsProductNotFoundException(productId));
|
||||
|
||||
this.fromApiJsonDataValidator.validateForUpdate(command.json(), product);
|
||||
|
||||
final Map<String, Object> changes = product.update(command);
|
||||
|
||||
if (changes.containsKey(chargesParamName)) {
|
||||
final Set<Charge> charges = this.currentProductAssembler.assembleListOfCurrentProductCharges(command,
|
||||
product.currency().getCode());
|
||||
final boolean updated = product.update(charges);
|
||||
if (!updated) {
|
||||
changes.remove(chargesParamName);
|
||||
}
|
||||
}
|
||||
|
||||
if (changes.containsKey(taxGroupIdParamName)) {
|
||||
final TaxGroup taxGroup = this.currentProductAssembler.assembleTaxGroup(command);
|
||||
product.setTaxGroup(taxGroup);
|
||||
if (product.withHoldTax() && product.getTaxGroup() == null) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors)
|
||||
.resource(DepositsApiConstants.CURRENT_PRODUCT_RESOURCE_NAME);
|
||||
final Long taxGroupId = null;
|
||||
baseDataValidator.reset().parameter(taxGroupIdParamName).value(taxGroupId).notBlank();
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
// Update facility config
|
||||
final CurrentProductFacilityConfig existingFacilityConfig = product.getFacilityConfig();
|
||||
final CurrentProductFacilityConfig newFacilityConfig =
|
||||
this.currentProductAssembler.assembleAccountFacilityConfig(command, product);
|
||||
|
||||
if (newFacilityConfig != null) {
|
||||
if (existingFacilityConfig != null) {
|
||||
existingFacilityConfig.updateFrom(newFacilityConfig);
|
||||
this.facilityConfigRepository.saveAndFlush(existingFacilityConfig);
|
||||
} else {
|
||||
this.facilityConfigRepository.saveAndFlush(newFacilityConfig);
|
||||
}
|
||||
} else if (existingFacilityConfig != null) {
|
||||
this.facilityConfigRepository.delete(existingFacilityConfig);
|
||||
}
|
||||
|
||||
// Update facility limits (delete old, insert new)
|
||||
final Set<CurrentProductFacilityLimit> newFacilityLimits =
|
||||
this.currentProductAssembler.assembleAccountFacilityLimits(command, product);
|
||||
|
||||
if (!newFacilityLimits.isEmpty() || command.hasParameter("accountFacilityLimits")) {
|
||||
if (product.getFacilityLimits() != null && !product.getFacilityLimits().isEmpty()) {
|
||||
this.facilityLimitRepository.deleteAll(product.getFacilityLimits());
|
||||
product.getFacilityLimits().clear();
|
||||
}
|
||||
if (!newFacilityLimits.isEmpty()) {
|
||||
this.facilityLimitRepository.saveAll(newFacilityLimits);
|
||||
product.setFacilityLimits(newFacilityLimits);
|
||||
}
|
||||
}
|
||||
|
||||
// Update deposit limit KYC
|
||||
final CurrentProductDepositLimitKyc existingDepositLimitKyc = product.getDepositLimitKyc();
|
||||
final CurrentProductDepositLimitKyc newDepositLimitKyc =
|
||||
this.currentProductAssembler.assembleDepositLimitKyc(command, product);
|
||||
|
||||
if (newDepositLimitKyc != null) {
|
||||
if (existingDepositLimitKyc != null) {
|
||||
existingDepositLimitKyc.updateFrom(newDepositLimitKyc);
|
||||
this.depositLimitKycRepository.saveAndFlush(existingDepositLimitKyc);
|
||||
} else {
|
||||
this.depositLimitKycRepository.saveAndFlush(newDepositLimitKyc);
|
||||
}
|
||||
} else if (existingDepositLimitKyc != null) {
|
||||
this.depositLimitKycRepository.delete(existingDepositLimitKyc);
|
||||
}
|
||||
|
||||
// accounting related changes
|
||||
final boolean accountingTypeChanged = changes.containsKey(accountingRuleParamName);
|
||||
final Map<String, Object> accountingMappingChanges = this.accountMappingWritePlatformService
|
||||
.updateSavingsProductToGLAccountMapping(product.getId(), command, accountingTypeChanged, product.getAccountingType(),
|
||||
DepositAccountType.SAVINGS_DEPOSIT);
|
||||
changes.putAll(accountingMappingChanges);
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
this.currentProductRepository.saveAndFlush(product);
|
||||
}
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(product.getId()) //
|
||||
.with(changes).build();
|
||||
} catch (final DataAccessException e) {
|
||||
handleDataIntegrityIssues(command, e.getMostSpecificCause(), e);
|
||||
return CommandProcessingResult.empty();
|
||||
} catch (final PersistenceException dve) {
|
||||
handleDataIntegrityIssues(command, ExceptionUtils.getRootCause(dve.getCause()), dve);
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult delete(final Long productId) {
|
||||
this.context.authenticatedUser();
|
||||
final CurrentProduct product = this.currentProductRepository.findById(productId)
|
||||
.orElseThrow(() -> new SavingsProductNotFoundException(productId));
|
||||
|
||||
this.currentProductRepository.delete(product);
|
||||
|
||||
return new CommandProcessingResultBuilder() //
|
||||
.withEntityId(product.getId()) //
|
||||
.build();
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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.currentproduct.starter;
|
||||
|
||||
import org.apache.fineract.accounting.producttoaccountmapping.service.ProductToGLAccountMappingWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.currentproduct.data.CurrentProductDataValidator;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductAssembler;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductDepositLimitKycRepository;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityConfigRepository;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductFacilityLimitRepository;
|
||||
import org.apache.fineract.portfolio.currentproduct.domain.CurrentProductRepository;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductReadPlatformService;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductWritePlatformService;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductWritePlatformServiceJpaRepositoryImpl;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@Configuration
|
||||
public class CurrentProductConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CurrentProductReadPlatformService.class)
|
||||
public CurrentProductReadPlatformService currentProductReadPlatformService(PlatformSecurityContext context,
|
||||
JdbcTemplate jdbcTemplate, CurrentProductFacilityConfigRepository currentFacilityConfigRepository,
|
||||
CurrentProductFacilityLimitRepository currentFacilityLimitRepository,
|
||||
CurrentProductDepositLimitKycRepository currentDepositLimitKycRepository) {
|
||||
return new CurrentProductReadPlatformServiceImpl(context, jdbcTemplate, currentFacilityConfigRepository,
|
||||
currentFacilityLimitRepository, currentDepositLimitKycRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CurrentProductWritePlatformService.class)
|
||||
public CurrentProductWritePlatformService currentProductWritePlatformService(PlatformSecurityContext context,
|
||||
CurrentProductRepository currentProductRepository, CurrentProductDataValidator currentProductDataValidator,
|
||||
CurrentProductAssembler currentProductAssembler,
|
||||
ProductToGLAccountMappingWritePlatformService accountMappingWritePlatformService,
|
||||
CurrentProductFacilityConfigRepository currentFacilityConfigRepository,
|
||||
CurrentProductFacilityLimitRepository currentFacilityLimitRepository,
|
||||
CurrentProductDepositLimitKycRepository currentDepositLimitKycRepository) {
|
||||
return new CurrentProductWritePlatformServiceJpaRepositoryImpl(context, currentProductRepository, currentProductDataValidator,
|
||||
currentProductAssembler, accountMappingWritePlatformService, currentFacilityConfigRepository,
|
||||
currentFacilityLimitRepository, currentDepositLimitKycRepository);
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ dependencies {
|
||||
implementation(project(path: ':fineract-charge'))
|
||||
implementation(project(path: ':fineract-loan'))
|
||||
implementation(project(path: ':fineract-savings'))
|
||||
implementation(project(path: ':fineract-current-product'))
|
||||
implementation(project(path: ':fineract-branch'))
|
||||
implementation(project(path: ':fineract-document'))
|
||||
implementation(project(path: ':fineract-progressive-loan'))
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
> Task :buildSrc:extractPluginRequests UP-TO-DATE
|
||||
> Task :buildSrc:generatePluginAdapters UP-TO-DATE
|
||||
> Task :buildSrc:compileJava UP-TO-DATE
|
||||
> Task :buildSrc:compileGroovy UP-TO-DATE
|
||||
> Task :buildSrc:compileGroovyPlugins UP-TO-DATE
|
||||
> Task :buildSrc:pluginDescriptors UP-TO-DATE
|
||||
> Task :buildSrc:processResources UP-TO-DATE
|
||||
> Task :buildSrc:classes UP-TO-DATE
|
||||
> Task :buildSrc:jar UP-TO-DATE
|
||||
|
||||
> Configure project :
|
||||
matching ref: COMMIT - d7821c7824067a96d31c4c031ea538fc5e4107fc
|
||||
ref configuration: COMMIT - pattern: null
|
||||
version: ${describe.tag.version.major}.${describe.tag.version.minor.next}.0-SNAPSHOT
|
||||
describeTagPattern: .*(\d+\.\d+\.\d+).*
|
||||
describeTagFirstParent: false
|
||||
|
||||
project version: 0.1.0-SNAPSHOT
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+10710
-1523
File diff suppressed because it is too large
Load Diff
+15
@@ -304,6 +304,10 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
|
||||
return chargeSchema() + " join m_share_product_charge mspc on mspc.charge_id = c.id";
|
||||
}
|
||||
|
||||
public String currentProductChargeSchema() {
|
||||
return chargeSchema() + " join m_current_product_charge cpc on cpc.charge_id = c.id";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChargeData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
final Long id = rs.getLong("id");
|
||||
@@ -438,6 +442,17 @@ public class ChargeReadPlatformServiceImpl implements ChargeReadPlatformService
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { shareProductId }); // NOSONAR
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChargeData> retrieveCurrentProductCharges(final Long currentProductId) {
|
||||
final ChargeMapper rm = new ChargeMapper();
|
||||
|
||||
String sql = "select " + rm.currentProductChargeSchema()
|
||||
+ " where c.is_deleted=false and c.is_active=true and cpc.current_product_id=? ";
|
||||
sql += addInClauseToSQL_toLimitChargesMappedToOffice_ifOfficeSpecificProductsEnabled();
|
||||
|
||||
return this.jdbcTemplate.query(sql, rm, new Object[] { currentProductId }); // NOSONAR
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChargeData> retrieveSavingsAccountApplicableCharges(Long savingsAccountId) {
|
||||
|
||||
|
||||
+4
-4
@@ -59,9 +59,9 @@ import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
|
||||
import org.apache.fineract.portfolio.savings.service.CurrentAccountTemplateReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountChargeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountTemplateReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -72,7 +72,7 @@ import org.springframework.util.CollectionUtils;
|
||||
public class CurrentAccountsApiResource {
|
||||
|
||||
private final SavingsAccountReadPlatformService savingsAccountReadPlatformService;
|
||||
private final SavingsAccountTemplateReadPlatformService savingsAccountTemplateReadPlatformService;
|
||||
private final CurrentAccountTemplateReadPlatformService currentAccountTemplateReadPlatformService;
|
||||
private final PlatformSecurityContext context;
|
||||
private final DefaultToApiJsonSerializer<SavingsAccountData> toApiJsonSerializer;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
@@ -93,7 +93,7 @@ public class CurrentAccountsApiResource {
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.CURRENT_ACCOUNT_RESOURCE_NAME);
|
||||
final SavingsAccountData savingsAccount = savingsAccountTemplateReadPlatformService.retrieveTemplate(clientId, groupId, productId,
|
||||
final SavingsAccountData savingsAccount = currentAccountTemplateReadPlatformService.retrieveTemplate(clientId, groupId, productId,
|
||||
staffInSelectedOfficeOnly);
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return toApiJsonSerializer.serialize(settings, savingsAccount, SavingsApiSetConstants.SAVINGS_ACCOUNT_RESPONSE_DATA_PARAMETERS);
|
||||
@@ -290,7 +290,7 @@ public class CurrentAccountsApiResource {
|
||||
SavingsAccountData templateData = null;
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
if (settings.isTemplate()) {
|
||||
templateData = savingsAccountTemplateReadPlatformService.retrieveTemplate(savingsAccount.getClientId(),
|
||||
templateData = currentAccountTemplateReadPlatformService.retrieveTemplate(savingsAccount.getClientId(),
|
||||
savingsAccount.getGroupId(), savingsAccount.getSavingsProductId(), staffInSelectedOfficeOnly);
|
||||
}
|
||||
|
||||
|
||||
+32
-6
@@ -71,11 +71,12 @@ import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYea
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsDropdownReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsProductReadPlatformService;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -85,7 +86,7 @@ import org.springframework.util.CollectionUtils;
|
||||
@RequiredArgsConstructor
|
||||
public class CurrentProductsApiResource {
|
||||
|
||||
private final SavingsProductReadPlatformService savingProductReadPlatformService;
|
||||
private final CurrentProductReadPlatformService savingProductReadPlatformService;
|
||||
private final SavingsDropdownReadPlatformService dropdownReadPlatformService;
|
||||
private final CurrencyReadPlatformService currencyReadPlatformService;
|
||||
private final PlatformSecurityContext context;
|
||||
@@ -99,6 +100,23 @@ public class CurrentProductsApiResource {
|
||||
private final TaxReadPlatformService taxReadPlatformService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final CodeValueReadPlatformService codeValueReadPlatformService;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
private String generateNextProductCode(final String tableName, final String prefix) {
|
||||
try {
|
||||
String maxCode = jdbcTemplate.queryForObject(
|
||||
"SELECT MAX(product_code) FROM " + tableName + " WHERE product_code LIKE ?",
|
||||
String.class, prefix + "%");
|
||||
if (maxCode == null || maxCode.isBlank()) {
|
||||
return prefix + "001";
|
||||
}
|
||||
String numStr = maxCode.substring(prefix.length());
|
||||
int num = Integer.parseInt(numStr);
|
||||
return prefix + String.format("%03d", num + 1);
|
||||
} catch (Exception e) {
|
||||
return prefix + "001";
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -147,7 +165,7 @@ public class CurrentProductsApiResource {
|
||||
context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.CURRENT_PRODUCT_RESOURCE_NAME);
|
||||
|
||||
SavingsProductData savingProductData = savingProductReadPlatformService.retrieveOne(productId);
|
||||
final Collection<ChargeData> charges = chargeReadPlatformService.retrieveSavingsProductCharges(productId);
|
||||
final Collection<ChargeData> charges = chargeReadPlatformService.retrieveCurrentProductCharges(productId);
|
||||
savingProductData = SavingsProductData.withCharges(savingProductData, charges);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
@@ -266,21 +284,29 @@ public class CurrentProductsApiResource {
|
||||
penaltyOptions = CollectionUtils.isEmpty(penaltyOptions) ? null : penaltyOptions;
|
||||
final Collection<TaxGroupData> taxGroupOptions = taxReadPlatformService.retrieveTaxGroupsForLookUp();
|
||||
|
||||
final List<CodeValueData> yesNoOptions = new ArrayList<>(
|
||||
codeValueReadPlatformService.retrieveCodeValuesByCode(SavingsApiConstants.YES_NO));
|
||||
final List<CodeValueData> accountTypeOptions = new ArrayList<>(
|
||||
codeValueReadPlatformService.retrieveCodeValuesByCode(SavingsApiConstants.CURRENT_PRODUCT_ACCOUNT_TYPE));
|
||||
final List<CodeValueData> customerSegmentOptions = new ArrayList<>(
|
||||
codeValueReadPlatformService.retrieveCodeValuesByCode(SavingsApiConstants.CURRENT_PRODUCT_CUSTOMER_SEGMENT));
|
||||
|
||||
SavingsProductData savingsProductToReturn = null;
|
||||
if (savingsProduct != null) {
|
||||
savingsProductToReturn = SavingsProductData.withTemplate(savingsProduct, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationTypeOption,
|
||||
interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, periodFrequencyOptions, paymentTypeOptions,
|
||||
accountingRuleOptions, accountingMappingOptions, chargeOptions, penaltyOptions, taxGroupOptions, null, null, null,
|
||||
accountMappingForPayment);
|
||||
accountingRuleOptions, accountingMappingOptions, chargeOptions, penaltyOptions, taxGroupOptions, yesNoOptions,
|
||||
accountTypeOptions, customerSegmentOptions, accountMappingForPayment);
|
||||
} else {
|
||||
savingsProductToReturn = SavingsProductData.template(currency, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, accountingRule, currencyOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationTypeOption, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions,
|
||||
periodFrequencyOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, chargeOptions,
|
||||
penaltyOptions, taxGroupOptions, null, null, null, accountMappingForPayment);
|
||||
penaltyOptions, taxGroupOptions, yesNoOptions, accountTypeOptions, customerSegmentOptions, accountMappingForPayment);
|
||||
savingsProductToReturn.setProductCode(generateNextProductCode("m_current_product", "CA-IND-"));
|
||||
}
|
||||
|
||||
return savingsProductToReturn;
|
||||
|
||||
+54
@@ -41,6 +41,7 @@ import jakarta.ws.rs.core.UriInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService;
|
||||
@@ -68,12 +69,16 @@ import org.apache.fineract.portfolio.interestratechart.data.InterestRateChartDat
|
||||
import org.apache.fineract.portfolio.interestratechart.service.InterestRateChartReadPlatformService;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
import org.apache.fineract.portfolio.paymenttype.service.PaymentTypeReadService;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.apache.fineract.portfolio.savings.DepositAccountType;
|
||||
import org.apache.fineract.portfolio.savings.DepositsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.data.RecurringDepositProductData;
|
||||
import org.apache.fineract.portfolio.savings.service.DepositProductReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.DepositsDropdownReadPlatformService;
|
||||
@@ -110,6 +115,8 @@ public class RecurringDepositProductsApiResource {
|
||||
private final DropdownReadPlatformService dropdownReadPlatformService;
|
||||
private final PaymentTypeReadService paymentTypeReadPlatformService;
|
||||
private final TaxReadPlatformService taxReadPlatformService;
|
||||
private final CodeValueReadPlatformService codeValueReadPlatformService;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -294,6 +301,15 @@ public class RecurringDepositProductsApiResource {
|
||||
final InterestRateChartData chartTemplate = this.interestRateChartReadPlatformService.template();
|
||||
final Collection<TaxGroupData> taxGroupOptions = this.taxReadPlatformService.retrieveTaxGroupsForLookUp();
|
||||
|
||||
final Collection<EnumOptionData> interestCalculationTypeOption = retrieveInterestCalculationTypeOption();
|
||||
final Collection<EnumOptionData> periodFrequencyOptions = retrievePeriodFrequencyOptions();
|
||||
final List<CodeValueData> yesNoOptions = new ArrayList<>(
|
||||
this.codeValueReadPlatformService.retrieveCodeValuesByCode(SavingsApiConstants.YES_NO));
|
||||
final List<CodeValueData> accountTypeOptions = new ArrayList<>(
|
||||
this.codeValueReadPlatformService.retrieveCodeValuesByCode(SavingsApiConstants.RD_PRODUCT_ACCOUNT_TYPE));
|
||||
final List<CodeValueData> customerSegmentOptions = new ArrayList<>(
|
||||
this.codeValueReadPlatformService.retrieveCodeValuesByCode(SavingsApiConstants.RD_PRODUCT_CUSTOMER_SEGMENT));
|
||||
|
||||
RecurringDepositProductData recurringDepositProductToReturn = null;
|
||||
if (savingsProduct != null) {
|
||||
recurringDepositProductToReturn = RecurringDepositProductData.withTemplate(savingsProduct, currencyOptions,
|
||||
@@ -308,11 +324,49 @@ public class RecurringDepositProductsApiResource {
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions,
|
||||
paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, chargeOptions, penaltyOptions, chartTemplate,
|
||||
preClosurePenalInterestOnTypeOptions, periodFrequencyTypeOptions, taxGroupOptions);
|
||||
recurringDepositProductToReturn.setProductCode(generateNextProductCode("m_savings_product", "RD-IND-"));
|
||||
}
|
||||
|
||||
recurringDepositProductToReturn.setInterestCalculationTypeOption(interestCalculationTypeOption);
|
||||
recurringDepositProductToReturn.setPeriodFrequencyOptions(periodFrequencyOptions);
|
||||
recurringDepositProductToReturn.setYesNoOptions(yesNoOptions);
|
||||
recurringDepositProductToReturn.setAccountTypeOptions(accountTypeOptions);
|
||||
recurringDepositProductToReturn.setCustomerSegmentOptions(customerSegmentOptions);
|
||||
|
||||
return recurringDepositProductToReturn;
|
||||
}
|
||||
|
||||
private Collection<EnumOptionData> retrievePeriodFrequencyOptions() {
|
||||
return this.codeValueReadPlatformService.retrieveCodeValuesByCode(SavingsApiConstants.PERIOD_FREQUENCY).stream()
|
||||
.map(codeValue -> new EnumOptionData(codeValue.getId(),
|
||||
"periodFrequencyType." + codeValue.getName().toLowerCase(Locale.ROOT).replace(' ', '_'), codeValue.getName()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private Collection<EnumOptionData> retrieveInterestCalculationTypeOption() {
|
||||
return this.codeValueReadPlatformService.retrieveCodeValuesByCode(SavingsApiConstants.INTEREST_CALCULATION_TYPE_OPTION).stream()
|
||||
.map(codeValue -> new EnumOptionData(codeValue.getId(),
|
||||
"interestCalculationTypeOption." + codeValue.getName().toLowerCase(Locale.ROOT).replace(' ', '_'),
|
||||
codeValue.getName()))
|
||||
.toList();
|
||||
}
|
||||
|
||||
private String generateNextProductCode(final String tableName, final String prefix) {
|
||||
try {
|
||||
String maxCode = jdbcTemplate.queryForObject(
|
||||
"SELECT MAX(product_code) FROM " + tableName + " WHERE product_code LIKE ? AND deposit_type_enum = 3",
|
||||
String.class, prefix + "%");
|
||||
if (maxCode == null || maxCode.isBlank()) {
|
||||
return prefix + "00";
|
||||
}
|
||||
String numStr = maxCode.substring(prefix.length());
|
||||
int num = Integer.parseInt(numStr);
|
||||
return prefix + String.format("%02d", num + 1);
|
||||
} catch (Exception e) {
|
||||
return prefix + "00";
|
||||
}
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{productId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
|
||||
+19
@@ -79,6 +79,7 @@ import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsProductReadPlatformService;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
import org.apache.fineract.portfolio.tax.service.TaxReadPlatformService;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
@@ -103,6 +104,23 @@ public class SavingsProductsApiResource {
|
||||
private final PaymentTypeReadService paymentTypeReadPlatformService;
|
||||
private final TaxReadPlatformService taxReadPlatformService;
|
||||
private final ConfigurationDomainService configurationDomainService;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
private String generateNextProductCode(final String tableName, final String prefix) {
|
||||
try {
|
||||
String maxCode = jdbcTemplate.queryForObject(
|
||||
"SELECT MAX(product_code) FROM " + tableName + " WHERE product_code LIKE ?",
|
||||
String.class, prefix + "%");
|
||||
if (maxCode == null || maxCode.isBlank()) {
|
||||
return prefix + "001";
|
||||
}
|
||||
String numStr = maxCode.substring(prefix.length());
|
||||
int num = Integer.parseInt(numStr);
|
||||
return prefix + String.format("%03d", num + 1);
|
||||
} catch (Exception e) {
|
||||
return prefix + "001";
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -297,6 +315,7 @@ public class SavingsProductsApiResource {
|
||||
periodFrequencyOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, chargeOptions,
|
||||
penaltyOptions, taxGroupOptions, yesNoOptions, accountTypeOptions, customerSegmentOptions,
|
||||
accountMappingForPayment);
|
||||
savingsProductToReturn.setProductCode(generateNextProductCode("m_savings_product", "SB-IND-"));
|
||||
}
|
||||
|
||||
return savingsProductToReturn;
|
||||
|
||||
+3
-3
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsProductWritePlatformService;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -31,10 +31,10 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@CommandType(entity = "CURRENTPRODUCT", action = "CREATE")
|
||||
public class CreateCurrentProductCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final SavingsProductWritePlatformService productWritePlatformService;
|
||||
private final CurrentProductWritePlatformService productWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public CreateCurrentProductCommandHandler(final SavingsProductWritePlatformService productWritePlatformService) {
|
||||
public CreateCurrentProductCommandHandler(final CurrentProductWritePlatformService productWritePlatformService) {
|
||||
this.productWritePlatformService = productWritePlatformService;
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsProductWritePlatformService;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@CommandType(entity = "CURRENTPRODUCT", action = "DELETE")
|
||||
public class DeleteCurrentProductCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final SavingsProductWritePlatformService productWritePlatformService;
|
||||
private final CurrentProductWritePlatformService productWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public DeleteCurrentProductCommandHandler(final SavingsProductWritePlatformService productWritePlatformService) {
|
||||
public DeleteCurrentProductCommandHandler(final CurrentProductWritePlatformService productWritePlatformService) {
|
||||
this.productWritePlatformService = productWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.productWritePlatformService.delete(command.getProductId());
|
||||
return this.productWritePlatformService.delete(command.entityId());
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -22,7 +22,7 @@ import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsProductWritePlatformService;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -31,16 +31,16 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@CommandType(entity = "CURRENTPRODUCT", action = "UPDATE")
|
||||
public class UpdateCurrentProductCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final SavingsProductWritePlatformService productWritePlatformService;
|
||||
private final CurrentProductWritePlatformService productWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public UpdateCurrentProductCommandHandler(final SavingsProductWritePlatformService productWritePlatformService) {
|
||||
public UpdateCurrentProductCommandHandler(final CurrentProductWritePlatformService productWritePlatformService) {
|
||||
this.productWritePlatformService = productWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
return this.productWritePlatformService.update(command.getProductId(), command);
|
||||
return this.productWritePlatformService.update(command.entityId(), command);
|
||||
}
|
||||
}
|
||||
|
||||
+375
@@ -0,0 +1,375 @@
|
||||
/**
|
||||
* 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.savings.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
|
||||
import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
|
||||
import org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.staff.data.StaffData;
|
||||
import org.apache.fineract.organisation.staff.service.StaffReadPlatformService;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
||||
import org.apache.fineract.portfolio.charge.util.ConvertChargeDataToSpecificChargeData;
|
||||
import org.apache.fineract.portfolio.client.data.ClientData;
|
||||
import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductReadPlatformService;
|
||||
import org.apache.fineract.portfolio.group.data.GroupGeneralData;
|
||||
import org.apache.fineract.portfolio.group.service.GroupReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountSummaryData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsProductData;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
public class CurrentAccountTemplateReadPlatformServiceImpl implements CurrentAccountTemplateReadPlatformService {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final ClientReadPlatformService clientReadPlatformService;
|
||||
private final GroupReadPlatformService groupReadPlatformService;
|
||||
private final CurrentProductReadPlatformService currentProductReadPlatformService;
|
||||
private final StaffReadPlatformService staffReadPlatformService;
|
||||
private final SavingsDropdownReadPlatformService dropdownReadPlatformService;
|
||||
private final ChargeReadPlatformService chargeReadPlatformService;
|
||||
private final EntityDatatableChecksReadService entityDatatableChecksReadService;
|
||||
|
||||
public CurrentAccountTemplateReadPlatformServiceImpl(final PlatformSecurityContext context, final JdbcTemplate jdbcTemplate,
|
||||
final ClientReadPlatformService clientReadPlatformService, final GroupReadPlatformService groupReadPlatformService,
|
||||
final CurrentProductReadPlatformService currentProductReadPlatformService,
|
||||
final StaffReadPlatformService staffReadPlatformService,
|
||||
final SavingsDropdownReadPlatformService dropdownReadPlatformService,
|
||||
final ChargeReadPlatformService chargeReadPlatformService,
|
||||
final EntityDatatableChecksReadService entityDatatableChecksReadService,
|
||||
final ColumnValidator columnValidator) {
|
||||
this.context = context;
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.clientReadPlatformService = clientReadPlatformService;
|
||||
this.groupReadPlatformService = groupReadPlatformService;
|
||||
this.currentProductReadPlatformService = currentProductReadPlatformService;
|
||||
this.staffReadPlatformService = staffReadPlatformService;
|
||||
this.dropdownReadPlatformService = dropdownReadPlatformService;
|
||||
this.chargeReadPlatformService = chargeReadPlatformService;
|
||||
this.entityDatatableChecksReadService = entityDatatableChecksReadService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingsAccountData retrieveTemplate(final Long clientId, final Long groupId, final Long productId,
|
||||
final boolean staffInSelectedOfficeOnly) {
|
||||
|
||||
final AppUser loggedInUser = this.context.authenticatedUser();
|
||||
Long officeId = loggedInUser.getOffice().getId();
|
||||
|
||||
ClientData client = null;
|
||||
if (clientId != null) {
|
||||
client = this.clientReadPlatformService.retrieveOne(clientId);
|
||||
officeId = client.getOfficeId();
|
||||
}
|
||||
|
||||
GroupGeneralData group = null;
|
||||
if (groupId != null) {
|
||||
group = this.groupReadPlatformService.retrieveOne(groupId);
|
||||
officeId = group.getOfficeId();
|
||||
}
|
||||
|
||||
final Collection<SavingsProductData> productOptions = this.currentProductReadPlatformService.retrieveAllForLookup();
|
||||
SavingsAccountData template = null;
|
||||
if (productId != null) {
|
||||
|
||||
final CurrentAccountTemplateMapper mapper = new CurrentAccountTemplateMapper(client, group);
|
||||
|
||||
final String sql = "select " + mapper.schema() + " where cp.id = ?";
|
||||
template = this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { productId }); // NOSONAR
|
||||
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = this.dropdownReadPlatformService
|
||||
.retrieveCompoundingInterestPeriodTypeOptions();
|
||||
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = this.dropdownReadPlatformService
|
||||
.retrieveInterestPostingPeriodTypeOptions();
|
||||
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions = this.dropdownReadPlatformService
|
||||
.retrieveInterestCalculationTypeOptions();
|
||||
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = this.dropdownReadPlatformService
|
||||
.retrieveInterestCalculationDaysInYearTypeOptions();
|
||||
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = this.dropdownReadPlatformService
|
||||
.retrieveLockinPeriodFrequencyTypeOptions();
|
||||
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = this.dropdownReadPlatformService.retrievewithdrawalFeeTypeOptions();
|
||||
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
final Collection<ChargeData> productCharges = this.chargeReadPlatformService.retrieveSavingsProductCharges(productId);
|
||||
final Collection<SavingsAccountChargeData> charges = fromChargesToSavingsCharges(productCharges);
|
||||
|
||||
final boolean feeChargesOnly = false;
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService
|
||||
.retrieveSavingsProductApplicableCharges(feeChargesOnly);
|
||||
|
||||
Collection<StaffData> fieldOfficerOptions = null;
|
||||
|
||||
if (officeId != null) {
|
||||
if (staffInSelectedOfficeOnly) {
|
||||
final Collection<StaffData> fieldOfficersInBranch = this.staffReadPlatformService
|
||||
.retrieveAllLoanOfficersInOfficeById(officeId);
|
||||
if (!CollectionUtils.isEmpty(fieldOfficersInBranch)) {
|
||||
fieldOfficerOptions = new ArrayList<>(fieldOfficersInBranch);
|
||||
}
|
||||
} else {
|
||||
final boolean restrictToLoanOfficersOnly = true;
|
||||
final Collection<StaffData> loanOfficersInHierarchy = this.staffReadPlatformService
|
||||
.retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(officeId, restrictToLoanOfficersOnly);
|
||||
if (!CollectionUtils.isEmpty(loanOfficersInHierarchy)) {
|
||||
fieldOfficerOptions = new ArrayList<>(loanOfficersInHierarchy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template = SavingsAccountData.withTemplateOptions(template, productOptions, fieldOfficerOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions,
|
||||
charges, chargeOptions);
|
||||
} else {
|
||||
|
||||
String clientName = null;
|
||||
if (client != null) {
|
||||
clientName = client.getDisplayName();
|
||||
}
|
||||
|
||||
String groupName = null;
|
||||
if (group != null) {
|
||||
groupName = group.getName();
|
||||
}
|
||||
|
||||
template = SavingsAccountData.withClientTemplate(clientId, clientName, groupId, groupName);
|
||||
|
||||
final Collection<StaffData> fieldOfficerOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
||||
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
final Collection<SavingsAccountChargeData> charges = null;
|
||||
|
||||
final boolean feeChargesOnly = false;
|
||||
final Collection<ChargeData> chargeOptions = this.chargeReadPlatformService
|
||||
.retrieveSavingsProductApplicableCharges(feeChargesOnly);
|
||||
|
||||
template = SavingsAccountData.withTemplateOptions(template, productOptions, fieldOfficerOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions,
|
||||
charges, chargeOptions);
|
||||
}
|
||||
|
||||
final List<DatatableData> datatableTemplates = this.entityDatatableChecksReadService.retrieveTemplates(StatusEnum.CREATE.getValue(),
|
||||
EntityTables.SAVINGS.getName(), productId);
|
||||
template.setDatatables(datatableTemplates);
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
private static final class CurrentAccountTemplateMapper implements RowMapper<SavingsAccountData> {
|
||||
|
||||
private final ClientData client;
|
||||
private final GroupGeneralData group;
|
||||
private final String schemaSql;
|
||||
|
||||
CurrentAccountTemplateMapper(final ClientData client, final GroupGeneralData group) {
|
||||
this.client = client;
|
||||
this.group = group;
|
||||
|
||||
final StringBuilder sqlBuilder = new StringBuilder(400);
|
||||
sqlBuilder.append("cp.id as productId, cp.name as productName, ");
|
||||
sqlBuilder.append(
|
||||
"cp.currency_code as currencyCode, cp.currency_digits as currencyDigits, cp.currency_multiplesof as inMultiplesOf, ");
|
||||
sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
|
||||
sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol, ");
|
||||
sqlBuilder.append("cp.nominal_annual_interest_rate as nominalAnnualIterestRate, ");
|
||||
sqlBuilder.append("cp.interest_compounding_period_enum as interestCompoundingPeriodType, ");
|
||||
sqlBuilder.append("cp.interest_posting_period_enum as interestPostingPeriodType, ");
|
||||
sqlBuilder.append("cp.interest_calculation_type_enum as interestCalculationType, ");
|
||||
sqlBuilder.append("cp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
|
||||
sqlBuilder.append("cp.min_required_opening_balance as minRequiredOpeningBalance, ");
|
||||
sqlBuilder.append("cp.lockin_period_frequency as lockinPeriodFrequency,");
|
||||
sqlBuilder.append("cp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
sqlBuilder.append("cp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, ");
|
||||
sqlBuilder.append("cp.min_balance_for_interest_calculation as minBalanceForInterestCalculation, ");
|
||||
sqlBuilder.append("cp.allow_overdraft as allowOverdraft, ");
|
||||
sqlBuilder.append("cp.overdraft_limit as overdraftLimit, ");
|
||||
sqlBuilder.append("cp.nominal_annual_interest_rate_overdraft as nominalAnnualInterestRateOverdraft, ");
|
||||
sqlBuilder.append("cp.min_overdraft_for_interest_calculation as minOverdraftForInterestCalculation, ");
|
||||
sqlBuilder.append("cp.withhold_tax as withHoldTax,");
|
||||
sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName, ");
|
||||
sqlBuilder.append("cp.min_required_balance as minRequiredBalance, ");
|
||||
sqlBuilder.append("cp.enforce_min_required_balance as enforceMinRequiredBalance, ");
|
||||
sqlBuilder.append("0 as maxAllowedLienLimit, ");
|
||||
sqlBuilder.append("0 as lienAllowed ");
|
||||
sqlBuilder.append("from m_current_product cp ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = cp.currency_code ");
|
||||
sqlBuilder.append("left join m_tax_group tg on tg.id = cp.tax_group_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schemaSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavingsAccountData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
|
||||
final String currencyCode = rs.getString("currencyCode");
|
||||
final String currencyName = rs.getString("currencyName");
|
||||
final String currencyNameCode = rs.getString("currencyNameCode");
|
||||
final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
|
||||
final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
|
||||
final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
|
||||
final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMultiplesOf, currencyDisplaySymbol,
|
||||
currencyNameCode);
|
||||
|
||||
final BigDecimal nominalAnnualIterestRate = rs.getBigDecimal("nominalAnnualIterestRate");
|
||||
|
||||
final EnumOptionData interestCompoundingPeriodType = SavingsEnumerations.compoundingInterestPeriodType(
|
||||
SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs, "interestCompoundingPeriodType")));
|
||||
|
||||
final EnumOptionData interestPostingPeriodType = SavingsEnumerations.interestPostingPeriodType(
|
||||
SavingsPostingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs, "interestPostingPeriodType")));
|
||||
|
||||
final EnumOptionData interestCalculationType = SavingsEnumerations
|
||||
.interestCalculationType(SavingsInterestCalculationType.fromInt(JdbcSupport.getInteger(rs, "interestCalculationType")));
|
||||
|
||||
final EnumOptionData interestCalculationDaysInYearType = SavingsEnumerations.interestCalculationDaysInYearType(
|
||||
SavingsInterestCalculationDaysInYearType.fromInt(JdbcSupport.getInteger(rs, "interestCalculationDaysInYearType")));
|
||||
|
||||
final BigDecimal minRequiredOpeningBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredOpeningBalance");
|
||||
|
||||
final Integer lockinPeriodFrequency = JdbcSupport.getInteger(rs, "lockinPeriodFrequency");
|
||||
EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final Integer lockinPeriodFrequencyTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodFrequencyType");
|
||||
if (lockinPeriodFrequencyTypeValue != null) {
|
||||
final SavingsPeriodFrequencyType lockinPeriodType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodType);
|
||||
}
|
||||
|
||||
final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers");
|
||||
|
||||
final boolean allowOverdraft = rs.getBoolean("allowOverdraft");
|
||||
final BigDecimal overdraftLimit = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "overdraftLimit");
|
||||
final BigDecimal nominalAnnualInterestRateOverdraft = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
|
||||
"nominalAnnualInterestRateOverdraft");
|
||||
final BigDecimal minOverdraftForInterestCalculation = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
|
||||
"minOverdraftForInterestCalculation");
|
||||
|
||||
final BigDecimal minRequiredBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredBalance");
|
||||
final boolean enforceMinRequiredBalance = rs.getBoolean("enforceMinRequiredBalance");
|
||||
final BigDecimal maxAllowedLienLimit = null;
|
||||
final boolean lienAllowed = false;
|
||||
final BigDecimal minBalanceForInterestCalculation = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
|
||||
"minBalanceForInterestCalculation");
|
||||
|
||||
final boolean withHoldTax = rs.getBoolean("withHoldTax");
|
||||
final Long taxGroupId = JdbcSupport.getLong(rs, "taxGroupId");
|
||||
final String taxGroupName = rs.getString("taxGroupName");
|
||||
TaxGroupData taxGroupData = null;
|
||||
if (taxGroupId != null) {
|
||||
taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
|
||||
}
|
||||
|
||||
Long clientId = null;
|
||||
String clientName = null;
|
||||
if (this.client != null) {
|
||||
clientId = this.client.getId();
|
||||
clientName = this.client.getDisplayName();
|
||||
}
|
||||
|
||||
Long groupId = null;
|
||||
String groupName = null;
|
||||
if (this.group != null) {
|
||||
groupId = this.group.getId();
|
||||
groupName = this.group.getName();
|
||||
}
|
||||
|
||||
final Long fieldOfficerId = null;
|
||||
final String fieldOfficerName = null;
|
||||
final SavingsAccountStatusEnumData status = null;
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final BigDecimal onHoldFunds = null;
|
||||
final BigDecimal savingsAmountOnHold = null;
|
||||
|
||||
final SavingsAccountSubStatusEnumData subStatus = null;
|
||||
final String reasonForBlock = null;
|
||||
final LocalDate lastActiveTransactionDate = null;
|
||||
final boolean isDormancyTrackingActive = false;
|
||||
final Integer daysToInactive = null;
|
||||
final Integer daysToDormancy = null;
|
||||
final Integer daysToEscheat = null;
|
||||
|
||||
final SavingsAccountApplicationTimelineData timeline = SavingsAccountApplicationTimelineData.templateDefault();
|
||||
final EnumOptionData depositType = null;
|
||||
return SavingsAccountData.instance(null, null, depositType, null, groupId, groupName, clientId, clientName, productId,
|
||||
productName, fieldOfficerId, fieldOfficerName, status, subStatus, reasonForBlock, timeline, currency,
|
||||
nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
|
||||
withdrawalFeeForTransfers, summary, allowOverdraft, overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
|
||||
maxAllowedLienLimit, lienAllowed, minBalanceForInterestCalculation, onHoldFunds, nominalAnnualInterestRateOverdraft,
|
||||
minOverdraftForInterestCalculation, withHoldTax, taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive,
|
||||
daysToInactive, daysToDormancy, daysToEscheat, savingsAmountOnHold);
|
||||
}
|
||||
}
|
||||
|
||||
private Collection<SavingsAccountChargeData> fromChargesToSavingsCharges(final Collection<ChargeData> productCharges) {
|
||||
final Collection<SavingsAccountChargeData> savingsCharges = new ArrayList<>();
|
||||
for (final ChargeData chargeData : productCharges) {
|
||||
final SavingsAccountChargeData savingsCharge = ConvertChargeDataToSpecificChargeData.toSavingsAccountChargeData(chargeData);
|
||||
savingsCharges.add(savingsCharge);
|
||||
}
|
||||
return savingsCharges;
|
||||
}
|
||||
}
|
||||
+24
-2
@@ -298,7 +298,12 @@ public class DepositProductReadPlatformServiceImpl implements DepositProductRead
|
||||
sqlBuilder.append("dptp.min_deposit_term_type_enum as minDepositTermTypeId, ");
|
||||
sqlBuilder.append("dptp.max_deposit_term_type_enum as maxDepositTermTypeId, ");
|
||||
sqlBuilder.append("dptp.in_multiples_of_deposit_term as inMultiplesOfDepositTerm, ");
|
||||
sqlBuilder.append("dptp.in_multiples_of_deposit_term_type_enum as inMultiplesOfDepositTermTypeId ");
|
||||
sqlBuilder.append("dptp.in_multiples_of_deposit_term_type_enum as inMultiplesOfDepositTermTypeId, ");
|
||||
sqlBuilder.append("sp.account_type as accountType, sp.customer_segment as customerSegment, ");
|
||||
sqlBuilder.append("sp.product_code as productCode, ");
|
||||
sqlBuilder.append("sp.interest_calculate_selector as interestCalculateSelector, ");
|
||||
sqlBuilder.append("sp.average_period as averagePeriod, ");
|
||||
sqlBuilder.append("sp.auto_post as autoPost, sp.frequency_fix_day as frequencyFixDay ");
|
||||
sqlBuilder.append("from m_savings_product sp ");
|
||||
sqlBuilder.append("left join m_deposit_product_term_and_preclosure dptp on sp.id=dptp.savings_product_id ");
|
||||
sqlBuilder.append("left join m_deposit_product_recurring_detail dprd on sp.id=dprd.savings_product_id ");
|
||||
@@ -342,10 +347,27 @@ public class DepositProductReadPlatformServiceImpl implements DepositProductRead
|
||||
final EnumOptionData inMultiplesOfDepositTermType = (inMultiplesOfDepositTermTypeId == null) ? null
|
||||
: SavingsEnumerations.depositTermFrequencyType(inMultiplesOfDepositTermTypeId);
|
||||
|
||||
return RecurringDepositProductData.instance(depositProductData, preClosurePenalApplicable, preClosurePenalInterest,
|
||||
final String accountType = rs.getString("accountType");
|
||||
final String customerSegment = rs.getString("customerSegment");
|
||||
final String productCode = rs.getString("productCode");
|
||||
final Integer interestCalculateSelector = JdbcSupport.getInteger(rs, "interestCalculateSelector");
|
||||
final String averagePeriod = rs.getString("averagePeriod");
|
||||
final Boolean autoPost = rs.getBoolean("autoPost");
|
||||
final Integer frequencyFixDay = JdbcSupport.getInteger(rs, "frequencyFixDay");
|
||||
|
||||
RecurringDepositProductData result = RecurringDepositProductData.instance(depositProductData,
|
||||
preClosurePenalApplicable, preClosurePenalInterest,
|
||||
preClosurePenalInterestOnType, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
|
||||
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, isMandatoryDeposit, allowWithdrawal,
|
||||
adjustAdvanceTowardsFuturePayments, minDepositAmount, depositAmount, maxDepositAmount);
|
||||
result.setAccountType(accountType);
|
||||
result.setCustomerSegment(customerSegment);
|
||||
result.setProductCode(productCode);
|
||||
result.setInterestCalculateSelector(interestCalculateSelector);
|
||||
result.setAveragePeriod(averagePeriod);
|
||||
result.setAutoPost(autoPost);
|
||||
result.setFrequencyFixDay(frequencyFixDay);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+23
-2
@@ -63,6 +63,7 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
private final SavingsProductDepositLimitKycRepository depositLimitKycRepository;
|
||||
private static final Gson GSON = new Gson();
|
||||
private static final Type OTHER_GL_MAPPINGS_TYPE = new TypeToken<List<Map<String, Object>>>() {}.getType();
|
||||
private static final Type OTHER_GL_MAPPINGS_MAP_TYPE = new TypeToken<Map<String, List<Map<String, Object>>>>() {}.getType();
|
||||
|
||||
@Override
|
||||
public Collection<SavingsProductData> retrieveAll() {
|
||||
@@ -300,7 +301,9 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
final Long daysToInactive = JdbcSupport.getLong(rs, "daysToInactive");
|
||||
final Long daysToDormancy = JdbcSupport.getLong(rs, "daysToDormancy");
|
||||
final Long daysToEscheat = JdbcSupport.getLong(rs, "daysToEscheat");
|
||||
final List<Map<String, Object>> otherGlMappings = parseOtherGlMappings(rs.getString("otherGlMappings"));
|
||||
final String otherGlMappingsJson = rs.getString("otherGlMappings");
|
||||
final List<Map<String, Object>> otherGlMappings = parseOtherGlMappings(otherGlMappingsJson);
|
||||
final Map<String, List<Map<String, Object>>> otherGlMappingsMap = parseOtherGlMappingsAsMap(otherGlMappingsJson);
|
||||
|
||||
SavingsProductData productData = SavingsProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate,
|
||||
compoundingInterestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||
@@ -309,6 +312,9 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
lienAllowed, minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation,
|
||||
withHoldTax, taxGroupData, null, null, null, isDormancyTrackingActive, daysToInactive, daysToDormancy,
|
||||
daysToEscheat, otherGlMappings);
|
||||
if (otherGlMappingsMap != null) {
|
||||
productData.setOtherGlMappingsMap(otherGlMappingsMap);
|
||||
}
|
||||
|
||||
// Populate Enhanced Fields
|
||||
productData.setAccountType(rs.getString("accountType"));
|
||||
@@ -354,7 +360,22 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
if (otherGlMappingsJson == null || otherGlMappingsJson.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
return GSON.fromJson(otherGlMappingsJson, OTHER_GL_MAPPINGS_TYPE);
|
||||
com.google.gson.JsonElement element = GSON.fromJson(otherGlMappingsJson, com.google.gson.JsonElement.class);
|
||||
if (!element.isJsonArray()) {
|
||||
return null;
|
||||
}
|
||||
return GSON.fromJson(element, OTHER_GL_MAPPINGS_TYPE);
|
||||
}
|
||||
|
||||
private static Map<String, List<Map<String, Object>>> parseOtherGlMappingsAsMap(final String otherGlMappingsJson) {
|
||||
if (otherGlMappingsJson == null || otherGlMappingsJson.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
com.google.gson.JsonElement element = GSON.fromJson(otherGlMappingsJson, com.google.gson.JsonElement.class);
|
||||
if (!element.isJsonObject()) {
|
||||
return null;
|
||||
}
|
||||
return GSON.fromJson(element, OTHER_GL_MAPPINGS_MAP_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+17
@@ -129,6 +129,9 @@ import org.apache.fineract.portfolio.savings.service.SavingsAccountInterestPosti
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountInterestPostingServiceImpl;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.currentproduct.service.CurrentProductReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.CurrentAccountTemplateReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.CurrentAccountTemplateReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountTemplateReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountTemplateReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
|
||||
@@ -361,6 +364,19 @@ public class SavingsConfiguration {
|
||||
entityDatatableChecksReadService, columnValidator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CurrentAccountTemplateReadPlatformService.class)
|
||||
public CurrentAccountTemplateReadPlatformService currentAccountTemplateReadPlatformService(PlatformSecurityContext context,
|
||||
JdbcTemplate jdbcTemplate, ClientReadPlatformService clientReadPlatformService,
|
||||
GroupReadPlatformService groupReadPlatformService, CurrentProductReadPlatformService currentProductReadPlatformService,
|
||||
StaffReadPlatformService staffReadPlatformService, SavingsDropdownReadPlatformService dropdownReadPlatformService,
|
||||
ChargeReadPlatformService chargeReadPlatformService, EntityDatatableChecksReadService entityDatatableChecksReadService,
|
||||
ColumnValidator columnValidator) {
|
||||
return new CurrentAccountTemplateReadPlatformServiceImpl(context, jdbcTemplate, clientReadPlatformService, groupReadPlatformService,
|
||||
currentProductReadPlatformService, staffReadPlatformService, dropdownReadPlatformService, chargeReadPlatformService,
|
||||
entityDatatableChecksReadService, columnValidator);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(SavingsAccountWritePlatformService.class)
|
||||
public SavingsAccountWritePlatformService savingsAccountWritePlatformService(PlatformSecurityContext context,
|
||||
@@ -460,4 +476,5 @@ public class SavingsConfiguration {
|
||||
public SavingsSchedularInterestPosterTask savingsSchedularInterestPosterTask(SavingsSchedularInterestPoster interestPoster) {
|
||||
return new SavingsSchedularInterestPosterTask(interestPoster);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -269,4 +269,6 @@
|
||||
<include file="parts/0248_add_cin_din_verification_fields.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0249_add_non_person_extended_fields.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0251_add_savings_product_enhanced_fields.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0255_create_current_product_tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0256_add_recurring_deposit_product_codes.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+390
@@ -0,0 +1,390 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<!-- Create m_current_product table (same structure as m_savings_product) -->
|
||||
<changeSet id="0255_create_current_product_table" author="system">
|
||||
<createTable tableName="m_current_product">
|
||||
<column name="id" type="bigint" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="name" type="varchar(100)">
|
||||
<constraints nullable="false" unique="true" uniqueConstraintName="cp_unq_name"/>
|
||||
</column>
|
||||
<column name="short_name" type="varchar(4)">
|
||||
<constraints nullable="false" unique="true" uniqueConstraintName="cp_unq_short_name"/>
|
||||
</column>
|
||||
<column name="description" type="varchar(500)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="deposit_type_enum" type="smallint" defaultValue="400">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="currency_code" type="varchar(3)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="currency_digits" type="smallint">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="currency_multiplesof" type="smallint">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="nominal_annual_interest_rate" type="decimal(19,6)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="interest_compounding_period_enum" type="smallint">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="interest_posting_period_enum" type="smallint" defaultValue="4">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="interest_calculation_type_enum" type="smallint">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="interest_calculation_days_in_year_type_enum" type="smallint">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="min_required_opening_balance" type="decimal(19,6)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="lockin_period_frequency" type="int">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="lockin_period_frequency_enum" type="smallint">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="accounting_type" type="smallint">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="withdrawal_fee_for_transfer" type="boolean" defaultValue="true">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="allow_overdraft" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="overdraft_limit" type="decimal(19,6)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="nominal_annual_interest_rate_overdraft" type="decimal(19,6)" defaultValue="0.000000">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="min_overdraft_for_interest_calculation" type="decimal(19,6)" defaultValue="0.000000">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="enforce_min_required_balance" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="min_required_balance" type="decimal(19,6)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="is_lien_allowed" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="max_allowed_lien_limit" type="decimal(19,6)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="min_balance_for_interest_calculation" type="decimal(19,6)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="withhold_tax" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="tax_group_id" type="bigint">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="is_dormancy_tracking_active" type="boolean">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="days_to_inactive" type="int">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="days_to_dormancy" type="int">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="days_to_escheat" type="int">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="other_gl_mappings" type="longtext">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<!-- Enhanced fields -->
|
||||
<column name="account_type" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="customer_segment" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="product_code" type="varchar(20)">
|
||||
<constraints nullable="true" unique="true" uniqueConstraintName="cp_unq_product_code"/>
|
||||
</column>
|
||||
<column name="effective_date" type="date">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="effective_to" type="date">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="end_date" type="date">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="introducer_required" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="share_linking_enabled" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="nomination_facility" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="dormancy_alert" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="interest_calculate_selector" type="int">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="average_period" type="varchar(20)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="auto_post" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="frequency_fix_day" type="int">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="last_interest_date" type="date">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="enable_lockin_period" type="boolean" defaultValue="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="balance_frequency" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="account_closed_zero_balance_in_day_closing" type="boolean" defaultValue="false">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
</createTable>
|
||||
|
||||
<addForeignKeyConstraint baseTableName="m_current_product" baseColumnNames="tax_group_id"
|
||||
constraintName="fk_current_product_tax_group"
|
||||
referencedTableName="m_tax_group" referencedColumnNames="id"/>
|
||||
</changeSet>
|
||||
|
||||
<!-- Create m_current_product_charge join table -->
|
||||
<changeSet id="0256_create_current_product_charge_table" author="system">
|
||||
<createTable tableName="m_current_product_charge">
|
||||
<column name="current_product_id" type="bigint">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="charge_id" type="bigint">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addPrimaryKey tableName="m_current_product_charge" columnNames="current_product_id,charge_id"
|
||||
constraintName="pk_current_product_charge"/>
|
||||
<addForeignKeyConstraint baseTableName="m_current_product_charge" baseColumnNames="current_product_id"
|
||||
constraintName="fk_current_product_charge_product"
|
||||
referencedTableName="m_current_product" referencedColumnNames="id"/>
|
||||
<addForeignKeyConstraint baseTableName="m_current_product_charge" baseColumnNames="charge_id"
|
||||
constraintName="fk_current_product_charge_charge"
|
||||
referencedTableName="m_charge" referencedColumnNames="id"/>
|
||||
</changeSet>
|
||||
|
||||
<!-- Create m_current_product_facility_config table -->
|
||||
<changeSet id="0257_create_current_product_facility_config_table" author="system">
|
||||
<createTable tableName="m_current_product_facility_config">
|
||||
<column name="id" type="bigint" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="current_product_id" type="bigint">
|
||||
<constraints nullable="false" unique="true" uniqueConstraintName="uq_current_product_facility_config_product_id"/>
|
||||
</column>
|
||||
<column name="atm_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="atm_withdrawal_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="upi_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="pos_transactions_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="cheque_book" type="boolean" defaultValue="false"/>
|
||||
<column name="imps_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="sms_alerts" type="boolean" defaultValue="false"/>
|
||||
<column name="bbps_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="insurance_cover" type="boolean" defaultValue="false"/>
|
||||
<column name="bepg_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="neft_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="rtgs_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="inter_bank_total_cap_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="withdrawal_facility" type="boolean" defaultValue="false"/>
|
||||
<column name="deposit_facility_kyc" type="boolean" defaultValue="false"/>
|
||||
<column name="virtual_debit_card" type="boolean" defaultValue="false"/>
|
||||
<column name="created_date" type="datetime">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseTableName="m_current_product_facility_config" baseColumnNames="current_product_id"
|
||||
constraintName="fk_current_product_facility_config_product_id"
|
||||
referencedTableName="m_current_product" referencedColumnNames="id"
|
||||
onDelete="CASCADE"/>
|
||||
</changeSet>
|
||||
|
||||
<!-- Create m_current_product_facility_limits table -->
|
||||
<changeSet id="0258_create_current_product_facility_limits_table" author="system">
|
||||
<createTable tableName="m_current_product_facility_limits">
|
||||
<column name="id" type="bigint" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="current_product_id" type="bigint">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="limit_type" type="varchar(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="general_limit" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="minor_account_limit" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="small_saving_limit" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="created_date" type="datetime">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseTableName="m_current_product_facility_limits" baseColumnNames="current_product_id"
|
||||
constraintName="fk_current_product_facility_limits_product_id"
|
||||
referencedTableName="m_current_product" referencedColumnNames="id"
|
||||
onDelete="CASCADE"/>
|
||||
<createIndex tableName="m_current_product_facility_limits" indexName="idx_current_product_facility_limits_product_type">
|
||||
<column name="current_product_id"/>
|
||||
<column name="limit_type"/>
|
||||
</createIndex>
|
||||
</changeSet>
|
||||
|
||||
<!-- Create m_current_product_deposit_limit_kyc table -->
|
||||
<changeSet id="0259_create_current_product_deposit_limit_kyc_table" author="system">
|
||||
<createTable tableName="m_current_product_deposit_limit_kyc">
|
||||
<column name="id" type="bigint" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="current_product_id" type="bigint">
|
||||
<constraints nullable="false" unique="true" uniqueConstraintName="uq_current_product_deposit_limit_kyc_product_id"/>
|
||||
</column>
|
||||
<column name="general_kyc_type" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="general_limit" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="minor_kyc_type" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="minor_limit" type="bigint">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="small_saving_kyc_type" type="varchar(50)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="small_saving_limit" type="bigint">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="created_date" type="datetime">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseTableName="m_current_product_deposit_limit_kyc" baseColumnNames="current_product_id"
|
||||
constraintName="fk_current_product_deposit_limit_kyc_product_id"
|
||||
referencedTableName="m_current_product" referencedColumnNames="id"
|
||||
onDelete="CASCADE"/>
|
||||
</changeSet>
|
||||
|
||||
<!-- Add new UI fields to m_current_product -->
|
||||
<changeSet id="0262_add_current_product_new_ui_fields" author="system">
|
||||
<addColumn tableName="m_current_product">
|
||||
<column name="balance_swap_option" type="boolean" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="msme" type="boolean" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="auto_debit_facility" type="boolean" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="avg_balance_calc_period" type="varchar(10)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="valid_for_period" type="varchar(10)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="od_account_closed_zero_balance_in_day_closing" type="boolean" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<!-- Insert CurrentProductAccountType code and values (separate from SavingsProductAccountType) -->
|
||||
<changeSet id="0260_add_current_product_account_type_code" author="system">
|
||||
<sql>
|
||||
INSERT INTO m_code (code_name, is_system_defined)
|
||||
SELECT 'CurrentProductAccountType', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'CurrentProductAccountType');
|
||||
</sql>
|
||||
<sql>
|
||||
INSERT INTO m_code_value (code_id, code_value, order_position, is_active, is_mandatory)
|
||||
SELECT c.id, v.code_value, v.order_position, true, false
|
||||
FROM m_code c,
|
||||
(VALUES
|
||||
('Standard Account', 1),
|
||||
('Basic Account', 2),
|
||||
('Premium Current Account', 3)
|
||||
) AS v(code_value, order_position)
|
||||
WHERE c.code_name = 'CurrentProductAccountType'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_code_value cv
|
||||
WHERE cv.code_id = c.id AND cv.code_value = v.code_value
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<!-- Insert CurrentProductCustomerSegment code and values (separate from SavingsProductCustomerSegment) -->
|
||||
<changeSet id="0261_add_current_product_customer_segment_code" author="system">
|
||||
<sql>
|
||||
INSERT INTO m_code (code_name, is_system_defined)
|
||||
SELECT 'CurrentProductCustomerSegment', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'CurrentProductCustomerSegment');
|
||||
</sql>
|
||||
<sql>
|
||||
INSERT INTO m_code_value (code_id, code_value, order_position, is_active, is_mandatory)
|
||||
SELECT c.id, v.code_value, v.order_position, true, false
|
||||
FROM m_code c,
|
||||
(VALUES
|
||||
('Non Individual', 1)
|
||||
) AS v(code_value, order_position)
|
||||
WHERE c.code_name = 'CurrentProductCustomerSegment'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_code_value cv
|
||||
WHERE cv.code_id = c.id AND cv.code_value = v.code_value
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<!-- RecurringDepositProductAccountType code and values -->
|
||||
<changeSet id="0262_add_rd_product_account_type_code" author="system">
|
||||
<sql>
|
||||
INSERT INTO m_code (code_name, is_system_defined)
|
||||
SELECT 'RecurringDepositProductAccountType', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'RecurringDepositProductAccountType');
|
||||
</sql>
|
||||
<sql>
|
||||
INSERT INTO m_code_value (code_id, code_value, order_position, is_active, is_mandatory)
|
||||
SELECT c.id, v.code_value, v.order_position, true, false
|
||||
FROM m_code c,
|
||||
(VALUES
|
||||
('Rd Account', 1)
|
||||
) AS v(code_value, order_position)
|
||||
WHERE c.code_name = 'RecurringDepositProductAccountType'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_code_value cv
|
||||
WHERE cv.code_id = c.id AND cv.code_value = v.code_value
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<!-- RecurringDepositProductCustomerSegment code and values -->
|
||||
<changeSet id="0263_add_rd_product_customer_segment_code" author="system">
|
||||
<sql>
|
||||
INSERT INTO m_code (code_name, is_system_defined)
|
||||
SELECT 'RecurringDepositProductCustomerSegment', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'RecurringDepositProductCustomerSegment');
|
||||
</sql>
|
||||
<sql>
|
||||
INSERT INTO m_code_value (code_id, code_value, order_position, is_active, is_mandatory)
|
||||
SELECT c.id, v.code_value, v.order_position, true, false
|
||||
FROM m_code c,
|
||||
(VALUES
|
||||
('Individual', 1),
|
||||
('Non-Individual', 2)
|
||||
) AS v(code_value, order_position)
|
||||
WHERE c.code_name = 'RecurringDepositProductCustomerSegment'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_code_value cv
|
||||
WHERE cv.code_id = c.id AND cv.code_value = v.code_value
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+8
-2
@@ -41,7 +41,7 @@ public class SavingsApiSetConstants extends SavingsApiConstants {
|
||||
"interestCalculationTypeOptions", "interestCalculationTypeOption", "interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions",
|
||||
"withdrawalFeeTypeOptions", nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
|
||||
withHoldTaxParamName, taxGroupIdParamName, isDormancyTrackingActiveParamName, daysToInactiveParamName,
|
||||
daysToDormancyParamName, daysToInactiveParamName, accountMappingForPaymentParamName, "otherGlMappings", "accountTypeOptions",
|
||||
daysToDormancyParamName, daysToInactiveParamName, accountMappingForPaymentParamName, "otherGlMappings", "otherGlMappingsMap", "accountTypeOptions",
|
||||
"customerSegmentOptions", "yesNoOptions",
|
||||
// Enhanced custom fields
|
||||
"accountType", "customerSegment", "productCode", "effectiveDate", "effectiveTo", "endDate",
|
||||
@@ -51,7 +51,13 @@ public class SavingsApiSetConstants extends SavingsApiConstants {
|
||||
"accountFacilityConfig", "accountFacilityLimits", "depositLimitKyc",
|
||||
"allowOverdraft", "overdraftLimit", "minRequiredBalance", "enforceMinRequiredBalance",
|
||||
"maxAllowedLienLimit", "lienAllowed", "minBalanceForInterestCalculation",
|
||||
"accountingRule", "accountingMappings", "charges", "periodFrequencyOptions"));
|
||||
"accountingRule", "accountingMappings", "charges", "periodFrequencyOptions",
|
||||
// New current product fields
|
||||
"balanceSwapOption", "msme", "autoDebitFacility",
|
||||
"avgBalanceCalcPeriod", "validForPeriod", "odAccountClosedZeroBalanceInDayClosing",
|
||||
// Accounting detail mappings
|
||||
"paymentChannelToFundSourceMappings", "feeToIncomeAccountMappings", "penaltyToIncomeAccountMappings",
|
||||
"paymentTypeOptions", "taxGroup", "taxGroupOptions", "accountingMappingOptions"));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of {@link SavingsAccountData}. Where possible, we try to
|
||||
|
||||
+27
@@ -56,6 +56,33 @@ public final class RecurringDepositProductData extends DepositProductData {
|
||||
private Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions;
|
||||
private Collection<EnumOptionData> periodFrequencyTypeOptions;
|
||||
|
||||
// CBS extended fields
|
||||
private Collection<EnumOptionData> interestCalculationTypeOption;
|
||||
private Collection<EnumOptionData> periodFrequencyOptions;
|
||||
private java.util.List<org.apache.fineract.infrastructure.codes.data.CodeValueData> yesNoOptions;
|
||||
private java.util.List<org.apache.fineract.infrastructure.codes.data.CodeValueData> accountTypeOptions;
|
||||
private java.util.List<org.apache.fineract.infrastructure.codes.data.CodeValueData> customerSegmentOptions;
|
||||
private String accountType;
|
||||
private String customerSegment;
|
||||
private String productCode;
|
||||
private Integer interestCalculateSelector;
|
||||
private String averagePeriod;
|
||||
private Boolean autoPost;
|
||||
private Integer frequencyFixDay;
|
||||
|
||||
public void setInterestCalculationTypeOption(Collection<EnumOptionData> v) { this.interestCalculationTypeOption = v; }
|
||||
public void setPeriodFrequencyOptions(Collection<EnumOptionData> v) { this.periodFrequencyOptions = v; }
|
||||
public void setYesNoOptions(java.util.List<org.apache.fineract.infrastructure.codes.data.CodeValueData> v) { this.yesNoOptions = v; }
|
||||
public void setAccountTypeOptions(java.util.List<org.apache.fineract.infrastructure.codes.data.CodeValueData> v) { this.accountTypeOptions = v; }
|
||||
public void setCustomerSegmentOptions(java.util.List<org.apache.fineract.infrastructure.codes.data.CodeValueData> v) { this.customerSegmentOptions = v; }
|
||||
public void setAccountType(String v) { this.accountType = v; }
|
||||
public void setCustomerSegment(String v) { this.customerSegment = v; }
|
||||
public void setProductCode(String v) { this.productCode = v; }
|
||||
public void setInterestCalculateSelector(Integer v) { this.interestCalculateSelector = v; }
|
||||
public void setAveragePeriod(String v) { this.averagePeriod = v; }
|
||||
public void setAutoPost(Boolean v) { this.autoPost = v; }
|
||||
public void setFrequencyFixDay(Integer v) { this.frequencyFixDay = v; }
|
||||
|
||||
public static RecurringDepositProductData template(final CurrencyData currency, final EnumOptionData interestCompoundingPeriodType,
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final EnumOptionData accountingRule,
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.savings.service;
|
||||
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
|
||||
|
||||
public interface CurrentAccountTemplateReadPlatformService {
|
||||
|
||||
SavingsAccountData retrieveTemplate(Long clientId, Long groupId, Long productId, boolean staffInSelectedOfficeOnly);
|
||||
|
||||
}
|
||||
+25
@@ -163,4 +163,29 @@
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="fineract" id="2005-6-savings-product-customer-segment-remove-corporate">
|
||||
<sql>
|
||||
DELETE FROM m_code_value
|
||||
WHERE code_value = 'Corporate'
|
||||
AND code_id = (SELECT id FROM m_code WHERE code_name = 'SavingsProductCustomerSegment');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="fineract" id="2005-7-savings-product-customer-segment-add-non-individual">
|
||||
<sql>
|
||||
INSERT INTO m_code (code_name, is_system_defined)
|
||||
SELECT 'SavingsProductCustomerSegment', TRUE
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'SavingsProductCustomerSegment');
|
||||
|
||||
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
|
||||
SELECT c.id, 'Non Individual', 3, 'Non Individual', TRUE, FALSE
|
||||
FROM m_code c
|
||||
WHERE c.code_name = 'SavingsProductCustomerSegment'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM m_code_value cv
|
||||
WHERE cv.code_id = c.id AND cv.code_value = 'Non Individual'
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -63,6 +63,7 @@ include ':fineract-tax'
|
||||
include ':fineract-loan-origination'
|
||||
include ':fineract-loan'
|
||||
include ':fineract-savings'
|
||||
include ':fineract-current-product'
|
||||
include ':fineract-report'
|
||||
include ':fineract-mix'
|
||||
include ':fineract-war'
|
||||
|
||||
Reference in New Issue
Block a user