update saving product code

This commit is contained in:
Nitesh Yadav
2026-04-13 13:26:33 +05:30
parent 011239f399
commit d7821c7824
56 changed files with 64009 additions and 21179 deletions
@@ -38,10 +38,20 @@ public class SavingsApiSetConstants extends SavingsApiConstants {
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, feeAmountParamName,
feeOnMonthDayParamName, "currencyOptions", "interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions",
"interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions",
"interestCalculationTypeOptions", "interestCalculationTypeOption", "interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions",
"withdrawalFeeTypeOptions", nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
withHoldTaxParamName, taxGroupIdParamName, isDormancyTrackingActiveParamName, daysToInactiveParamName,
daysToDormancyParamName, daysToInactiveParamName, accountMappingForPaymentParamName));
daysToDormancyParamName, daysToInactiveParamName, accountMappingForPaymentParamName, "otherGlMappings", "accountTypeOptions",
"customerSegmentOptions", "yesNoOptions",
// Enhanced custom fields
"accountType", "customerSegment", "productCode", "effectiveDate", "effectiveTo", "endDate",
"introducerRequired", "shareLinkingEnabled", "nominationFacility", "dormancyAlert",
"interestCalculateSelector", "averagePeriod", "autoPost", "frequencyFixDay", "lastInterestDate",
"enableLockinPeriod", "balanceFrequency", "accountClosedZeroBalanceInDayClosing",
"accountFacilityConfig", "accountFacilityLimits", "depositLimitKyc",
"allowOverdraft", "overdraftLimit", "minRequiredBalance", "enforceMinRequiredBalance",
"maxAllowedLienLimit", "lienAllowed", "minBalanceForInterestCalculation",
"accountingRule", "accountingMappings", "charges", "periodFrequencyOptions"));
/**
* These parameters will match the class level parameters of {@link SavingsAccountData}. Where possible, we try to
@@ -88,13 +88,14 @@ public class SavingsProductDataValidator {
private final FromJsonHelper fromApiJsonHelper;
private final SavingsProductAccountingDataValidator savingsProductAccountingDataValidator;
private static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(
SavingsApiConstants.localeParamName, SavingsApiConstants.monthDayFormatParamName, nameParamName, shortNameParamName,
SavingsApiConstants.localeParamName, SavingsApiConstants.dateFormatParamName, SavingsApiConstants.monthDayFormatParamName, nameParamName, shortNameParamName,
descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName, inMultiplesOfParamName,
nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName,
interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, SavingsApiConstants.withdrawalFeeAmountParamName,
SavingsApiConstants.withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, feeAmountParamName, feeOnMonthDayParamName,
SavingsApiConstants.accountingRuleParamName, SavingsApiConstants.chargesParamName,
SavingsApiConstants.otherGlMappingsParamName,
SavingProductAccountingParams.INCOME_FROM_FEES.getValue(), SavingProductAccountingParams.INCOME_FROM_PENALTIES.getValue(),
SavingProductAccountingParams.INTEREST_ON_SAVINGS.getValue(), SavingProductAccountingParams.PENALTIES_RECEIVABLE.getValue(),
SavingProductAccountingParams.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(),
@@ -110,7 +111,20 @@ public class SavingsProductDataValidator {
minOverdraftForInterestCalculationParamName, SavingsApiConstants.minRequiredBalanceParamName,
SavingsApiConstants.enforceMinRequiredBalanceParamName, SavingsApiConstants.maxAllowedLienLimitParamName,
SavingsApiConstants.lienAllowedParamName, minBalanceForInterestCalculationParamName, withHoldTaxParamName,
taxGroupIdParamName));
taxGroupIdParamName,
// Enhanced Savings Product Fields
SavingsApiConstants.accountTypeParamName, SavingsApiConstants.customerSegmentParamName,
SavingsApiConstants.productCodeParamName, SavingsApiConstants.effectiveDateParamName,
SavingsApiConstants.effectiveToParamName, SavingsApiConstants.endDateParamName,
SavingsApiConstants.introducerRequiredParamName, SavingsApiConstants.shareLinkingEnabledParamName,
SavingsApiConstants.nominationFacilityParamName, SavingsApiConstants.dormancyAlertParamName,
SavingsApiConstants.interestCalculateSelectorParamName, SavingsApiConstants.averagePeriodParamName,
SavingsApiConstants.autoPostParamName, SavingsApiConstants.frequencyFixDayParamName,
SavingsApiConstants.lastInterestDateParamName, SavingsApiConstants.enableLockinPeriodParamName,
SavingsApiConstants.accountFacilityConfigParamName, SavingsApiConstants.accountFacilityLimitsParamName,
SavingsApiConstants.depositLimitKycParamName,
// Additional custom fields
SavingsApiConstants.balanceFrequencyParamName, SavingsApiConstants.accountClosedZeroBalanceInDayClosingParamName));
public void validateForCreate(final String json) {
@@ -159,8 +173,7 @@ public class SavingsProductDataValidator {
final Integer interestCalculationType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(interestCalculationTypeParamName,
element);
baseDataValidator.reset().parameter(interestCalculationTypeParamName).value(interestCalculationType).notNull()
.isOneOfTheseValues(SavingsInterestCalculationType.integerValues());
baseDataValidator.reset().parameter(interestCalculationTypeParamName).value(interestCalculationType).notNull();
final Integer interestCalculationDaysInYearType = this.fromApiJsonHelper
.extractIntegerSansLocaleNamed(interestCalculationDaysInYearTypeParamName, element);
@@ -253,6 +266,15 @@ public class SavingsProductDataValidator {
}
}
if (this.fromApiJsonHelper.parameterExists(SavingsApiConstants.effectiveToParamName, element) && this.fromApiJsonHelper.parameterExists(SavingsApiConstants.effectiveDateParamName, element)) {
final java.time.LocalDate effectiveDate = this.fromApiJsonHelper.extractLocalDateNamed(SavingsApiConstants.effectiveDateParamName, element);
final java.time.LocalDate effectiveTo = this.fromApiJsonHelper.extractLocalDateNamed(SavingsApiConstants.effectiveToParamName, element);
if (effectiveDate != null && effectiveTo != null && effectiveTo.isBefore(effectiveDate)) {
baseDataValidator.reset().parameter(SavingsApiConstants.effectiveToParamName).value(effectiveTo).failWithCode("error.msg.effectiveto.cannot.be.before.effectivedate");
}
}
// accounting related data validation
final Integer accountingRuleType = this.fromApiJsonHelper.extractIntegerNamed("accountingRule", element, Locale.getDefault());
baseDataValidator.reset().parameter("accountingRule").value(accountingRuleType).notNull().inMinMaxRange(1, 3);
@@ -263,6 +285,15 @@ public class SavingsProductDataValidator {
baseDataValidator, DepositAccountType.SAVINGS_DEPOSIT, true);
}
if (this.fromApiJsonHelper.parameterExists(SavingsApiConstants.effectiveToParamName, element) && this.fromApiJsonHelper.parameterExists(SavingsApiConstants.effectiveDateParamName, element)) {
final java.time.LocalDate effectiveDate = this.fromApiJsonHelper.extractLocalDateNamed(SavingsApiConstants.effectiveDateParamName, element);
final java.time.LocalDate effectiveTo = this.fromApiJsonHelper.extractLocalDateNamed(SavingsApiConstants.effectiveToParamName, element);
if (effectiveDate != null && effectiveTo != null && effectiveTo.isBefore(effectiveDate)) {
baseDataValidator.reset().parameter(SavingsApiConstants.effectiveToParamName).value(effectiveTo).failWithCode("error.msg.effectiveto.cannot.be.before.effectivedate");
}
}
validateOverdraftParams(baseDataValidator, element);
if (this.fromApiJsonHelper.parameterExists(minBalanceForInterestCalculationParamName, element)) {
@@ -0,0 +1,100 @@
<?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.3.xsd">
<changeSet id="1" author="fineract">
<addColumn tableName="m_savings_product">
<column name="account_type" type="VARCHAR(50)"/>
<column name="customer_segment" type="VARCHAR(50)"/>
<column name="product_code" type="VARCHAR(20)">
<constraints unique="true" uniqueConstraintName="uq_savings_product_code"/>
</column>
<column name="effective_date" type="DATE"/>
<column name="effective_to" type="DATE"/>
<column name="end_date" type="DATE"/>
<column name="introducer_required" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="share_linking_enabled" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="nomination_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="dormancy_alert" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="interest_calculate_selector" type="INT"/>
<column name="average_period" type="VARCHAR(20)"/>
<column name="auto_post" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="frequency_fix_day" type="INT"/>
<column name="last_interest_date" type="DATE"/>
<column name="enable_lockin_period" type="BOOLEAN" defaultValueBoolean="false"/>
</addColumn>
</changeSet>
<changeSet id="2" author="fineract">
<createTable tableName="m_savings_product_facility_config">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="savings_product_id" type="BIGINT">
<constraints nullable="false" unique="true" uniqueConstraintName="uq_savings_product_facility_config" foreignKeyName="fk_facility_config_savings_product" references="m_savings_product(id)" deleteCascade="true"/>
</column>
<column name="atm_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="atm_withdrawal_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="upi_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="pos_transactions_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="cheque_book" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="imps_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="sms_alerts" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="bbps_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="insurance_cover" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="bepg_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="neft_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="rtgs_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="inter_bank_total_cap_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="withdrawal_facility" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="deposit_facility_kyc" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="virtual_debit_card" type="BOOLEAN" defaultValueBoolean="false"/>
<column name="created_date" type="DATETIME" defaultValueComputed="CURRENT_TIMESTAMP">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<changeSet id="3" author="fineract">
<createTable tableName="m_savings_product_facility_limits">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="savings_product_id" type="BIGINT">
<constraints nullable="false" foreignKeyName="fk_facility_limits_savings_product" references="m_savings_product(id)" deleteCascade="true"/>
</column>
<column name="limit_type" type="VARCHAR(100)">
<constraints nullable="false"/>
</column>
<column name="general_limit" type="VARCHAR(50)"/>
<column name="minor_account_limit" type="VARCHAR(50)"/>
<column name="small_saving_limit" type="VARCHAR(50)"/>
<column name="created_date" type="DATETIME" defaultValueComputed="CURRENT_TIMESTAMP">
<constraints nullable="false"/>
</column>
</createTable>
<addUniqueConstraint tableName="m_savings_product_facility_limits" columnNames="savings_product_id, limit_type" constraintName="uq_product_limit_type"/>
</changeSet>
<changeSet id="4" author="fineract">
<createTable tableName="m_savings_product_deposit_limit_kyc">
<column name="id" type="BIGINT" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="savings_product_id" type="BIGINT">
<constraints nullable="false" unique="true" uniqueConstraintName="uq_savings_product_deposit_limit" foreignKeyName="fk_deposit_limit_savings_product" references="m_savings_product(id)" deleteCascade="true"/>
</column>
<column name="general_kyc_type" type="VARCHAR(50)"/>
<column name="general_limit" type="VARCHAR(50)"/>
<column name="minor_kyc_type" type="VARCHAR(50)"/>
<column name="minor_limit" type="BIGINT"/>
<column name="small_saving_kyc_type" type="VARCHAR(50)"/>
<column name="small_saving_limit" type="BIGINT"/>
<column name="created_date" type="DATETIME" defaultValueComputed="CURRENT_TIMESTAMP">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
</databaseChangeLog>
@@ -48,12 +48,30 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.namePara
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateOverdraftParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.otherGlMappingsParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNameParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountTypeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.customerSegmentParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.productCodeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveToParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.endDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.introducerRequiredParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shareLinkingEnabledParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominationFacilityParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.dormancyAlertParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculateSelectorParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.averagePeriodParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoPostParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.frequencyFixDayParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lastInterestDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enableLockinPeriodParamName;
import com.google.gson.JsonArray;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.DiscriminatorType;
@@ -65,6 +83,9 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Lob;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import java.math.BigDecimal;
@@ -75,6 +96,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Objects;
import org.apache.fineract.accounting.common.AccountingRuleType;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
@@ -209,6 +231,75 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
@Column(name = "days_to_escheat")
private Long daysToEscheat;
@Lob
@Column(name = "other_gl_mappings")
private String otherGlMappings;
// Enhanced Savings Product Fields
@Column(name = "account_type", length = 50)
private String accountType;
@Column(name = "customer_segment", length = 50)
private String customerSegment;
@Column(name = "product_code", length = 20, unique = true)
private String productCode;
@Column(name = "effective_date")
private LocalDate effectiveDate;
@Column(name = "effective_to")
private LocalDate effectiveTo;
@Column(name = "end_date")
private LocalDate endDate;
@Column(name = "introducer_required")
private boolean introducerRequired = false;
@Column(name = "share_linking_enabled")
private boolean shareLinkingEnabled = false;
@Column(name = "nomination_facility")
private boolean nominationFacility = false;
@Column(name = "dormancy_alert")
private boolean dormancyAlert = false;
@Column(name = "interest_calculate_selector")
private Integer interestCalculateSelector;
@Column(name = "average_period", length = 20)
private String averagePeriod;
@Column(name = "auto_post")
private boolean autoPost = false;
@Column(name = "frequency_fix_day")
private Integer frequencyFixDay;
@Column(name = "last_interest_date")
private LocalDate lastInterestDate;
@Column(name = "enable_lockin_period")
private boolean enableLockinPeriod = false;
@Column(name = "balance_frequency", length = 50)
private String balanceFrequency;
@Column(name = "account_closed_zero_balance_in_day_closing")
private Boolean accountClosedZeroBalanceInDayClosing = false;
// Relationships for complex objects
@OneToOne(cascade = CascadeType.ALL, mappedBy = "savingsProduct", orphanRemoval = true)
private SavingsProductFacilityConfig facilityConfig;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "savingsProduct", orphanRemoval = true)
private Set<SavingsProductFacilityLimit> facilityLimits = new HashSet<>();
@OneToOne(cascade = CascadeType.ALL, mappedBy = "savingsProduct", orphanRemoval = true)
private SavingsProductDepositLimitKyc depositLimitKyc;
public static SavingsProduct createNew(final String name, final String shortName, final String description,
final MonetaryCurrency currency, final BigDecimal interestRate,
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
@@ -220,14 +311,15 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
final BigDecimal minRequiredBalance, final boolean lienAllowed, final BigDecimal maxAllowedLienLimit,
final BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
final BigDecimal minOverdraftForInterestCalculation, boolean withHoldTax, TaxGroup taxGroup,
final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy, final Long daysToEscheat) {
final String otherGlMappings, final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy,
final Long daysToEscheat) {
return new SavingsProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges,
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, lienAllowed, maxAllowedLienLimit,
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
taxGroup, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
taxGroup, otherGlMappings, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
}
protected SavingsProduct() {
@@ -235,6 +327,22 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
this.description = null;
}
protected SavingsProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency,
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set<Charge> charges,
final boolean allowOverdraft, final BigDecimal overdraftLimit, BigDecimal minBalanceForInterestCalculation, boolean withHoldTax,
TaxGroup taxGroup, final String otherGlMappings) {
this(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit,
false, null, false, null, minBalanceForInterestCalculation, null, null, withHoldTax, taxGroup, null, null, null, null,
null);
this.otherGlMappings = otherGlMappings;
}
protected SavingsProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency,
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
final SavingsPostingInterestPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
@@ -246,7 +354,7 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
this(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit,
false, null, false, null, minBalanceForInterestCalculation, null, null, withHoldTax, taxGroup, null, null, null, null);
minBalanceForInterestCalculation, withHoldTax, taxGroup, null);
}
protected SavingsProduct(final String name, final String shortName, final String description, final MonetaryCurrency currency,
@@ -259,7 +367,8 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
final BigDecimal minRequiredBalance, final boolean lienAllowed, final BigDecimal maxAllowedLienLimit,
BigDecimal minBalanceForInterestCalculation, final BigDecimal nominalAnnualInterestRateOverdraft,
final BigDecimal minOverdraftForInterestCalculation, final boolean withHoldTax, final TaxGroup taxGroup,
final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy, final Long daysToEscheat) {
final String otherGlMappings, final Boolean isDormancyTrackingActive, final Long daysToInactive, final Long daysToDormancy,
final Long daysToEscheat) {
this.name = name;
this.shortName = shortName;
@@ -306,6 +415,7 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
this.minBalanceForInterestCalculation = minBalanceForInterestCalculation;
this.withHoldTax = withHoldTax;
this.taxGroup = taxGroup;
this.otherGlMappings = otherGlMappings;
if (isDormancyTrackingActive == null) {
this.isDormancyTrackingActive = Boolean.FALSE;
@@ -444,7 +554,7 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
if (command.isChangeInIntegerParameterNamed(interestCalculationTypeParamName, this.interestCalculationType)) {
final Integer newValue = command.integerValueOfParameterNamed(interestCalculationTypeParamName);
actualChanges.put(interestCalculationTypeParamName, newValue);
this.interestCalculationType = SavingsInterestCalculationType.fromInt(newValue).getValue();
this.interestCalculationType = newValue;
}
if (command.isChangeInIntegerParameterNamed(interestCalculationDaysInYearTypeParamName, this.interestCalculationDaysInYearType)) {
@@ -586,6 +696,14 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
this.taxGroup = null;
}
if (command.hasParameter(otherGlMappingsParamName)) {
final String newValue = command.jsonFragment(otherGlMappingsParamName);
if (!Objects.equals(this.otherGlMappings, newValue)) {
actualChanges.put(otherGlMappingsParamName, newValue);
this.otherGlMappings = newValue;
}
}
if (command.isChangeInBooleanParameterNamed(isDormancyTrackingActiveParamName, this.isDormancyTrackingActive)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(isDormancyTrackingActiveParamName);
actualChanges.put(isDormancyTrackingActiveParamName, newValue);
@@ -616,6 +734,102 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
this.daysToEscheat = null;
}
// Enhanced Savings Product Field Updates
if (command.isChangeInStringParameterNamed(accountTypeParamName, this.accountType)) {
final String newValue = command.stringValueOfParameterNamed(accountTypeParamName);
actualChanges.put(accountTypeParamName, newValue);
this.accountType = newValue;
}
if (command.isChangeInStringParameterNamed(customerSegmentParamName, this.customerSegment)) {
final String newValue = command.stringValueOfParameterNamed(customerSegmentParamName);
actualChanges.put(customerSegmentParamName, newValue);
this.customerSegment = newValue;
}
if (command.isChangeInStringParameterNamed(productCodeParamName, this.productCode)) {
final String newValue = command.stringValueOfParameterNamed(productCodeParamName);
actualChanges.put(productCodeParamName, newValue);
this.productCode = newValue;
}
if (command.isChangeInLocalDateParameterNamed(effectiveDateParamName, this.effectiveDate)) {
final LocalDate newValue = command.localDateValueOfParameterNamed(effectiveDateParamName);
actualChanges.put(effectiveDateParamName, newValue);
this.effectiveDate = newValue;
}
if (command.isChangeInLocalDateParameterNamed(effectiveToParamName, this.effectiveTo)) {
final LocalDate newValue = command.localDateValueOfParameterNamed(effectiveToParamName);
actualChanges.put(effectiveToParamName, newValue);
this.effectiveTo = newValue;
}
if (command.isChangeInLocalDateParameterNamed(endDateParamName, this.endDate)) {
final LocalDate newValue = command.localDateValueOfParameterNamed(endDateParamName);
actualChanges.put(endDateParamName, newValue);
this.endDate = newValue;
}
if (command.isChangeInBooleanParameterNamed(introducerRequiredParamName, this.introducerRequired)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(introducerRequiredParamName);
actualChanges.put(introducerRequiredParamName, newValue);
this.introducerRequired = newValue;
}
if (command.isChangeInBooleanParameterNamed(shareLinkingEnabledParamName, this.shareLinkingEnabled)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(shareLinkingEnabledParamName);
actualChanges.put(shareLinkingEnabledParamName, newValue);
this.shareLinkingEnabled = newValue;
}
if (command.isChangeInBooleanParameterNamed(nominationFacilityParamName, this.nominationFacility)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(nominationFacilityParamName);
actualChanges.put(nominationFacilityParamName, newValue);
this.nominationFacility = newValue;
}
if (command.isChangeInBooleanParameterNamed(dormancyAlertParamName, this.dormancyAlert)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(dormancyAlertParamName);
actualChanges.put(dormancyAlertParamName, newValue);
this.dormancyAlert = newValue;
}
if (command.isChangeInIntegerParameterNamed(interestCalculateSelectorParamName, this.interestCalculateSelector)) {
final Integer newValue = command.integerValueOfParameterNamed(interestCalculateSelectorParamName);
actualChanges.put(interestCalculateSelectorParamName, newValue);
this.interestCalculateSelector = newValue;
}
if (command.isChangeInStringParameterNamed(averagePeriodParamName, this.averagePeriod)) {
final String newValue = command.stringValueOfParameterNamed(averagePeriodParamName);
actualChanges.put(averagePeriodParamName, newValue);
this.averagePeriod = newValue;
}
if (command.isChangeInBooleanParameterNamed(autoPostParamName, this.autoPost)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(autoPostParamName);
actualChanges.put(autoPostParamName, newValue);
this.autoPost = newValue;
}
if (command.isChangeInIntegerParameterNamed(frequencyFixDayParamName, this.frequencyFixDay)) {
final Integer newValue = command.integerValueOfParameterNamed(frequencyFixDayParamName);
actualChanges.put(frequencyFixDayParamName, newValue);
this.frequencyFixDay = newValue;
}
if (command.isChangeInLocalDateParameterNamed(lastInterestDateParamName, this.lastInterestDate)) {
final LocalDate newValue = command.localDateValueOfParameterNamed(lastInterestDateParamName);
actualChanges.put(lastInterestDateParamName, newValue);
this.lastInterestDate = newValue;
}
if (command.isChangeInBooleanParameterNamed(enableLockinPeriodParamName, this.enableLockinPeriod)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(enableLockinPeriodParamName);
actualChanges.put(enableLockinPeriodParamName, newValue);
this.enableLockinPeriod = newValue;
}
// Update balanceFrequency
if (command.isChangeInStringParameterNamed("balanceFrequency", this.balanceFrequency)) {
final String newValue = command.stringValueOfParameterNamed("balanceFrequency");
actualChanges.put("balanceFrequency", newValue);
this.balanceFrequency = newValue;
}
// Update accountClosedZeroBalanceInDayClosing
if (command.isChangeInBooleanParameterNamed("accountClosedZeroBalanceInDayClosing", this.accountClosedZeroBalanceInDayClosing)) {
final Boolean newValue = command.booleanObjectValueOfParameterNamed("accountClosedZeroBalanceInDayClosing");
actualChanges.put("accountClosedZeroBalanceInDayClosing", newValue);
this.accountClosedZeroBalanceInDayClosing = newValue;
}
validateLockinDetails();
esnureOverdraftLimitsSetForOverdraftAccounts();
@@ -779,4 +993,185 @@ public class SavingsProduct extends AbstractPersistableCustom<Long> {
return this.daysToEscheat;
}
public String getOtherGlMappings() {
return this.otherGlMappings;
}
// Enhanced Savings Product Getters and Setters
public String getAccountType() {
return accountType;
}
public void setAccountType(String accountType) {
this.accountType = accountType;
}
public String getCustomerSegment() {
return customerSegment;
}
public void setCustomerSegment(String customerSegment) {
this.customerSegment = customerSegment;
}
public String getProductCode() {
return productCode;
}
public void setProductCode(String productCode) {
this.productCode = productCode;
}
public LocalDate getEffectiveDate() {
return effectiveDate;
}
public void setEffectiveDate(LocalDate effectiveDate) {
this.effectiveDate = effectiveDate;
}
public LocalDate getEffectiveTo() {
return effectiveTo;
}
public void setEffectiveTo(LocalDate effectiveTo) {
this.effectiveTo = effectiveTo;
}
public LocalDate getEndDate() {
return endDate;
}
public void setEndDate(LocalDate endDate) {
this.endDate = endDate;
}
public boolean isIntroducerRequired() {
return introducerRequired;
}
public void setIntroducerRequired(boolean introducerRequired) {
this.introducerRequired = introducerRequired;
}
public boolean isShareLinkingEnabled() {
return shareLinkingEnabled;
}
public void setShareLinkingEnabled(boolean shareLinkingEnabled) {
this.shareLinkingEnabled = shareLinkingEnabled;
}
public boolean isNominationFacility() {
return nominationFacility;
}
public void setNominationFacility(boolean nominationFacility) {
this.nominationFacility = nominationFacility;
}
public boolean isDormancyAlert() {
return dormancyAlert;
}
public void setDormancyAlert(boolean dormancyAlert) {
this.dormancyAlert = dormancyAlert;
}
public Integer getInterestCalculateSelector() {
return interestCalculateSelector;
}
public void setInterestCalculateSelector(Integer interestCalculateSelector) {
this.interestCalculateSelector = interestCalculateSelector;
}
public String getAveragePeriod() {
return averagePeriod;
}
public void setAveragePeriod(String averagePeriod) {
this.averagePeriod = averagePeriod;
}
public boolean isAutoPost() {
return autoPost;
}
public void setAutoPost(boolean autoPost) {
this.autoPost = autoPost;
}
public Integer getFrequencyFixDay() {
return frequencyFixDay;
}
public void setFrequencyFixDay(Integer frequencyFixDay) {
this.frequencyFixDay = frequencyFixDay;
}
public LocalDate getLastInterestDate() {
return lastInterestDate;
}
public void setLastInterestDate(LocalDate lastInterestDate) {
this.lastInterestDate = lastInterestDate;
}
public boolean isEnableLockinPeriod() {
return enableLockinPeriod;
}
public void setEnableLockinPeriod(boolean enableLockinPeriod) {
this.enableLockinPeriod = enableLockinPeriod;
}
public String getBalanceFrequency() {
return balanceFrequency;
}
public void setBalanceFrequency(String balanceFrequency) {
this.balanceFrequency = balanceFrequency;
}
public Boolean getAccountClosedZeroBalanceInDayClosing() {
return accountClosedZeroBalanceInDayClosing;
}
public void setAccountClosedZeroBalanceInDayClosing(Boolean accountClosedZeroBalanceInDayClosing) {
this.accountClosedZeroBalanceInDayClosing = accountClosedZeroBalanceInDayClosing;
}
public SavingsProductFacilityConfig getFacilityConfig() {
return facilityConfig;
}
public void setFacilityConfig(SavingsProductFacilityConfig facilityConfig) {
this.facilityConfig = facilityConfig;
}
public Set<SavingsProductFacilityLimit> getFacilityLimits() {
return facilityLimits;
}
public void setFacilityLimits(Set<SavingsProductFacilityLimit> facilityLimits) {
this.facilityLimits = facilityLimits;
}
public SavingsProductDepositLimitKyc getDepositLimitKyc() {
return depositLimitKyc;
}
public void setDepositLimitKyc(SavingsProductDepositLimitKyc depositLimitKyc) {
this.depositLimitKyc = depositLimitKyc;
}
// Helper methods for safely updating complex objects (avoids JPA Orphan removal crash on PUT)
public void updateFacilityLimits(Set<SavingsProductFacilityLimit> newLimits) {
if (newLimits != null) {
this.facilityLimits.clear();
this.facilityLimits.addAll(newLimits);
}
}
}
@@ -18,7 +18,25 @@
*/
package org.apache.fineract.portfolio.savings.domain;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountFacilityConfigParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountFacilityLimitsParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.accountTypeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.averagePeriodParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoPostParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.customerSegmentParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.depositLimitKycParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.dormancyAlertParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.effectiveToParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enableLockinPeriodParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.endDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.frequencyFixDayParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.introducerRequiredParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.lastInterestDateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominationFacilityParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.productCodeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shareLinkingEnabledParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.chargesParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.currencyCodeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.daysToDormancyParamName;
@@ -29,6 +47,7 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.digitsAf
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enforceMinRequiredBalanceParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.idParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.inMultiplesOfParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculateSelectorParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCalculationTypeParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
@@ -46,12 +65,14 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.namePara
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateOverdraftParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.overdraftLimitParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.otherGlMappingsParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.shortNameParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.taxGroupIdParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withHoldTaxParamName;
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.math.BigDecimal;
import java.util.HashSet;
@@ -192,13 +213,72 @@ public class SavingsProductAssembler {
final Long daysToInactive = command.longValueOfParameterNamed(daysToInactiveParamName);
final Long daysToDormancy = command.longValueOfParameterNamed(daysToDormancyParamName);
final Long daysToEscheat = command.longValueOfParameterNamed(daysToEscheatParamName);
final String otherGlMappings = command.hasParameter(otherGlMappingsParamName) ? command.jsonFragment(otherGlMappingsParamName) : null;
return SavingsProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
SavingsProduct product = SavingsProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges,
allowOverdraft, overdraftLimit, enforceMinRequiredBalance, minRequiredBalance, lienAllowed, maxAllowedLienLimit,
minBalanceForInterestCalculation, nominalAnnualInterestRateOverdraft, minOverdraftForInterestCalculation, withHoldTax,
taxGroup, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
taxGroup, otherGlMappings, isDormancyTrackingActive, daysToInactive, daysToDormancy, daysToEscheat);
// Set enhanced fields
if (command.parameterExists(accountTypeParamName)) {
product.setAccountType(command.stringValueOfParameterNamed(accountTypeParamName));
}
if (command.parameterExists(customerSegmentParamName)) {
product.setCustomerSegment(command.stringValueOfParameterNamed(customerSegmentParamName));
}
if (command.parameterExists(productCodeParamName)) {
product.setProductCode(command.stringValueOfParameterNamed(productCodeParamName));
}
if (command.parameterExists(effectiveDateParamName)) {
product.setEffectiveDate(command.localDateValueOfParameterNamed(effectiveDateParamName));
}
if (command.parameterExists(effectiveToParamName)) {
product.setEffectiveTo(command.localDateValueOfParameterNamed(effectiveToParamName));
}
if (command.parameterExists(endDateParamName)) {
product.setEndDate(command.localDateValueOfParameterNamed(endDateParamName));
}
if (command.parameterExists(introducerRequiredParamName)) {
product.setIntroducerRequired(command.booleanPrimitiveValueOfParameterNamed(introducerRequiredParamName));
}
if (command.parameterExists(shareLinkingEnabledParamName)) {
product.setShareLinkingEnabled(command.booleanPrimitiveValueOfParameterNamed(shareLinkingEnabledParamName));
}
if (command.parameterExists(nominationFacilityParamName)) {
product.setNominationFacility(command.booleanPrimitiveValueOfParameterNamed(nominationFacilityParamName));
}
if (command.parameterExists(dormancyAlertParamName)) {
product.setDormancyAlert(command.booleanPrimitiveValueOfParameterNamed(dormancyAlertParamName));
}
if (command.parameterExists(interestCalculateSelectorParamName)) {
product.setInterestCalculateSelector(command.integerValueOfParameterNamed(interestCalculateSelectorParamName));
}
if (command.parameterExists(averagePeriodParamName)) {
product.setAveragePeriod(command.stringValueOfParameterNamed(averagePeriodParamName));
}
if (command.parameterExists(autoPostParamName)) {
product.setAutoPost(command.booleanPrimitiveValueOfParameterNamed(autoPostParamName));
}
if (command.parameterExists(frequencyFixDayParamName)) {
product.setFrequencyFixDay(command.integerValueOfParameterNamed(frequencyFixDayParamName));
}
if (command.parameterExists(lastInterestDateParamName)) {
product.setLastInterestDate(command.localDateValueOfParameterNamed(lastInterestDateParamName));
}
if (command.parameterExists(enableLockinPeriodParamName)) {
product.setEnableLockinPeriod(command.booleanPrimitiveValueOfParameterNamed(enableLockinPeriodParamName));
}
if (command.parameterExists("balanceFrequency")) {
product.setBalanceFrequency(command.stringValueOfParameterNamed("balanceFrequency"));
}
if (command.parameterExists("accountClosedZeroBalanceInDayClosing")) {
product.setAccountClosedZeroBalanceInDayClosing(command.booleanObjectValueOfParameterNamed("accountClosedZeroBalanceInDayClosing"));
}
return product;
}
public Set<Charge> assembleListOfSavingsProductCharges(final JsonCommand command, final String savingsProductCurrencyCode) {
@@ -243,4 +323,120 @@ public class SavingsProductAssembler {
}
return taxGroup;
}
public SavingsProductFacilityConfig assembleAccountFacilityConfig(final JsonCommand command, final SavingsProduct product) {
if (!command.hasParameter(accountFacilityConfigParamName)) {
return null;
}
JsonElement facilityConfigElement = command.parsedJson().getAsJsonObject().get(accountFacilityConfigParamName);
if (facilityConfigElement == null || facilityConfigElement.isJsonNull()) {
return null;
}
final JsonObject facilityConfigJson = facilityConfigElement.getAsJsonObject();
if (facilityConfigJson == null) {
return null;
}
SavingsProductFacilityConfig config = new SavingsProductFacilityConfig(product);
config.setAtmFacility(facilityConfigJson.has("atmFacility") ?
facilityConfigJson.get("atmFacility").getAsBoolean() : false);
config.setAtmWithdrawalFacility(facilityConfigJson.has("atmWithdrawalFacility") ?
facilityConfigJson.get("atmWithdrawalFacility").getAsBoolean() : false);
config.setUpiFacility(facilityConfigJson.has("upiFacility") ?
facilityConfigJson.get("upiFacility").getAsBoolean() : false);
config.setPosTransactionsFacility(facilityConfigJson.has("posTransactionsFacility") ?
facilityConfigJson.get("posTransactionsFacility").getAsBoolean() : false);
config.setChequeBook(facilityConfigJson.has("chequeBook") ?
facilityConfigJson.get("chequeBook").getAsBoolean() : false);
config.setImpsFacility(facilityConfigJson.has("impsFacility") ?
facilityConfigJson.get("impsFacility").getAsBoolean() : false);
config.setSmsAlerts(facilityConfigJson.has("smsAlerts") ?
facilityConfigJson.get("smsAlerts").getAsBoolean() : false);
config.setBbpsFacility(facilityConfigJson.has("bbpsFacility") ?
facilityConfigJson.get("bbpsFacility").getAsBoolean() : false);
config.setInsuranceCover(facilityConfigJson.has("insuranceCover") ?
facilityConfigJson.get("insuranceCover").getAsBoolean() : false);
config.setBepgFacility(facilityConfigJson.has("bepgFacility") ?
facilityConfigJson.get("bepgFacility").getAsBoolean() : false);
config.setNeftFacility(facilityConfigJson.has("neftFacility") ?
facilityConfigJson.get("neftFacility").getAsBoolean() : false);
config.setRtgsFacility(facilityConfigJson.has("rtgsFacility") ?
facilityConfigJson.get("rtgsFacility").getAsBoolean() : false);
config.setInterBankTotalCapFacility(facilityConfigJson.has("interBankTotalCapFacility") ?
facilityConfigJson.get("interBankTotalCapFacility").getAsBoolean() : false);
config.setWithdrawalFacility(facilityConfigJson.has("withdrawalFacility") ?
facilityConfigJson.get("withdrawalFacility").getAsBoolean() : false);
config.setDepositFacilityKyc(facilityConfigJson.has("depositFacilityKyc") ?
facilityConfigJson.get("depositFacilityKyc").getAsBoolean() : false);
config.setVirtualDebitCard(facilityConfigJson.has("virtualDebitCard") ?
facilityConfigJson.get("virtualDebitCard").getAsBoolean() : false);
return config;
}
public Set<SavingsProductFacilityLimit> assembleAccountFacilityLimits(final JsonCommand command, final SavingsProduct product) {
final Set<SavingsProductFacilityLimit> limits = new HashSet<>();
if (!command.hasParameter(accountFacilityLimitsParamName)) {
return limits;
}
final JsonArray limitsArray = command.arrayOfParameterNamed(accountFacilityLimitsParamName);
if (limitsArray == null) {
return limits;
}
for (int i = 0; i < limitsArray.size(); i++) {
final JsonObject limitJson = limitsArray.get(i).getAsJsonObject();
SavingsProductFacilityLimit limit = SavingsProductFacilityLimit.create(
product,
limitJson.has("limitType") ? limitJson.get("limitType").getAsString() : null,
limitJson.has("generalLimit") ? limitJson.get("generalLimit").getAsString() : null,
limitJson.has("minorAccountLimit") ? limitJson.get("minorAccountLimit").getAsString() : null,
limitJson.has("smallSavingLimit") ? limitJson.get("smallSavingLimit").getAsString() : null
);
limits.add(limit);
}
return limits;
}
public SavingsProductDepositLimitKyc assembleDepositLimitKyc(final JsonCommand command, final SavingsProduct product) {
if (!command.hasParameter(depositLimitKycParamName)) {
return null;
}
JsonElement kycElement = command.parsedJson().getAsJsonObject().get(depositLimitKycParamName);
if (kycElement == null || kycElement.isJsonNull()) {
return null;
}
final JsonObject kycJson = kycElement.getAsJsonObject();
if (kycJson == null) {
return null;
}
SavingsProductDepositLimitKyc kyc = new SavingsProductDepositLimitKyc(product);
if (kycJson.has("general")) {
final JsonObject generalJson = kycJson.getAsJsonObject("general");
kyc.setGeneralKycType(generalJson.has("kycType") ? generalJson.get("kycType").getAsString() : null);
kyc.setGeneralLimit(generalJson.has("limit") ? generalJson.get("limit").getAsString() : null);
}
if (kycJson.has("minor")) {
final JsonObject minorJson = kycJson.getAsJsonObject("minor");
kyc.setMinorKycType(minorJson.has("kycType") ? minorJson.get("kycType").getAsString() : null);
kyc.setMinorLimit(minorJson.has("limit") ? minorJson.get("limit").getAsLong() : null);
}
if (kycJson.has("smallSaving")) {
final JsonObject smallSavingJson = kycJson.getAsJsonObject("smallSaving");
kyc.setSmallSavingKycType(smallSavingJson.has("kycType") ? smallSavingJson.get("kycType").getAsString() : null);
kyc.setSmallSavingLimit(smallSavingJson.has("limit") ? smallSavingJson.get("limit").getAsLong() : null);
}
return kyc;
}
}
@@ -0,0 +1,137 @@
/**
* 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.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
@Entity
@Table(name = "m_savings_product_deposit_limit_kyc")
public class SavingsProductDepositLimitKyc extends AbstractPersistableCustom<Long> {
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "savings_product_id", nullable = false)
private SavingsProduct savingsProduct;
@Column(name = "general_kyc_type", length = 50)
private String generalKycType;
@Column(name = "general_limit", length = 50)
private String generalLimit; // "No Limit" or numeric
@Column(name = "minor_kyc_type", length = 50)
private String minorKycType;
@Column(name = "minor_limit")
private Long minorLimit;
@Column(name = "small_saving_kyc_type", length = 50)
private String smallSavingKycType;
@Column(name = "small_saving_limit")
private Long smallSavingLimit;
@Column(name = "created_date", nullable = false)
private LocalDateTime createdDate;
protected SavingsProductDepositLimitKyc() {
this.createdDate = LocalDateTime.now();
}
public SavingsProductDepositLimitKyc(SavingsProduct savingsProduct) {
this();
this.savingsProduct = savingsProduct;
}
// Getters and setters
public SavingsProduct getSavingsProduct() {
return savingsProduct;
}
public void setSavingsProduct(SavingsProduct savingsProduct) {
this.savingsProduct = savingsProduct;
}
public String getGeneralKycType() {
return generalKycType;
}
public void setGeneralKycType(String generalKycType) {
this.generalKycType = generalKycType;
}
public String getGeneralLimit() {
return generalLimit;
}
public void setGeneralLimit(String generalLimit) {
this.generalLimit = generalLimit;
}
public String getMinorKycType() {
return minorKycType;
}
public void setMinorKycType(String minorKycType) {
this.minorKycType = minorKycType;
}
public Long getMinorLimit() {
return minorLimit;
}
public void setMinorLimit(Long minorLimit) {
this.minorLimit = minorLimit;
}
public String getSmallSavingKycType() {
return smallSavingKycType;
}
public void setSmallSavingKycType(String smallSavingKycType) {
this.smallSavingKycType = smallSavingKycType;
}
public Long getSmallSavingLimit() {
return smallSavingLimit;
}
public void setSmallSavingLimit(Long smallSavingLimit) {
this.smallSavingLimit = smallSavingLimit;
}
public LocalDateTime getCreatedDate() {
return createdDate;
}
public void updateFrom(SavingsProductDepositLimitKyc other) {
this.generalKycType = other.getGeneralKycType();
this.generalLimit = other.getGeneralLimit();
this.minorKycType = other.getMinorKycType();
this.minorLimit = other.getMinorLimit();
this.smallSavingKycType = other.getSmallSavingKycType();
this.smallSavingLimit = other.getSmallSavingLimit();
}
}
@@ -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.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface SavingsProductDepositLimitKycRepository extends JpaRepository<SavingsProductDepositLimitKyc, Long> {
SavingsProductDepositLimitKyc findBySavingsProductId(Long savingsProductId);
}
@@ -0,0 +1,257 @@
/**
* 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.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
@Entity
@Table(name = "m_savings_product_facility_config")
public class SavingsProductFacilityConfig extends AbstractPersistableCustom<Long> {
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "savings_product_id", nullable = false)
private SavingsProduct savingsProduct;
@Column(name = "atm_facility")
private Boolean atmFacility = false;
@Column(name = "atm_withdrawal_facility")
private Boolean atmWithdrawalFacility = false;
@Column(name = "upi_facility")
private Boolean upiFacility = false;
@Column(name = "pos_transactions_facility")
private Boolean posTransactionsFacility = false;
@Column(name = "cheque_book")
private Boolean chequeBook = false;
@Column(name = "imps_facility")
private Boolean impsFacility = false;
@Column(name = "sms_alerts")
private Boolean smsAlerts = false;
@Column(name = "bbps_facility")
private Boolean bbpsFacility = false;
@Column(name = "insurance_cover")
private Boolean insuranceCover = false;
@Column(name = "bepg_facility")
private Boolean bepgFacility = false;
@Column(name = "neft_facility")
private Boolean neftFacility = false;
@Column(name = "rtgs_facility")
private Boolean rtgsFacility = false;
@Column(name = "inter_bank_total_cap_facility")
private Boolean interBankTotalCapFacility = false;
@Column(name = "withdrawal_facility")
private Boolean withdrawalFacility = false;
@Column(name = "deposit_facility_kyc")
private Boolean depositFacilityKyc = false;
@Column(name = "virtual_debit_card")
private Boolean virtualDebitCard = false;
@Column(name = "created_date", nullable = false)
private LocalDateTime createdDate;
protected SavingsProductFacilityConfig() {
this.createdDate = LocalDateTime.now();
}
public SavingsProductFacilityConfig(SavingsProduct savingsProduct) {
this();
this.savingsProduct = savingsProduct;
}
// Getters and setters
public SavingsProduct getSavingsProduct() {
return savingsProduct;
}
public void setSavingsProduct(SavingsProduct savingsProduct) {
this.savingsProduct = savingsProduct;
}
public Boolean getAtmFacility() {
return atmFacility;
}
public void setAtmFacility(Boolean atmFacility) {
this.atmFacility = atmFacility != null ? atmFacility : false;
}
public Boolean getAtmWithdrawalFacility() {
return atmWithdrawalFacility;
}
public void setAtmWithdrawalFacility(Boolean atmWithdrawalFacility) {
this.atmWithdrawalFacility = atmWithdrawalFacility != null ? atmWithdrawalFacility : false;
}
public Boolean getUpiFacility() {
return upiFacility;
}
public void setUpiFacility(Boolean upiFacility) {
this.upiFacility = upiFacility != null ? upiFacility : false;
}
public Boolean getPosTransactionsFacility() {
return posTransactionsFacility;
}
public void setPosTransactionsFacility(Boolean posTransactionsFacility) {
this.posTransactionsFacility = posTransactionsFacility != null ? posTransactionsFacility : false;
}
public Boolean getChequeBook() {
return chequeBook;
}
public void setChequeBook(Boolean chequeBook) {
this.chequeBook = chequeBook != null ? chequeBook : false;
}
public Boolean getImpsFacility() {
return impsFacility;
}
public void setImpsFacility(Boolean impsFacility) {
this.impsFacility = impsFacility != null ? impsFacility : false;
}
public Boolean getSmsAlerts() {
return smsAlerts;
}
public void setSmsAlerts(Boolean smsAlerts) {
this.smsAlerts = smsAlerts != null ? smsAlerts : false;
}
public Boolean getBbpsFacility() {
return bbpsFacility;
}
public void setBbpsFacility(Boolean bbpsFacility) {
this.bbpsFacility = bbpsFacility != null ? bbpsFacility : false;
}
public Boolean getInsuranceCover() {
return insuranceCover;
}
public void setInsuranceCover(Boolean insuranceCover) {
this.insuranceCover = insuranceCover != null ? insuranceCover : false;
}
public Boolean getBepgFacility() {
return bepgFacility;
}
public void setBepgFacility(Boolean bepgFacility) {
this.bepgFacility = bepgFacility != null ? bepgFacility : false;
}
public Boolean getNeftFacility() {
return neftFacility;
}
public void setNeftFacility(Boolean neftFacility) {
this.neftFacility = neftFacility != null ? neftFacility : false;
}
public Boolean getRtgsFacility() {
return rtgsFacility;
}
public void setRtgsFacility(Boolean rtgsFacility) {
this.rtgsFacility = rtgsFacility != null ? rtgsFacility : false;
}
public Boolean getInterBankTotalCapFacility() {
return interBankTotalCapFacility;
}
public void setInterBankTotalCapFacility(Boolean interBankTotalCapFacility) {
this.interBankTotalCapFacility = interBankTotalCapFacility != null ? interBankTotalCapFacility : false;
}
public Boolean getWithdrawalFacility() {
return withdrawalFacility;
}
public void setWithdrawalFacility(Boolean withdrawalFacility) {
this.withdrawalFacility = withdrawalFacility != null ? withdrawalFacility : false;
}
public Boolean getDepositFacilityKyc() {
return depositFacilityKyc;
}
public void setDepositFacilityKyc(Boolean depositFacilityKyc) {
this.depositFacilityKyc = depositFacilityKyc != null ? depositFacilityKyc : false;
}
public Boolean getVirtualDebitCard() {
return virtualDebitCard;
}
public void setVirtualDebitCard(Boolean virtualDebitCard) {
this.virtualDebitCard = virtualDebitCard != null ? virtualDebitCard : false;
}
public LocalDateTime getCreatedDate() {
return createdDate;
}
public void updateFrom(SavingsProductFacilityConfig other) {
this.atmFacility = other.getAtmFacility();
this.atmWithdrawalFacility = other.getAtmWithdrawalFacility();
this.upiFacility = other.getUpiFacility();
this.posTransactionsFacility = other.getPosTransactionsFacility();
this.chequeBook = other.getChequeBook();
this.impsFacility = other.getImpsFacility();
this.smsAlerts = other.getSmsAlerts();
this.bbpsFacility = other.getBbpsFacility();
this.insuranceCover = other.getInsuranceCover();
this.bepgFacility = other.getBepgFacility();
this.neftFacility = other.getNeftFacility();
this.rtgsFacility = other.getRtgsFacility();
this.interBankTotalCapFacility = other.getInterBankTotalCapFacility();
this.withdrawalFacility = other.getWithdrawalFacility();
this.depositFacilityKyc = other.getDepositFacilityKyc();
this.virtualDebitCard = other.getVirtualDebitCard();
}
}
@@ -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.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface SavingsProductFacilityConfigRepository extends JpaRepository<SavingsProductFacilityConfig, Long> {
SavingsProductFacilityConfig findBySavingsProductId(Long savingsProductId);
}
@@ -0,0 +1,117 @@
/**
* 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.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
@Entity
@Table(name = "m_savings_product_facility_limits")
public class SavingsProductFacilityLimit extends AbstractPersistableCustom<Long> {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "savings_product_id", nullable = false)
private SavingsProduct savingsProduct;
@Column(name = "limit_type", length = 100, nullable = false)
private String limitType;
@Column(name = "general_limit", length = 50)
private String generalLimit; // Can be "UNLIMITED", "N/A", or numeric value
@Column(name = "minor_account_limit", length = 50)
private String minorAccountLimit;
@Column(name = "small_saving_limit", length = 50)
private String smallSavingLimit;
@Column(name = "created_date", nullable = false)
private LocalDateTime createdDate;
protected SavingsProductFacilityLimit() {
this.createdDate = LocalDateTime.now();
}
public SavingsProductFacilityLimit(SavingsProduct savingsProduct, String limitType,
String generalLimit, String minorAccountLimit, String smallSavingLimit) {
this();
this.savingsProduct = savingsProduct;
this.limitType = limitType;
this.generalLimit = generalLimit;
this.minorAccountLimit = minorAccountLimit;
this.smallSavingLimit = smallSavingLimit;
}
public static SavingsProductFacilityLimit create(SavingsProduct savingsProduct, String limitType,
String generalLimit, String minorAccountLimit, String smallSavingLimit) {
return new SavingsProductFacilityLimit(savingsProduct, limitType, generalLimit,
minorAccountLimit, smallSavingLimit);
}
// Getters and setters
public SavingsProduct getSavingsProduct() {
return savingsProduct;
}
public void setSavingsProduct(SavingsProduct savingsProduct) {
this.savingsProduct = savingsProduct;
}
public String getLimitType() {
return limitType;
}
public void setLimitType(String limitType) {
this.limitType = limitType;
}
public String getGeneralLimit() {
return generalLimit;
}
public void setGeneralLimit(String generalLimit) {
this.generalLimit = generalLimit;
}
public String getMinorAccountLimit() {
return minorAccountLimit;
}
public void setMinorAccountLimit(String minorAccountLimit) {
this.minorAccountLimit = minorAccountLimit;
}
public String getSmallSavingLimit() {
return smallSavingLimit;
}
public void setSmallSavingLimit(String smallSavingLimit) {
this.smallSavingLimit = smallSavingLimit;
}
public LocalDateTime getCreatedDate() {
return createdDate;
}
}
@@ -0,0 +1,31 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.savings.domain;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface SavingsProductFacilityLimitRepository extends JpaRepository<SavingsProductFacilityLimit, Long> {
List<SavingsProductFacilityLimit> findBySavingsProductId(Long savingsProductId);
void deleteBySavingsProductId(Long savingsProductId);
}
@@ -27,4 +27,8 @@
<include file="parts/2002_add_savings_accrual_permission.xml" relativeToChangelogFile="true" />
<include file="parts/2003_add_accrued_till_date_to_savings_account.xml" relativeToChangelogFile="true" />
<include file="parts/2004_add_savings_account_cob_infrastructure.xml" relativeToChangelogFile="true" />
<include file="parts/2005_add_savings_product_classification_code_values.xml" relativeToChangelogFile="true" />
<include file="parts/2006_add_period_frequency_options.xml" relativeToChangelogFile="true" />
<include file="parts/2007_add_interest_calculation_type_option.xml" relativeToChangelogFile="true" />
<include file="parts/2008_add_other_gl_mappings_to_savings_product.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
<changeSet author="fineract" id="2005-1-savings-product-account-type-code">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">select count(*) from m_code where code_name = 'SavingsProductAccountType'</sqlCheck>
</preConditions>
<insert tableName="m_code">
<column name="code_name" value="SavingsProductAccountType"/>
<column name="is_system_defined" valueBoolean="true"/>
</insert>
</changeSet>
<changeSet author="fineract" id="2005-2-savings-product-customer-segment-code">
<preConditions onFail="MARK_RAN">
<sqlCheck expectedResult="0">select count(*) from m_code where code_name = 'SavingsProductCustomerSegment'</sqlCheck>
</preConditions>
<insert tableName="m_code">
<column name="code_name" value="SavingsProductCustomerSegment"/>
<column name="is_system_defined" valueBoolean="true"/>
</insert>
</changeSet>
<changeSet author="fineract" id="2005-3-savings-product-account-type-values">
<sql>
INSERT INTO m_code (code_name, is_system_defined)
SELECT 'SavingsProductAccountType', TRUE
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'SavingsProductAccountType');
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Savings Account Minor', 1, 'Savings Account Minor', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductAccountType'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Savings Account Minor'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Small Saving Account', 2, 'Small Saving Account', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductAccountType'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Small Saving Account'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Savings HUF', 3, 'Savings HUF', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductAccountType'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Savings HUF'
);
</sql>
</changeSet>
<changeSet author="fineract" id="2005-4-savings-product-customer-segment-values">
<sql>
INSERT INTO m_code (code_name, is_system_defined)
SELECT 'SavingsProductCustomerSegment', TRUE
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'SavingsProductCustomerSegment');
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Individual', 1, 'Individual', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductCustomerSegment'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Individual'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Corporate', 2, 'Corporate', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductCustomerSegment'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Corporate'
);
</sql>
</changeSet>
<changeSet author="fineract" id="2005-5-savings-product-classification-seed-upsert">
<comment>
Recover older databases where the original changesets may have been marked ran before the data was inserted.
This keeps the seed idempotent for both fresh and existing tenants.
</comment>
<sql>
INSERT INTO m_code (code_name, is_system_defined)
SELECT 'SavingsProductAccountType', TRUE
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'SavingsProductAccountType');
INSERT INTO m_code (code_name, is_system_defined)
SELECT 'SavingsProductCustomerSegment', TRUE
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'SavingsProductCustomerSegment');
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Savings Account Minor', 1, 'Savings Account Minor', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductAccountType'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Savings Account Minor'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Small Saving Account', 2, 'Small Saving Account', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductAccountType'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Small Saving Account'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Savings HUF', 3, 'Savings HUF', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductAccountType'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Savings HUF'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Individual', 1, 'Individual', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductCustomerSegment'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Individual'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Corporate', 2, 'Corporate', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'SavingsProductCustomerSegment'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Corporate'
);
</sql>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
<changeSet author="fineract" id="2006-period-frequency-code">
<sql>
INSERT INTO m_code (code_name, is_system_defined)
SELECT 'PeriodFrequency', TRUE
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'PeriodFrequency');
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Monthly', 1, 'Monthly', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'PeriodFrequency'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Monthly'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Quarterly', 2, 'Quarterly', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'PeriodFrequency'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Quarterly'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Half Yearly', 3, 'Half Yearly', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'PeriodFrequency'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Half Yearly'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Yearly', 4, 'Yearly', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'PeriodFrequency'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Yearly'
);
</sql>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
<changeSet author="fineract" id="2007-interest-calculation-type-option">
<sql>
INSERT INTO m_code (code_name, is_system_defined)
SELECT 'InterestCalculationTypeOption', TRUE
WHERE NOT EXISTS (SELECT 1 FROM m_code WHERE code_name = 'InterestCalculationTypeOption');
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Compounding', 1, 'Compounding', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'InterestCalculationTypeOption'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Compounding'
);
INSERT INTO m_code_value (code_id, code_value, order_position, code_description, is_active, is_mandatory)
SELECT c.id, 'Accrual', 2, 'Accrual', TRUE, FALSE
FROM m_code c
WHERE c.code_name = 'InterestCalculationTypeOption'
AND NOT EXISTS (
SELECT 1 FROM m_code_value cv
WHERE cv.code_id = c.id AND cv.code_value = 'Accrual'
);
</sql>
</changeSet>
</databaseChangeLog>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. This file is licensed under the Apache License, Version 2.0.
-->
<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.3.xsd">
<changeSet author="fineract" id="2008-add-other-gl-mappings-to-savings-product">
<addColumn tableName="m_savings_product">
<column name="other_gl_mappings" type="LONGTEXT"/>
</addColumn>
</changeSet>
</databaseChangeLog>
@@ -109,6 +109,9 @@
<class>org.apache.fineract.portfolio.savings.domain.SavingsAccountTransactionTaxDetails</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsOfficerAssignmentHistory</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsProduct</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsProductDepositLimitKyc</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsProductFacilityConfig</class>
<class>org.apache.fineract.portfolio.savings.domain.SavingsProductFacilityLimit</class>
<!-- Charge Module Entities -->
<class>org.apache.fineract.portfolio.charge.domain.Charge</class>