diff --git a/mifosng-db/migrations/core_db/V182__added_min_required_balance_to_savings_product.sql b/mifosng-db/migrations/core_db/V182__added_min_required_balance_to_savings_product.sql new file mode 100644 index 000000000..c5be4a734 --- /dev/null +++ b/mifosng-db/migrations/core_db/V182__added_min_required_balance_to_savings_product.sql @@ -0,0 +1,7 @@ +ALTER TABLE `m_savings_product` + ADD COLUMN `min_required_balance` DECIMAL(19,6) NULL AFTER `overdraft_limit`, + ADD COLUMN `allow_overdraft_min_balance` TINYINT(1) NOT NULL DEFAULT '0' AFTER `min_required_balance`; + +ALTER TABLE `m_savings_account` + ADD COLUMN `min_required_balance` DECIMAL(19,6) NULL AFTER `account_balance_derived`, + ADD COLUMN `allow_overdraft_min_balance` TINYINT(1) NOT NULL DEFAULT '0' AFTER `min_required_balance`; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java index 6158b683a..d040d2ffc 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java @@ -95,6 +95,8 @@ public class SavingsApiConstants { public static final String bankNumberParamName = "bankNumber"; public static final String allowOverdraftParamName = "allowOverdraft"; public static final String overdraftLimitParamName = "overdraftLimit"; + public static final String minRequiredBalanceParamName = "minRequiredBalance"; + public static final String allowOverdraftMinBalanceParamName = "allowOverdraftMinBalance"; // transaction parameters public static final String transactionDateParamName = "transactionDate"; @@ -149,7 +151,8 @@ public class SavingsApiConstants { SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PENALTY_INCOME_ACCOUNT_MAPPING.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.OVERDRAFT_PORTFOLIO_CONTROL.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.LOSSES_WRITTEN_OFF.getValue(), - SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), allowOverdraftParamName, overdraftLimitParamName)); + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_INTEREST.getValue(), allowOverdraftParamName, overdraftLimitParamName, + minRequiredBalanceParamName, allowOverdraftMinBalanceParamName)); /** * These parameters will match the class level parameters of @@ -173,7 +176,7 @@ public class SavingsApiConstants { lockinPeriodFrequencyTypeParamName, // withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, withdrawalFeeForTransfersParamName, feeAmountParamName, feeOnMonthDayParamName, chargesParamName, allowOverdraftParamName, - overdraftLimitParamName)); + overdraftLimitParamName, minRequiredBalanceParamName, allowOverdraftMinBalanceParamName)); /** * These parameters will match the class level parameters of diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java index 85afca2b2..564bee17a 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountData.java @@ -47,6 +47,8 @@ public class SavingsAccountData { private final boolean withdrawalFeeForTransfers; private final boolean allowOverdraft; private final BigDecimal overdraftLimit; + private final BigDecimal minRequiredBalance; + private final boolean allowOverdraftMinBalance; // associations private final SavingsAccountSummaryData summary; @@ -79,7 +81,8 @@ public class SavingsAccountData { final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, - final SavingsAccountSummaryData summary, final boolean allowOverdraft, final BigDecimal overdraftLimit) { + final SavingsAccountSummaryData summary, final boolean allowOverdraft, final BigDecimal overdraftLimit, + final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance) { final Collection productOptions = null; final Collection fieldOfficerOptions = null; @@ -100,7 +103,8 @@ public class SavingsAccountData { lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, - withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit); + withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance, + allowOverdraftMinBalance); } public static SavingsAccountData lookup(final Long accountId, final String accountNo, final EnumOptionData depositType) { @@ -133,6 +137,8 @@ public class SavingsAccountData { // final LocalDate annualFeeNextDueDate = null; final boolean allowOverdraft = false; final BigDecimal overdraftLimit = null; + final BigDecimal minRequiredBalance = null; + final boolean allowOverdraftMinBalance = false; final SavingsAccountSummaryData summary = null; final Collection transactions = null; @@ -155,7 +161,8 @@ public class SavingsAccountData { lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, - withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit); + withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance, + allowOverdraftMinBalance); } public static SavingsAccountData lookupWithProductDetails(final Long accountId, final String accountNo, @@ -186,6 +193,8 @@ public class SavingsAccountData { // final LocalDate annualFeeNextDueDate = null; final boolean allowOverdraft = false; final BigDecimal overdraftLimit = null; + final BigDecimal minRequiredBalance = null; + final boolean allowOverdraftMinBalance = false; final SavingsAccountSummaryData summary = null; final Collection transactions = null; @@ -208,7 +217,8 @@ public class SavingsAccountData { lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, - withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit); + withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance, + allowOverdraftMinBalance); } public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, final SavingsAccountData template, @@ -239,7 +249,8 @@ public class SavingsAccountData { transactions, template.productOptions, template.fieldOfficerOptions, template.interestCompoundingPeriodTypeOptions, template.interestPostingPeriodTypeOptions, template.interestCalculationTypeOptions, template.interestCalculationDaysInYearTypeOptions, template.lockinPeriodFrequencyTypeOptions, - template.withdrawalFeeTypeOptions, charges, template.chargeOptions, account.allowOverdraft, account.overdraftLimit); + template.withdrawalFeeTypeOptions, charges, template.chargeOptions, account.allowOverdraft, account.overdraftLimit, + account.minRequiredBalance, account.allowOverdraftMinBalance); } public static SavingsAccountData withTemplateOptions(final SavingsAccountData account, @@ -260,7 +271,8 @@ public class SavingsAccountData { account.lockinPeriodFrequency, account.lockinPeriodFrequencyType, account.withdrawalFeeForTransfers, account.summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, - withdrawalFeeTypeOptions, charges, chargeOptions, account.allowOverdraft, account.overdraftLimit); + withdrawalFeeTypeOptions, charges, chargeOptions, account.allowOverdraft, account.overdraftLimit, + account.minRequiredBalance, account.allowOverdraftMinBalance); } public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId, @@ -293,6 +305,8 @@ public class SavingsAccountData { // final LocalDate annualFeeNextDueDate = null; final boolean allowOverdraft = false; final BigDecimal overdraftLimit = null; + final BigDecimal minRequiredBalance = null; + final boolean allowOverdraftMinBalance = false; final SavingsAccountSummaryData summary = null; final Collection transactions = null; @@ -315,7 +329,8 @@ public class SavingsAccountData { lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, transactions, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, - withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit); + withdrawalFeeTypeOptions, charges, chargeOptions, allowOverdraft, overdraftLimit, minRequiredBalance, + allowOverdraftMinBalance); } private SavingsAccountData(final Long id, final String accountNo, final EnumOptionData depositType, final String externalId, @@ -334,7 +349,7 @@ public class SavingsAccountData { final Collection interestCalculationDaysInYearTypeOptions, final Collection lockinPeriodFrequencyTypeOptions, final Collection withdrawalFeeTypeOptions, final Collection charges, final Collection chargeOptions, final boolean allowOverdraft, - final BigDecimal overdraftLimit) { + final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance) { this.id = id; this.accountNo = accountNo; this.depositType = depositType; @@ -386,6 +401,8 @@ public class SavingsAccountData { this.annualFee = getAnnualFee(); this.allowOverdraft = allowOverdraft; this.overdraftLimit = overdraftLimit; + this.minRequiredBalance = minRequiredBalance; + this.allowOverdraftMinBalance = allowOverdraftMinBalance; } private SavingsAccountChargeData getWithdrawalFee() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductData.java index 52df0b5f9..edd0827b3 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductData.java @@ -40,6 +40,8 @@ public class SavingsProductData { private final boolean withdrawalFeeForTransfers; private final boolean allowOverdraft; private final BigDecimal overdraftLimit; + private final BigDecimal minRequiredBalance; + private final boolean allowOverdraftMinBalance; // accounting private final EnumOptionData accountingRule; @@ -93,6 +95,8 @@ public class SavingsProductData { final Collection penaltyToIncomeAccountMappings = null; final boolean allowOverdraft = false; final BigDecimal overdraftLimit = null; + final BigDecimal minRequiredBalance = null; + final boolean allowOverdraftMinBalance = false; return new SavingsProductData(id, name, shortName, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, @@ -101,7 +105,7 @@ public class SavingsProductData { interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit); + penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); } public static SavingsProductData withCharges(final SavingsProductData product, final Collection charges) { @@ -114,7 +118,8 @@ public class SavingsProductData { product.interestCalculationTypeOptions, product.interestCalculationDaysInYearTypeOptions, product.lockinPeriodFrequencyTypeOptions, product.withdrawalFeeTypeOptions, product.paymentTypeOptions, product.accountingRuleOptions, product.accountingMappingOptions, charges, product.chargeOptions, product.penaltyOptions, - product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings, product.allowOverdraft, product.overdraftLimit); + product.feeToIncomeAccountMappings, product.penaltyToIncomeAccountMappings, product.allowOverdraft, product.overdraftLimit, + product.minRequiredBalance, product.allowOverdraftMinBalance); } /** @@ -142,7 +147,7 @@ public class SavingsProductData { lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, existingProduct.feeToIncomeAccountMappings, existingProduct.penaltyToIncomeAccountMappings, existingProduct.allowOverdraft, - existingProduct.overdraftLimit); + existingProduct.overdraftLimit, existingProduct.minRequiredBalance, existingProduct.allowOverdraftMinBalance); } public static SavingsProductData withAccountingDetails(final SavingsProductData existingProduct, @@ -174,7 +179,8 @@ public class SavingsProductData { interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, existingProduct.charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, existingProduct.allowOverdraft, existingProduct.overdraftLimit); + penaltyToIncomeAccountMappings, existingProduct.allowOverdraft, existingProduct.overdraftLimit, + existingProduct.minRequiredBalance, existingProduct.allowOverdraftMinBalance); } public static SavingsProductData instance(final Long id, final String name, final String shortName, final String description, @@ -182,7 +188,8 @@ public class SavingsProductData { final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final boolean withdrawalFeeForTransfers, - final EnumOptionData accountingType, final boolean allowOverdraft, final BigDecimal overdraftLimit) { + final EnumOptionData accountingType, final boolean allowOverdraft, final BigDecimal overdraftLimit, + final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance) { final Map accountingMappings = null; final Collection paymentChannelToFundSourceMappings = null; @@ -210,7 +217,7 @@ public class SavingsProductData { interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit); + penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); } public static SavingsProductData lookup(final Long id, final String name) { @@ -232,6 +239,8 @@ public class SavingsProductData { final Collection paymentChannelToFundSourceMappings = null; final boolean allowOverdraft = false; final BigDecimal overdraftLimit = null; + final BigDecimal minRequiredBalance = null; + final boolean allowOverdraftMinBalance = false; final Collection currencyOptions = null; final Collection interestCompoundingPeriodTypeOptions = null; @@ -256,7 +265,7 @@ public class SavingsProductData { interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, paymentTypeOptions, accountingRuleOptions, accountingMappingOptions, charges, chargeOptions, penaltyOptions, feeToIncomeAccountMappings, - penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit); + penaltyToIncomeAccountMappings, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); } private SavingsProductData(final Long id, final String name, final String shortName, final String description, @@ -276,7 +285,7 @@ public class SavingsProductData { final Collection chargeOptions, final Collection penaltyOptions, final Collection feeToIncomeAccountMappings, final Collection penaltyToIncomeAccountMappings, final boolean allowOverdraft, - final BigDecimal overdraftLimit) { + final BigDecimal overdraftLimit, final BigDecimal minRequiredBalance, final boolean allowOverdraftMinBalance) { this.id = id; this.name = name; this.shortName = shortName; @@ -321,6 +330,8 @@ public class SavingsProductData { this.penaltyToIncomeAccountMappings = penaltyToIncomeAccountMappings; this.allowOverdraft = allowOverdraft; this.overdraftLimit = overdraftLimit; + this.minRequiredBalance = minRequiredBalance; + this.allowOverdraftMinBalance = allowOverdraftMinBalance; } public boolean hasAccountingEnabled() { @@ -330,7 +341,7 @@ public class SavingsProductData { public int accountingRuleTypeId() { return this.accountingRule.getId().intValue(); } - + @Override public boolean equals(final Object obj) { final SavingsProductData productData = (SavingsProductData) obj; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositProduct.java index 28f742a36..36033beae 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositProduct.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/FixedDepositProduct.java @@ -99,7 +99,8 @@ public class FixedDepositProduct extends SavingsProduct { super(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, - lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit); + lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, + overdraftLimit); if (charts != null) { this.charts = charts; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java index fcb0581d6..0c0a6a88d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java @@ -13,6 +13,8 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeri import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftMinBalanceParamName; import java.math.BigDecimal; import java.math.MathContext; @@ -239,6 +241,12 @@ public class SavingsAccount extends AbstractPersistable { @Column(name = "overdraft_limit", scale = 6, precision = 19, nullable = true) private BigDecimal overdraftLimit; + @Column(name = "allow_overdraft_min_balance") + private boolean allowOverdraftMinBalance; + + @Column(name = "min_required_balance", scale = 6, precision = 19, nullable = true) + private BigDecimal minRequiredBalance; + @Embedded protected SavingsAccountSummary summary; @@ -273,13 +281,30 @@ public class SavingsAccount extends AbstractPersistable { final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final Set savingsAccountCharges, - final boolean allowOverdraft, final BigDecimal overdraftLimit) { + final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean allowOverdraftMinBalance, + final BigDecimal minRequiredBalance) { final SavingsAccountStatusType status = SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL; return new SavingsAccount(client, group, product, fieldOfficer, accountNo, externalId, status, accountType, submittedOnDate, submittedBy, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, - withdrawalFeeApplicableForTransfer, savingsAccountCharges, allowOverdraft, overdraftLimit); + withdrawalFeeApplicableForTransfer, savingsAccountCharges, allowOverdraft, overdraftLimit, allowOverdraftMinBalance, + minRequiredBalance); + } + + protected SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff fieldOfficer, + final String accountNo, final String externalId, final SavingsAccountStatusType status, final AccountType accountType, + final LocalDate submittedOnDate, final AppUser submittedBy, final BigDecimal nominalAnnualInterestRate, + 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 Set savingsAccountCharges, + final boolean allowOverdraft, final BigDecimal overdraftLimit) { + this(client, group, product, fieldOfficer, accountNo, externalId, status, accountType, submittedOnDate, + submittedBy, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, + interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, + withdrawalFeeApplicableForTransfer, savingsAccountCharges, allowOverdraft, overdraftLimit, false, null); } protected SavingsAccount(final Client client, final Group group, final SavingsProduct product, final Staff fieldOfficer, @@ -290,7 +315,8 @@ public class SavingsAccount extends AbstractPersistable { final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final Set savingsAccountCharges, - final boolean allowOverdraft, final BigDecimal overdraftLimit) { + final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean allowOverdraftMinBalance, + final BigDecimal minRequiredBalance) { this.client = client; this.group = group; this.product = product; @@ -327,6 +353,9 @@ public class SavingsAccount extends AbstractPersistable { this.summary = new SavingsAccountSummary(); this.allowOverdraft = allowOverdraft; this.overdraftLimit = overdraftLimit; + + this.allowOverdraftMinBalance = allowOverdraftMinBalance; + this.minRequiredBalance = minRequiredBalance; } /** @@ -766,9 +795,16 @@ public class SavingsAccount extends AbstractPersistable { runningBalance = runningBalance.minus(transaction.getAmount(this.currency)); } + final BigDecimal withdrawalFee = null; + // deal with potential minRequiredBalance and allowOverdraftMinBalance + if (this.minRequiredBalance != null && !this.allowOverdraftMinBalance) { + if (runningBalance.minus(this.minRequiredBalance).isLessThanZero()) { + throw new InsufficientAccountBalanceException("transactionAmount", + getAccountBalance(), withdrawalFee, transactionAmount); + } + } + if (runningBalance.isLessThanZero()) { - // - final BigDecimal withdrawalFee = null; Money limit = runningBalance.zero(); if (this.allowOverdraft) { if (this.overdraftLimit != null) { @@ -999,6 +1035,23 @@ public class SavingsAccount extends AbstractPersistable { this.overdraftLimit = null; } + if (command.isChangeInBooleanParameterNamed(allowOverdraftMinBalanceParamName, this.allowOverdraftMinBalance)) { + final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftMinBalanceParamName); + actualChanges.put(allowOverdraftMinBalanceParamName, newValue); + this.allowOverdraftMinBalance = newValue; + } + + if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minRequiredBalanceParamName, this.minRequiredBalance)) { + final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredBalanceParamName); + actualChanges.put(minRequiredBalanceParamName, newValue); + actualChanges.put(localeParamName, localeAsInput); + this.minRequiredBalance = newValue; + } + + if (!this.allowOverdraftMinBalance) { + this.minRequiredBalance = null; + } + validateLockinDetails(baseDataValidator); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountAssembler.java index 868dd25fb..11701d10b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountAssembler.java @@ -24,6 +24,8 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftL import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawalFeeForTransfersParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftMinBalanceParamName; import java.math.BigDecimal; import java.util.Set; @@ -214,11 +216,18 @@ public class SavingsAccountAssembler { final BigDecimal overdraftLimit = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(overdraftLimitParamName); + boolean allowOverdraftMinBalance = false; + if (command.parameterExists(allowOverdraftMinBalanceParamName)) { + allowOverdraft = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftMinBalanceParamName); + } + + final BigDecimal minRequiredBalance = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredBalanceParamName); + final SavingsAccount account = SavingsAccount.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNo, externalId, accountType, submittedOnDate, submittedBy, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, charges, allowOverdraft, - overdraftLimit); + overdraftLimit, allowOverdraftMinBalance, minRequiredBalance); account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper); account.validateNewApplicationState(DateUtils.getLocalDateOfTenant(), SAVINGS_ACCOUNT_RESOURCE_NAME); @@ -271,7 +280,8 @@ public class SavingsAccountAssembler { accountType, appliedonDate, appliedBy, product.nominalAnnualInterestRate(), product.interestCompoundingPeriodType(), product.interestPostingPeriodType(), product.interestCalculationType(), product.interestCalculationDaysInYearType(), product.minRequiredOpeningBalance(), product.lockinPeriodFrequency(), product.lockinPeriodFrequencyType(), - product.isWithdrawalFeeApplicableForTransfer(), charges, product.isAllowOverdraft(), product.overdraftLimit()); + product.isWithdrawalFeeApplicableForTransfer(), charges, product.isAllowOverdraft(), product.overdraftLimit(), + product.isAllowOverdraftMinBalance(), product.minRequiredBalance()); account.setHelpers(this.savingsAccountTransactionSummaryWrapper, this.savingsHelper); account.validateNewApplicationState(DateUtils.getLocalDateOfTenant(), SAVINGS_ACCOUNT_RESOURCE_NAME); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java index 494bf87e5..fc280275c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProduct.java @@ -7,6 +7,7 @@ package org.mifosplatform.portfolio.savings.domain; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.accountingRuleParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftMinBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.chargesParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.currencyCodeParamName; @@ -20,6 +21,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.interestPo import static org.mifosplatform.portfolio.savings.SavingsApiConstants.localeParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.lockinPeriodFrequencyTypeParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredOpeningBalanceParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nameParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName; @@ -147,6 +149,12 @@ public class SavingsProduct extends AbstractPersistable { @Column(name = "overdraft_limit", scale = 6, precision = 19, nullable = true) private BigDecimal overdraftLimit; + @Column(name = "allow_overdraft_min_balance") + private boolean allowOverdraftMinBalance; + + @Column(name = "min_required_balance", scale = 6, precision = 19, nullable = true) + private BigDecimal minRequiredBalance; + public static SavingsProduct createNew(final String name, final String shortName, final String description, final MonetaryCurrency currency, final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType, @@ -154,12 +162,13 @@ public class SavingsProduct extends AbstractPersistable { final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set charges, - final boolean allowOverdraft, final BigDecimal overdraftLimit) { + final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean allowOverdraftMinBalance, + final BigDecimal minRequiredBalance) { return new SavingsProduct(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, - allowOverdraft, overdraftLimit); + allowOverdraft, overdraftLimit, allowOverdraftMinBalance, minRequiredBalance); } protected SavingsProduct() { @@ -174,6 +183,20 @@ public class SavingsProduct extends AbstractPersistable { final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType, final boolean withdrawalFeeApplicableForTransfer, final AccountingRuleType accountingRuleType, final Set charges, final boolean allowOverdraft, final BigDecimal overdraftLimit) { + this(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, + interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, + lockinPeriodFrequencyType, withdrawalFeeApplicableForTransfer, accountingRuleType, charges, allowOverdraft, overdraftLimit, + false, 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 charges, + final boolean allowOverdraft, final BigDecimal overdraftLimit, final boolean allowOverdraftMinBalance, + final BigDecimal minRequiredBalance) { this.name = name; this.shortName = shortName; @@ -208,6 +231,9 @@ public class SavingsProduct extends AbstractPersistable { validateLockinDetails(); this.allowOverdraft = allowOverdraft; this.overdraftLimit = overdraftLimit; + + this.allowOverdraftMinBalance = allowOverdraftMinBalance; + this.minRequiredBalance = minRequiredBalance; } public MonetaryCurrency currency() { @@ -394,6 +420,23 @@ public class SavingsProduct extends AbstractPersistable { this.overdraftLimit = null; } + if (command.isChangeInBooleanParameterNamed(allowOverdraftMinBalanceParamName, this.allowOverdraftMinBalance)) { + final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftMinBalanceParamName); + actualChanges.put(allowOverdraftMinBalanceParamName, newValue); + this.allowOverdraftMinBalance = newValue; + } + + if (command.isChangeInBigDecimalParameterNamedDefaultingZeroToNull(minRequiredBalanceParamName, this.minRequiredBalance)) { + final BigDecimal newValue = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredBalanceParamName); + actualChanges.put(minRequiredBalanceParamName, newValue); + actualChanges.put(localeParamName, localeAsInput); + this.minRequiredBalance = newValue; + } + + if (!this.allowOverdraftMinBalance) { + this.minRequiredBalance = null; + } + validateLockinDetails(); return actualChanges; @@ -476,6 +519,14 @@ public class SavingsProduct extends AbstractPersistable { return this.allowOverdraft; } + public BigDecimal minRequiredBalance() { + return this.minRequiredBalance; + } + + public boolean isAllowOverdraftMinBalance() { + return this.allowOverdraftMinBalance; + } + public Set charges() { return this.charges; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProductAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProductAssembler.java index c57f57592..ac16582fc 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProductAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsProductAssembler.java @@ -24,6 +24,8 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.withdrawal import static org.mifosplatform.portfolio.savings.SavingsApiConstants.shortNameParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.overdraftLimitParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequiredBalanceParamName; +import static org.mifosplatform.portfolio.savings.SavingsApiConstants.allowOverdraftMinBalanceParamName; import java.math.BigDecimal; import java.util.HashSet; @@ -122,10 +124,17 @@ public class SavingsProductAssembler { final BigDecimal overdraftLimit = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(overdraftLimitParamName); + boolean allowOverdraftMinBalance = false; + if (command.parameterExists(allowOverdraftMinBalanceParamName)) { + allowOverdraftMinBalance = command.booleanPrimitiveValueOfParameterNamed(allowOverdraftMinBalanceParamName); + } + + final BigDecimal minRequiredBalance = command.bigDecimalValueOfParameterNamedDefaultToNullIfZero(minRequiredBalanceParamName); + return SavingsProduct.createNew(name, shortName, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, iswithdrawalFeeApplicableForTransfer, accountingRuleType, charges, - allowOverdraft, overdraftLimit); + allowOverdraft, overdraftLimit, allowOverdraftMinBalance, minRequiredBalance); } public Set assembleListOfSavingsProductCharges(final JsonCommand command, final String savingsProductCurrencyCode) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java index e0b17acb9..b23127ae8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java @@ -250,6 +250,8 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead sqlBuilder.append("sa.account_balance_derived as accountBalance, "); sqlBuilder.append("sa.total_fees_charge_derived as totalFeeCharge, "); sqlBuilder.append("sa.total_penalty_charge_derived as totalPenaltyCharge "); + sqlBuilder.append("sp.min_required_balance as minRequiredBalance, "); + sqlBuilder.append("sp.allow_overdraft_min_balance as allowOverdraftMinBalance, "); sqlBuilder.append("from m_savings_account sa "); sqlBuilder.append("join m_savings_product sp ON sa.product_id = sp.id "); sqlBuilder.append("join m_currency curr on curr.code = sa.currency_code "); @@ -381,6 +383,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead final boolean allowOverdraft = rs.getBoolean("allowOverdraft"); final BigDecimal overdraftLimit = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "overdraftLimit"); + final BigDecimal minRequiredBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredBalance"); + final boolean allowOverdraftMinBalance = rs.getBoolean("allowOverdraftMinBalance"); + /* * final BigDecimal annualFeeAmount = * JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, @@ -415,7 +420,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, - allowOverdraft, overdraftLimit); + allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); } } @@ -877,6 +882,9 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead final boolean allowOverdraft = rs.getBoolean("allowOverdraft"); final BigDecimal overdraftLimit = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "overdraftLimit"); + final BigDecimal minRequiredBalance = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredBalance"); + final boolean allowOverdraftMinBalance = rs.getBoolean("allowOverdraftMinBalance"); + // final BigDecimal annualFeeAmount = // JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, // "annualFeeAmount"); @@ -916,7 +924,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, summary, - allowOverdraft, overdraftLimit); + allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java index 2576c1978..06e874841 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java @@ -92,6 +92,8 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead sqlBuilder.append("sp.withdrawal_fee_for_transfer as withdrawalFeeForTransfers, "); sqlBuilder.append("sp.allow_overdraft as allowOverdraft, "); sqlBuilder.append("sp.overdraft_limit as overdraftLimit, "); + sqlBuilder.append("sp.min_required_balance as minRequiredBalance, "); + sqlBuilder.append("sp.allow_overdraft_min_balance as allowOverdraftMinBalance, "); sqlBuilder.append("sp.accounting_type as accountingType "); sqlBuilder.append("from m_savings_product sp "); sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code "); @@ -153,10 +155,14 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead final boolean withdrawalFeeForTransfers = rs.getBoolean("withdrawalFeeForTransfers"); final boolean allowOverdraft = rs.getBoolean("allowOverdraft"); final BigDecimal overdraftLimit = rs.getBigDecimal("overdraftLimit"); + + final BigDecimal minRequiredBalance = rs.getBigDecimal("minRequiredBalance"); + final boolean allowOverdraftMinBalance = rs.getBoolean("allowOverdraftMinBalance"); + return SavingsProductData.instance(id, name, shortName, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeForTransfers, - accountingRuleType, allowOverdraft, overdraftLimit); + accountingRuleType, allowOverdraft, overdraftLimit, minRequiredBalance, allowOverdraftMinBalance); } }