rd and fd product and account code update
This commit is contained in:
+144
@@ -274,6 +274,46 @@ public final class DepositsApiConstants {
|
||||
fixedDepositRequestData.addAll(DEPOSIT_PRODUCT_REQUEST_DATA_PARAMETERS);
|
||||
fixedDepositRequestData.addAll(PRECLOSURE_REQUEST_DATA_PARAMETERS);
|
||||
fixedDepositRequestData.addAll(DEPOSIT_TERM_REQUEST_DATA_PARAMETERS);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.minBalanceForInterestCalculationParamName);
|
||||
fixedDepositRequestData.add("accountType");
|
||||
fixedDepositRequestData.add("customerSegment");
|
||||
fixedDepositRequestData.add("productCode");
|
||||
fixedDepositRequestData.add("fdType");
|
||||
fixedDepositRequestData.add(SavingsApiConstants.glAccountIdParamName);
|
||||
fixedDepositRequestData.add("effectiveDate");
|
||||
fixedDepositRequestData.add("effectiveTo");
|
||||
fixedDepositRequestData.add("endDate");
|
||||
fixedDepositRequestData.add("introducerRequired");
|
||||
fixedDepositRequestData.add("shareLinkingEnabled");
|
||||
fixedDepositRequestData.add("nominationFacility");
|
||||
fixedDepositRequestData.add("dormancyAlert");
|
||||
fixedDepositRequestData.add(SavingsApiConstants.isDormancyTrackingActiveParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.daysToInactiveParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.daysToDormancyParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.daysToEscheatParamName);
|
||||
fixedDepositRequestData.add("interestCalculateSelector");
|
||||
fixedDepositRequestData.add("averagePeriod");
|
||||
fixedDepositRequestData.add("autoPost");
|
||||
fixedDepositRequestData.add("frequencyFixDay");
|
||||
fixedDepositRequestData.add("lastInterestDate");
|
||||
fixedDepositRequestData.add("enableLockinPeriod");
|
||||
fixedDepositRequestData.add("balanceFrequency");
|
||||
fixedDepositRequestData.add("accountClosedZeroBalanceInDayClosing");
|
||||
fixedDepositRequestData.add("autoDebitFacility");
|
||||
fixedDepositRequestData.add("loanFacility");
|
||||
fixedDepositRequestData.add("prematureWithdrawalOption");
|
||||
fixedDepositRequestData.add("tenureFlexibility");
|
||||
fixedDepositRequestData.add("lienMarked");
|
||||
fixedDepositRequestData.add("withdrawalFeeForTransfers");
|
||||
fixedDepositRequestData.add("maturityInstructions");
|
||||
fixedDepositRequestData.add("creditMaturityProceeds");
|
||||
fixedDepositRequestData.add("penaltyGracePeriodMissedInstallments");
|
||||
fixedDepositRequestData.add("panelRequestApplicable");
|
||||
fixedDepositRequestData.add("noPenaltyNomineeHeirClosure");
|
||||
fixedDepositRequestData.add("deceasedSettlement");
|
||||
fixedDepositRequestData.add("allowDebitTxnAfterDueDate");
|
||||
fixedDepositRequestData.add("escheatLiabilityId");
|
||||
fixedDepositRequestData.add("fdSlabs");
|
||||
return fixedDepositRequestData;
|
||||
}
|
||||
|
||||
@@ -282,6 +322,54 @@ public final class DepositsApiConstants {
|
||||
fixedDepositRequestData.addAll(DEPOSIT_PRODUCT_REQUEST_DATA_PARAMETERS);
|
||||
fixedDepositRequestData.addAll(PRECLOSURE_RESPONSE_DATA_PARAMETERS);
|
||||
fixedDepositRequestData.addAll(DEPOSIT_TERM_RESPONSE_DATA_PARAMETERS);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.minBalanceForInterestCalculationParamName);
|
||||
fixedDepositRequestData.add("interestCalculationTypeOption");
|
||||
fixedDepositRequestData.add("periodFrequencyOptions");
|
||||
fixedDepositRequestData.add("yesNoOptions");
|
||||
fixedDepositRequestData.add("accountTypeOptions");
|
||||
fixedDepositRequestData.add("customerSegmentOptions");
|
||||
fixedDepositRequestData.add("accountType");
|
||||
fixedDepositRequestData.add("customerSegment");
|
||||
fixedDepositRequestData.add("productCode");
|
||||
fixedDepositRequestData.add("fdType");
|
||||
fixedDepositRequestData.add(SavingsApiConstants.glAccountIdParamName);
|
||||
fixedDepositRequestData.add("glAccountName");
|
||||
fixedDepositRequestData.add("effectiveDate");
|
||||
fixedDepositRequestData.add("effectiveTo");
|
||||
fixedDepositRequestData.add("endDate");
|
||||
fixedDepositRequestData.add("introducerRequired");
|
||||
fixedDepositRequestData.add("shareLinkingEnabled");
|
||||
fixedDepositRequestData.add("nominationFacility");
|
||||
fixedDepositRequestData.add("dormancyAlert");
|
||||
fixedDepositRequestData.add(SavingsApiConstants.isDormancyTrackingActiveParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.daysToInactiveParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.daysToDormancyParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.daysToEscheatParamName);
|
||||
fixedDepositRequestData.add("interestCalculateSelector");
|
||||
fixedDepositRequestData.add("averagePeriod");
|
||||
fixedDepositRequestData.add("autoPost");
|
||||
fixedDepositRequestData.add("frequencyFixDay");
|
||||
fixedDepositRequestData.add("lastInterestDate");
|
||||
fixedDepositRequestData.add("enableLockinPeriod");
|
||||
fixedDepositRequestData.add("balanceFrequency");
|
||||
fixedDepositRequestData.add("accountClosedZeroBalanceInDayClosing");
|
||||
fixedDepositRequestData.add("autoDebitFacility");
|
||||
fixedDepositRequestData.add("loanFacility");
|
||||
fixedDepositRequestData.add("prematureWithdrawalOption");
|
||||
fixedDepositRequestData.add("tenureFlexibility");
|
||||
fixedDepositRequestData.add("lienMarked");
|
||||
fixedDepositRequestData.add("withdrawalFeeForTransfers");
|
||||
fixedDepositRequestData.add("maturityInstructions");
|
||||
fixedDepositRequestData.add("creditMaturityProceeds");
|
||||
fixedDepositRequestData.add("penaltyGracePeriodMissedInstallments");
|
||||
fixedDepositRequestData.add("panelRequestApplicable");
|
||||
fixedDepositRequestData.add("noPenaltyNomineeHeirClosure");
|
||||
fixedDepositRequestData.add("deceasedSettlement");
|
||||
fixedDepositRequestData.add("allowDebitTxnAfterDueDate");
|
||||
fixedDepositRequestData.add("accountingMappings");
|
||||
fixedDepositRequestData.add("paymentChannelToFundSourceMappings");
|
||||
fixedDepositRequestData.add("feeToIncomeAccountMappings");
|
||||
fixedDepositRequestData.add("penaltyToIncomeAccountMappings");
|
||||
return fixedDepositRequestData;
|
||||
}
|
||||
|
||||
@@ -332,6 +420,7 @@ public final class DepositsApiConstants {
|
||||
recurringDepositRequestData.add("deceasedSettlement");
|
||||
recurringDepositRequestData.add("allowDebitTxnAfterDueDate");
|
||||
recurringDepositRequestData.add("accountClosedZeroBalanceInDayClosing");
|
||||
recurringDepositRequestData.add("escheatLiabilityId");
|
||||
// Custom CBS fields — Interest rate slabs (sent inline but ignored server-side; saved separately)
|
||||
recurringDepositRequestData.add("rdSlabs");
|
||||
return recurringDepositRequestData;
|
||||
@@ -387,6 +476,11 @@ public final class DepositsApiConstants {
|
||||
recurringDepositRequestData.add("noPenaltyNomineeHeirClosure");
|
||||
recurringDepositRequestData.add("deceasedSettlement");
|
||||
recurringDepositRequestData.add("allowDebitTxnAfterDueDate");
|
||||
recurringDepositRequestData.add("escheatLiabilityId");
|
||||
recurringDepositRequestData.add("accountingMappings");
|
||||
recurringDepositRequestData.add("paymentChannelToFundSourceMappings");
|
||||
recurringDepositRequestData.add("feeToIncomeAccountMappings");
|
||||
recurringDepositRequestData.add("penaltyToIncomeAccountMappings");
|
||||
return recurringDepositRequestData;
|
||||
}
|
||||
|
||||
@@ -428,6 +522,27 @@ public final class DepositsApiConstants {
|
||||
fixedDepositRequestData.addAll(DEPOSIT_TERM_REQUEST_DATA_PARAMETERS);
|
||||
fixedDepositRequestData.add(linkedAccountParamName);
|
||||
fixedDepositRequestData.add(transferInterestToSavingsParamName);
|
||||
fixedDepositRequestData.add("accountType");
|
||||
fixedDepositRequestData.add("customerSegment");
|
||||
fixedDepositRequestData.add(SavingsApiConstants.accountStatusParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.modeOfOperationParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.specialCategoryParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.weakerSectionParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.guardianNameParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.guardianCifNumberParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.guardianRelationshipParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.guardianClientIdParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.minorDateOfBirthParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.introducerIdParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.introducerNameParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.introducerCifNumberParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.nomineeParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.linkedAccountIdParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.linkedAccountTypeParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.linkedAccountNoParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.jointHoldersParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.autoDebitFacilityParamName);
|
||||
fixedDepositRequestData.add(SavingsApiConstants.nominationFacilityParamName);
|
||||
return fixedDepositRequestData;
|
||||
}
|
||||
|
||||
@@ -438,6 +553,31 @@ public final class DepositsApiConstants {
|
||||
fixedDepositResponseData.addAll(DEPOSIT_TERM_RESPONSE_DATA_PARAMETERS);
|
||||
fixedDepositResponseData.add(linkedAccountParamName);
|
||||
fixedDepositResponseData.add(transferInterestToSavingsParamName);
|
||||
fixedDepositResponseData.add("accountType");
|
||||
fixedDepositResponseData.add("customerSegment");
|
||||
fixedDepositResponseData.add("accountTypeOptions");
|
||||
fixedDepositResponseData.add("customerSegmentOptions");
|
||||
fixedDepositResponseData.add("productCode");
|
||||
fixedDepositResponseData.add("previewAccountNo");
|
||||
fixedDepositResponseData.add(SavingsApiConstants.accountStatusParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.modeOfOperationParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.specialCategoryParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.weakerSectionParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.guardianNameParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.guardianCifNumberParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.guardianRelationshipParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.guardianClientIdParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.minorDateOfBirthParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.introducerIdParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.introducerNameParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.introducerCifNumberParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.nomineeParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.linkedAccountIdParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.linkedAccountTypeParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.linkedAccountNoParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.jointHoldersParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.nominationFacilityParamName);
|
||||
fixedDepositResponseData.add(SavingsApiConstants.autoDebitFacilityParamName);
|
||||
return fixedDepositResponseData;
|
||||
}
|
||||
|
||||
@@ -517,6 +657,10 @@ public final class DepositsApiConstants {
|
||||
recurringDepositResponseData.add("noPenaltyNomineeHeirClosure");
|
||||
recurringDepositResponseData.add("deceasedSettlement");
|
||||
recurringDepositResponseData.add("allowDebitTxnAfterDueDate");
|
||||
recurringDepositResponseData.add("accountingMappings");
|
||||
recurringDepositResponseData.add("paymentChannelToFundSourceMappings");
|
||||
recurringDepositResponseData.add("feeToIncomeAccountMappings");
|
||||
recurringDepositResponseData.add("penaltyToIncomeAccountMappings");
|
||||
return recurringDepositResponseData;
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -32,6 +32,8 @@ public class SavingsApiConstants {
|
||||
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 FD_PRODUCT_ACCOUNT_TYPE = "FixedDepositProductAccountType";
|
||||
public static final String FD_PRODUCT_CUSTOMER_SEGMENT = "FixedDepositProductCustomerSegment";
|
||||
public static final String PERIOD_FREQUENCY = "PeriodFrequency";
|
||||
public static final String INTEREST_CALCULATION_TYPE_OPTION = "InterestCalculationTypeOption";
|
||||
|
||||
|
||||
+1
-1
@@ -226,7 +226,7 @@ public class CurrentProduct extends AbstractPersistableCustom<Long> {
|
||||
@Column(name = "customer_segment", length = 50)
|
||||
private String customerSegment;
|
||||
|
||||
@Column(name = "product_code", length = 20, unique = true)
|
||||
@Column(name = "product_code", length = 20)
|
||||
private String productCode;
|
||||
|
||||
@Column(name = "gl_account_id")
|
||||
|
||||
+10
-1
@@ -189,7 +189,16 @@ public class AccountAssociationsReadPlatformServiceImpl implements AccountAssoci
|
||||
|
||||
@Override
|
||||
public PortfolioAccountData retriveSavingsAccount(final Long savingsId) {
|
||||
String accountNo = jdbcTemplate.queryForObject("select account_no from m_savings_account where id = ?", String.class, savingsId);
|
||||
String accountNo = null;
|
||||
try {
|
||||
accountNo = jdbcTemplate.queryForObject("select account_no from m_savings_account where id = ?", String.class, savingsId);
|
||||
} catch (EmptyResultDataAccessException e) {
|
||||
try {
|
||||
accountNo = jdbcTemplate.queryForObject("select account_no from m_current_account where id = ?", String.class, savingsId);
|
||||
} catch (EmptyResultDataAccessException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return PortfolioAccountData.lookup(savingsId, accountNo);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-16
@@ -102,21 +102,6 @@ public class CurrentProductsApiResource {
|
||||
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 })
|
||||
@@ -306,7 +291,7 @@ public class CurrentProductsApiResource {
|
||||
interestCalculationTypeOption, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions,
|
||||
periodFrequencyOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, chargeOptions,
|
||||
penaltyOptions, taxGroupOptions, yesNoOptions, accountTypeOptions, customerSegmentOptions, accountMappingForPayment);
|
||||
savingsProductToReturn.setProductCode(generateNextProductCode("m_current_product", "CA-IND-"));
|
||||
// product code removed
|
||||
}
|
||||
|
||||
return savingsProductToReturn;
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.api;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class FdInterestRateSaveRequest {
|
||||
|
||||
private String fdType;
|
||||
private String versionLabel;
|
||||
private String remarks;
|
||||
private List<SlabRequest> slabs;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public static class SlabRequest {
|
||||
private Integer srNo;
|
||||
private String description;
|
||||
private Integer periodTypeEnum;
|
||||
private Integer fromPeriod;
|
||||
private Integer toPeriod;
|
||||
private BigDecimal annualInterestRate;
|
||||
private BigDecimal seniorCitizenRate;
|
||||
}
|
||||
}
|
||||
+39
@@ -54,9 +54,13 @@ import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import java.util.Locale;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService;
|
||||
@@ -110,6 +114,8 @@ public class FixedDepositProductsApiResource {
|
||||
private final DropdownReadPlatformService dropdownReadPlatformService;
|
||||
private final PaymentTypeReadService paymentTypeReadPlatformService;
|
||||
private final TaxReadPlatformService taxReadPlatformService;
|
||||
private final CodeValueReadPlatformService codeValueReadPlatformService;
|
||||
private final org.springframework.jdbc.core.JdbcTemplate jdbcTemplate;
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@@ -315,6 +321,16 @@ public class FixedDepositProductsApiResource {
|
||||
// interest rate chart template
|
||||
final InterestRateChartData chartTemplate = this.interestRateChartReadPlatformService.template();
|
||||
|
||||
// CBS custom options
|
||||
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.FD_PRODUCT_ACCOUNT_TYPE));
|
||||
final List<CodeValueData> customerSegmentOptions = new ArrayList<>(
|
||||
this.codeValueReadPlatformService.retrieveCodeValuesByCode(SavingsApiConstants.FD_PRODUCT_CUSTOMER_SEGMENT));
|
||||
|
||||
FixedDepositProductData fixedDepositProductToReturn = null;
|
||||
if (savingsProduct != null) {
|
||||
fixedDepositProductToReturn = FixedDepositProductData.withTemplate(savingsProduct, currencyOptions,
|
||||
@@ -329,11 +345,34 @@ public class FixedDepositProductsApiResource {
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions,
|
||||
paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, chargeOptions, penaltyOptions, chartTemplate,
|
||||
preClosurePenalInterestOnTypeOptions, periodFrequencyTypeOptions, taxGroupOptions);
|
||||
// product code removed
|
||||
}
|
||||
|
||||
fixedDepositProductToReturn.setInterestCalculationTypeOption(interestCalculationTypeOption);
|
||||
fixedDepositProductToReturn.setPeriodFrequencyOptions(periodFrequencyOptions);
|
||||
fixedDepositProductToReturn.setYesNoOptions(yesNoOptions);
|
||||
fixedDepositProductToReturn.setAccountTypeOptions(accountTypeOptions);
|
||||
fixedDepositProductToReturn.setCustomerSegmentOptions(customerSegmentOptions);
|
||||
|
||||
return fixedDepositProductToReturn;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@DELETE
|
||||
@Path("{productId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
|
||||
+1
@@ -342,6 +342,7 @@ final class FixedDepositProductsApiResourceSwagger {
|
||||
public GetFixedDepositProductsGlAccount interestOnSavingsAccount;
|
||||
public GetFixedDepositProductsGlAccount savingsControlAccount;
|
||||
public GetFixedDepositProductsGlAccount transfersInSuspenseAccount;
|
||||
public GetFixedDepositProductsGlAccount escheatLiabilityAccount;
|
||||
public GetFixedDepositProductsGlAccount interestPayableAccount;
|
||||
}
|
||||
|
||||
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.savings.DepositsApiConstants;
|
||||
import org.apache.fineract.portfolio.savings.data.FdInterestRateEffectiveData;
|
||||
import org.apache.fineract.portfolio.savings.service.FdBaseInterestRateReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/fixeddepositproducts/baseinterestrates")
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class FixedDepositProductsBaseInterestRatesApiResource {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final FdBaseInterestRateReadPlatformService fdBaseInterestRateReadPlatformService;
|
||||
private final Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(LocalDate.class,
|
||||
(JsonSerializer<LocalDate>) (src, typeOfSrc, ctx) -> new JsonPrimitive(src.toString()))
|
||||
.create();
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Get all active FD base interest rate charts", description = "Returns active CBS FD base interest-rate versions with slabs. Optionally filter by fdType (SINGLE, DOUBLE, SPECIAL).")
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
|
||||
public String retrieveAllActiveInterestRates(@QueryParam("fdType") final String fdType) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME);
|
||||
final List<FdInterestRateEffectiveData> data = fdType != null && !fdType.isBlank()
|
||||
? this.fdBaseInterestRateReadPlatformService.retrieveActiveInterestRatesByType(fdType)
|
||||
: this.fdBaseInterestRateReadPlatformService.retrieveAllActiveInterestRates();
|
||||
return gson.toJson(data);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("history")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Get all FD base interest rate charts", description = "Returns the full FD base chart history.")
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
|
||||
public String retrieveHistory() {
|
||||
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME);
|
||||
final List<FdInterestRateEffectiveData> data = this.fdBaseInterestRateReadPlatformService.retrieveAllInterestRates();
|
||||
return gson.toJson(data);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Save new FD base interest rate version", description = "Creates a new FD CBS base chart version for the given fdType and deactivates the previous active version.")
|
||||
@ApiResponses({ @ApiResponse(responseCode = "200", description = "OK") })
|
||||
public String saveInterestRates(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(DepositsApiConstants.FIXED_DEPOSIT_PRODUCT_RESOURCE_NAME);
|
||||
final FdInterestRateSaveRequest request = gson.fromJson(apiRequestBodyAsJson, FdInterestRateSaveRequest.class);
|
||||
final Long createdById = this.context.authenticatedUser().getId();
|
||||
final FdInterestRateEffectiveData saved = this.fdBaseInterestRateReadPlatformService.saveInterestRates(request, createdById);
|
||||
return gson.toJson(saved);
|
||||
}
|
||||
}
|
||||
+15
@@ -45,6 +45,7 @@ import jakarta.ws.rs.core.UriInfo;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -77,6 +78,7 @@ import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
|
||||
import org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
|
||||
import org.apache.fineract.portfolio.savings.service.DepositAccountPreMatureCalculationPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.DepositAccountReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.RecurringDepositAccountInterestCalculationService;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsAccountChargeReadPlatformService;
|
||||
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
|
||||
import org.glassfish.jersey.media.multipart.FormDataParam;
|
||||
@@ -99,6 +101,7 @@ public class RecurringDepositAccountsApiResource {
|
||||
private final DepositAccountPreMatureCalculationPlatformService accountPreMatureCalculationPlatformService;
|
||||
private final BulkImportWorkbookService bulkImportWorkbookService;
|
||||
private final BulkImportWorkbookPopulatorService bulkImportWorkbookPopulatorService;
|
||||
private final RecurringDepositAccountInterestCalculationService recurringDepositAccountInterestCalculationService;
|
||||
private final SqlValidator sqlValidator;
|
||||
|
||||
@GET
|
||||
@@ -369,6 +372,18 @@ public class RecurringDepositAccountsApiResource {
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("calculate-rd-interest")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public String calculateRecurringDepositInterest(@Context final UriInfo uriInfo, final String apiRequestBodyAsJson) {
|
||||
JsonElement jsonElement = fromJsonHelper.parse(apiRequestBodyAsJson);
|
||||
HashMap<String, Object> result = recurringDepositAccountInterestCalculationService
|
||||
.calculateInterest(new JsonQuery(apiRequestBodyAsJson, jsonElement, fromJsonHelper));
|
||||
|
||||
return toApiJsonSerializer.serializeResult(result);
|
||||
}
|
||||
|
||||
private boolean is(final String commandParam, final String commandValue) {
|
||||
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
|
||||
}
|
||||
|
||||
+1
-16
@@ -333,7 +333,7 @@ public class RecurringDepositProductsApiResource {
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions,
|
||||
paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, chargeOptions, penaltyOptions, chartTemplate,
|
||||
preClosurePenalInterestOnTypeOptions, periodFrequencyTypeOptions, taxGroupOptions);
|
||||
recurringDepositProductToReturn.setProductCode(generateNextProductCode("m_savings_product", "RD-IND-"));
|
||||
// product code removed
|
||||
}
|
||||
|
||||
recurringDepositProductToReturn.setInterestCalculationTypeOption(interestCalculationTypeOption);
|
||||
@@ -360,21 +360,6 @@ public class RecurringDepositProductsApiResource {
|
||||
.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 = 300",
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
// ── RD Interest Rate Chart endpoints ────────────────────────────────────
|
||||
|
||||
|
||||
+1
@@ -360,6 +360,7 @@ final class RecurringDepositProductsApiResourceSwagger {
|
||||
public GetRecurringDepositProductsGlAccount interestOnSavingsAccount;
|
||||
public GetRecurringDepositProductsGlAccount savingsControlAccount;
|
||||
public GetRecurringDepositProductsGlAccount transfersInSuspenseAccount;
|
||||
public GetRecurringDepositProductsGlAccount escheatLiabilityAccount;
|
||||
public GetRecurringDepositProductsGlAccount feeReceivableAccount;
|
||||
public GetRecurringDepositProductsGlAccount penaltyReceivableAccount;
|
||||
public GetRecurringDepositProductsGlAccount interestPayableAccount;
|
||||
|
||||
+1
-16
@@ -106,21 +106,6 @@ public class SavingsProductsApiResource {
|
||||
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 })
|
||||
@@ -315,7 +300,7 @@ public class SavingsProductsApiResource {
|
||||
periodFrequencyOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, chargeOptions,
|
||||
penaltyOptions, taxGroupOptions, yesNoOptions, accountTypeOptions, customerSegmentOptions,
|
||||
accountMappingForPayment);
|
||||
savingsProductToReturn.setProductCode(generateNextProductCode("m_savings_product", "SB-IND-"));
|
||||
// product code generation removed
|
||||
}
|
||||
|
||||
return savingsProductToReturn;
|
||||
|
||||
+1
@@ -285,6 +285,7 @@ final class SavingsProductsApiResourceSwagger {
|
||||
public GetSavingsProductsGlAccount writeOffAccount;
|
||||
public GetSavingsProductsGlAccount savingsControlAccount;
|
||||
public GetSavingsProductsGlAccount transfersInSuspenseAccount;
|
||||
public GetSavingsProductsGlAccount escheatLiabilityAccount;
|
||||
public GetSavingsProductsGlAccount interestPayableAccount;
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -632,8 +632,12 @@ public class DepositProductDataValidator {
|
||||
}
|
||||
|
||||
private void validateDepositAmountForCreate(JsonElement element, DataValidatorBuilder baseDataValidator) {
|
||||
final BigDecimal depositAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(depositAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(depositAmountParamName).value(depositAmount).notNull().positiveAmount();
|
||||
final BigDecimal depositAmount = this.fromApiJsonHelper.parameterExists(depositAmountParamName, element)
|
||||
? this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(depositAmountParamName, element)
|
||||
: null;
|
||||
if (depositAmount != null) {
|
||||
baseDataValidator.reset().parameter(depositAmountParamName).value(depositAmount).positiveAmount();
|
||||
}
|
||||
|
||||
BigDecimal depositMinAmount = null;
|
||||
if (this.fromApiJsonHelper.parameterExists(depositMinAmountParamName, element)) {
|
||||
@@ -667,7 +671,7 @@ public class DepositProductDataValidator {
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(depositAmountParamName, element)) {
|
||||
depositAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(depositAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(depositAmountParamName).value(depositAmount).notNull().positiveAmount();
|
||||
baseDataValidator.reset().parameter(depositAmountParamName).value(depositAmount).positiveAmount();
|
||||
}
|
||||
|
||||
BigDecimal depositMinAmount = null;
|
||||
|
||||
+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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.data;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class FdInterestRateEffectiveData {
|
||||
|
||||
private Long id;
|
||||
private String fdType;
|
||||
private String versionLabel;
|
||||
private LocalDate effectiveFromDate;
|
||||
private LocalDate effectiveToDate;
|
||||
private Boolean isActive;
|
||||
private String remarks;
|
||||
private List<FdInterestRateSlabData> slabs;
|
||||
}
|
||||
+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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class FdInterestRateSlabData {
|
||||
|
||||
private Long id;
|
||||
private Integer srNo;
|
||||
private String description;
|
||||
private Integer periodTypeEnum;
|
||||
private String periodTypeLabel;
|
||||
private Integer fromPeriod;
|
||||
private Integer toPeriod;
|
||||
private BigDecimal annualInterestRate;
|
||||
private BigDecimal seniorCitizenRate;
|
||||
}
|
||||
+7
-1
@@ -120,6 +120,7 @@ public class DepositAccountAssembler {
|
||||
private final PaymentDetailAssembler paymentDetailAssembler;
|
||||
|
||||
private final ExternalIdFactory externalIdFactory;
|
||||
private final SavingsAccountAssembler savingsAccountAssembler;
|
||||
|
||||
@Autowired
|
||||
public DepositAccountAssembler(final SavingsAccountTransactionSummaryWrapper savingsAccountTransactionSummaryWrapper,
|
||||
@@ -130,7 +131,8 @@ public class DepositAccountAssembler {
|
||||
final DepositProductAssembler depositProductAssembler,
|
||||
final RecurringDepositProductRepository recurringDepositProductRepository,
|
||||
final AccountTransfersReadPlatformService accountTransfersReadPlatformService, final PlatformSecurityContext context,
|
||||
final PaymentDetailAssembler paymentDetailAssembler, ExternalIdFactory externalIdFactory) {
|
||||
final PaymentDetailAssembler paymentDetailAssembler, ExternalIdFactory externalIdFactory,
|
||||
final SavingsAccountAssembler savingsAccountAssembler) {
|
||||
|
||||
this.savingsAccountTransactionSummaryWrapper = savingsAccountTransactionSummaryWrapper;
|
||||
this.clientRepository = clientRepository;
|
||||
@@ -146,6 +148,7 @@ public class DepositAccountAssembler {
|
||||
this.context = context;
|
||||
this.paymentDetailAssembler = paymentDetailAssembler;
|
||||
this.externalIdFactory = externalIdFactory;
|
||||
this.savingsAccountAssembler = savingsAccountAssembler;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,6 +361,9 @@ public class DepositAccountAssembler {
|
||||
if (account != null) {
|
||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper);
|
||||
account.validateNewApplicationState(depositAccountType.resourceName());
|
||||
// Apply CBS-specific fields (accountStatus, customerSegment, autoDebitFacility,
|
||||
// linkedAccount, nominee, jointHolders, guardian, etc.)
|
||||
this.savingsAccountAssembler.applyCbsFields(command, element, account);
|
||||
}
|
||||
|
||||
return account;
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_fd_base_interest_rate_effective")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class FdBaseInterestRateEffective {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "fd_type", length = 20)
|
||||
private String fdType;
|
||||
|
||||
@Column(name = "version_label")
|
||||
private String versionLabel;
|
||||
|
||||
@Column(name = "effective_from_date")
|
||||
private LocalDate effectiveFromDate;
|
||||
|
||||
@Column(name = "effective_to_date")
|
||||
private LocalDate effectiveToDate;
|
||||
|
||||
@Column(name = "is_active")
|
||||
private Boolean isActive;
|
||||
|
||||
@Column(name = "remarks")
|
||||
private String remarks;
|
||||
|
||||
@Column(name = "created_by_id")
|
||||
private Long createdById;
|
||||
|
||||
@Column(name = "created_date")
|
||||
private LocalDate createdDate;
|
||||
|
||||
public static FdBaseInterestRateEffective create(String fdType, String versionLabel, LocalDate effectiveFromDate, String remarks,
|
||||
Long createdById) {
|
||||
FdBaseInterestRateEffective e = new FdBaseInterestRateEffective();
|
||||
e.fdType = fdType;
|
||||
e.versionLabel = versionLabel;
|
||||
e.effectiveFromDate = effectiveFromDate;
|
||||
e.isActive = true;
|
||||
e.remarks = remarks;
|
||||
e.createdById = createdById;
|
||||
e.createdDate = LocalDate.now();
|
||||
return e;
|
||||
}
|
||||
|
||||
public void deactivate(LocalDate toDate) {
|
||||
this.isActive = false;
|
||||
this.effectiveToDate = toDate;
|
||||
}
|
||||
}
|
||||
+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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface FdBaseInterestRateEffectiveRepository extends JpaRepository<FdBaseInterestRateEffective, Long> {
|
||||
|
||||
List<FdBaseInterestRateEffective> findByFdTypeAndIsActiveTrueOrderByEffectiveFromDateDesc(String fdType);
|
||||
|
||||
List<FdBaseInterestRateEffective> findByFdTypeOrderByEffectiveFromDateDesc(String fdType);
|
||||
|
||||
List<FdBaseInterestRateEffective> findByIsActiveTrueOrderByEffectiveFromDateDesc();
|
||||
|
||||
List<FdBaseInterestRateEffective> findByOrderByEffectiveFromDateDesc();
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_fd_base_interest_rate_slab_history")
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class FdBaseInterestRateSlabHistory {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "effective_id")
|
||||
private Long effectiveId;
|
||||
|
||||
@Column(name = "sr_no")
|
||||
private Integer srNo;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
@Column(name = "period_type_enum")
|
||||
private Integer periodTypeEnum;
|
||||
|
||||
@Column(name = "from_period")
|
||||
private Integer fromPeriod;
|
||||
|
||||
@Column(name = "to_period")
|
||||
private Integer toPeriod;
|
||||
|
||||
@Column(name = "annual_interest_rate")
|
||||
private BigDecimal annualInterestRate;
|
||||
|
||||
@Column(name = "senior_citizen_rate")
|
||||
private BigDecimal seniorCitizenRate;
|
||||
|
||||
@Column(name = "created_date")
|
||||
private LocalDate createdDate;
|
||||
|
||||
public static FdBaseInterestRateSlabHistory create(Long effectiveId, Integer srNo, String description, Integer periodTypeEnum,
|
||||
Integer fromPeriod, Integer toPeriod, BigDecimal annualInterestRate, BigDecimal seniorCitizenRate) {
|
||||
FdBaseInterestRateSlabHistory s = new FdBaseInterestRateSlabHistory();
|
||||
s.effectiveId = effectiveId;
|
||||
s.srNo = srNo;
|
||||
s.description = description;
|
||||
s.periodTypeEnum = periodTypeEnum != null ? periodTypeEnum : 1;
|
||||
s.fromPeriod = fromPeriod;
|
||||
s.toPeriod = toPeriod;
|
||||
s.annualInterestRate = annualInterestRate;
|
||||
s.seniorCitizenRate = seniorCitizenRate;
|
||||
s.createdDate = LocalDate.now();
|
||||
return s;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface FdBaseInterestRateSlabHistoryRepository extends JpaRepository<FdBaseInterestRateSlabHistory, Long> {
|
||||
|
||||
List<FdBaseInterestRateSlabHistory> findByEffectiveIdOrderBySrNo(Long effectiveId);
|
||||
}
|
||||
+10
@@ -40,6 +40,8 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.minorDat
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nomineeParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.specialCategoryParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.weakerSectionParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominationFacilityParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoDebitFacilityParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.clientIdParamName;
|
||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enforceMinRequiredBalanceParamName;
|
||||
@@ -384,6 +386,14 @@ public class SavingsAccountAssembler {
|
||||
|
||||
account.setSpecialCategory(this.fromApiJsonHelper.extractStringNamed(specialCategoryParamName, element));
|
||||
account.setWeakerSection(this.fromApiJsonHelper.extractStringNamed(weakerSectionParamName, element));
|
||||
|
||||
if (command.parameterExists(nominationFacilityParamName)) {
|
||||
account.setNominationFacility(this.fromApiJsonHelper.extractBooleanNamed(nominationFacilityParamName, element));
|
||||
}
|
||||
if (command.parameterExists(autoDebitFacilityParamName)) {
|
||||
account.setAutoDebitFacility(this.fromApiJsonHelper.extractBooleanNamed(autoDebitFacilityParamName, element));
|
||||
}
|
||||
|
||||
account.setGuardianName(this.fromApiJsonHelper.extractStringNamed(guardianNameParamName, element));
|
||||
account.setGuardianCifNumber(this.fromApiJsonHelper.extractStringNamed(guardianCifNumberParamName, element));
|
||||
account.setGuardianRelationship(this.fromApiJsonHelper.extractStringNamed(guardianRelationshipParamName, element));
|
||||
|
||||
+161
-14
@@ -408,6 +408,24 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
periodFrequencyTypeOptions, savingsAccountDatas, maturityInstructionOptions);
|
||||
|
||||
template = FixedDepositAccountData.withInterestChart((FixedDepositAccountData) template, accountChart);
|
||||
|
||||
try {
|
||||
final Collection<CodeValueData> accountTypeOpts = this.codeValueReadPlatformService
|
||||
.retrieveCodeValuesByCode(SavingsApiConstants.FD_PRODUCT_ACCOUNT_TYPE);
|
||||
final Collection<CodeValueData> customerSegmentOpts = this.codeValueReadPlatformService
|
||||
.retrieveCodeValuesByCode(SavingsApiConstants.FD_PRODUCT_CUSTOMER_SEGMENT);
|
||||
((FixedDepositAccountData) template).setAccountTypeOptions(accountTypeOpts);
|
||||
((FixedDepositAccountData) template).setCustomerSegmentOptions(customerSegmentOpts);
|
||||
} catch (final Exception ex) {
|
||||
log.warn("Failed to load FD account type/customer segment options: {}", ex.getMessage());
|
||||
}
|
||||
|
||||
try {
|
||||
final String preview = accountNumberGenerator.previewAccountNumber(productId, officeId);
|
||||
template.setPreviewAccountNo(preview);
|
||||
} catch (final Exception ex) {
|
||||
log.warn("Failed to generate preview account number for FD productId={}: {}", productId, ex.getMessage());
|
||||
}
|
||||
} else if (depositAccountType.isRecurringDeposit()) {
|
||||
// Save CBS fields from mapper result before factory methods create new objects
|
||||
final RecurringDepositAccountData rdTemplateWithCbs = (RecurringDepositAccountData) template;
|
||||
@@ -696,6 +714,16 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
selectFieldsSqlBuilder.append("sa.total_penalty_charge_derived as totalPenaltyCharge, ");
|
||||
selectFieldsSqlBuilder.append("sa.total_withhold_tax_derived as totalWithholdTax,");
|
||||
selectFieldsSqlBuilder.append("sa.deposit_type_enum as depositTypeId, ");
|
||||
selectFieldsSqlBuilder.append("sa.cbs_account_type as accountType, sa.customer_segment as customerSegment, ");
|
||||
selectFieldsSqlBuilder.append("sa.account_status as accountStatus, sa.mode_of_operation as modeOfOperation, ");
|
||||
selectFieldsSqlBuilder.append("sa.special_category as specialCategory, sa.weaker_section as weakerSection, ");
|
||||
selectFieldsSqlBuilder.append("sa.guardian_name as guardianName, sa.guardian_cif_number as guardianCifNumber, ");
|
||||
selectFieldsSqlBuilder.append("sa.guardian_relationship as guardianRelationship, sa.guardian_client_id as guardianClientId, ");
|
||||
selectFieldsSqlBuilder.append("sa.minor_date_of_birth as minorDateOfBirth, ");
|
||||
selectFieldsSqlBuilder.append("sa.introducer_client_id as introducerClientId, sa.introducer_name as introducerName, ");
|
||||
selectFieldsSqlBuilder.append("sa.introducer_cif_number as introducerCifNumber, ");
|
||||
selectFieldsSqlBuilder.append("sa.linked_account_id as linkedAccountId, sa.linked_account_type as linkedAccountType, ");
|
||||
selectFieldsSqlBuilder.append("sa.linked_account_no as linkedAccountNo, ");
|
||||
selectFieldsSqlBuilder.append("sa.min_balance_for_interest_calculation as minBalanceForInterestCalculation, ");
|
||||
selectFieldsSqlBuilder.append("sa.withhold_tax as withHoldTax,");
|
||||
selectFieldsSqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName ");
|
||||
@@ -706,6 +734,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
selectTablesSqlBuilder.append("from m_savings_account sa ");
|
||||
selectTablesSqlBuilder.append("left join m_deposit_account_term_and_preclosure datp on sa.id = datp.savings_account_id ");
|
||||
selectTablesSqlBuilder.append("join m_savings_product sp ON sa.product_id = sp.id ");
|
||||
selectTablesSqlBuilder.append("left join m_code_value icv on icv.id = sp.interest_calculate_selector ");
|
||||
selectTablesSqlBuilder.append("join m_currency curr on curr.code = sa.currency_code ");
|
||||
selectTablesSqlBuilder.append("left join m_client c ON c.id = sa.client_id ");
|
||||
selectTablesSqlBuilder.append("left join m_group g ON g.id = sa.group_id ");
|
||||
@@ -714,7 +743,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
selectTablesSqlBuilder.append("left join m_appuser rbu on rbu.id = sa.rejectedon_userid ");
|
||||
selectTablesSqlBuilder.append("left join m_appuser wbu on wbu.id = sa.withdrawnon_userid ");
|
||||
selectTablesSqlBuilder.append("left join m_appuser abu on abu.id = sa.approvedon_userid ");
|
||||
selectTablesSqlBuilder.append("left join m_appuser avbu on rbu.id = sa.activatedon_userid ");
|
||||
selectTablesSqlBuilder.append("left join m_appuser avbu on avbu.id = sa.activatedon_userid ");
|
||||
selectTablesSqlBuilder.append("left join m_appuser cbu on cbu.id = sa.closedon_userid ");
|
||||
selectTablesSqlBuilder.append("left join m_tax_group tg on tg.id = sa.tax_group_id ");
|
||||
|
||||
@@ -904,7 +933,28 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
sqlBuilder.append("datp.deposit_period_frequency_enum as depositPeriodFrequencyTypeId, ");
|
||||
sqlBuilder.append("datp.on_account_closure_enum as onAccountClosureId, ");
|
||||
sqlBuilder.append("datp.transfer_interest_to_linked_account as transferInterestToSavings, ");
|
||||
sqlBuilder.append("datp.transfer_to_savings_account_id as transferToSavingsId ");
|
||||
sqlBuilder.append("datp.transfer_to_savings_account_id as transferToSavingsId, ");
|
||||
sqlBuilder.append("sp.fd_type as fdType, sp.product_code as productCode, sp.effective_date as effectiveDate, ");
|
||||
sqlBuilder.append("sp.effective_to as effectiveTo, sp.end_date as endDate, sp.introducer_required as introducerRequired, ");
|
||||
sqlBuilder.append("sp.share_linking_enabled as shareLinkingEnabled, ");
|
||||
sqlBuilder.append("COALESCE(sa.nomination_facility, sp.nomination_facility) as nominationFacility, ");
|
||||
sqlBuilder.append("sp.dormancy_alert as dormancyAlert, sp.is_dormancy_tracking_active as isDormancyTrackingActive, ");
|
||||
sqlBuilder.append("sp.days_to_inactive as daysToInactive, sp.days_to_dormancy as daysToDormancy, ");
|
||||
sqlBuilder.append("sp.days_to_escheat as daysToEscheat, sp.interest_calculate_selector as interestCalculateSelector, ");
|
||||
sqlBuilder.append("icv.code_value as interestCalculationTypeName, sp.average_period as averagePeriod, ");
|
||||
sqlBuilder.append("sp.auto_post as autoPost, sp.frequency_fix_day as frequencyFixDay, ");
|
||||
sqlBuilder.append("sp.last_interest_date as lastInterestDate, sp.enable_lockin_period as enableLockinPeriod, ");
|
||||
sqlBuilder.append("sp.balance_frequency as balanceFrequency, ");
|
||||
sqlBuilder.append("sp.account_closed_zero_balance_in_day_closing as accountClosedZeroBalanceInDayClosing, ");
|
||||
sqlBuilder.append("sp.balance_swap_option as balanceSwapOption, sp.msme as msme, ");
|
||||
sqlBuilder.append("COALESCE(sa.auto_debit_facility, sp.auto_debit_facility) as autoDebitFacility, ");
|
||||
sqlBuilder.append("sp.loan_facility as loanFacility, sp.premature_withdrawal_option as prematureWithdrawalOption, ");
|
||||
sqlBuilder.append("sp.tenure_flexibility as tenureFlexibility, sp.lien_marked as lienMarked, ");
|
||||
sqlBuilder.append("sp.maturity_instructions as maturityInstructions, sp.credit_maturity_proceeds as creditMaturityProceeds, ");
|
||||
sqlBuilder.append("sp.penalty_grace_period_missed_installments as penaltyGracePeriodMissedInstallments, ");
|
||||
sqlBuilder.append("sp.panel_request_applicable as panelRequestApplicable, ");
|
||||
sqlBuilder.append("sp.no_penalty_nominee_heir_closure as noPenaltyNomineeHeirClosure, ");
|
||||
sqlBuilder.append("sp.deceased_settlement as deceasedSettlement, sp.allow_debit_txn_after_due_date as allowDebitTxnAfterDueDate ");
|
||||
|
||||
sqlBuilder.append(super.selectTablesSql());
|
||||
|
||||
@@ -954,10 +1004,26 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
|
||||
final Long transferToSavingsId = JdbcSupport.getLong(rs, TRANSFER_TO_SAVINGS_ID);
|
||||
|
||||
return FixedDepositAccountData.instance(depositAccountData, preClosurePenalApplicable, preClosurePenalInterest,
|
||||
final FixedDepositAccountData result = FixedDepositAccountData.instance(depositAccountData, preClosurePenalApplicable, preClosurePenalInterest,
|
||||
preClosurePenalInterestOnType, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
|
||||
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod,
|
||||
depositPeriodFrequencyType, onAccountClosureType, transferInterestToSavings, transferToSavingsId);
|
||||
result.setCbsProductFields(rs.getString("accountType"), rs.getString("customerSegment"), rs.getString("fdType"), rs.getString("productCode"),
|
||||
JdbcSupport.getLocalDate(rs, "effectiveDate"), JdbcSupport.getLocalDate(rs, "effectiveTo"),
|
||||
JdbcSupport.getLocalDate(rs, "endDate"), rs.getBoolean("introducerRequired"), rs.getBoolean("shareLinkingEnabled"),
|
||||
rs.getBoolean("nominationFacility"), rs.getBoolean("dormancyAlert"), rs.getBoolean("isDormancyTrackingActive"),
|
||||
JdbcSupport.getLong(rs, "daysToInactive"), JdbcSupport.getLong(rs, "daysToDormancy"),
|
||||
JdbcSupport.getLong(rs, "daysToEscheat"), JdbcSupport.getInteger(rs, "interestCalculateSelector"),
|
||||
rs.getString("interestCalculationTypeName"), rs.getString("averagePeriod"), rs.getBoolean("autoPost"),
|
||||
JdbcSupport.getInteger(rs, "frequencyFixDay"), JdbcSupport.getLocalDate(rs, "lastInterestDate"),
|
||||
rs.getBoolean("enableLockinPeriod"), rs.getString("balanceFrequency"),
|
||||
rs.getBoolean("accountClosedZeroBalanceInDayClosing"), rs.getBoolean("balanceSwapOption"), rs.getBoolean("msme"),
|
||||
rs.getBoolean("autoDebitFacility"), rs.getBoolean("loanFacility"), rs.getBoolean("prematureWithdrawalOption"),
|
||||
rs.getBoolean("tenureFlexibility"), rs.getBoolean("lienMarked"), rs.getBoolean("maturityInstructions"),
|
||||
rs.getBoolean("creditMaturityProceeds"), rs.getBoolean("penaltyGracePeriodMissedInstallments"),
|
||||
rs.getBoolean("panelRequestApplicable"), rs.getBoolean("noPenaltyNomineeHeirClosure"),
|
||||
rs.getBoolean("deceasedSettlement"), rs.getBoolean("allowDebitTxnAfterDueDate"));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1014,7 +1080,28 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
sqlBuilder.append("datp.maturity_date as maturityDate, ");
|
||||
sqlBuilder.append("datp.deposit_period as depositPeriod, ");
|
||||
sqlBuilder.append("datp.deposit_period_frequency_enum as depositPeriodFrequencyTypeId, ");
|
||||
sqlBuilder.append("datp.on_account_closure_enum as onAccountClosureId ");
|
||||
sqlBuilder.append("datp.on_account_closure_enum as onAccountClosureId, ");
|
||||
sqlBuilder.append("sp.product_code as productCode, sp.effective_date as effectiveDate, ");
|
||||
sqlBuilder.append("sp.effective_to as effectiveTo, sp.end_date as endDate, sp.introducer_required as introducerRequired, ");
|
||||
sqlBuilder.append("sp.share_linking_enabled as shareLinkingEnabled, ");
|
||||
sqlBuilder.append("COALESCE(sa.nomination_facility, sp.nomination_facility) as nominationFacility, ");
|
||||
sqlBuilder.append("sp.dormancy_alert as dormancyAlert, sp.is_dormancy_tracking_active as isDormancyTrackingActive, ");
|
||||
sqlBuilder.append("sp.days_to_inactive as daysToInactive, sp.days_to_dormancy as daysToDormancy, ");
|
||||
sqlBuilder.append("sp.days_to_escheat as daysToEscheat, sp.interest_calculate_selector as interestCalculateSelector, ");
|
||||
sqlBuilder.append("icv.code_value as interestCalculationTypeName, sp.average_period as averagePeriod, ");
|
||||
sqlBuilder.append("sp.auto_post as autoPost, sp.frequency_fix_day as frequencyFixDay, ");
|
||||
sqlBuilder.append("sp.last_interest_date as lastInterestDate, sp.enable_lockin_period as enableLockinPeriod, ");
|
||||
sqlBuilder.append("sp.balance_frequency as balanceFrequency, ");
|
||||
sqlBuilder.append("sp.account_closed_zero_balance_in_day_closing as accountClosedZeroBalanceInDayClosing, ");
|
||||
sqlBuilder.append("sp.balance_swap_option as balanceSwapOption, sp.msme as msme, ");
|
||||
sqlBuilder.append("COALESCE(sa.auto_debit_facility, sp.auto_debit_facility) as autoDebitFacility, ");
|
||||
sqlBuilder.append("sp.loan_facility as loanFacility, sp.premature_withdrawal_option as prematureWithdrawalOption, ");
|
||||
sqlBuilder.append("sp.tenure_flexibility as tenureFlexibility, sp.lien_marked as lienMarked, ");
|
||||
sqlBuilder.append("sp.maturity_instructions as maturityInstructions, sp.credit_maturity_proceeds as creditMaturityProceeds, ");
|
||||
sqlBuilder.append("sp.penalty_grace_period_missed_installments as penaltyGracePeriodMissedInstallments, ");
|
||||
sqlBuilder.append("sp.panel_request_applicable as panelRequestApplicable, ");
|
||||
sqlBuilder.append("sp.no_penalty_nominee_heir_closure as noPenaltyNomineeHeirClosure, ");
|
||||
sqlBuilder.append("sp.deceased_settlement as deceasedSettlement, sp.allow_debit_txn_after_due_date as allowDebitTxnAfterDueDate ");
|
||||
|
||||
sqlBuilder.append(this.selectTablesSql());
|
||||
sqlBuilder.append("left join m_deposit_account_recurring_detail dard on sa.id = dard.savings_account_id ");
|
||||
@@ -1071,12 +1158,30 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
: SavingsEnumerations.depositAccountOnClosureType(onAccountClosureId);
|
||||
final LocalDate expectedFirstDepositOnDate = JdbcSupport.getLocalDate(rs, EXPECTED_FIRST_DEPOSIT_ON_DATE);
|
||||
|
||||
return RecurringDepositAccountData.instance(depositAccountData, preClosurePenalApplicable, preClosurePenalInterest,
|
||||
preClosurePenalInterestOnType, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
|
||||
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod,
|
||||
depositPeriodFrequencyType, mandatoryRecommendedDepositAmount, onAccountClosureType, expectedFirstDepositOnDate,
|
||||
totalOverdueAmount, noOfOverdueInstallments, isMandatoryDeposit, allowWithdrawal, adjustAdvanceTowardsFuturePayments,
|
||||
isCalendarInherited);
|
||||
final RecurringDepositAccountData result = RecurringDepositAccountData.instance(depositAccountData,
|
||||
preClosurePenalApplicable, preClosurePenalInterest, preClosurePenalInterestOnType, minDepositTerm, maxDepositTerm,
|
||||
minDepositTermType, maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount,
|
||||
maturityAmount, maturityDate, depositPeriod, depositPeriodFrequencyType, mandatoryRecommendedDepositAmount,
|
||||
onAccountClosureType, expectedFirstDepositOnDate, totalOverdueAmount, noOfOverdueInstallments, isMandatoryDeposit,
|
||||
allowWithdrawal, adjustAdvanceTowardsFuturePayments, isCalendarInherited);
|
||||
|
||||
result.setCbsProductFields(rs.getString("accountType"), rs.getString("customerSegment"), rs.getString("productCode"),
|
||||
JdbcSupport.getLocalDate(rs, "effectiveDate"), JdbcSupport.getLocalDate(rs, "effectiveTo"),
|
||||
JdbcSupport.getLocalDate(rs, "endDate"), rs.getBoolean("introducerRequired"), rs.getBoolean("shareLinkingEnabled"),
|
||||
rs.getBoolean("nominationFacility"), rs.getBoolean("dormancyAlert"), rs.getBoolean("isDormancyTrackingActive"),
|
||||
JdbcSupport.getInteger(rs, "daysToInactive"), JdbcSupport.getInteger(rs, "daysToDormancy"),
|
||||
JdbcSupport.getInteger(rs, "daysToEscheat"), JdbcSupport.getInteger(rs, "interestCalculateSelector"),
|
||||
rs.getString("interestCalculationTypeName"), rs.getString("averagePeriod"), rs.getBoolean("autoPost"),
|
||||
JdbcSupport.getInteger(rs, "frequencyFixDay"), JdbcSupport.getLocalDate(rs, "lastInterestDate"),
|
||||
rs.getBoolean("enableLockinPeriod"), rs.getString("balanceFrequency"),
|
||||
rs.getBoolean("accountClosedZeroBalanceInDayClosing"), rs.getBoolean("balanceSwapOption"), rs.getBoolean("msme"),
|
||||
rs.getBoolean("autoDebitFacility"), rs.getBoolean("loanFacility"), rs.getBoolean("prematureWithdrawalOption"),
|
||||
rs.getBoolean("tenureFlexibility"), rs.getBoolean("lienMarked"), rs.getBoolean("maturityInstructions"),
|
||||
rs.getBoolean("creditMaturityProceeds"), rs.getBoolean("penaltyGracePeriodMissedInstallments"),
|
||||
rs.getBoolean("panelRequestApplicable"), rs.getBoolean("noPenaltyNomineeHeirClosure"),
|
||||
rs.getBoolean("deceasedSettlement"), rs.getBoolean("allowDebitTxnAfterDueDate"));
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1423,6 +1528,31 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
sqlBuilder.append(", dptp.pre_closure_penal_applicable as preClosurePenalApplicable, ");
|
||||
sqlBuilder.append("dptp.pre_closure_penal_interest as preClosurePenalInterest, ");
|
||||
sqlBuilder.append("dptp.pre_closure_penal_interest_on_enum as preClosurePenalInterestOnId, ");
|
||||
sqlBuilder.append("sa.account_type as accountType, sa.customer_segment as customerSegment, sa.fd_type as fdType, ");
|
||||
sqlBuilder.append("sa.product_code as productCode, ");
|
||||
sqlBuilder.append("sa.effective_date as effectiveDate, sa.effective_to as effectiveTo, sa.end_date as endDate, ");
|
||||
sqlBuilder.append("sa.introducer_required as introducerRequired, sa.share_linking_enabled as shareLinkingEnabled, ");
|
||||
sqlBuilder.append("sa.nomination_facility as nominationFacility, sa.dormancy_alert as dormancyAlert, ");
|
||||
sqlBuilder.append("sa.is_dormancy_tracking_active as isDormancyTrackingActive, ");
|
||||
sqlBuilder.append("sa.days_to_inactive as daysToInactive, sa.days_to_dormancy as daysToDormancy, ");
|
||||
sqlBuilder.append("sa.days_to_escheat as daysToEscheat, ");
|
||||
sqlBuilder.append("sa.interest_calculate_selector as interestCalculateSelector, ");
|
||||
sqlBuilder.append("icv.code_value as interestCalculationTypeName, ");
|
||||
sqlBuilder.append("sa.average_period as averagePeriod, ");
|
||||
sqlBuilder.append("sa.auto_post as autoPost, sa.frequency_fix_day as frequencyFixDay, ");
|
||||
sqlBuilder.append("sa.last_interest_date as lastInterestDate, sa.enable_lockin_period as enableLockinPeriod, ");
|
||||
sqlBuilder.append("sa.balance_frequency as balanceFrequency, ");
|
||||
sqlBuilder.append("sa.account_closed_zero_balance_in_day_closing as accountClosedZeroBalanceInDayClosing, ");
|
||||
sqlBuilder.append("sa.balance_swap_option as balanceSwapOption, sa.msme as msme, ");
|
||||
sqlBuilder.append("sa.auto_debit_facility as autoDebitFacility, sa.loan_facility as loanFacility, ");
|
||||
sqlBuilder.append("sa.premature_withdrawal_option as prematureWithdrawalOption, sa.tenure_flexibility as tenureFlexibility, ");
|
||||
sqlBuilder.append("sa.lien_marked as lienMarked, sa.maturity_instructions as maturityInstructions, ");
|
||||
sqlBuilder.append("sa.credit_maturity_proceeds as creditMaturityProceeds, ");
|
||||
sqlBuilder.append("sa.penalty_grace_period_missed_installments as penaltyGracePeriodMissedInstallments, ");
|
||||
sqlBuilder.append("sa.panel_request_applicable as panelRequestApplicable, ");
|
||||
sqlBuilder.append("sa.no_penalty_nominee_heir_closure as noPenaltyNomineeHeirClosure, ");
|
||||
sqlBuilder.append("sa.deceased_settlement as deceasedSettlement, ");
|
||||
sqlBuilder.append("sa.allow_debit_txn_after_due_date as allowDebitTxnAfterDueDate, ");
|
||||
sqlBuilder.append("dptp.min_deposit_term as minDepositTerm, ");
|
||||
sqlBuilder.append("dptp.max_deposit_term as maxDepositTerm, ");
|
||||
sqlBuilder.append("dptp.min_deposit_term_type_enum as minDepositTermTypeId, ");
|
||||
@@ -1431,6 +1561,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
sqlBuilder.append("dptp.in_multiples_of_deposit_term_type_enum as inMultiplesOfDepositTermTypeId ");
|
||||
|
||||
sqlBuilder.append(super.selectTablesSql());
|
||||
sqlBuilder.append("left join m_code_value icv on icv.id = sa.interest_calculate_selector ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
@@ -1472,10 +1603,26 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
|
||||
final EnumOptionData onAccountClosureType = null;
|
||||
final Boolean transferInterestToSavings = false;
|
||||
|
||||
return FixedDepositAccountData.instance(depositAccountData, preClosurePenalApplicable, preClosurePenalInterest,
|
||||
preClosurePenalInterestOnType, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
|
||||
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod,
|
||||
depositPeriodFrequencyType, onAccountClosureType, transferInterestToSavings, null);
|
||||
final FixedDepositAccountData result = FixedDepositAccountData.instance(depositAccountData, preClosurePenalApplicable,
|
||||
preClosurePenalInterest, preClosurePenalInterestOnType, minDepositTerm, maxDepositTerm, minDepositTermType,
|
||||
maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount,
|
||||
maturityDate, depositPeriod, depositPeriodFrequencyType, onAccountClosureType, transferInterestToSavings, null);
|
||||
result.setCbsProductFields(rs.getString("accountType"), rs.getString("customerSegment"), rs.getString("fdType"), rs.getString("productCode"),
|
||||
JdbcSupport.getLocalDate(rs, "effectiveDate"), JdbcSupport.getLocalDate(rs, "effectiveTo"),
|
||||
JdbcSupport.getLocalDate(rs, "endDate"), rs.getBoolean("introducerRequired"), rs.getBoolean("shareLinkingEnabled"),
|
||||
rs.getBoolean("nominationFacility"), rs.getBoolean("dormancyAlert"), rs.getBoolean("isDormancyTrackingActive"),
|
||||
JdbcSupport.getLong(rs, "daysToInactive"), JdbcSupport.getLong(rs, "daysToDormancy"),
|
||||
JdbcSupport.getLong(rs, "daysToEscheat"), JdbcSupport.getInteger(rs, "interestCalculateSelector"),
|
||||
rs.getString("interestCalculationTypeName"), rs.getString("averagePeriod"), rs.getBoolean("autoPost"),
|
||||
JdbcSupport.getInteger(rs, "frequencyFixDay"), JdbcSupport.getLocalDate(rs, "lastInterestDate"),
|
||||
rs.getBoolean("enableLockinPeriod"), rs.getString("balanceFrequency"),
|
||||
rs.getBoolean("accountClosedZeroBalanceInDayClosing"), rs.getBoolean("balanceSwapOption"), rs.getBoolean("msme"),
|
||||
rs.getBoolean("autoDebitFacility"), rs.getBoolean("loanFacility"), rs.getBoolean("prematureWithdrawalOption"),
|
||||
rs.getBoolean("tenureFlexibility"), rs.getBoolean("lienMarked"), rs.getBoolean("maturityInstructions"),
|
||||
rs.getBoolean("creditMaturityProceeds"), rs.getBoolean("penaltyGracePeriodMissedInstallments"),
|
||||
rs.getBoolean("panelRequestApplicable"), rs.getBoolean("noPenaltyNomineeHeirClosure"),
|
||||
rs.getBoolean("deceasedSettlement"), rs.getBoolean("allowDebitTxnAfterDueDate"));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -172,6 +172,9 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
|
||||
account.updateMaturityDateAndAmountBeforeAccountActivation(mc, isPreMatureClosure, isSavingsInterestPostingAtCurrentPeriodEnd,
|
||||
financialYearBeginningMonth);
|
||||
|
||||
this.savingsAccountAssembler.applyCbsFields(command, command.parsedJson(), account);
|
||||
|
||||
this.fixedDepositAccountRepository.saveAndFlush(account);
|
||||
|
||||
if (account.isAccountNumberRequiresAutoGeneration()) {
|
||||
@@ -350,6 +353,7 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
DepositAccountType.FIXED_DEPOSIT);
|
||||
checkClientOrGroupActive(account);
|
||||
account.modifyApplication(command, changes);
|
||||
this.savingsAccountAssembler.applyCbsFields(command, command.parsedJson(), account);
|
||||
account.validateNewApplicationState(DepositAccountType.FIXED_DEPOSIT.resourceName());
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
@@ -440,6 +444,7 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
|
||||
DepositAccountType.RECURRING_DEPOSIT);
|
||||
checkClientOrGroupActive(account);
|
||||
account.modifyApplication(command, changes);
|
||||
this.savingsAccountAssembler.applyCbsFields(command, command.parsedJson(), account);
|
||||
account.validateNewApplicationState(DepositAccountType.RECURRING_DEPOSIT.resourceName());
|
||||
|
||||
if (!changes.isEmpty()) {
|
||||
|
||||
+76
-4
@@ -230,11 +230,37 @@ public class DepositProductReadPlatformServiceImpl implements DepositProductRead
|
||||
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.min_deposit_amount as minDepositAmount, dptp.deposit_amount as depositAmount, ");
|
||||
sqlBuilder.append("dptp.max_deposit_amount as maxDepositAmount ");
|
||||
sqlBuilder.append("dptp.max_deposit_amount as maxDepositAmount, ");
|
||||
sqlBuilder.append("sp.account_type as accountType, sp.fd_type as fdType, sp.product_code as productCode, ");
|
||||
sqlBuilder.append("sp.customer_segment as customerSegment, ");
|
||||
sqlBuilder.append("sp.gl_account_id as glAccountId, gla.name as glAccountName, ");
|
||||
sqlBuilder.append("sp.effective_date as effectiveDate, sp.effective_to as effectiveTo, sp.end_date as endDate, ");
|
||||
sqlBuilder.append("sp.introducer_required as introducerRequired, sp.share_linking_enabled as shareLinkingEnabled, ");
|
||||
sqlBuilder.append("sp.nomination_facility as nominationFacility, sp.dormancy_alert as dormancyAlert, ");
|
||||
sqlBuilder.append("sp.is_dormancy_tracking_active as isDormancyTrackingActive, ");
|
||||
sqlBuilder.append("sp.days_to_inactive as daysToInactive, sp.days_to_dormancy as daysToDormancy, ");
|
||||
sqlBuilder.append("sp.days_to_escheat as daysToEscheat, ");
|
||||
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("sp.last_interest_date as lastInterestDate, sp.enable_lockin_period as enableLockinPeriod, ");
|
||||
sqlBuilder.append("sp.balance_frequency as balanceFrequency, ");
|
||||
sqlBuilder.append("sp.account_closed_zero_balance_in_day_closing as accountClosedZeroBalanceInDayClosing, ");
|
||||
sqlBuilder.append("sp.auto_debit_facility as autoDebitFacility, sp.loan_facility as loanFacility, ");
|
||||
sqlBuilder.append("sp.premature_withdrawal_option as prematureWithdrawalOption, sp.tenure_flexibility as tenureFlexibility, ");
|
||||
sqlBuilder.append("sp.lien_marked as lienMarked, sp.maturity_instructions as maturityInstructions, ");
|
||||
sqlBuilder.append("sp.credit_maturity_proceeds as creditMaturityProceeds, ");
|
||||
sqlBuilder.append("sp.penalty_grace_period_missed_installments as penaltyGracePeriodMissedInstallments, ");
|
||||
sqlBuilder.append("sp.panel_request_applicable as panelRequestApplicable, ");
|
||||
sqlBuilder.append("sp.no_penalty_nominee_heir_closure as noPenaltyNomineeHeirClosure, ");
|
||||
sqlBuilder.append("sp.deceased_settlement as deceasedSettlement, ");
|
||||
sqlBuilder.append("sp.allow_debit_txn_after_due_date as allowDebitTxnAfterDueDate, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers ");
|
||||
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("join m_currency curr on curr.code = sp.currency_code ");
|
||||
sqlBuilder.append("left join m_tax_group tg on tg.id = sp.tax_group_id ");
|
||||
sqlBuilder.append("left join acc_gl_account gla on gla.id = sp.gl_account_id ");
|
||||
|
||||
this.schemaSql = sqlBuilder.toString();
|
||||
}
|
||||
@@ -271,9 +297,55 @@ public class DepositProductReadPlatformServiceImpl implements DepositProductRead
|
||||
final BigDecimal depositAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "depositAmount");
|
||||
final BigDecimal maxDepositAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "maxDepositAmount");
|
||||
|
||||
return FixedDepositProductData.instance(depositProductData, preClosurePenalApplicable, preClosurePenalInterest,
|
||||
preClosurePenalInterestOnType, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
|
||||
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, minDepositAmount, depositAmount, maxDepositAmount);
|
||||
final FixedDepositProductData result = FixedDepositProductData.instance(depositProductData, preClosurePenalApplicable,
|
||||
preClosurePenalInterest, preClosurePenalInterestOnType, minDepositTerm, maxDepositTerm, minDepositTermType,
|
||||
maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, minDepositAmount, depositAmount,
|
||||
maxDepositAmount);
|
||||
|
||||
// CBS Custom Fields
|
||||
result.setAccountType(rs.getString("accountType"));
|
||||
result.setFdType(rs.getString("fdType"));
|
||||
result.setProductCode(rs.getString("productCode"));
|
||||
result.setCustomerSegment(rs.getString("customerSegment"));
|
||||
result.setGlAccountId(JdbcSupport.getLong(rs, "glAccountId"));
|
||||
result.setGlAccountName(rs.getString("glAccountName"));
|
||||
final java.time.LocalDate effectiveDate = JdbcSupport.getLocalDate(rs, "effectiveDate");
|
||||
result.setEffectiveDate(effectiveDate != null ? effectiveDate.toString() : null);
|
||||
final java.time.LocalDate effectiveTo = JdbcSupport.getLocalDate(rs, "effectiveTo");
|
||||
result.setEffectiveTo(effectiveTo != null ? effectiveTo.toString() : null);
|
||||
final java.time.LocalDate endDate = JdbcSupport.getLocalDate(rs, "endDate");
|
||||
result.setEndDate(endDate != null ? endDate.toString() : null);
|
||||
result.setIntroducerRequired(rs.getBoolean("introducerRequired"));
|
||||
result.setShareLinkingEnabled(rs.getBoolean("shareLinkingEnabled"));
|
||||
result.setNominationFacility(rs.getBoolean("nominationFacility"));
|
||||
result.setDormancyAlert(rs.getBoolean("dormancyAlert"));
|
||||
result.setIsDormancyTrackingActive(rs.getBoolean("isDormancyTrackingActive"));
|
||||
result.setDaysToInactive(JdbcSupport.getLong(rs, "daysToInactive"));
|
||||
result.setDaysToDormancy(JdbcSupport.getLong(rs, "daysToDormancy"));
|
||||
result.setDaysToEscheat(JdbcSupport.getLong(rs, "daysToEscheat"));
|
||||
result.setInterestCalculateSelector(JdbcSupport.getInteger(rs, "interestCalculateSelector"));
|
||||
result.setAveragePeriod(rs.getString("averagePeriod"));
|
||||
result.setAutoPost(rs.getBoolean("autoPost"));
|
||||
result.setFrequencyFixDay(JdbcSupport.getInteger(rs, "frequencyFixDay"));
|
||||
final java.time.LocalDate lastInterestDate = JdbcSupport.getLocalDate(rs, "lastInterestDate");
|
||||
result.setLastInterestDate(lastInterestDate != null ? lastInterestDate.toString() : null);
|
||||
result.setEnableLockinPeriod(rs.getBoolean("enableLockinPeriod"));
|
||||
result.setBalanceFrequency(rs.getString("balanceFrequency"));
|
||||
result.setAccountClosedZeroBalanceInDayClosing(rs.getBoolean("accountClosedZeroBalanceInDayClosing"));
|
||||
result.setAutoDebitFacility(rs.getBoolean("autoDebitFacility"));
|
||||
result.setLoanFacility(rs.getBoolean("loanFacility"));
|
||||
result.setPrematureWithdrawalOption(rs.getBoolean("prematureWithdrawalOption"));
|
||||
result.setTenureFlexibility(rs.getBoolean("tenureFlexibility"));
|
||||
result.setLienMarked(rs.getBoolean("lienMarked"));
|
||||
result.setMaturityInstructions(rs.getBoolean("maturityInstructions"));
|
||||
result.setCreditMaturityProceeds(rs.getBoolean("creditMaturityProceeds"));
|
||||
result.setPenaltyGracePeriodMissedInstallments(rs.getBoolean("penaltyGracePeriodMissedInstallments"));
|
||||
result.setPanelRequestApplicable(rs.getBoolean("panelRequestApplicable"));
|
||||
result.setNoPenaltyNomineeHeirClosure(rs.getBoolean("noPenaltyNomineeHeirClosure"));
|
||||
result.setDeceasedSettlement(rs.getBoolean("deceasedSettlement"));
|
||||
result.setAllowDebitTxnAfterDueDate(rs.getBoolean("allowDebitTxnAfterDueDate"));
|
||||
result.setWithdrawalFeeForTransfers(rs.getBoolean("withdrawalFeeForTransfers"));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.service;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.portfolio.savings.api.FdInterestRateSaveRequest;
|
||||
import org.apache.fineract.portfolio.savings.data.FdInterestRateEffectiveData;
|
||||
|
||||
public interface FdBaseInterestRateReadPlatformService {
|
||||
|
||||
List<FdInterestRateEffectiveData> retrieveAllInterestRates();
|
||||
|
||||
List<FdInterestRateEffectiveData> retrieveAllActiveInterestRates();
|
||||
|
||||
List<FdInterestRateEffectiveData> retrieveActiveInterestRatesByType(String fdType);
|
||||
|
||||
FdInterestRateEffectiveData saveInterestRates(FdInterestRateSaveRequest request, Long createdById);
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
package org.apache.fineract.portfolio.savings.service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.portfolio.savings.api.FdInterestRateSaveRequest;
|
||||
import org.apache.fineract.portfolio.savings.data.FdInterestRateEffectiveData;
|
||||
import org.apache.fineract.portfolio.savings.data.FdInterestRateSlabData;
|
||||
import org.apache.fineract.portfolio.savings.domain.FdBaseInterestRateEffective;
|
||||
import org.apache.fineract.portfolio.savings.domain.FdBaseInterestRateEffectiveRepository;
|
||||
import org.apache.fineract.portfolio.savings.domain.FdBaseInterestRateSlabHistory;
|
||||
import org.apache.fineract.portfolio.savings.domain.FdBaseInterestRateSlabHistoryRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class FdBaseInterestRateReadPlatformServiceImpl implements FdBaseInterestRateReadPlatformService {
|
||||
|
||||
private final FdBaseInterestRateEffectiveRepository effectiveRepository;
|
||||
private final FdBaseInterestRateSlabHistoryRepository slabRepository;
|
||||
|
||||
@Override
|
||||
public List<FdInterestRateEffectiveData> retrieveAllInterestRates() {
|
||||
return effectiveRepository.findByOrderByEffectiveFromDateDesc().stream().map(this::toData).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FdInterestRateEffectiveData> retrieveAllActiveInterestRates() {
|
||||
return effectiveRepository.findByIsActiveTrueOrderByEffectiveFromDateDesc().stream().map(this::toData)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FdInterestRateEffectiveData> retrieveActiveInterestRatesByType(String fdType) {
|
||||
return effectiveRepository.findByFdTypeAndIsActiveTrueOrderByEffectiveFromDateDesc(fdType).stream().map(this::toData)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public FdInterestRateEffectiveData saveInterestRates(FdInterestRateSaveRequest request, Long createdById) {
|
||||
final String fdType = request.getFdType();
|
||||
final LocalDate today = LocalDate.now();
|
||||
|
||||
final List<FdBaseInterestRateEffective> activeVersions = effectiveRepository
|
||||
.findByFdTypeAndIsActiveTrueOrderByEffectiveFromDateDesc(fdType);
|
||||
for (FdBaseInterestRateEffective version : activeVersions) {
|
||||
version.deactivate(today);
|
||||
}
|
||||
if (!activeVersions.isEmpty()) {
|
||||
effectiveRepository.saveAll(activeVersions);
|
||||
}
|
||||
|
||||
final String label = request.getVersionLabel() != null && !request.getVersionLabel().isBlank()
|
||||
? request.getVersionLabel()
|
||||
: "FD " + fdType + " Rate Version " + LocalDate.now();
|
||||
|
||||
FdBaseInterestRateEffective newVersion = FdBaseInterestRateEffective.create(fdType, label, today, request.getRemarks(), createdById);
|
||||
newVersion = effectiveRepository.saveAndFlush(newVersion);
|
||||
|
||||
final Long versionId = newVersion.getId();
|
||||
int srCounter = 1;
|
||||
if (request.getSlabs() != null) {
|
||||
for (FdInterestRateSaveRequest.SlabRequest slabRequest : request.getSlabs()) {
|
||||
final int sr = slabRequest.getSrNo() != null ? slabRequest.getSrNo() : srCounter++;
|
||||
final FdBaseInterestRateSlabHistory slab = FdBaseInterestRateSlabHistory.create(versionId, sr,
|
||||
slabRequest.getDescription(), slabRequest.getPeriodTypeEnum(), slabRequest.getFromPeriod(),
|
||||
slabRequest.getToPeriod(), slabRequest.getAnnualInterestRate(), slabRequest.getSeniorCitizenRate());
|
||||
slabRepository.save(slab);
|
||||
}
|
||||
}
|
||||
|
||||
return toData(newVersion);
|
||||
}
|
||||
|
||||
private FdInterestRateEffectiveData toData(FdBaseInterestRateEffective e) {
|
||||
List<FdInterestRateSlabData> slabs = slabRepository.findByEffectiveIdOrderBySrNo(e.getId()).stream()
|
||||
.map(s -> FdInterestRateSlabData.builder()
|
||||
.id(s.getId())
|
||||
.srNo(s.getSrNo())
|
||||
.description(s.getDescription())
|
||||
.periodTypeEnum(s.getPeriodTypeEnum())
|
||||
.periodTypeLabel(periodLabel(s.getPeriodTypeEnum()))
|
||||
.fromPeriod(s.getFromPeriod())
|
||||
.toPeriod(s.getToPeriod())
|
||||
.annualInterestRate(s.getAnnualInterestRate())
|
||||
.seniorCitizenRate(s.getSeniorCitizenRate())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return FdInterestRateEffectiveData.builder()
|
||||
.id(e.getId())
|
||||
.fdType(e.getFdType())
|
||||
.versionLabel(e.getVersionLabel())
|
||||
.effectiveFromDate(e.getEffectiveFromDate())
|
||||
.effectiveToDate(e.getEffectiveToDate())
|
||||
.isActive(e.getIsActive())
|
||||
.remarks(e.getRemarks())
|
||||
.slabs(slabs)
|
||||
.build();
|
||||
}
|
||||
|
||||
private String periodLabel(Integer code) {
|
||||
if (code == null) {
|
||||
return "Days";
|
||||
}
|
||||
|
||||
return switch (code) {
|
||||
case 0 -> "Days";
|
||||
case 1 -> "Weeks";
|
||||
case 2 -> "Months";
|
||||
case 3 -> "Years";
|
||||
default -> "Days";
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.apache.fineract.portfolio.savings.service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonQuery;
|
||||
|
||||
public interface RecurringDepositAccountInterestCalculationService {
|
||||
|
||||
HashMap<String, Object> calculateInterest(JsonQuery query);
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* 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 static org.apache.fineract.portfolio.savings.DepositsApiConstants.annualInterestRateParamName;
|
||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.depositAmountParamName;
|
||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.interestCompoundingPeriodInMonthsParamName;
|
||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.tenureInMonthsParamName;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonQuery;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.organisation.monetary.domain.MoneyHelper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RecurringDepositAccountInterestCalculationServiceImpl implements RecurringDepositAccountInterestCalculationService {
|
||||
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Override
|
||||
public HashMap<String, Object> calculateInterest(JsonQuery query) {
|
||||
JsonElement element = query.parsedJson();
|
||||
BigDecimal depositAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(depositAmountParamName, element);
|
||||
BigDecimal annualInterestRate = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualInterestRateParamName, element);
|
||||
Long tenureInMonths = this.fromApiJsonHelper.extractLongNamed(tenureInMonthsParamName, element);
|
||||
Long interestCompoundingPeriodInMonths = this.fromApiJsonHelper.extractLongNamed(interestCompoundingPeriodInMonthsParamName,
|
||||
element);
|
||||
LocalDate submittedOnDate = this.fromApiJsonHelper.extractLocalDateNamed("submittedOnDate", element);
|
||||
if (submittedOnDate == null) {
|
||||
submittedOnDate = LocalDate.now();
|
||||
}
|
||||
|
||||
BigDecimal maturityAmount = this.calculateInterestInternal(depositAmount, annualInterestRate, tenureInMonths,
|
||||
interestCompoundingPeriodInMonths, submittedOnDate);
|
||||
|
||||
BigDecimal totalPrincipal = depositAmount.multiply(BigDecimal.valueOf(tenureInMonths));
|
||||
BigDecimal totalInterest = maturityAmount.subtract(totalPrincipal);
|
||||
|
||||
String warning = "This is an approximate calculated amount - it may vary slightly when the account is created";
|
||||
|
||||
HashMap<String, Object> result = new HashMap<>();
|
||||
result.put("maturityAmount", maturityAmount);
|
||||
result.put("totalPrincipal", totalPrincipal);
|
||||
result.put("totalInterest", totalInterest);
|
||||
result.put("daysInYear", 365); // Standard for this product as per image
|
||||
result.put("warning", warning);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public BigDecimal calculateInterestInternal(BigDecimal installmentAmount, BigDecimal annualInterestRate, Long tenureInMonths,
|
||||
Long interestCompoundingPeriodInMonths, LocalDate submittedOnDate) {
|
||||
MathContext mc = MoneyHelper.getMathContext();
|
||||
BigDecimal maturityAmount = BigDecimal.ZERO;
|
||||
int totalMonths = Math.toIntExact(tenureInMonths);
|
||||
|
||||
if (interestCompoundingPeriodInMonths == 0) {
|
||||
// Standard Banking Approach for Daily Compounding RD using Actual Calendar Days
|
||||
BigDecimal currentBalance = BigDecimal.ZERO;
|
||||
double dailyRate = annualInterestRate.doubleValue() / 36500.0;
|
||||
LocalDate date = submittedOnDate;
|
||||
|
||||
for (int m = 1; m <= totalMonths; m++) {
|
||||
// Add monthly installment at the start of the month
|
||||
currentBalance = currentBalance.add(installmentAmount);
|
||||
|
||||
// Get actual days in the current month
|
||||
int daysInMonth = date.lengthOfMonth();
|
||||
|
||||
// Calculate interest for the month using daily compounding
|
||||
double multiplier = Math.pow(1.0 + dailyRate, daysInMonth);
|
||||
currentBalance = currentBalance.multiply(BigDecimal.valueOf(multiplier), mc);
|
||||
|
||||
// Move to next month
|
||||
date = date.plusMonths(1);
|
||||
}
|
||||
maturityAmount = currentBalance;
|
||||
} else {
|
||||
// Periodic Compounding (Monthly, Quarterly, etc.)
|
||||
BigDecimal monthlyRate = annualInterestRate.divide(BigDecimal.valueOf(1200), mc);
|
||||
BigDecimal i = monthlyRate;
|
||||
int n = totalMonths;
|
||||
|
||||
// Standard RD formula for monthly compounding:
|
||||
// M = P * ((1+i)^n - 1) / i * (1+i)
|
||||
// For other periods, we can approximate or use a loop.
|
||||
// Using loop for consistency with various compounding periods.
|
||||
BigDecimal compoundingFrequencyMonths = BigDecimal.valueOf(interestCompoundingPeriodInMonths);
|
||||
BigDecimal ratePerCompounding = annualInterestRate.divide(BigDecimal.valueOf(100), mc)
|
||||
.multiply(compoundingFrequencyMonths).divide(BigDecimal.valueOf(12), mc);
|
||||
|
||||
for (int m = 1; m <= totalMonths; m++) {
|
||||
BigDecimal monthsRemaining = BigDecimal.valueOf(totalMonths - m + 1);
|
||||
BigDecimal numberOfCompoundings = monthsRemaining.divide(compoundingFrequencyMonths, mc);
|
||||
|
||||
BigDecimal installmentMaturity = installmentAmount.multiply(
|
||||
BigDecimal.ONE.add(ratePerCompounding).pow(numberOfCompoundings.intValue(), mc), mc);
|
||||
|
||||
// Add remaining partial compounding period interest (simple interest for the rest)
|
||||
BigDecimal remainingMonths = monthsRemaining.remainder(compoundingFrequencyMonths);
|
||||
if (remainingMonths.compareTo(BigDecimal.ZERO) > 0) {
|
||||
BigDecimal partialInterest = installmentMaturity.multiply(annualInterestRate).multiply(remainingMonths)
|
||||
.divide(BigDecimal.valueOf(1200), mc);
|
||||
installmentMaturity = installmentMaturity.add(partialInterest);
|
||||
}
|
||||
|
||||
maturityAmount = maturityAmount.add(installmentMaturity);
|
||||
}
|
||||
}
|
||||
|
||||
return maturityAmount.setScale(2, RoundingMode.HALF_UP);
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -800,7 +800,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sa.linked_account_no as linkedAccountNo, ");
|
||||
sqlBuilder.append("sp.balance_swap_option as balanceSwapOption, ");
|
||||
sqlBuilder.append("sp.msme as msme, ");
|
||||
sqlBuilder.append("sp.auto_debit_facility as autoDebitFacility, ");
|
||||
sqlBuilder.append("COALESCE(sa.nomination_facility, sp.nomination_facility) as nominationFacility, ");
|
||||
sqlBuilder.append("COALESCE(sa.auto_debit_facility, sp.auto_debit_facility) as autoDebitFacility, ");
|
||||
// Facility config fields
|
||||
sqlBuilder.append("safc.atm_facility as atmFacility, ");
|
||||
sqlBuilder.append("safc.atm_withdrawal_facility as atmWithdrawalFacility, ");
|
||||
@@ -1054,6 +1055,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
accountData.setLinkedAccountNo(rs.getString("linkedAccountNo"));
|
||||
accountData.setBalanceSwapOption(rs.getObject("balanceSwapOption") != null ? rs.getBoolean("balanceSwapOption") : null);
|
||||
accountData.setMsme(rs.getObject("msme") != null ? rs.getBoolean("msme") : null);
|
||||
accountData.setNominationFacility(rs.getObject("nominationFacility") != null ? rs.getBoolean("nominationFacility") : null);
|
||||
accountData.setAutoDebitFacility(rs.getObject("autoDebitFacility") != null ? rs.getBoolean("autoDebitFacility") : null);
|
||||
|
||||
// Nominee as parsed map
|
||||
|
||||
+1
-2
@@ -1391,8 +1391,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
public SavingsAccountData fallbackPostInterest(SavingsAccountData savingsAccountData, boolean postInterestAs, LocalDate transactionDate,
|
||||
boolean backdatedTxnsAllowedTill, Throwable t) {
|
||||
// NOTE: allow caller to catch the exceptions
|
||||
// NOTE: wrap throwable only if really necessary
|
||||
throw errorHandler.getMappable(t, null, null, "savings.postinterest");
|
||||
throw org.apache.fineract.infrastructure.core.exception.ErrorHandler.getMappable(t, null, null, "savings.postinterest");
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
+12
@@ -146,8 +146,12 @@ import org.apache.fineract.portfolio.savings.service.SavingsProductWritePlatform
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsProductWritePlatformServiceJpaRepositoryImpl;
|
||||
import org.apache.fineract.portfolio.savings.domain.RdBaseInterestRateEffectiveRepository;
|
||||
import org.apache.fineract.portfolio.savings.domain.RdBaseInterestRateSlabHistoryRepository;
|
||||
import org.apache.fineract.portfolio.savings.domain.FdBaseInterestRateEffectiveRepository;
|
||||
import org.apache.fineract.portfolio.savings.domain.FdBaseInterestRateSlabHistoryRepository;
|
||||
import org.apache.fineract.portfolio.savings.service.RdBaseInterestRateReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.RdBaseInterestRateReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.savings.service.FdBaseInterestRateReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.FdBaseInterestRateReadPlatformServiceImpl;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsSchedularInterestPoster;
|
||||
import org.apache.fineract.portfolio.savings.service.SavingsSchedularInterestPosterTask;
|
||||
import org.apache.fineract.portfolio.savings.service.search.SavingsAccountTransactionSearchService;
|
||||
@@ -171,6 +175,14 @@ public class SavingsConfiguration {
|
||||
return new RdBaseInterestRateReadPlatformServiceImpl(effectiveRepository, slabRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(FdBaseInterestRateReadPlatformService.class)
|
||||
public FdBaseInterestRateReadPlatformService fdBaseInterestRateReadPlatformService(
|
||||
FdBaseInterestRateEffectiveRepository effectiveRepository,
|
||||
FdBaseInterestRateSlabHistoryRepository slabRepository) {
|
||||
return new FdBaseInterestRateReadPlatformServiceImpl(effectiveRepository, slabRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(SavingsAccountTransactionSearchService.class)
|
||||
public SavingsAccountTransactionSearchService savingsAccountTransactionSearchService(PlatformSecurityContext context,
|
||||
|
||||
@@ -290,4 +290,8 @@
|
||||
<include file="parts/0276_create_current_account_tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0277_fix_current_account_audit_columns.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0278_add_is_mandatory_to_joint_holder.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0279_add_fd_type_and_base_interest_rate_tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0280_add_fixed_deposit_product_codes.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0284_remove_product_code_unique_constraints.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0281_update_fd_base_interest_rate_seed_data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+300
@@ -0,0 +1,300 @@
|
||||
<?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">
|
||||
|
||||
<!-- 1. Add fd_type column to m_savings_product -->
|
||||
<changeSet id="0279a_add_fd_type_to_savings_product" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><columnExists tableName="m_savings_product" columnName="fd_type"/></not>
|
||||
</preConditions>
|
||||
<addColumn tableName="m_savings_product">
|
||||
<column name="fd_type" type="VARCHAR(20)" defaultValue="SINGLE">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
<!-- 2. Create FD base interest rate effective (version) table -->
|
||||
<changeSet id="0279b_create_fd_base_interest_rate_effective" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><tableExists tableName="m_fd_base_interest_rate_effective"/></not>
|
||||
</preConditions>
|
||||
<createTable tableName="m_fd_base_interest_rate_effective">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="fd_type" type="VARCHAR(20)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="version_label" type="VARCHAR(100)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="effective_from_date" type="DATE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="effective_to_date" type="DATE"/>
|
||||
<column name="is_active" type="BOOLEAN" defaultValueBoolean="true">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="remarks" type="VARCHAR(500)"/>
|
||||
<column name="created_by_id" type="BIGINT"/>
|
||||
<column name="created_date" type="DATE"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
<!-- 3. Create FD base interest rate slab history table -->
|
||||
<changeSet id="0279c_create_fd_base_interest_rate_slab_history" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<not><tableExists tableName="m_fd_base_interest_rate_slab_history"/></not>
|
||||
</preConditions>
|
||||
<createTable tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="effective_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="sr_no" type="INT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(200)"/>
|
||||
<!-- period_type_enum: 0=DAYS, 1=WEEKS, 2=MONTHS, 3=YEARS -->
|
||||
<column name="period_type_enum" type="INT" defaultValueNumeric="0">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="from_period" type="INT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="to_period" type="INT"/>
|
||||
<column name="annual_interest_rate" type="DECIMAL(19,6)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<!-- senior_citizen_rate: additional rate for senior citizens -->
|
||||
<column name="senior_citizen_rate" type="DECIMAL(19,6)" defaultValueNumeric="0"/>
|
||||
<column name="created_date" type="DATE"/>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint
|
||||
baseTableName="m_fd_base_interest_rate_slab_history"
|
||||
baseColumnNames="effective_id"
|
||||
referencedTableName="m_fd_base_interest_rate_effective"
|
||||
referencedColumnNames="id"
|
||||
constraintName="fk_fd_base_rate_slab_effective"/>
|
||||
</changeSet>
|
||||
|
||||
<!-- 4. Seed initial FD base interest rate data -->
|
||||
<changeSet id="0279d_seed_fd_base_interest_rate_single" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_fd_base_interest_rate_effective WHERE fd_type = 'SINGLE'</sqlCheck>
|
||||
</preConditions>
|
||||
<!-- FD SINGLE: < 1 year, period in DAYS -->
|
||||
<insert tableName="m_fd_base_interest_rate_effective">
|
||||
<column name="fd_type" value="SINGLE"/>
|
||||
<column name="version_label" value="FD-SINGLE-V1"/>
|
||||
<column name="effective_from_date" value="2025-01-01"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="remarks" value="Initial FD Single (Short Term) rates"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0279e_seed_fd_single_slabs" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_fd_base_interest_rate_slab_history sh JOIN m_fd_base_interest_rate_effective e ON sh.effective_id = e.id WHERE e.fd_type = 'SINGLE'</sqlCheck>
|
||||
</preConditions>
|
||||
<!-- 1-29 days -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='SINGLE' AND version_label='FD-SINGLE-V1')"/>
|
||||
<column name="sr_no" valueNumeric="1"/>
|
||||
<column name="description" value="1 to 29 Days"/>
|
||||
<column name="period_type_enum" valueNumeric="0"/>
|
||||
<column name="from_period" valueNumeric="1"/>
|
||||
<column name="to_period" valueNumeric="29"/>
|
||||
<column name="annual_interest_rate" valueNumeric="4.50"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="5.00"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
<!-- 30-89 days -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='SINGLE' AND version_label='FD-SINGLE-V1')"/>
|
||||
<column name="sr_no" valueNumeric="2"/>
|
||||
<column name="description" value="30 to 89 Days"/>
|
||||
<column name="period_type_enum" valueNumeric="0"/>
|
||||
<column name="from_period" valueNumeric="30"/>
|
||||
<column name="to_period" valueNumeric="89"/>
|
||||
<column name="annual_interest_rate" valueNumeric="5.00"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="5.50"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
<!-- 90-179 days -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='SINGLE' AND version_label='FD-SINGLE-V1')"/>
|
||||
<column name="sr_no" valueNumeric="3"/>
|
||||
<column name="description" value="90 to 179 Days"/>
|
||||
<column name="period_type_enum" valueNumeric="0"/>
|
||||
<column name="from_period" valueNumeric="90"/>
|
||||
<column name="to_period" valueNumeric="179"/>
|
||||
<column name="annual_interest_rate" valueNumeric="5.50"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="6.00"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
<!-- 180+ days -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='SINGLE' AND version_label='FD-SINGLE-V1')"/>
|
||||
<column name="sr_no" valueNumeric="4"/>
|
||||
<column name="description" value="180+ Days"/>
|
||||
<column name="period_type_enum" valueNumeric="0"/>
|
||||
<column name="from_period" valueNumeric="180"/>
|
||||
<column name="annual_interest_rate" valueNumeric="6.00"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="6.50"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0279f_seed_fd_base_interest_rate_double" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_fd_base_interest_rate_effective WHERE fd_type = 'DOUBLE'</sqlCheck>
|
||||
</preConditions>
|
||||
<!-- FD DOUBLE: >= 1 year, period in YEARS -->
|
||||
<insert tableName="m_fd_base_interest_rate_effective">
|
||||
<column name="fd_type" value="DOUBLE"/>
|
||||
<column name="version_label" value="FD-DOUBLE-V1"/>
|
||||
<column name="effective_from_date" value="2025-01-01"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="remarks" value="Initial FD Double (Long Term) rates"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0279g_seed_fd_double_slabs" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_fd_base_interest_rate_slab_history sh JOIN m_fd_base_interest_rate_effective e ON sh.effective_id = e.id WHERE e.fd_type = 'DOUBLE'</sqlCheck>
|
||||
</preConditions>
|
||||
<!-- 1-2 years -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='DOUBLE' AND version_label='FD-DOUBLE-V1')"/>
|
||||
<column name="sr_no" valueNumeric="1"/>
|
||||
<column name="description" value="1 to 2 Years"/>
|
||||
<column name="period_type_enum" valueNumeric="3"/>
|
||||
<column name="from_period" valueNumeric="1"/>
|
||||
<column name="to_period" valueNumeric="2"/>
|
||||
<column name="annual_interest_rate" valueNumeric="6.50"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="7.00"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
<!-- 3-5 years -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='DOUBLE' AND version_label='FD-DOUBLE-V1')"/>
|
||||
<column name="sr_no" valueNumeric="2"/>
|
||||
<column name="description" value="3 to 5 Years"/>
|
||||
<column name="period_type_enum" valueNumeric="3"/>
|
||||
<column name="from_period" valueNumeric="3"/>
|
||||
<column name="to_period" valueNumeric="5"/>
|
||||
<column name="annual_interest_rate" valueNumeric="6.75"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="7.25"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
<!-- 6-10 years -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='DOUBLE' AND version_label='FD-DOUBLE-V1')"/>
|
||||
<column name="sr_no" valueNumeric="3"/>
|
||||
<column name="description" value="6 to 10 Years"/>
|
||||
<column name="period_type_enum" valueNumeric="3"/>
|
||||
<column name="from_period" valueNumeric="6"/>
|
||||
<column name="to_period" valueNumeric="10"/>
|
||||
<column name="annual_interest_rate" valueNumeric="7.00"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="7.50"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
<!-- 11+ years -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='DOUBLE' AND version_label='FD-DOUBLE-V1')"/>
|
||||
<column name="sr_no" valueNumeric="4"/>
|
||||
<column name="description" value="11+ Years"/>
|
||||
<column name="period_type_enum" valueNumeric="3"/>
|
||||
<column name="from_period" valueNumeric="11"/>
|
||||
<column name="annual_interest_rate" valueNumeric="7.25"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="7.75"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0279h_seed_fd_base_interest_rate_special" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_fd_base_interest_rate_effective WHERE fd_type = 'SPECIAL'</sqlCheck>
|
||||
</preConditions>
|
||||
<!-- FD SPECIAL: monthly interest payout, period in MONTHS -->
|
||||
<insert tableName="m_fd_base_interest_rate_effective">
|
||||
<column name="fd_type" value="SPECIAL"/>
|
||||
<column name="version_label" value="FD-SPECIAL-V1"/>
|
||||
<column name="effective_from_date" value="2025-01-01"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="remarks" value="Initial FD Special (Monthly Payout) rates"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="0279i_seed_fd_special_slabs" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<sqlCheck expectedResult="0">SELECT COUNT(*) FROM m_fd_base_interest_rate_slab_history sh JOIN m_fd_base_interest_rate_effective e ON sh.effective_id = e.id WHERE e.fd_type = 'SPECIAL'</sqlCheck>
|
||||
</preConditions>
|
||||
<!-- 1-12 months -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='SPECIAL' AND version_label='FD-SPECIAL-V1')"/>
|
||||
<column name="sr_no" valueNumeric="1"/>
|
||||
<column name="description" value="1 to 12 Months"/>
|
||||
<column name="period_type_enum" valueNumeric="2"/>
|
||||
<column name="from_period" valueNumeric="1"/>
|
||||
<column name="to_period" valueNumeric="12"/>
|
||||
<column name="annual_interest_rate" valueNumeric="6.00"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="6.50"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
<!-- 13-24 months -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='SPECIAL' AND version_label='FD-SPECIAL-V1')"/>
|
||||
<column name="sr_no" valueNumeric="2"/>
|
||||
<column name="description" value="13 to 24 Months"/>
|
||||
<column name="period_type_enum" valueNumeric="2"/>
|
||||
<column name="from_period" valueNumeric="13"/>
|
||||
<column name="to_period" valueNumeric="24"/>
|
||||
<column name="annual_interest_rate" valueNumeric="6.50"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="7.00"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
<!-- 25-60 months -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='SPECIAL' AND version_label='FD-SPECIAL-V1')"/>
|
||||
<column name="sr_no" valueNumeric="3"/>
|
||||
<column name="description" value="25 to 60 Months"/>
|
||||
<column name="period_type_enum" valueNumeric="2"/>
|
||||
<column name="from_period" valueNumeric="25"/>
|
||||
<column name="to_period" valueNumeric="60"/>
|
||||
<column name="annual_interest_rate" valueNumeric="7.00"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="7.50"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
<!-- 61+ months -->
|
||||
<insert tableName="m_fd_base_interest_rate_slab_history">
|
||||
<column name="effective_id" valueComputed="(SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type='SPECIAL' AND version_label='FD-SPECIAL-V1')"/>
|
||||
<column name="sr_no" valueNumeric="4"/>
|
||||
<column name="description" value="61+ Months"/>
|
||||
<column name="period_type_enum" valueNumeric="2"/>
|
||||
<column name="from_period" valueNumeric="61"/>
|
||||
<column name="annual_interest_rate" valueNumeric="7.25"/>
|
||||
<column name="senior_citizen_rate" valueNumeric="7.75"/>
|
||||
<column name="created_date" valueDate="2025-01-01"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
<?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">
|
||||
|
||||
<!-- FixedDepositProductAccountType code and values -->
|
||||
<changeSet id="0280a_add_fd_product_account_type_code" author="system">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_code (code_name, is_system_defined)
|
||||
SELECT 'FixedDepositProductAccountType', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'FixedDepositProductAccountType');
|
||||
</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
|
||||
('Fd Account', 1)
|
||||
) AS v(code_value, order_position)
|
||||
WHERE c.code_name = 'FixedDepositProductAccountType'
|
||||
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>
|
||||
|
||||
<!-- FixedDepositProductCustomerSegment code and values -->
|
||||
<changeSet id="0280b_add_fd_product_customer_segment_code" author="system">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<sql>
|
||||
INSERT INTO m_code (code_name, is_system_defined)
|
||||
SELECT 'FixedDepositProductCustomerSegment', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'FixedDepositProductCustomerSegment');
|
||||
</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 = 'FixedDepositProductCustomerSegment'
|
||||
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>
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
<?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">
|
||||
|
||||
<changeSet id="0281_update_fd_base_interest_rate_seed_data" author="fineract">
|
||||
<validCheckSum>ANY</validCheckSum>
|
||||
<preConditions onFail="MARK_RAN">
|
||||
<tableExists tableName="m_fd_base_interest_rate_effective"/>
|
||||
</preConditions>
|
||||
|
||||
<sql>
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '1 to 29 Days',
|
||||
from_period = 1,
|
||||
to_period = 29
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'SINGLE' AND version_label = 'FD-SINGLE-V1')
|
||||
AND sr_no = 1;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '30 to 89 Days',
|
||||
from_period = 30,
|
||||
to_period = 89
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'SINGLE' AND version_label = 'FD-SINGLE-V1')
|
||||
AND sr_no = 2;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '90 to 179 Days',
|
||||
from_period = 90,
|
||||
to_period = 179
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'SINGLE' AND version_label = 'FD-SINGLE-V1')
|
||||
AND sr_no = 3;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '180+ Days',
|
||||
from_period = 180,
|
||||
to_period = NULL
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'SINGLE' AND version_label = 'FD-SINGLE-V1')
|
||||
AND sr_no = 4;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '1 to 2 Years',
|
||||
from_period = 1,
|
||||
to_period = 2
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'DOUBLE' AND version_label = 'FD-DOUBLE-V1')
|
||||
AND sr_no = 1;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '3 to 5 Years',
|
||||
from_period = 3,
|
||||
to_period = 5
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'DOUBLE' AND version_label = 'FD-DOUBLE-V1')
|
||||
AND sr_no = 2;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '6 to 10 Years',
|
||||
from_period = 6,
|
||||
to_period = 10
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'DOUBLE' AND version_label = 'FD-DOUBLE-V1')
|
||||
AND sr_no = 3;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '11+ Years',
|
||||
from_period = 11,
|
||||
to_period = NULL
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'DOUBLE' AND version_label = 'FD-DOUBLE-V1')
|
||||
AND sr_no = 4;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '1 to 12 Months',
|
||||
from_period = 1,
|
||||
to_period = 12
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'SPECIAL' AND version_label = 'FD-SPECIAL-V1')
|
||||
AND sr_no = 1;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '13 to 24 Months',
|
||||
from_period = 13,
|
||||
to_period = 24
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'SPECIAL' AND version_label = 'FD-SPECIAL-V1')
|
||||
AND sr_no = 2;
|
||||
|
||||
UPDATE m_fd_base_interest_rate_slab_history
|
||||
SET description = '25 to 60 Months',
|
||||
from_period = 25,
|
||||
to_period = 60
|
||||
WHERE effective_id = (SELECT id FROM m_fd_base_interest_rate_effective WHERE fd_type = 'SPECIAL' AND version_label = 'FD-SPECIAL-V1')
|
||||
AND sr_no = 3;
|
||||
|
||||
INSERT INTO m_fd_base_interest_rate_slab_history
|
||||
(effective_id, sr_no, description, period_type_enum, from_period, to_period, annual_interest_rate, senior_citizen_rate, created_date)
|
||||
SELECT e.id, 4, '61+ Months', 2, 61, NULL, 7.250000, 7.750000, CURRENT_DATE
|
||||
FROM m_fd_base_interest_rate_effective e
|
||||
WHERE e.fd_type = 'SPECIAL' AND e.version_label = 'FD-SPECIAL-V1'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM m_fd_base_interest_rate_slab_history sh
|
||||
WHERE sh.effective_id = e.id
|
||||
AND sh.sr_no = 4
|
||||
);
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<?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">
|
||||
|
||||
<changeSet id="0284_remove_product_code_unique_constraints" author="system">
|
||||
<!-- For Savings/RD/FD products -->
|
||||
<dropUniqueConstraint tableName="m_savings_product" constraintName="m_savings_product_product_code_key"/>
|
||||
|
||||
<!-- For Current products -->
|
||||
<dropUniqueConstraint tableName="m_current_product" constraintName="cp_unq_product_code"/>
|
||||
|
||||
<!-- Set existing empty or blank product_codes to NULL to avoid future issues -->
|
||||
<update tableName="m_savings_product">
|
||||
<column name="product_code" valueComputed="NULL"/>
|
||||
<where>product_code = '' OR product_code IS NULL</where>
|
||||
</update>
|
||||
|
||||
<update tableName="m_current_product">
|
||||
<column name="product_code" valueComputed="NULL"/>
|
||||
<where>product_code = '' OR product_code IS NULL</where>
|
||||
</update>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+4
-1
@@ -45,6 +45,7 @@ import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccount;
|
||||
import org.apache.fineract.portfolio.shareproducts.domain.ShareProduct;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
public class AccountNumberGeneratorTest {
|
||||
|
||||
@@ -54,6 +55,7 @@ public class AccountNumberGeneratorTest {
|
||||
private SavingsAccountRepository savingsRepo;
|
||||
private GLAccountRepository glAccountRepo;
|
||||
private SavingsProductRepository savingsProductRepo;
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
private AccountNumberGenerator generator;
|
||||
|
||||
@@ -65,8 +67,9 @@ public class AccountNumberGeneratorTest {
|
||||
savingsRepo = mock(SavingsAccountRepository.class);
|
||||
glAccountRepo = mock(GLAccountRepository.class);
|
||||
savingsProductRepo = mock(SavingsProductRepository.class);
|
||||
jdbcTemplate = mock(JdbcTemplate.class);
|
||||
|
||||
generator = new AccountNumberGenerator(configService, clientRepo, loanRepo, savingsRepo, glAccountRepo, savingsProductRepo);
|
||||
generator = new AccountNumberGenerator(configService, clientRepo, loanRepo, savingsRepo, glAccountRepo, savingsProductRepo, jdbcTemplate);
|
||||
|
||||
GlobalConfigurationPropertyData accountLengthConfig = mock(GlobalConfigurationPropertyData.class);
|
||||
when(accountLengthConfig.getValue()).thenReturn(Long.valueOf("9"));
|
||||
|
||||
+177
-6
@@ -24,6 +24,7 @@ import java.util.Collection;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.organisation.staff.data.StaffData;
|
||||
@@ -73,6 +74,48 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
private Collection<PaymentTypeData> paymentTypeOptions;
|
||||
private final Collection<EnumOptionData> maturityInstructionOptions;
|
||||
|
||||
// CBS product/account fields used by the FD UI
|
||||
private String accountType;
|
||||
private String customerSegment;
|
||||
private String fdType;
|
||||
private Collection<CodeValueData> accountTypeOptions;
|
||||
private Collection<CodeValueData> customerSegmentOptions;
|
||||
private String productCode;
|
||||
private LocalDate effectiveDate;
|
||||
private LocalDate effectiveTo;
|
||||
private LocalDate endDate;
|
||||
private Boolean introducerRequired;
|
||||
private Boolean shareLinkingEnabled;
|
||||
private Boolean nominationFacility;
|
||||
private Boolean dormancyAlert;
|
||||
private Boolean isDormancyTrackingActive;
|
||||
private Long daysToInactive;
|
||||
private Long daysToDormancy;
|
||||
private Long daysToEscheat;
|
||||
private Integer interestCalculateSelector;
|
||||
private String interestCalculationTypeName;
|
||||
private String averagePeriod;
|
||||
private Boolean autoPost;
|
||||
private Integer frequencyFixDay;
|
||||
private LocalDate lastInterestDate;
|
||||
private Boolean enableLockinPeriod;
|
||||
private String balanceFrequency;
|
||||
private Boolean accountClosedZeroBalanceInDayClosing;
|
||||
private Boolean balanceSwapOption;
|
||||
private Boolean msme;
|
||||
private Boolean autoDebitFacility;
|
||||
private Boolean loanFacility;
|
||||
private Boolean prematureWithdrawalOption;
|
||||
private Boolean tenureFlexibility;
|
||||
private Boolean lienMarked;
|
||||
private Boolean maturityInstructions;
|
||||
private Boolean creditMaturityProceeds;
|
||||
private Boolean penaltyGracePeriodMissedInstallments;
|
||||
private Boolean panelRequestApplicable;
|
||||
private Boolean noPenaltyNomineeHeirClosure;
|
||||
private Boolean deceasedSettlement;
|
||||
private Boolean allowDebitTxnAfterDueDate;
|
||||
|
||||
// import fields
|
||||
private transient Integer rowIndex;
|
||||
private String dateFormat;
|
||||
@@ -92,6 +135,123 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
locale, dateFormat);
|
||||
}
|
||||
|
||||
public void setAccountType(String accountType) {
|
||||
this.accountType = accountType;
|
||||
}
|
||||
|
||||
public void setCustomerSegment(String customerSegment) {
|
||||
this.customerSegment = customerSegment;
|
||||
}
|
||||
|
||||
public void setAccountTypeOptions(Collection<CodeValueData> accountTypeOptions) {
|
||||
this.accountTypeOptions = accountTypeOptions;
|
||||
}
|
||||
|
||||
public void setCustomerSegmentOptions(Collection<CodeValueData> customerSegmentOptions) {
|
||||
this.customerSegmentOptions = customerSegmentOptions;
|
||||
}
|
||||
|
||||
public void setFdType(String fdType) { this.fdType = fdType; }
|
||||
public String getFdType() { return fdType; }
|
||||
|
||||
public void setCbsProductFields(final String accountType, final String customerSegment, final String fdType, final String productCode,
|
||||
final LocalDate effectiveDate, final LocalDate effectiveTo, final LocalDate endDate, final Boolean introducerRequired,
|
||||
final Boolean shareLinkingEnabled, final Boolean nominationFacility, final Boolean dormancyAlert,
|
||||
final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy, final Long daysToEscheat,
|
||||
final Integer interestCalculateSelector, final String interestCalculationTypeName, final String averagePeriod,
|
||||
final Boolean autoPost, final Integer frequencyFixDay, final LocalDate lastInterestDate, final Boolean enableLockinPeriod,
|
||||
final String balanceFrequency, final Boolean accountClosedZeroBalanceInDayClosing, final Boolean balanceSwapOption,
|
||||
final Boolean msme, final Boolean autoDebitFacility, final Boolean loanFacility, final Boolean prematureWithdrawalOption,
|
||||
final Boolean tenureFlexibility, final Boolean lienMarked, final Boolean maturityInstructions,
|
||||
final Boolean creditMaturityProceeds, final Boolean penaltyGracePeriodMissedInstallments,
|
||||
final Boolean panelRequestApplicable, final Boolean noPenaltyNomineeHeirClosure, final Boolean deceasedSettlement,
|
||||
final Boolean allowDebitTxnAfterDueDate) {
|
||||
this.accountType = accountType;
|
||||
this.customerSegment = customerSegment;
|
||||
this.fdType = fdType;
|
||||
this.productCode = productCode;
|
||||
this.effectiveDate = effectiveDate;
|
||||
this.effectiveTo = effectiveTo;
|
||||
this.endDate = endDate;
|
||||
this.introducerRequired = introducerRequired;
|
||||
this.shareLinkingEnabled = shareLinkingEnabled;
|
||||
this.nominationFacility = nominationFacility;
|
||||
this.dormancyAlert = dormancyAlert;
|
||||
this.isDormancyTrackingActive = isDormancyTrackingActive;
|
||||
this.daysToInactive = daysToInactive;
|
||||
this.daysToDormancy = daysToDormancy;
|
||||
this.daysToEscheat = daysToEscheat;
|
||||
this.interestCalculateSelector = interestCalculateSelector;
|
||||
this.interestCalculationTypeName = interestCalculationTypeName;
|
||||
this.averagePeriod = averagePeriod;
|
||||
this.autoPost = autoPost;
|
||||
this.frequencyFixDay = frequencyFixDay;
|
||||
this.lastInterestDate = lastInterestDate;
|
||||
this.enableLockinPeriod = enableLockinPeriod;
|
||||
this.balanceFrequency = balanceFrequency;
|
||||
this.accountClosedZeroBalanceInDayClosing = accountClosedZeroBalanceInDayClosing;
|
||||
this.balanceSwapOption = balanceSwapOption;
|
||||
this.msme = msme;
|
||||
this.autoDebitFacility = autoDebitFacility;
|
||||
this.loanFacility = loanFacility;
|
||||
this.prematureWithdrawalOption = prematureWithdrawalOption;
|
||||
this.tenureFlexibility = tenureFlexibility;
|
||||
this.lienMarked = lienMarked;
|
||||
this.maturityInstructions = maturityInstructions;
|
||||
this.creditMaturityProceeds = creditMaturityProceeds;
|
||||
this.penaltyGracePeriodMissedInstallments = penaltyGracePeriodMissedInstallments;
|
||||
this.panelRequestApplicable = panelRequestApplicable;
|
||||
this.noPenaltyNomineeHeirClosure = noPenaltyNomineeHeirClosure;
|
||||
this.deceasedSettlement = deceasedSettlement;
|
||||
this.allowDebitTxnAfterDueDate = allowDebitTxnAfterDueDate;
|
||||
}
|
||||
|
||||
public void copyCbsFieldsFrom(final FixedDepositAccountData src) {
|
||||
if (src == null) {
|
||||
return;
|
||||
}
|
||||
this.accountType = src.accountType;
|
||||
this.customerSegment = src.customerSegment;
|
||||
this.fdType = src.fdType;
|
||||
this.accountTypeOptions = src.accountTypeOptions;
|
||||
this.customerSegmentOptions = src.customerSegmentOptions;
|
||||
this.productCode = src.productCode;
|
||||
this.effectiveDate = src.effectiveDate;
|
||||
this.effectiveTo = src.effectiveTo;
|
||||
this.endDate = src.endDate;
|
||||
this.introducerRequired = src.introducerRequired;
|
||||
this.shareLinkingEnabled = src.shareLinkingEnabled;
|
||||
this.nominationFacility = src.nominationFacility;
|
||||
this.dormancyAlert = src.dormancyAlert;
|
||||
this.isDormancyTrackingActive = src.isDormancyTrackingActive;
|
||||
this.daysToInactive = src.daysToInactive;
|
||||
this.daysToDormancy = src.daysToDormancy;
|
||||
this.daysToEscheat = src.daysToEscheat;
|
||||
this.interestCalculateSelector = src.interestCalculateSelector;
|
||||
this.interestCalculationTypeName = src.interestCalculationTypeName;
|
||||
this.averagePeriod = src.averagePeriod;
|
||||
this.autoPost = src.autoPost;
|
||||
this.frequencyFixDay = src.frequencyFixDay;
|
||||
this.lastInterestDate = src.lastInterestDate;
|
||||
this.enableLockinPeriod = src.enableLockinPeriod;
|
||||
this.balanceFrequency = src.balanceFrequency;
|
||||
this.accountClosedZeroBalanceInDayClosing = src.accountClosedZeroBalanceInDayClosing;
|
||||
this.balanceSwapOption = src.balanceSwapOption;
|
||||
this.msme = src.msme;
|
||||
this.autoDebitFacility = src.autoDebitFacility;
|
||||
this.loanFacility = src.loanFacility;
|
||||
this.prematureWithdrawalOption = src.prematureWithdrawalOption;
|
||||
this.tenureFlexibility = src.tenureFlexibility;
|
||||
this.lienMarked = src.lienMarked;
|
||||
this.maturityInstructions = src.maturityInstructions;
|
||||
this.creditMaturityProceeds = src.creditMaturityProceeds;
|
||||
this.penaltyGracePeriodMissedInstallments = src.penaltyGracePeriodMissedInstallments;
|
||||
this.panelRequestApplicable = src.panelRequestApplicable;
|
||||
this.noPenaltyNomineeHeirClosure = src.noPenaltyNomineeHeirClosure;
|
||||
this.deceasedSettlement = src.deceasedSettlement;
|
||||
this.allowDebitTxnAfterDueDate = src.allowDebitTxnAfterDueDate;
|
||||
}
|
||||
|
||||
private FixedDepositAccountData(Long clientId, Long productId, Long fieldofficerId, LocalDate submittedOnDate,
|
||||
EnumOptionData interestCompoundingPeriodType, EnumOptionData interestPostingPeriodType, EnumOptionData interestCalculationType,
|
||||
EnumOptionData interestCalculationDaysInYearType, Integer lockinPeriodFrequency, EnumOptionData lockinPeriodFrequencyType,
|
||||
@@ -150,7 +310,7 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
final Collection<PaymentTypeData> paymentTypeOptions = null;
|
||||
final Collection<SavingsAccountData> savingsAccountDatas = null;
|
||||
|
||||
return new FixedDepositAccountData(depositAccountData.id, depositAccountData.accountNo, depositAccountData.externalId,
|
||||
final FixedDepositAccountData result = new FixedDepositAccountData(depositAccountData.id, depositAccountData.accountNo, depositAccountData.externalId,
|
||||
depositAccountData.groupId, depositAccountData.groupName, depositAccountData.clientId, depositAccountData.clientName,
|
||||
depositAccountData.depositProductId, depositAccountData.depositProductName, depositAccountData.fieldOfficerId,
|
||||
depositAccountData.fieldOfficerName, depositAccountData.status, depositAccountData.timeline, depositAccountData.currency,
|
||||
@@ -170,11 +330,15 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
depositPeriod, depositPeriodFrequency, periodFrequencyTypeOptions, depositType, onAccountClosure, onAccountClosureOptions,
|
||||
paymentTypeOptions, savingsAccountDatas, linkedAccount, transferInterestToSavings, depositAccountData.withHoldTax,
|
||||
depositAccountData.taxGroup, maturityInstructionOptions, transferToSavingsId, transferToSavingsAccount);
|
||||
if (depositAccountData instanceof FixedDepositAccountData) {
|
||||
result.copyCbsFieldsFrom((FixedDepositAccountData) depositAccountData);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FixedDepositAccountData withInterestChart(final FixedDepositAccountData account,
|
||||
final DepositAccountInterestRateChartData accountChart) {
|
||||
return new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
|
||||
final FixedDepositAccountData result = new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
|
||||
account.clientId, account.clientName, account.depositProductId, account.depositProductName, account.fieldOfficerId,
|
||||
account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate,
|
||||
account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType,
|
||||
@@ -192,6 +356,8 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions, account.savingsAccounts,
|
||||
account.linkedAccount, account.transferInterestToSavings, account.withHoldTax, account.taxGroup,
|
||||
account.maturityInstructionOptions, account.transferToSavingsId, account.transferToSavingsAccount);
|
||||
result.copyCbsFieldsFrom(account);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FixedDepositAccountData associationsAndTemplate(final FixedDepositAccountData account, FixedDepositAccountData template,
|
||||
@@ -202,7 +368,7 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
template = account;
|
||||
}
|
||||
|
||||
return new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
|
||||
final FixedDepositAccountData result = new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
|
||||
account.clientId, account.clientName, account.depositProductId, account.depositProductName, account.fieldOfficerId,
|
||||
account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate,
|
||||
account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType,
|
||||
@@ -220,6 +386,8 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions, template.savingsAccounts,
|
||||
linkedAccount, account.transferInterestToSavings, account.withHoldTax, account.taxGroup, account.maturityInstructionOptions,
|
||||
account.transferToSavingsId, transferToSavingsAccount);
|
||||
result.copyCbsFieldsFrom(account);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FixedDepositAccountData withTemplateOptions(final FixedDepositAccountData account,
|
||||
@@ -234,7 +402,7 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
final Collection<EnumOptionData> periodFrequencyTypeOptions, final Collection<SavingsAccountData> savingsAccounts,
|
||||
final Collection<EnumOptionData> maturityInstructionOptions) {
|
||||
|
||||
return new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
|
||||
final FixedDepositAccountData result = new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
|
||||
account.clientId, account.clientName, account.depositProductId, account.depositProductName, account.fieldOfficerId,
|
||||
account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate,
|
||||
account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType,
|
||||
@@ -251,6 +419,8 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions, savingsAccounts,
|
||||
account.linkedAccount, account.transferInterestToSavings, account.withHoldTax, account.taxGroup, maturityInstructionOptions,
|
||||
account.transferToSavingsId, account.transferToSavingsAccount);
|
||||
result.copyCbsFieldsFrom(account);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FixedDepositAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||
@@ -427,7 +597,7 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
final Collection<EnumOptionData> onAccountClosureOptions, final Collection<PaymentTypeData> paymentTypeOptions,
|
||||
final Collection<SavingsAccountData> savingsAccountDatas) {
|
||||
|
||||
return new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
|
||||
final FixedDepositAccountData result = new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
|
||||
account.clientId, account.clientName, account.depositProductId, account.depositProductName, account.fieldOfficerId,
|
||||
account.fieldOfficerName, account.status, account.timeline, account.currency, account.nominalAnnualInterestRate,
|
||||
account.interestCompoundingPeriodType, account.interestPostingPeriodType, account.interestCalculationType,
|
||||
@@ -445,7 +615,8 @@ public final class FixedDepositAccountData extends DepositAccountData {
|
||||
account.onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, account.linkedAccount,
|
||||
account.transferInterestToSavings, account.withHoldTax, account.taxGroup, account.maturityInstructionOptions,
|
||||
account.transferToSavingsId, account.transferToSavingsAccount);
|
||||
|
||||
result.copyCbsFieldsFrom(account);
|
||||
return result;
|
||||
}
|
||||
|
||||
private FixedDepositAccountData(final Long id, final String accountNo, final String externalId, final Long groupId,
|
||||
|
||||
+177
-14
@@ -112,9 +112,9 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
}
|
||||
|
||||
public static FixedDepositProductData withCharges(final FixedDepositProductData existingProduct, final Collection<ChargeData> charges) {
|
||||
return new FixedDepositProductData(existingProduct.id, existingProduct.name, existingProduct.shortName, existingProduct.description,
|
||||
existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
|
||||
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
final FixedDepositProductData result = new FixedDepositProductData(existingProduct.id, existingProduct.name, existingProduct.shortName,
|
||||
existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate,
|
||||
existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
existingProduct.interestCalculationDaysInYearType, existingProduct.lockinPeriodFrequency,
|
||||
existingProduct.lockinPeriodFrequencyType, existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule,
|
||||
existingProduct.accountingMappings, existingProduct.paymentChannelToFundSourceMappings, existingProduct.currencyOptions,
|
||||
@@ -131,6 +131,8 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
existingProduct.minDepositAmount, existingProduct.depositAmount, existingProduct.maxDepositAmount,
|
||||
existingProduct.periodFrequencyTypeOptions, existingProduct.withHoldTax, existingProduct.taxGroup,
|
||||
existingProduct.taxGroupOptions);
|
||||
result.copyCbsFieldsFrom(existingProduct);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -152,9 +154,9 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions,
|
||||
final Collection<EnumOptionData> periodFrequencyTypeOptions, final Collection<TaxGroupData> taxGroupOptions) {
|
||||
|
||||
return new FixedDepositProductData(existingProduct.id, existingProduct.name, existingProduct.shortName, existingProduct.description,
|
||||
existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
|
||||
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
final FixedDepositProductData result = new FixedDepositProductData(existingProduct.id, existingProduct.name, existingProduct.shortName,
|
||||
existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate,
|
||||
existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
existingProduct.interestCalculationDaysInYearType, existingProduct.lockinPeriodFrequency,
|
||||
existingProduct.lockinPeriodFrequencyType, existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule,
|
||||
existingProduct.accountingMappings, existingProduct.paymentChannelToFundSourceMappings, currencyOptions,
|
||||
@@ -169,6 +171,8 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
existingProduct.inMultiplesOfDepositTermType, existingProduct.minDepositAmount, existingProduct.depositAmount,
|
||||
existingProduct.maxDepositAmount, periodFrequencyTypeOptions, existingProduct.withHoldTax, existingProduct.taxGroup,
|
||||
taxGroupOptions);
|
||||
result.copyCbsFieldsFrom(existingProduct);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FixedDepositProductData withAccountingDetails(final FixedDepositProductData existingProduct,
|
||||
@@ -189,9 +193,9 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
final Collection<ChargeData> chargeOptions = null;
|
||||
final Collection<ChargeData> penaltyOptions = null;
|
||||
|
||||
return new FixedDepositProductData(existingProduct.id, existingProduct.name, existingProduct.shortName, existingProduct.description,
|
||||
existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
|
||||
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
final FixedDepositProductData result = new FixedDepositProductData(existingProduct.id, existingProduct.name,
|
||||
existingProduct.shortName, existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate,
|
||||
existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
existingProduct.interestCalculationDaysInYearType, existingProduct.lockinPeriodFrequency,
|
||||
existingProduct.lockinPeriodFrequencyType, existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule,
|
||||
accountingMappings, paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
@@ -206,6 +210,8 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
existingProduct.minDepositAmount, existingProduct.depositAmount, existingProduct.maxDepositAmount,
|
||||
existingProduct.periodFrequencyTypeOptions, existingProduct.withHoldTax, existingProduct.taxGroup,
|
||||
existingProduct.taxGroupOptions);
|
||||
result.copyCbsFieldsFrom(existingProduct);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static FixedDepositProductData instance(final DepositProductData depositProductData, final boolean preClosurePenalApplicable,
|
||||
@@ -243,7 +249,7 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
depositProductData.interestCompoundingPeriodType, depositProductData.interestPostingPeriodType,
|
||||
depositProductData.interestCalculationType, depositProductData.interestCalculationDaysInYearType,
|
||||
depositProductData.lockinPeriodFrequency, depositProductData.lockinPeriodFrequencyType,
|
||||
depositProductData.minBalanceForInterestCalculation, depositProductData.accountingRule, accountingMappings,
|
||||
depositProductData.getMinBalanceForInterestCalculation(), depositProductData.accountingRule, accountingMappings,
|
||||
paymentChannelToFundSourceMappings, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions,
|
||||
@@ -321,9 +327,9 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
|
||||
public static FixedDepositProductData withInterestChart(final FixedDepositProductData existingProduct,
|
||||
final Collection<InterestRateChartData> interestRateCharts) {
|
||||
return new FixedDepositProductData(existingProduct.id, existingProduct.name, existingProduct.shortName, existingProduct.description,
|
||||
existingProduct.currency, existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
|
||||
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
final FixedDepositProductData result = new FixedDepositProductData(existingProduct.id, existingProduct.name,
|
||||
existingProduct.shortName, existingProduct.description, existingProduct.currency, existingProduct.nominalAnnualInterestRate,
|
||||
existingProduct.interestCompoundingPeriodType, existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
existingProduct.interestCalculationDaysInYearType, existingProduct.lockinPeriodFrequency,
|
||||
existingProduct.lockinPeriodFrequencyType, existingProduct.minBalanceForInterestCalculation, existingProduct.accountingRule,
|
||||
existingProduct.accountingMappings, existingProduct.paymentChannelToFundSourceMappings, existingProduct.currencyOptions,
|
||||
@@ -340,7 +346,8 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
existingProduct.minDepositAmount, existingProduct.depositAmount, existingProduct.maxDepositAmount,
|
||||
existingProduct.periodFrequencyTypeOptions, existingProduct.withHoldTax, existingProduct.taxGroup,
|
||||
existingProduct.taxGroupOptions);
|
||||
|
||||
result.copyCbsFieldsFrom(existingProduct);
|
||||
return result;
|
||||
}
|
||||
|
||||
private FixedDepositProductData(final Long id, final String name, final String shortName, final String description,
|
||||
@@ -445,4 +452,160 @@ public final class FixedDepositProductData extends DepositProductData {
|
||||
return preClosurePenalApplicable;
|
||||
}
|
||||
|
||||
// CBS Custom Fields
|
||||
private Collection<org.apache.fineract.infrastructure.core.data.EnumOptionData> interestCalculationTypeOption;
|
||||
private Collection<org.apache.fineract.infrastructure.core.data.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 productCode;
|
||||
private String accountType;
|
||||
private String fdType;
|
||||
private Long glAccountId;
|
||||
private String glAccountName;
|
||||
private String customerSegment;
|
||||
private Boolean introducerRequired;
|
||||
private Boolean shareLinkingEnabled;
|
||||
private Boolean nominationFacility;
|
||||
private Boolean dormancyAlert;
|
||||
private Boolean isDormancyTrackingActive;
|
||||
private Long daysToInactive;
|
||||
private Long daysToDormancy;
|
||||
private Long daysToEscheat;
|
||||
private String effectiveDate;
|
||||
private String effectiveTo;
|
||||
private String endDate;
|
||||
private Integer interestCalculateSelector;
|
||||
private String averagePeriod;
|
||||
private Boolean autoPost;
|
||||
private Integer frequencyFixDay;
|
||||
private String lastInterestDate;
|
||||
private Boolean enableLockinPeriod;
|
||||
private Boolean autoDebitFacility;
|
||||
private Boolean loanFacility;
|
||||
private Boolean prematureWithdrawalOption;
|
||||
private Boolean tenureFlexibility;
|
||||
private Boolean lienMarked;
|
||||
private Boolean maturityInstructions;
|
||||
private Boolean creditMaturityProceeds;
|
||||
private Boolean penaltyGracePeriodMissedInstallments;
|
||||
private Boolean panelRequestApplicable;
|
||||
private Boolean noPenaltyNomineeHeirClosure;
|
||||
private Boolean deceasedSettlement;
|
||||
private Boolean allowDebitTxnAfterDueDate;
|
||||
private Boolean accountClosedZeroBalanceInDayClosing;
|
||||
private String balanceFrequency;
|
||||
|
||||
// Template option setters
|
||||
public void setInterestCalculationTypeOption(Collection<org.apache.fineract.infrastructure.core.data.EnumOptionData> v) { this.interestCalculationTypeOption = v; }
|
||||
public void setPeriodFrequencyOptions(Collection<org.apache.fineract.infrastructure.core.data.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; }
|
||||
|
||||
// CBS field setters
|
||||
public void setProductCode(String v) { this.productCode = v; }
|
||||
public void setAccountType(String v) { this.accountType = v; }
|
||||
public void setFdType(String v) { this.fdType = v; }
|
||||
public void setGlAccountId(Long v) { this.glAccountId = v; }
|
||||
public void setGlAccountName(String v) { this.glAccountName = v; }
|
||||
public void setCustomerSegment(String v) { this.customerSegment = v; }
|
||||
public void setIntroducerRequired(Boolean v) { this.introducerRequired = v; }
|
||||
public void setShareLinkingEnabled(Boolean v) { this.shareLinkingEnabled = v; }
|
||||
public void setNominationFacility(Boolean v) { this.nominationFacility = v; }
|
||||
public void setDormancyAlert(Boolean v) { this.dormancyAlert = v; }
|
||||
public void setIsDormancyTrackingActive(Boolean v) { this.isDormancyTrackingActive = v; }
|
||||
public void setDaysToInactive(Long v) { this.daysToInactive = v; }
|
||||
public void setDaysToDormancy(Long v) { this.daysToDormancy = v; }
|
||||
public void setDaysToEscheat(Long v) { this.daysToEscheat = v; }
|
||||
public void setEffectiveDate(String v) { this.effectiveDate = v; }
|
||||
public void setEffectiveTo(String v) { this.effectiveTo = v; }
|
||||
public void setEndDate(String v) { this.endDate = 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 void setLastInterestDate(String v) { this.lastInterestDate = v; }
|
||||
public void setEnableLockinPeriod(Boolean v) { this.enableLockinPeriod = v; }
|
||||
public void setAutoDebitFacility(Boolean v) { this.autoDebitFacility = v; }
|
||||
public void setLoanFacility(Boolean v) { this.loanFacility = v; }
|
||||
public void setPrematureWithdrawalOption(Boolean v) { this.prematureWithdrawalOption = v; }
|
||||
public void setTenureFlexibility(Boolean v) { this.tenureFlexibility = v; }
|
||||
public void setLienMarked(Boolean v) { this.lienMarked = v; }
|
||||
public void setMaturityInstructions(Boolean v) { this.maturityInstructions = v; }
|
||||
public void setCreditMaturityProceeds(Boolean v) { this.creditMaturityProceeds = v; }
|
||||
public void setPenaltyGracePeriodMissedInstallments(Boolean v) { this.penaltyGracePeriodMissedInstallments = v; }
|
||||
public void setPanelRequestApplicable(Boolean v) { this.panelRequestApplicable = v; }
|
||||
public void setNoPenaltyNomineeHeirClosure(Boolean v) { this.noPenaltyNomineeHeirClosure = v; }
|
||||
public void setDeceasedSettlement(Boolean v) { this.deceasedSettlement = v; }
|
||||
public void setAllowDebitTxnAfterDueDate(Boolean v) { this.allowDebitTxnAfterDueDate = v; }
|
||||
public void setAccountClosedZeroBalanceInDayClosing(Boolean v) { this.accountClosedZeroBalanceInDayClosing = v; }
|
||||
public void setBalanceFrequency(String v) { this.balanceFrequency = v; }
|
||||
|
||||
// CBS field getters
|
||||
public String getProductCode() { return productCode; }
|
||||
public String getAccountType() { return accountType; }
|
||||
public String getFdType() { return fdType; }
|
||||
public Long getGlAccountId() { return glAccountId; }
|
||||
public String getGlAccountName() { return glAccountName; }
|
||||
public String getCustomerSegment() { return customerSegment; }
|
||||
public Boolean getIntroducerRequired() { return introducerRequired; }
|
||||
public Boolean getShareLinkingEnabled() { return shareLinkingEnabled; }
|
||||
public Boolean getNominationFacility() { return nominationFacility; }
|
||||
public Boolean getDormancyAlert() { return dormancyAlert; }
|
||||
public Boolean getIsDormancyTrackingActive() { return isDormancyTrackingActive; }
|
||||
public Long getDaysToInactive() { return daysToInactive; }
|
||||
public Long getDaysToDormancy() { return daysToDormancy; }
|
||||
public Long getDaysToEscheat() { return daysToEscheat; }
|
||||
|
||||
public void copyCbsFieldsFrom(FixedDepositProductData src) {
|
||||
if (src == null) return;
|
||||
this.accountType = src.accountType;
|
||||
this.fdType = src.fdType;
|
||||
this.customerSegmentOptions = src.customerSegmentOptions;
|
||||
this.productCode = src.productCode;
|
||||
this.glAccountId = src.glAccountId;
|
||||
this.glAccountName = src.glAccountName;
|
||||
this.interestCalculationTypeOption = src.interestCalculationTypeOption;
|
||||
this.periodFrequencyOptions = src.periodFrequencyOptions;
|
||||
this.yesNoOptions = src.yesNoOptions;
|
||||
this.accountTypeOptions = src.accountTypeOptions;
|
||||
this.customerSegment = src.customerSegment;
|
||||
this.introducerRequired = src.introducerRequired;
|
||||
this.shareLinkingEnabled = src.shareLinkingEnabled;
|
||||
this.nominationFacility = src.nominationFacility;
|
||||
this.dormancyAlert = src.dormancyAlert;
|
||||
this.isDormancyTrackingActive = src.isDormancyTrackingActive;
|
||||
this.daysToInactive = src.daysToInactive;
|
||||
this.daysToDormancy = src.daysToDormancy;
|
||||
this.daysToEscheat = src.daysToEscheat;
|
||||
this.effectiveDate = src.effectiveDate;
|
||||
this.effectiveTo = src.effectiveTo;
|
||||
this.endDate = src.endDate;
|
||||
this.interestCalculateSelector = src.interestCalculateSelector;
|
||||
this.averagePeriod = src.averagePeriod;
|
||||
this.autoPost = src.autoPost;
|
||||
this.frequencyFixDay = src.frequencyFixDay;
|
||||
this.lastInterestDate = src.lastInterestDate;
|
||||
this.enableLockinPeriod = src.enableLockinPeriod;
|
||||
this.autoDebitFacility = src.autoDebitFacility;
|
||||
this.loanFacility = src.loanFacility;
|
||||
this.prematureWithdrawalOption = src.prematureWithdrawalOption;
|
||||
this.tenureFlexibility = src.tenureFlexibility;
|
||||
this.lienMarked = src.lienMarked;
|
||||
this.maturityInstructions = src.maturityInstructions;
|
||||
this.creditMaturityProceeds = src.creditMaturityProceeds;
|
||||
this.penaltyGracePeriodMissedInstallments = src.penaltyGracePeriodMissedInstallments;
|
||||
this.panelRequestApplicable = src.panelRequestApplicable;
|
||||
this.noPenaltyNomineeHeirClosure = src.noPenaltyNomineeHeirClosure;
|
||||
this.deceasedSettlement = src.deceasedSettlement;
|
||||
this.allowDebitTxnAfterDueDate = src.allowDebitTxnAfterDueDate;
|
||||
this.accountClosedZeroBalanceInDayClosing = src.accountClosedZeroBalanceInDayClosing;
|
||||
this.balanceFrequency = src.balanceFrequency;
|
||||
this.withdrawalFeeForTransfers = src.withdrawalFeeForTransfers;
|
||||
}
|
||||
|
||||
private Boolean withdrawalFeeForTransfers;
|
||||
public void setWithdrawalFeeForTransfers(Boolean v) { this.withdrawalFeeForTransfers = v; }
|
||||
public Boolean getWithdrawalFeeForTransfers() { return withdrawalFeeForTransfers; }
|
||||
}
|
||||
|
||||
+63
@@ -187,6 +187,65 @@ public class DepositProductAssembler {
|
||||
// update product reference
|
||||
productTermAndPreClosure.updateProductReference(fixedDepositProduct);
|
||||
|
||||
// CBS Custom Fields
|
||||
fixedDepositProduct.setAccountType(command.stringValueOfParameterNamed("accountType"));
|
||||
fixedDepositProduct.setCustomerSegment(command.stringValueOfParameterNamed("customerSegment"));
|
||||
final String fdProductCode = command.stringValueOfParameterNamed("productCode");
|
||||
fixedDepositProduct.setProductCode((fdProductCode != null && !fdProductCode.isBlank()) ? fdProductCode : null);
|
||||
final String fdType = command.stringValueOfParameterNamed("fdType");
|
||||
fixedDepositProduct.setFdType((fdType != null && !fdType.isBlank()) ? fdType : null);
|
||||
if (command.parameterExists("glAccountId")) {
|
||||
fixedDepositProduct.setGlAccountId(command.longValueOfParameterNamed("glAccountId"));
|
||||
}
|
||||
fixedDepositProduct.setIntroducerRequired(command.booleanPrimitiveValueOfParameterNamed("introducerRequired"));
|
||||
fixedDepositProduct.setShareLinkingEnabled(command.booleanPrimitiveValueOfParameterNamed("shareLinkingEnabled"));
|
||||
fixedDepositProduct.setEffectiveDate(parseCbsDate(command.stringValueOfParameterNamed("effectiveDate")));
|
||||
fixedDepositProduct.setEffectiveTo(parseCbsDate(command.stringValueOfParameterNamed("effectiveTo")));
|
||||
fixedDepositProduct.setEndDate(parseCbsDate(command.stringValueOfParameterNamed("endDate")));
|
||||
fixedDepositProduct.setNominationFacility(command.booleanPrimitiveValueOfParameterNamed("nominationFacility"));
|
||||
final boolean dormancyAlertValue = command.booleanPrimitiveValueOfParameterNamed("dormancyAlert");
|
||||
fixedDepositProduct.setDormancyAlert(dormancyAlertValue);
|
||||
// isDormancyTrackingActive is driven by dormancyAlert for FD products (same as RD)
|
||||
fixedDepositProduct.setIsDormancyTrackingActive(dormancyAlertValue);
|
||||
if (command.parameterExists("daysToInactive")) {
|
||||
fixedDepositProduct.setDaysToInactive(command.longValueOfParameterNamed("daysToInactive"));
|
||||
}
|
||||
if (command.parameterExists("daysToDormancy")) {
|
||||
fixedDepositProduct.setDaysToDormancy(command.longValueOfParameterNamed("daysToDormancy"));
|
||||
}
|
||||
if (command.parameterExists("daysToEscheat")) {
|
||||
fixedDepositProduct.setDaysToEscheat(command.longValueOfParameterNamed("daysToEscheat"));
|
||||
}
|
||||
fixedDepositProduct.setInterestCalculateSelector(command.integerValueOfParameterNamed("interestCalculateSelector"));
|
||||
fixedDepositProduct.setAveragePeriod(command.stringValueOfParameterNamed("averagePeriod"));
|
||||
fixedDepositProduct.setAutoPost(command.booleanPrimitiveValueOfParameterNamed("autoPost"));
|
||||
fixedDepositProduct.setFrequencyFixDay(command.integerValueOfParameterNamed("frequencyFixDay"));
|
||||
fixedDepositProduct.setLastInterestDate(parseCbsDate(command.stringValueOfParameterNamed("lastInterestDate")));
|
||||
fixedDepositProduct.setEnableLockinPeriod(command.booleanPrimitiveValueOfParameterNamed("enableLockinPeriod"));
|
||||
fixedDepositProduct.setAutoDebitFacility(command.booleanPrimitiveValueOfParameterNamed("autoDebitFacility"));
|
||||
fixedDepositProduct.setLoanFacility(command.booleanPrimitiveValueOfParameterNamed("loanFacility"));
|
||||
fixedDepositProduct.setPrematureWithdrawalOption(command.booleanPrimitiveValueOfParameterNamed("prematureWithdrawalOption"));
|
||||
fixedDepositProduct.setTenureFlexibility(command.booleanPrimitiveValueOfParameterNamed("tenureFlexibility"));
|
||||
fixedDepositProduct.setLienMarked(command.booleanPrimitiveValueOfParameterNamed("lienMarked"));
|
||||
fixedDepositProduct.setMaturityInstructions(command.booleanPrimitiveValueOfParameterNamed("maturityInstructions"));
|
||||
fixedDepositProduct.setCreditMaturityProceeds(command.booleanPrimitiveValueOfParameterNamed("creditMaturityProceeds"));
|
||||
fixedDepositProduct.setPenaltyGracePeriodMissedInstallments(
|
||||
command.booleanPrimitiveValueOfParameterNamed("penaltyGracePeriodMissedInstallments"));
|
||||
fixedDepositProduct.setPanelRequestApplicable(command.booleanPrimitiveValueOfParameterNamed("panelRequestApplicable"));
|
||||
fixedDepositProduct.setNoPenaltyNomineeHeirClosure(
|
||||
command.booleanPrimitiveValueOfParameterNamed("noPenaltyNomineeHeirClosure"));
|
||||
fixedDepositProduct.setDeceasedSettlement(command.booleanPrimitiveValueOfParameterNamed("deceasedSettlement"));
|
||||
fixedDepositProduct.setAllowDebitTxnAfterDueDate(command.booleanPrimitiveValueOfParameterNamed("allowDebitTxnAfterDueDate"));
|
||||
if (command.parameterExists("accountClosedZeroBalanceInDayClosing")) {
|
||||
fixedDepositProduct.setAccountClosedZeroBalanceInDayClosing(
|
||||
command.booleanPrimitiveValueOfParameterNamed("accountClosedZeroBalanceInDayClosing"));
|
||||
}
|
||||
fixedDepositProduct.setBalanceFrequency(command.stringValueOfParameterNamed("balanceFrequency"));
|
||||
|
||||
if (command.parameterExists("withdrawalFeeForTransfers")) {
|
||||
fixedDepositProduct.setWithdrawalFeeApplicableForTransfer(command.booleanPrimitiveValueOfParameterNamed("withdrawalFeeForTransfers"));
|
||||
}
|
||||
|
||||
fixedDepositProduct.validateDomainRules();
|
||||
|
||||
return fixedDepositProduct;
|
||||
@@ -338,6 +397,10 @@ public class DepositProductAssembler {
|
||||
recurringDepositProduct.setDeceasedSettlement(command.booleanPrimitiveValueOfParameterNamed("deceasedSettlement"));
|
||||
recurringDepositProduct.setAllowDebitTxnAfterDueDate(command.booleanPrimitiveValueOfParameterNamed("allowDebitTxnAfterDueDate"));
|
||||
|
||||
if (command.parameterExists("withdrawalFeeForTransfers")) {
|
||||
recurringDepositProduct.setWithdrawalFeeApplicableForTransfer(command.booleanPrimitiveValueOfParameterNamed("withdrawalFeeForTransfers"));
|
||||
}
|
||||
|
||||
recurringDepositProduct.validateDomainRules();
|
||||
|
||||
return recurringDepositProduct;
|
||||
|
||||
+19
@@ -26,6 +26,7 @@ import static org.apache.fineract.portfolio.savings.DepositsApiConstants.maxDepo
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.DiscriminatorValue;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
@@ -34,6 +35,7 @@ import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Transient;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
@@ -76,6 +78,17 @@ public class FixedDepositProduct extends SavingsProduct {
|
||||
@Transient
|
||||
protected InterestRateChartAssembler chartAssembler;
|
||||
|
||||
@Column(name = "fd_type", length = 50)
|
||||
private String fdType;
|
||||
|
||||
public String getFdType() {
|
||||
return fdType;
|
||||
}
|
||||
|
||||
public void setFdType(String fdType) {
|
||||
this.fdType = fdType;
|
||||
}
|
||||
|
||||
protected FixedDepositProduct() {
|
||||
|
||||
}
|
||||
@@ -161,6 +174,12 @@ public class FixedDepositProduct extends SavingsProduct {
|
||||
|
||||
actualChanges.putAll(super.update(command));
|
||||
|
||||
if (command.isChangeInStringParameterNamed("fdType", this.fdType)) {
|
||||
final String newValue = command.stringValueOfParameterNamed("fdType");
|
||||
actualChanges.put("fdType", newValue);
|
||||
this.fdType = (newValue != null && !newValue.isBlank()) ? newValue : null;
|
||||
}
|
||||
|
||||
if (this.productTermAndPreClosure != null) {
|
||||
actualChanges.putAll(this.productTermAndPreClosure.update(command, baseDataValidator));
|
||||
}
|
||||
|
||||
+13
@@ -3957,6 +3957,13 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
|
||||
@Column(name = "linked_account_no", length = 50)
|
||||
private String linkedAccountNo;
|
||||
|
||||
@Column(name = "nomination_facility")
|
||||
private Boolean nominationFacility;
|
||||
|
||||
@Column(name = "auto_debit_facility")
|
||||
private Boolean autoDebitFacility;
|
||||
|
||||
|
||||
@jakarta.persistence.OneToOne(cascade = jakarta.persistence.CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true, fetch = FetchType.LAZY)
|
||||
private SavingsAccountFacilityConfig facilityConfig;
|
||||
|
||||
@@ -4022,4 +4029,10 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
|
||||
|
||||
public List<SavingsAccountJointHolder> getJointHolders() { return jointHolders; }
|
||||
public void setJointHolders(List<SavingsAccountJointHolder> v) { this.jointHolders = v; }
|
||||
|
||||
public Boolean getNominationFacility() { return nominationFacility; }
|
||||
public void setNominationFacility(Boolean v) { this.nominationFacility = v; }
|
||||
|
||||
public Boolean getAutoDebitFacility() { return autoDebitFacility; }
|
||||
public void setAutoDebitFacility(Boolean v) { this.autoDebitFacility = v; }
|
||||
}
|
||||
|
||||
+5
-1
@@ -246,7 +246,7 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
|
||||
@Column(name = "customer_segment", length = 50)
|
||||
private String customerSegment;
|
||||
|
||||
@Column(name = "product_code", length = 20, unique = true)
|
||||
@Column(name = "product_code", length = 20)
|
||||
private String productCode;
|
||||
|
||||
@Column(name = "gl_account_id")
|
||||
@@ -1034,6 +1034,10 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
|
||||
return this.withdrawalFeeApplicableForTransfer;
|
||||
}
|
||||
|
||||
public void setWithdrawalFeeApplicableForTransfer(boolean withdrawalFeeApplicableForTransfer) {
|
||||
this.withdrawalFeeApplicableForTransfer = withdrawalFeeApplicableForTransfer;
|
||||
}
|
||||
|
||||
public boolean isAllowOverdraft() {
|
||||
return this.allowOverdraft;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user