feat: senior citizen interest rate fix for FD/RD accounts + CBS table renames
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
- Apply senior citizen rate override in FixedDepositAccount and RecurringDepositAccount getEffectiveInterestRateAsFraction() so maturity is calculated at correct rate (e.g. 7.5%) instead of chart slab rate on every event: submit, activate, posting, pre-closure, maturity - Override getEffectiveInterestRateAsFractionAccrual() in both FD/RD to keep accrual consistent with maturity calculation — independent of DB nominalAnnualInterestRate value - Add isSeniorCitizen and seniorCitizenInterestRate fields to SavingsAccount entity with JPA mapping and accessor methods; updateNominalAnnualInterestRate() helper added - Extend DepositsApiConstants whitelist and SavingsAccountAssembler.applyCbsFields() to read and persist senior citizen fields from API request as final override step - Add DepositAccountAssembler early-stage rate override for senior citizen accounts - Liquibase migration 2015: add is_senior_citizen and senior_citizen_interest_rate columns to m_savings_account table - Liquibase migration 0300: rename fd_base_interest_rate tables to CBS naming convention - Update CBS copyright header in FdBaseInterestRateEffective and FdBaseInterestRateSlabHistory Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
9f627bde61
commit
ea2dfd789d
+6
@@ -120,6 +120,8 @@ public final class DepositsApiConstants {
|
|||||||
public static final String principalAmountParamName = "principalAmount";
|
public static final String principalAmountParamName = "principalAmount";
|
||||||
public static final String annualInterestRateParamName = "annualInterestRate";
|
public static final String annualInterestRateParamName = "annualInterestRate";
|
||||||
public static final String interestPostingPeriodInMonthsParamName = "interestPostingPeriodInMonths";
|
public static final String interestPostingPeriodInMonthsParamName = "interestPostingPeriodInMonths";
|
||||||
|
public static final String isSeniorCitizenParamName = "isSeniorCitizen";
|
||||||
|
public static final String seniorCitizenInterestRateParamName = "seniorCitizenInterestRate";
|
||||||
public static final String tenureInMonthsParamName = "tenureInMonths";
|
public static final String tenureInMonthsParamName = "tenureInMonths";
|
||||||
public static final String interestCompoundingPeriodInMonthsParamName = "interestCompoundingPeriodInMonths";
|
public static final String interestCompoundingPeriodInMonthsParamName = "interestCompoundingPeriodInMonths";
|
||||||
|
|
||||||
@@ -544,6 +546,8 @@ public final class DepositsApiConstants {
|
|||||||
fixedDepositRequestData.add(SavingsApiConstants.jointHoldersParamName);
|
fixedDepositRequestData.add(SavingsApiConstants.jointHoldersParamName);
|
||||||
fixedDepositRequestData.add(SavingsApiConstants.autoDebitFacilityParamName);
|
fixedDepositRequestData.add(SavingsApiConstants.autoDebitFacilityParamName);
|
||||||
fixedDepositRequestData.add(SavingsApiConstants.nominationFacilityParamName);
|
fixedDepositRequestData.add(SavingsApiConstants.nominationFacilityParamName);
|
||||||
|
fixedDepositRequestData.add(isSeniorCitizenParamName);
|
||||||
|
fixedDepositRequestData.add(seniorCitizenInterestRateParamName);
|
||||||
return fixedDepositRequestData;
|
return fixedDepositRequestData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,6 +616,8 @@ public final class DepositsApiConstants {
|
|||||||
recurringDepositRequestData.add(SavingsApiConstants.balanceSwapOptionParamName);
|
recurringDepositRequestData.add(SavingsApiConstants.balanceSwapOptionParamName);
|
||||||
recurringDepositRequestData.add(SavingsApiConstants.msmeParamName);
|
recurringDepositRequestData.add(SavingsApiConstants.msmeParamName);
|
||||||
recurringDepositRequestData.add(SavingsApiConstants.autoDebitFacilityParamName);
|
recurringDepositRequestData.add(SavingsApiConstants.autoDebitFacilityParamName);
|
||||||
|
recurringDepositRequestData.add(isSeniorCitizenParamName);
|
||||||
|
recurringDepositRequestData.add(seniorCitizenInterestRateParamName);
|
||||||
return recurringDepositRequestData;
|
return recurringDepositRequestData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
@@ -31,6 +31,8 @@ import static org.apache.fineract.portfolio.savings.DepositsApiConstants.deposit
|
|||||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.expectedFirstDepositOnDateParamName;
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.expectedFirstDepositOnDateParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.isCalendarInheritedParamName;
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.isCalendarInheritedParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.isMandatoryDepositParamName;
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.isMandatoryDepositParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.isSeniorCitizenParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.seniorCitizenInterestRateParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.mandatoryRecommendedDepositAmountParamName;
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.mandatoryRecommendedDepositAmountParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.maturityInstructionIdParamName;
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.maturityInstructionIdParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.transferInterestToSavingsParamName;
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.transferInterestToSavingsParamName;
|
||||||
@@ -230,6 +232,16 @@ public class DepositAccountAssembler {
|
|||||||
interestRate = product.nominalAnnualInterestRate();
|
interestRate = product.nominalAnnualInterestRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Senior citizen interest rate override: use the higher rate when applicable
|
||||||
|
if (command.parameterExists(isSeniorCitizenParamName) && command.booleanPrimitiveValueOfParameterNamed(isSeniorCitizenParamName)) {
|
||||||
|
if (command.parameterExists(seniorCitizenInterestRateParamName)) {
|
||||||
|
final BigDecimal scRate = command.bigDecimalValueOfParameterNamed(seniorCitizenInterestRateParamName);
|
||||||
|
if (scRate != null && scRate.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
interestRate = scRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SavingsCompoundingInterestPeriodType interestCompoundingPeriodType = null;
|
SavingsCompoundingInterestPeriodType interestCompoundingPeriodType = null;
|
||||||
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
|
final Integer interestPeriodTypeValue = command.integerValueOfParameterNamed(interestCompoundingPeriodTypeParamName);
|
||||||
if (interestPeriodTypeValue != null) {
|
if (interestPeriodTypeValue != null) {
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ import lombok.Getter;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "m_fd_base_interest_rate_effective")
|
@Table(name = "m_cbs_base_interest_rate_effective")
|
||||||
@Getter
|
@Getter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class FdBaseInterestRateEffective {
|
public class FdBaseInterestRateEffective {
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ import lombok.Getter;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "m_fd_base_interest_rate_slab_history")
|
@Table(name = "m_cbs_base_interest_rate_slab_history")
|
||||||
@Getter
|
@Getter
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class FdBaseInterestRateSlabHistory {
|
public class FdBaseInterestRateSlabHistory {
|
||||||
|
|||||||
+16
@@ -182,6 +182,12 @@ public class FixedDepositAccount extends SavingsAccount {
|
|||||||
final BigDecimal depositAmount = accountTermAndPreClosure.depositAmount();
|
final BigDecimal depositAmount = accountTermAndPreClosure.depositAmount();
|
||||||
applicableInterestRate = this.chart.getApplicableInterestRate(depositAmount, depositStartDate(), depositCloseDate, this.client);
|
applicableInterestRate = this.chart.getApplicableInterestRate(depositAmount, depositStartDate(), depositCloseDate, this.client);
|
||||||
|
|
||||||
|
// CBS: override with senior citizen rate if applicable
|
||||||
|
if (isSeniorCitizen() && getSeniorCitizenInterestRate() != null
|
||||||
|
&& getSeniorCitizenInterestRate().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
applicableInterestRate = getSeniorCitizenInterestRate();
|
||||||
|
}
|
||||||
|
|
||||||
if (applyPreMaturePenalty) {
|
if (applyPreMaturePenalty) {
|
||||||
applicableInterestRate = applicableInterestRate.subtract(penalInterest);
|
applicableInterestRate = applicableInterestRate.subtract(penalInterest);
|
||||||
applicableInterestRate = applicableInterestRate.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : applicableInterestRate;
|
applicableInterestRate = applicableInterestRate.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : applicableInterestRate;
|
||||||
@@ -192,6 +198,16 @@ public class FixedDepositAccount extends SavingsAccount {
|
|||||||
return applicableInterestRate.divide(BigDecimal.valueOf(100L), mc);
|
return applicableInterestRate.divide(BigDecimal.valueOf(100L), mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getEffectiveInterestRateAsFractionAccrual(final MathContext mc, final LocalDate upToInterestCalculationDate) {
|
||||||
|
// CBS: accrual must also use senior citizen rate to stay consistent with maturity calculation
|
||||||
|
if (isSeniorCitizen() && getSeniorCitizenInterestRate() != null
|
||||||
|
&& getSeniorCitizenInterestRate().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
return getSeniorCitizenInterestRate().divide(BigDecimal.valueOf(100L), mc);
|
||||||
|
}
|
||||||
|
return super.getEffectiveInterestRateAsFractionAccrual(mc, upToInterestCalculationDate);
|
||||||
|
}
|
||||||
|
|
||||||
public void updateMaturityDateAndAmountBeforeAccountActivation(final MathContext mc, final boolean isPreMatureClosure,
|
public void updateMaturityDateAndAmountBeforeAccountActivation(final MathContext mc, final boolean isPreMatureClosure,
|
||||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
|
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
|
||||||
List<SavingsAccountTransaction> allTransactions = new ArrayList<>();
|
List<SavingsAccountTransaction> allTransactions = new ArrayList<>();
|
||||||
|
|||||||
+16
@@ -234,6 +234,12 @@ public class RecurringDepositAccount extends SavingsAccount {
|
|||||||
if (this.chart != null) {
|
if (this.chart != null) {
|
||||||
applicableInterestRate = this.chart.getApplicableInterestRate(depositAmount, depositStartDate(), depositCloseDate, this.client);
|
applicableInterestRate = this.chart.getApplicableInterestRate(depositAmount, depositStartDate(), depositCloseDate, this.client);
|
||||||
|
|
||||||
|
// CBS: override with senior citizen rate if applicable
|
||||||
|
if (isSeniorCitizen() && getSeniorCitizenInterestRate() != null
|
||||||
|
&& getSeniorCitizenInterestRate().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
applicableInterestRate = getSeniorCitizenInterestRate();
|
||||||
|
}
|
||||||
|
|
||||||
if (applyPreMaturePenalty) {
|
if (applyPreMaturePenalty) {
|
||||||
applicableInterestRate = applicableInterestRate.subtract(penalInterest);
|
applicableInterestRate = applicableInterestRate.subtract(penalInterest);
|
||||||
applicableInterestRate = applicableInterestRate.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : applicableInterestRate;
|
applicableInterestRate = applicableInterestRate.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : applicableInterestRate;
|
||||||
@@ -245,6 +251,16 @@ public class RecurringDepositAccount extends SavingsAccount {
|
|||||||
return applicableInterestRate.divide(BigDecimal.valueOf(100L), mc);
|
return applicableInterestRate.divide(BigDecimal.valueOf(100L), mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getEffectiveInterestRateAsFractionAccrual(final MathContext mc, final LocalDate upToInterestCalculationDate) {
|
||||||
|
// CBS: accrual must also use senior citizen rate to stay consistent with maturity calculation
|
||||||
|
if (isSeniorCitizen() && getSeniorCitizenInterestRate() != null
|
||||||
|
&& getSeniorCitizenInterestRate().compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
return getSeniorCitizenInterestRate().divide(BigDecimal.valueOf(100L), mc);
|
||||||
|
}
|
||||||
|
return super.getEffectiveInterestRateAsFractionAccrual(mc, upToInterestCalculationDate);
|
||||||
|
}
|
||||||
|
|
||||||
public void updateMaturityDateAndAmount(final MathContext mc, final boolean isPreMatureClosure,
|
public void updateMaturityDateAndAmount(final MathContext mc, final boolean isPreMatureClosure,
|
||||||
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
|
final boolean isSavingsInterestPostingAtCurrentPeriodEnd, final Integer financialYearBeginningMonth) {
|
||||||
final LocalDate maturityDate = calculateMaturityDate();
|
final LocalDate maturityDate = calculateMaturityDate();
|
||||||
|
|||||||
+18
@@ -42,6 +42,8 @@ import static org.apache.fineract.portfolio.savings.SavingsApiConstants.specialC
|
|||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.weakerSectionParamName;
|
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.nominationFacilityParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoDebitFacilityParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.autoDebitFacilityParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.isSeniorCitizenParamName;
|
||||||
|
import static org.apache.fineract.portfolio.savings.DepositsApiConstants.seniorCitizenInterestRateParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.allowOverdraftParamName;
|
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.clientIdParamName;
|
||||||
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enforceMinRequiredBalanceParamName;
|
import static org.apache.fineract.portfolio.savings.SavingsApiConstants.enforceMinRequiredBalanceParamName;
|
||||||
@@ -394,6 +396,22 @@ public class SavingsAccountAssembler {
|
|||||||
account.setAutoDebitFacility(this.fromApiJsonHelper.extractBooleanNamed(autoDebitFacilityParamName, element));
|
account.setAutoDebitFacility(this.fromApiJsonHelper.extractBooleanNamed(autoDebitFacilityParamName, element));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Senior citizen rate — runs after validateDomainRules so it is the final persisted value
|
||||||
|
if (command.parameterExists(isSeniorCitizenParamName)) {
|
||||||
|
final Boolean scFlag = this.fromApiJsonHelper.extractBooleanNamed(isSeniorCitizenParamName, element);
|
||||||
|
if (scFlag != null) {
|
||||||
|
account.setSeniorCitizen(scFlag);
|
||||||
|
if (Boolean.TRUE.equals(scFlag) && command.parameterExists(seniorCitizenInterestRateParamName)) {
|
||||||
|
final BigDecimal scRate = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
|
||||||
|
seniorCitizenInterestRateParamName, element);
|
||||||
|
if (scRate != null && scRate.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
account.setSeniorCitizenInterestRate(scRate);
|
||||||
|
account.updateNominalAnnualInterestRate(scRate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
account.setGuardianName(this.fromApiJsonHelper.extractStringNamed(guardianNameParamName, element));
|
account.setGuardianName(this.fromApiJsonHelper.extractStringNamed(guardianNameParamName, element));
|
||||||
account.setGuardianCifNumber(this.fromApiJsonHelper.extractStringNamed(guardianCifNumberParamName, element));
|
account.setGuardianCifNumber(this.fromApiJsonHelper.extractStringNamed(guardianCifNumberParamName, element));
|
||||||
account.setGuardianRelationship(this.fromApiJsonHelper.extractStringNamed(guardianRelationshipParamName, element));
|
account.setGuardianRelationship(this.fromApiJsonHelper.extractStringNamed(guardianRelationshipParamName, element));
|
||||||
|
|||||||
@@ -316,4 +316,5 @@
|
|||||||
<include file="parts/0297_fix_unique_nominee_per_account.xml" relativeToChangelogFile="true"/>
|
<include file="parts/0297_fix_unique_nominee_per_account.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="parts/0298_unique_external_id_on_current_account.xml" relativeToChangelogFile="true"/>
|
<include file="parts/0298_unique_external_id_on_current_account.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="parts/0299_seed_indian_states.xml" relativeToChangelogFile="true"/>
|
<include file="parts/0299_seed_indian_states.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="parts/0300_rename_fd_base_interest_rate_tables_to_cbs.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
-->
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||||
|
|
||||||
|
<changeSet id="0300-1" author="cbs">
|
||||||
|
<preConditions onFail="MARK_RAN">
|
||||||
|
<tableExists tableName="m_fd_base_interest_rate_effective"/>
|
||||||
|
</preConditions>
|
||||||
|
<renameTable oldTableName="m_fd_base_interest_rate_effective"
|
||||||
|
newTableName="m_cbs_base_interest_rate_effective"/>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet id="0300-2" author="cbs">
|
||||||
|
<preConditions onFail="MARK_RAN">
|
||||||
|
<tableExists tableName="m_fd_base_interest_rate_slab_history"/>
|
||||||
|
</preConditions>
|
||||||
|
<renameTable oldTableName="m_fd_base_interest_rate_slab_history"
|
||||||
|
newTableName="m_cbs_base_interest_rate_slab_history"/>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
||||||
+18
@@ -3969,6 +3969,12 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
|
|||||||
@Column(name = "auto_debit_facility", nullable = false, columnDefinition = "boolean default false")
|
@Column(name = "auto_debit_facility", nullable = false, columnDefinition = "boolean default false")
|
||||||
private Boolean autoDebitFacility = false;
|
private Boolean autoDebitFacility = false;
|
||||||
|
|
||||||
|
@Column(name = "is_senior_citizen", nullable = false, columnDefinition = "boolean default false")
|
||||||
|
private boolean isSeniorCitizen = false;
|
||||||
|
|
||||||
|
@Column(name = "senior_citizen_interest_rate", scale = 6, precision = 19, nullable = true)
|
||||||
|
private BigDecimal seniorCitizenInterestRate;
|
||||||
|
|
||||||
|
|
||||||
@jakarta.persistence.OneToOne(cascade = jakarta.persistence.CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true, fetch = FetchType.LAZY)
|
@jakarta.persistence.OneToOne(cascade = jakarta.persistence.CascadeType.ALL, mappedBy = "savingsAccount", orphanRemoval = true, fetch = FetchType.LAZY)
|
||||||
private SavingsAccountFacilityConfig facilityConfig;
|
private SavingsAccountFacilityConfig facilityConfig;
|
||||||
@@ -4041,4 +4047,16 @@ public class SavingsAccount extends AbstractAuditableWithUTCDateTimeCustom<Long>
|
|||||||
|
|
||||||
public Boolean getAutoDebitFacility() { return autoDebitFacility; }
|
public Boolean getAutoDebitFacility() { return autoDebitFacility; }
|
||||||
public void setAutoDebitFacility(Boolean v) { this.autoDebitFacility = v; }
|
public void setAutoDebitFacility(Boolean v) { this.autoDebitFacility = v; }
|
||||||
|
|
||||||
|
public boolean isSeniorCitizen() { return isSeniorCitizen; }
|
||||||
|
public void setSeniorCitizen(boolean v) { this.isSeniorCitizen = v; }
|
||||||
|
|
||||||
|
public BigDecimal getSeniorCitizenInterestRate() { return seniorCitizenInterestRate; }
|
||||||
|
public void setSeniorCitizenInterestRate(BigDecimal v) { this.seniorCitizenInterestRate = v; }
|
||||||
|
|
||||||
|
public void updateNominalAnnualInterestRate(BigDecimal rate) {
|
||||||
|
if (rate != null && rate.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
|
this.nominalAnnualInterestRate = rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -37,4 +37,5 @@
|
|||||||
<include file="parts/2012_add_current_account_permissions.xml" relativeToChangelogFile="true" />
|
<include file="parts/2012_add_current_account_permissions.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/2013_add_missing_current_account_columns.xml" relativeToChangelogFile="true" />
|
<include file="parts/2013_add_missing_current_account_columns.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/2014_add_is_mandatory_to_joint_holders.xml" relativeToChangelogFile="true" />
|
<include file="parts/2014_add_is_mandatory_to_joint_holders.xml" relativeToChangelogFile="true" />
|
||||||
|
<include file="parts/2015_add_senior_citizen_to_savings_account.xml" relativeToChangelogFile="true" />
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
<?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.
|
||||||
|
-->
|
||||||
|
<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="2015_add_senior_citizen_to_savings_account" author="CBS">
|
||||||
|
<preConditions onFail="MARK_RAN">
|
||||||
|
<tableExists tableName="m_savings_account"/>
|
||||||
|
<not><columnExists tableName="m_savings_account" columnName="is_senior_citizen"/></not>
|
||||||
|
</preConditions>
|
||||||
|
<addColumn tableName="m_savings_account">
|
||||||
|
<column name="is_senior_citizen" type="BOOLEAN" defaultValueBoolean="false">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="senior_citizen_interest_rate" type="DECIMAL(19,6)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
||||||
Reference in New Issue
Block a user