MIFOSX-246: support for withdrawal fees on savings accounts.
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
ALTER TABLE `m_savings_product`
|
||||
ADD COLUMN `withdrawal_fee_amount` DECIMAL(19,6) NULL DEFAULT NULL AFTER `lockin_period_frequency_enum`,
|
||||
ADD COLUMN `withdrawal_fee_type_enum` SMALLINT(5) NULL DEFAULT NULL AFTER `withdrawal_fee_amount`;
|
||||
|
||||
|
||||
ALTER TABLE `m_savings_account`
|
||||
ADD COLUMN `withdrawal_fee_amount` DECIMAL(19,6) NULL DEFAULT NULL AFTER `lockin_period_frequency_enum`,
|
||||
ADD COLUMN `withdrawal_fee_type_enum` SMALLINT(5) NULL DEFAULT NULL AFTER `withdrawal_fee_amount`;
|
||||
|
||||
|
||||
ALTER TABLE `m_savings_account`
|
||||
ADD COLUMN `total_withdrawal_fees_derived` DECIMAL(19,6) NULL DEFAULT NULL AFTER `total_withdrawals_derived`;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.infrastructure.core.exception;
|
||||
|
||||
/**
|
||||
* A {@link RuntimeException} thrown when valid api request end up violating
|
||||
* some domain rule.
|
||||
*/
|
||||
public final class GeneralPlatformDomainRuleException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public GeneralPlatformDomainRuleException(final String globalisationMessageCode, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
+1
-4
@@ -16,7 +16,7 @@ public enum ChargeCalculationType {
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
private ChargeCalculationType(Integer value, String code) {
|
||||
private ChargeCalculationType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
@@ -44,9 +44,6 @@ public enum ChargeCalculationType {
|
||||
case 4:
|
||||
chargeCalculationType = PERCENT_OF_INTEREST;
|
||||
break;
|
||||
default:
|
||||
chargeCalculationType = INVALID;
|
||||
break;
|
||||
}
|
||||
return chargeCalculationType;
|
||||
}
|
||||
|
||||
+3
-1
@@ -145,6 +145,7 @@ public class SavingsAccountsApiResource {
|
||||
Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||
Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
|
||||
Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||
Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
||||
|
||||
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
|
||||
if (!associationParameters.isEmpty()) {
|
||||
@@ -170,11 +171,12 @@ public class SavingsAccountsApiResource {
|
||||
interestCompoundingPostingTypeOptions = this.dropdownReadPlatformService.retrieveInterestPostingPeriodTypeOptions();
|
||||
interestCalculationTypeOptions = this.dropdownReadPlatformService.retrieveInterestCalculationTypeOptions();
|
||||
lockinPeriodFrequencyTypeOptions = this.dropdownReadPlatformService.retrieveLockinPeriodFrequencyTypeOptions();
|
||||
withdrawalFeeTypeOptions = this.dropdownReadPlatformService.retrievewithdrawalFeeTypeOptions();
|
||||
}
|
||||
|
||||
return SavingsAccountData.withTemplateOptions(savingsAccount, productOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestCompoundingPostingTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, transactions);
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions);
|
||||
}
|
||||
|
||||
@PUT
|
||||
|
||||
+12
-8
@@ -39,6 +39,8 @@ public class SavingsApiConstants {
|
||||
public static final String minRequiredOpeningBalanceParamName = "minRequiredOpeningBalance";
|
||||
public static final String lockinPeriodFrequencyParamName = "lockinPeriodFrequency";
|
||||
public static final String lockinPeriodFrequencyTypeParamName = "lockinPeriodFrequencyType";
|
||||
public static final String withdrawalFeeAmountParamName = "withdrawalFeeAmount";
|
||||
public static final String withdrawalFeeTypeParamName = "withdrawalFeeType";
|
||||
|
||||
// transaction parameters
|
||||
public static final String transactionDateParamName = "transactionDate";
|
||||
@@ -48,7 +50,7 @@ public class SavingsApiConstants {
|
||||
nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
|
||||
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
||||
lockinPeriodFrequencyTypeParamName));
|
||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
@@ -59,15 +61,16 @@ public class SavingsApiConstants {
|
||||
nameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
|
||||
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
||||
lockinPeriodFrequencyTypeParamName, "currencyOptions", "interestCompoundingPeriodTypeOptions",
|
||||
"interestPostingPeriodTypeOptions", "interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions",
|
||||
"lockinPeriodFrequencyTypeOptions"));
|
||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, "currencyOptions",
|
||||
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
|
||||
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions"));
|
||||
|
||||
public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName,
|
||||
activeParamName, activationDateParamName, nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName,
|
||||
interestPostingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
|
||||
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName));
|
||||
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
@@ -78,9 +81,10 @@ public class SavingsApiConstants {
|
||||
accountNoParamName, externalIdParamName, statusParamName, activationDateParamName, clientIdParamName, "clientName",
|
||||
groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", nominalAnnualInterestRateParamName,
|
||||
interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
|
||||
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, "summary",
|
||||
"transactions", "productOptions", "interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions",
|
||||
"interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions"));
|
||||
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, "summary", "transactions", "productOptions",
|
||||
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
|
||||
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions"));
|
||||
|
||||
public static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
|
||||
localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName));
|
||||
|
||||
+4
-2
@@ -180,16 +180,18 @@ public class SavingsProductsApiResource {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = this.dropdownReadPlatformService
|
||||
.retrieveLockinPeriodFrequencyTypeOptions();
|
||||
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = this.dropdownReadPlatformService.retrievewithdrawalFeeTypeOptions();
|
||||
|
||||
SavingsProductData savingsProductToReturn = null;
|
||||
if (savingsProduct != null) {
|
||||
savingsProductToReturn = SavingsProductData.withTemplate(savingsProduct, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions);
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
} else {
|
||||
savingsProductToReturn = SavingsProductData.template(currency, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions);
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
return savingsProductToReturn;
|
||||
|
||||
+34
-13
@@ -37,6 +37,8 @@ public class SavingsAccountData {
|
||||
private final BigDecimal minRequiredOpeningBalance;
|
||||
private final Integer lockinPeriodFrequency;
|
||||
private final EnumOptionData lockinPeriodFrequencyType;
|
||||
private final BigDecimal withdrawalFeeAmount;
|
||||
private final EnumOptionData withdrawalFeeType;
|
||||
|
||||
// associations
|
||||
private final SavingsAccountSummaryData summary;
|
||||
@@ -56,6 +58,8 @@ public class SavingsAccountData {
|
||||
private final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<EnumOptionData> withdrawalFeeTypeOptions;
|
||||
|
||||
public static SavingsAccountData instance(final Long id, final String accountNo, final String externalId,
|
||||
final SavingsAccountStatusEnumData status, final LocalDate activationDate, final Long groupId, final String groupName,
|
||||
@@ -63,7 +67,8 @@ public class SavingsAccountData {
|
||||
final BigDecimal interestRate, final EnumOptionData interestCompoundingPeriodType,
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary) {
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||
final EnumOptionData withdrawalFeeType, final SavingsAccountSummaryData summary) {
|
||||
|
||||
final Collection<SavingsProductData> productOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
@@ -71,13 +76,16 @@ public class SavingsAccountData {
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
||||
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
|
||||
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
||||
productId, productName, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, summary, productOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, summary, transactions, productOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||
@@ -85,15 +93,17 @@ public class SavingsAccountData {
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<SavingsAccountTransactionData> transactions) {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions,
|
||||
final Collection<SavingsAccountTransactionData> transactions) {
|
||||
|
||||
return new SavingsAccountData(account.id, account.accountNo, account.externalId, account.status, account.activationDate,
|
||||
account.groupId, account.groupName, account.clientId, account.clientName, account.savingsProductId,
|
||||
account.savingsProductName, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
|
||||
account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType,
|
||||
account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType, account.summary,
|
||||
productOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
|
||||
account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType,
|
||||
account.withdrawalFeeAmount, account.withdrawalFeeType, account.summary, transactions, productOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||
@@ -115,20 +125,26 @@ public class SavingsAccountData {
|
||||
final BigDecimal minRequiredOpeningBalance = null;
|
||||
final Integer lockinPeriodFrequency = null;
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final BigDecimal withdrawalFeeAmount = null;
|
||||
final EnumOptionData withdrawalFeeType = null;
|
||||
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
|
||||
final Collection<SavingsProductData> productOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
||||
|
||||
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
||||
productId, productName, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, summary, productOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, transactions);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, summary, transactions, productOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
private SavingsAccountData(final Long id, final String accountNo, final String externalId, final SavingsAccountStatusEnumData status,
|
||||
@@ -137,12 +153,13 @@ public class SavingsAccountData {
|
||||
final EnumOptionData interestPeriodType, final EnumOptionData interestPostingPeriodType,
|
||||
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
|
||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
||||
final EnumOptionData lockinPeriodFrequencyType, final SavingsAccountSummaryData summary,
|
||||
final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount, final EnumOptionData withdrawalFeeType,
|
||||
final SavingsAccountSummaryData summary, final Collection<SavingsAccountTransactionData> transactions,
|
||||
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<SavingsAccountTransactionData> transactions) {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions) {
|
||||
this.id = id;
|
||||
this.accountNo = accountNo;
|
||||
this.externalId = externalId;
|
||||
@@ -163,7 +180,11 @@ public class SavingsAccountData {
|
||||
this.minRequiredOpeningBalance = minRequiredOpeningBalance;
|
||||
this.lockinPeriodFrequency = lockinPeriodFrequency;
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
this.withdrawalFeeType = withdrawalFeeType;
|
||||
|
||||
this.summary = summary;
|
||||
this.transactions = transactions;
|
||||
|
||||
this.productOptions = productOptions;
|
||||
this.interestCompoundingPeriodTypeOptions = interestCompoundingPeriodTypeOptions;
|
||||
@@ -171,6 +192,6 @@ public class SavingsAccountData {
|
||||
this.interestCalculationTypeOptions = interestCalculationTypeOptions;
|
||||
this.interestCalculationDaysInYearTypeOptions = interestCalculationDaysInYearTypeOptions;
|
||||
this.lockinPeriodFrequencyTypeOptions = lockinPeriodFrequencyTypeOptions;
|
||||
this.transactions = transactions;
|
||||
this.withdrawalFeeTypeOptions = withdrawalFeeTypeOptions;
|
||||
}
|
||||
}
|
||||
+26
@@ -15,6 +15,8 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockin
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.productIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
@@ -159,6 +161,18 @@ public class SavingsAccountDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -290,6 +304,18 @@ public class SavingsAccountDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).notNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
|
||||
}
|
||||
|
||||
+4
-1
@@ -18,15 +18,18 @@ public class SavingsAccountSummaryData {
|
||||
private final CurrencyData currency;
|
||||
private final BigDecimal totalDeposits;
|
||||
private final BigDecimal totalWithdrawals;
|
||||
private final BigDecimal totalWithdrawalFees;
|
||||
private final BigDecimal totalInterestEarned;
|
||||
private final BigDecimal totalInterestPosted;
|
||||
private final BigDecimal accountBalance;
|
||||
|
||||
public SavingsAccountSummaryData(final CurrencyData currency, final BigDecimal totalDeposits, final BigDecimal totalWithdrawals,
|
||||
final BigDecimal totalInterestEarned, final BigDecimal totalInterestPosted, final BigDecimal accountBalance) {
|
||||
final BigDecimal totalWithdrawalFees, final BigDecimal totalInterestEarned, final BigDecimal totalInterestPosted,
|
||||
final BigDecimal accountBalance) {
|
||||
this.currency = currency;
|
||||
this.totalDeposits = totalDeposits;
|
||||
this.totalWithdrawals = totalWithdrawals;
|
||||
this.totalWithdrawalFees = totalWithdrawalFees;
|
||||
this.totalInterestEarned = totalInterestEarned;
|
||||
this.totalInterestPosted = totalInterestPosted;
|
||||
this.accountBalance = accountBalance;
|
||||
|
||||
+35
-18
@@ -28,6 +28,8 @@ public class SavingsProductData {
|
||||
private final BigDecimal minRequiredOpeningBalance;
|
||||
private final Integer lockinPeriodFrequency;
|
||||
private final EnumOptionData lockinPeriodFrequencyType;
|
||||
private final BigDecimal withdrawalFeeAmount;
|
||||
private final EnumOptionData withdrawalFeeType;
|
||||
|
||||
// template
|
||||
@SuppressWarnings("unused")
|
||||
@@ -42,6 +44,8 @@ public class SavingsProductData {
|
||||
private final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions;
|
||||
@SuppressWarnings("unused")
|
||||
private final Collection<EnumOptionData> withdrawalFeeTypeOptions;
|
||||
|
||||
public static SavingsProductData template(final CurrencyData currency, final EnumOptionData interestCompoundingPeriodType,
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
@@ -50,7 +54,7 @@ public class SavingsProductData {
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions) {
|
||||
|
||||
final Long id = null;
|
||||
final String name = null;
|
||||
@@ -59,12 +63,14 @@ public class SavingsProductData {
|
||||
final BigDecimal minRequiredOpeningBalance = null;
|
||||
final Integer lockinPeriodFrequency = null;
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final BigDecimal withdrawalFeeAmount = null;
|
||||
final EnumOptionData withdrawalFeeType = null;
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, currencyOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,22 +82,24 @@ public class SavingsProductData {
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions) {
|
||||
|
||||
return new SavingsProductData(existingProduct.id, existingProduct.name, existingProduct.description, existingProduct.currency,
|
||||
existingProduct.nominalAnnualInterestRate, existingProduct.interestCompoundingPeriodType,
|
||||
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
existingProduct.interestCalculationDaysInYearType, existingProduct.minRequiredOpeningBalance,
|
||||
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, currencyOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions);
|
||||
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.withdrawalFeeAmount,
|
||||
existingProduct.withdrawalFeeType, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
public static SavingsProductData instance(final Long id, final String name, final String description, final CurrencyData currency,
|
||||
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType) {
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||
final EnumOptionData withdrawalFeeType) {
|
||||
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
@@ -99,12 +107,13 @@ public class SavingsProductData {
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, currencyOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
public static SavingsProductData lookup(final Long id, final String name) {
|
||||
@@ -119,6 +128,8 @@ public class SavingsProductData {
|
||||
final BigDecimal minRequiredOpeningBalance = null;
|
||||
final Integer lockinPeriodFrequency = null;
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final BigDecimal withdrawalFeeAmount = null;
|
||||
final EnumOptionData withdrawalFeeType = null;
|
||||
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
@@ -126,24 +137,27 @@ public class SavingsProductData {
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, currencyOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, currencyOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
private SavingsProductData(final Long id, final String name, final String description, final CurrencyData currency,
|
||||
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType,
|
||||
final Collection<CurrencyData> currencyOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final EnumOptionData withdrawalFeeType,
|
||||
final Collection<CurrencyData> currencyOptions,
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions) {
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions, final Collection<EnumOptionData> withdrawalFeeTypeOptions) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
@@ -156,6 +170,8 @@ public class SavingsProductData {
|
||||
this.minRequiredOpeningBalance = minRequiredOpeningBalance;
|
||||
this.lockinPeriodFrequency = lockinPeriodFrequency;
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
this.withdrawalFeeType = withdrawalFeeType;
|
||||
|
||||
this.currencyOptions = currencyOptions;
|
||||
this.interestCompoundingPeriodTypeOptions = interestCompoundingPeriodTypeOptions;
|
||||
@@ -163,5 +179,6 @@ public class SavingsProductData {
|
||||
this.interestCalculationTypeOptions = interestCalculationTypeOptions;
|
||||
this.interestCalculationDaysInYearTypeOptions = interestCalculationDaysInYearTypeOptions;
|
||||
this.lockinPeriodFrequencyTypeOptions = lockinPeriodFrequencyTypeOptions;
|
||||
this.withdrawalFeeTypeOptions = withdrawalFeeTypeOptions;
|
||||
}
|
||||
}
|
||||
+30
-7
@@ -14,6 +14,8 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockin
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
@@ -67,8 +69,10 @@ public class SavingsProductDataValidator {
|
||||
final Integer digitsAfterDecimal = fromApiJsonHelper.extractIntegerSansLocaleNamed(digitsAfterDecimalParamName, element);
|
||||
baseDataValidator.reset().parameter(digitsAfterDecimalParamName).value(digitsAfterDecimal).notNull().inMinMaxRange(0, 6);
|
||||
|
||||
final BigDecimal nominalAnnualInterestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName, element);
|
||||
baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(nominalAnnualInterestRate).notNull().zeroOrPositiveAmount();
|
||||
final BigDecimal nominalAnnualInterestRate = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(nominalAnnualInterestRateParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(nominalAnnualInterestRateParamName).value(nominalAnnualInterestRate).notNull()
|
||||
.zeroOrPositiveAmount();
|
||||
|
||||
final Integer interestCompoundingPeriodType = fromApiJsonHelper.extractIntegerSansLocaleNamed(
|
||||
interestCompoundingPeriodTypeParamName, element);
|
||||
@@ -121,6 +125,17 @@ public class SavingsProductDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
||||
|
||||
if (withdrawalFeeType != null) {
|
||||
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName,
|
||||
element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).notNull().positiveAmount();
|
||||
}
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -195,14 +210,22 @@ public class SavingsProductDataValidator {
|
||||
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(1, 3);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeAmountParamName, element)) {
|
||||
final BigDecimal withdrawalFeeAmount = fromApiJsonHelper
|
||||
.extractBigDecimalWithLocaleNamed(withdrawalFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeAmountParamName).value(withdrawalFeeAmount).ignoreIfNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(withdrawalFeeTypeParamName, element)) {
|
||||
final Integer withdrawalFeeType = fromApiJsonHelper.extractIntegerSansLocaleNamed(withdrawalFeeTypeParamName, element);
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).ignoreIfNull()
|
||||
.isOneOfTheseValues(1, 2);
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
//
|
||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
||||
dataValidationErrors);
|
||||
}
|
||||
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||
}
|
||||
}
|
||||
+47
-7
@@ -136,6 +136,12 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
@Column(name = "lockedin_until_date_derived", nullable = true)
|
||||
private Date lockedInUntilDate;
|
||||
|
||||
@Column(name = "withdrawal_fee_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal withdrawalFeeAmount;
|
||||
|
||||
@Column(name = "withdrawal_fee_type_enum", nullable = true)
|
||||
private Integer withdrawalFeeType;
|
||||
|
||||
@Embedded
|
||||
private SavingsAccountSummary summary;
|
||||
|
||||
@@ -158,13 +164,14 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
||||
|
||||
final SavingsAccountStatusType status = SavingsAccountStatusType.UNACTIVATED;
|
||||
final LocalDate activationDate = null;
|
||||
return new SavingsAccount(client, group, product, accountNo, externalId, status, activationDate, interestRate,
|
||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType);
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
||||
}
|
||||
|
||||
private SavingsAccount(final Client client, final Group group, final SavingsProduct product, final String accountNo,
|
||||
@@ -172,7 +179,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final BigDecimal nominalAnnualInterestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
||||
this.client = client;
|
||||
this.group = group;
|
||||
this.product = product;
|
||||
@@ -198,6 +206,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
if (lockinPeriodFrequencyType != null) {
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType.getValue();
|
||||
}
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
if (withdrawalFeeType != null) {
|
||||
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
||||
}
|
||||
this.summary = new SavingsAccountSummary();
|
||||
}
|
||||
|
||||
@@ -313,7 +325,7 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (recalucateDailyBalanceDetails) {
|
||||
// no openingBalance concept supported yet but probably will to
|
||||
// allow
|
||||
@@ -411,6 +423,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
|
||||
this.summary.updateFromInterestPeriodSummaries(currency, compoundingPeriods);
|
||||
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
|
||||
return compoundingPeriods;
|
||||
}
|
||||
|
||||
@@ -788,16 +802,38 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
final Money amount = Money.of(this.currency, transactionAmount);
|
||||
final Money transactionAmountMoney = Money.of(this.currency, transactionAmount);
|
||||
|
||||
if (isNotEnoughFundsToWithdraw(amount)) {
|
||||
if (isNotEnoughFundsToWithdraw(transactionAmountMoney)) {
|
||||
//
|
||||
throw new InsufficientAccountBalanceException("transactionAmount", getAccountBalance(), transactionAmount);
|
||||
}
|
||||
|
||||
final SavingsAccountTransaction transaction = SavingsAccountTransaction.withdrawal(this, transactionDate, amount);
|
||||
final SavingsAccountTransaction transaction = SavingsAccountTransaction.withdrawal(this, transactionDate, transactionAmountMoney);
|
||||
this.transactions.add(transaction);
|
||||
|
||||
if (isAutomaticWithdrawalFee()) {
|
||||
|
||||
SavingsAccountTransaction withdrawalFeeTransaction = null;
|
||||
Money feeAmount = null;
|
||||
switch (SavingsWithdrawalFeesType.fromInt(this.withdrawalFeeType)) {
|
||||
case INVALID:
|
||||
break;
|
||||
case FLAT:
|
||||
feeAmount = Money.of(this.currency, this.withdrawalFeeAmount);
|
||||
withdrawalFeeTransaction = SavingsAccountTransaction.fee(this, transactionDate, feeAmount);
|
||||
this.transactions.add(withdrawalFeeTransaction);
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT:
|
||||
final BigDecimal feeAmountDecimal = transactionAmount.multiply(this.withdrawalFeeAmount).divide(
|
||||
BigDecimal.valueOf(100l));
|
||||
feeAmount = Money.of(this.currency, feeAmountDecimal);
|
||||
withdrawalFeeTransaction = SavingsAccountTransaction.fee(this, transactionDate, feeAmount);
|
||||
this.transactions.add(withdrawalFeeTransaction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
@@ -806,6 +842,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
private boolean isAutomaticWithdrawalFee() {
|
||||
return this.withdrawalFeeType != null;
|
||||
}
|
||||
|
||||
private boolean isAccountLocked(final LocalDate transactionDate) {
|
||||
boolean isLocked = false;
|
||||
final boolean accountHasLockedInSetting = this.lockedInUntilDate != null;
|
||||
|
||||
+21
-1
@@ -15,6 +15,8 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockin
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockinPeriodFrequencyTypeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Locale;
|
||||
@@ -153,9 +155,27 @@ public class SavingsAccountAssembler {
|
||||
lockinPeriodFrequencyType = product.lockinPeriodFrequencyType();
|
||||
}
|
||||
|
||||
BigDecimal withdrawalFeeAmount = null;
|
||||
if (command.parameterExists(withdrawalFeeAmountParamName)) {
|
||||
withdrawalFeeAmount = command.bigDecimalValueOfParameterNamed(withdrawalFeeAmountParamName);
|
||||
} else {
|
||||
withdrawalFeeAmount = product.withdrawalFeeAmount();
|
||||
}
|
||||
|
||||
SavingsWithdrawalFeesType withdrawalFeeType = null;
|
||||
if (command.parameterExists(withdrawalFeeAmountParamName)) {
|
||||
final Integer withdrawalFeeTypeValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(withdrawalFeeTypeValue);
|
||||
}
|
||||
} else {
|
||||
withdrawalFeeType = product.withdrawalFeeType();
|
||||
}
|
||||
|
||||
|
||||
final SavingsAccount account = SavingsAccount.createNewAccount(client, group, product, accountNo, externalId, interestRate,
|
||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType);
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper);
|
||||
|
||||
if (active) {
|
||||
|
||||
+5
-1
@@ -29,6 +29,9 @@ public final class SavingsAccountSummary {
|
||||
@Column(name = "total_interest_posted_derived", scale = 6, precision = 19)
|
||||
private BigDecimal totalInterestPosted;
|
||||
|
||||
@Column(name = "total_withdrawal_fees_derived", scale = 6, precision = 19)
|
||||
private BigDecimal totalWithdrawalFees;
|
||||
|
||||
@Column(name = "account_balance_derived", scale = 6, precision = 19)
|
||||
private BigDecimal accountBalance = BigDecimal.ZERO;
|
||||
|
||||
@@ -42,9 +45,10 @@ public final class SavingsAccountSummary {
|
||||
this.totalDeposits = wrapper.calculateTotalDeposits(currency, transactions);
|
||||
this.totalWithdrawals = wrapper.calculateTotalWithdrawals(currency, transactions);
|
||||
this.totalInterestPosted = wrapper.calculateTotalInterestPosted(currency, transactions);
|
||||
this.totalWithdrawalFees = wrapper.calculateTotalWithdrawalFees(currency, transactions);
|
||||
|
||||
this.accountBalance = Money.of(currency, this.totalDeposits).plus(this.totalInterestPosted).minus(this.totalWithdrawals)
|
||||
.getAmount();
|
||||
.minus(this.totalWithdrawalFees).getAmount();
|
||||
}
|
||||
|
||||
public void updateFromInterestPeriodSummaries(final MonetaryCurrency currency,
|
||||
|
||||
+10
@@ -82,6 +82,12 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
isReversed);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction fee(final SavingsAccount savingsAccount, final LocalDate date, final Money amount) {
|
||||
final boolean isReversed = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue(), date, amount,
|
||||
isReversed);
|
||||
}
|
||||
|
||||
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Integer typeOf, final LocalDate transactionLocalDate,
|
||||
final Money amount, final boolean isReversed) {
|
||||
this.savingsAccount = savingsAccount;
|
||||
@@ -115,6 +121,10 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isInterestPosting() && isNotReversed();
|
||||
}
|
||||
|
||||
public boolean isWithdrawalFee() {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawalFee() && isNotReversed();
|
||||
}
|
||||
|
||||
public boolean isNotReversed() {
|
||||
return !isReversed();
|
||||
}
|
||||
|
||||
+10
@@ -43,4 +43,14 @@ public final class SavingsAccountTransactionSummaryWrapper {
|
||||
}
|
||||
return total.getAmountDefaultedToNullIfZero();
|
||||
}
|
||||
|
||||
public BigDecimal calculateTotalWithdrawalFees(final MonetaryCurrency currency, final List<SavingsAccountTransaction> transactions) {
|
||||
Money total = Money.zero(currency);
|
||||
for (SavingsAccountTransaction transaction : transactions) {
|
||||
if (transaction.isWithdrawalFee() && transaction.isNotReversed()) {
|
||||
total = total.plus(transaction.getAmount(currency));
|
||||
}
|
||||
}
|
||||
return total.getAmountDefaultedToNullIfZero();
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -14,7 +14,8 @@ public enum SavingsAccountTransactionType {
|
||||
INVALID(0, "savingsAccountTransactionType.invalid"), //
|
||||
DEPOSIT(1, "savingsAccountTransactionType.deposit"), //
|
||||
WITHDRAWAL(2, "savingsAccountTransactionType.withdrawal"), //
|
||||
INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting");
|
||||
INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), //
|
||||
WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -47,6 +48,9 @@ public enum SavingsAccountTransactionType {
|
||||
case 3:
|
||||
loanTransactionType = SavingsAccountTransactionType.INTEREST_POSTING;
|
||||
break;
|
||||
case 4:
|
||||
loanTransactionType = SavingsAccountTransactionType.WITHDRAWAL_FEE;
|
||||
break;
|
||||
}
|
||||
return loanTransactionType;
|
||||
}
|
||||
@@ -62,4 +66,8 @@ public enum SavingsAccountTransactionType {
|
||||
public boolean isInterestPosting() {
|
||||
return this.value.equals(SavingsAccountTransactionType.INTEREST_POSTING.getValue());
|
||||
}
|
||||
|
||||
public boolean isWithdrawalFee() {
|
||||
return this.value.equals(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue());
|
||||
}
|
||||
}
|
||||
+62
-7
@@ -18,6 +18,8 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockin
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -29,9 +31,9 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.mifosplatform.organisation.monetary.domain.Money;
|
||||
import org.mifosplatform.portfolio.savings.exception.InvalidSavingsProductSettingsException;
|
||||
import org.springframework.data.jpa.domain.AbstractPersistable;
|
||||
|
||||
@Entity
|
||||
@@ -88,15 +90,22 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
@Column(name = "lockin_period_frequency_enum", nullable = true)
|
||||
private Integer lockinPeriodFrequencyType;
|
||||
|
||||
@Column(name = "withdrawal_fee_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal withdrawalFeeAmount;
|
||||
|
||||
@Column(name = "withdrawal_fee_type_enum", nullable = true)
|
||||
private Integer withdrawalFeeType;
|
||||
|
||||
public static SavingsProduct createNew(final String name, final String description, final MonetaryCurrency currency,
|
||||
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
||||
|
||||
return new SavingsProduct(name, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
||||
}
|
||||
|
||||
protected SavingsProduct() {
|
||||
@@ -108,7 +117,8 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType) {
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
||||
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
@@ -129,7 +139,13 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType.getValue();
|
||||
}
|
||||
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
if (withdrawalFeeType != null) {
|
||||
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
validateWithdrawalFeeDetails();
|
||||
}
|
||||
|
||||
public MonetaryCurrency currency() {
|
||||
@@ -172,6 +188,18 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
return type;
|
||||
}
|
||||
|
||||
public BigDecimal withdrawalFeeAmount() {
|
||||
return this.withdrawalFeeAmount;
|
||||
}
|
||||
|
||||
public SavingsWithdrawalFeesType withdrawalFeeType() {
|
||||
SavingsWithdrawalFeesType type = null;
|
||||
if (this.withdrawalFeeType != null) {
|
||||
type = SavingsWithdrawalFeesType.fromInt(this.withdrawalFeeType);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(10);
|
||||
@@ -258,16 +286,43 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
this.lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamed(withdrawalFeeAmountParamName, this.withdrawalFeeAmount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(withdrawalFeeAmountParamName);
|
||||
actualChanges.put(withdrawalFeeAmountParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.withdrawalFeeAmount = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(withdrawalFeeTypeParamName, this.withdrawalFeeType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
||||
actualChanges.put(withdrawalFeeTypeParamName, newValue);
|
||||
this.withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
validateWithdrawalFeeDetails();
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void validateWithdrawalFeeDetails() {
|
||||
if (isInvalidConfigurationOfWithdrawalFeeSettings()) {
|
||||
Object[] defaultUserMessageArgs = new Object[] { withdrawalFeeAmountParamName };
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.product.savings.invalid.withdrawalfee.settings",
|
||||
"Invalid configuration of withdrawal fee settings.", defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInvalidConfigurationOfWithdrawalFeeSettings() {
|
||||
return (this.withdrawalFeeAmount == null && this.withdrawalFeeType != null)
|
||||
|| (this.withdrawalFeeType == null && this.withdrawalFeeAmount != null);
|
||||
}
|
||||
|
||||
private void validateLockinDetails() {
|
||||
if (isInvalidConfigurationOfLockinSettings()) {
|
||||
//
|
||||
throw new InvalidSavingsProductSettingsException("error.msg.product.savings.invalid.lockin.settings",
|
||||
"Invalid configuration of lock in settings.", lockinPeriodFrequencyParamName);
|
||||
Object[] defaultUserMessageArgs = new Object[] { lockinPeriodFrequencyParamName };
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.product.savings.invalid.lockin.settings",
|
||||
"Invalid configuration of lock in settings.", defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-2
@@ -12,6 +12,8 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.lockin
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.minRequiredOpeningBalanceParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nameParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.nominalAnnualInterestRateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@@ -67,8 +69,15 @@ public class SavingsProductAssembler {
|
||||
lockinPeriodFrequencyType = SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = command.bigDecimalValueOfParameterNamed(withdrawalFeeAmountParamName);
|
||||
SavingsWithdrawalFeesType withdrawalFeeType = null;
|
||||
final Integer withdrawalFeeTypeValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
return SavingsProduct.createNew(name, description, currency, interestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType,
|
||||
interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType);
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
public enum SavingsWithdrawalFeesType {
|
||||
|
||||
INVALID(0, "savingsWithdrawalFeesType.invalid"), //
|
||||
FLAT(1, "savingsWithdrawalFeesType.flat"), //
|
||||
PERCENT_OF_AMOUNT(2, "savingsWithdrawalFeesType.percent.of.amount");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
private SavingsWithdrawalFeesType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public static SavingsWithdrawalFeesType fromInt(final Integer type) {
|
||||
|
||||
SavingsWithdrawalFeesType withdrawalFeeType = SavingsWithdrawalFeesType.INVALID;
|
||||
switch (type) {
|
||||
case 1:
|
||||
withdrawalFeeType = FLAT;
|
||||
break;
|
||||
case 2:
|
||||
withdrawalFeeType = PERCENT_OF_AMOUNT;
|
||||
break;
|
||||
}
|
||||
return withdrawalFeeType;
|
||||
}
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
package org.mifosplatform.portfolio.savings.exception;
|
||||
|
||||
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class InvalidSavingsProductSettingsException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public InvalidSavingsProductSettingsException(final String errorCode, final String defaultMessage, final String paramName) {
|
||||
super(errorCode, defaultMessage, paramName);
|
||||
}
|
||||
}
|
||||
+35
-7
@@ -112,8 +112,11 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sa.min_required_opening_balance as minRequiredOpeningBalance, ");
|
||||
sqlBuilder.append("sa.lockin_period_frequency as lockinPeriodFrequency,");
|
||||
sqlBuilder.append("sa.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
sqlBuilder.append("sa.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
sqlBuilder.append("sa.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sa.total_deposits_derived as totalDeposits, ");
|
||||
sqlBuilder.append("sa.total_withdrawals_derived as totalWithdrawals, ");
|
||||
sqlBuilder.append("sa.total_withdrawal_fees_derived as totalWithdrawalFees, ");
|
||||
sqlBuilder.append("sa.total_interest_earned_derived as totalInterestEarned, ");
|
||||
sqlBuilder.append("sa.total_interest_posted_derived as totalInterestPosted, ");
|
||||
sqlBuilder.append("sa.account_balance_derived as accountBalance ");
|
||||
@@ -184,19 +187,29 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodType);
|
||||
}
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
|
||||
EnumOptionData withdrawalFeeType = null;
|
||||
final Integer withdrawalFeeTypeValue = JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum");
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal totalDeposits = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalDeposits");
|
||||
final BigDecimal totalWithdrawals = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawals");
|
||||
final BigDecimal totalWithdrawalFees = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawalFees");
|
||||
|
||||
final BigDecimal totalInterestEarned = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalInterestEarned");
|
||||
final BigDecimal totalInterestPosted = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalInterestPosted");
|
||||
final BigDecimal accountBalance = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "accountBalance");
|
||||
|
||||
final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals,
|
||||
totalInterestEarned, totalInterestPosted, accountBalance);
|
||||
totalWithdrawalFees, totalInterestEarned, totalInterestPosted, accountBalance);
|
||||
|
||||
return SavingsAccountData.instance(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
||||
productId, productName, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, summary);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, summary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,11 +251,14 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = this.dropdownReadPlatformService
|
||||
.retrieveLockinPeriodFrequencyTypeOptions();
|
||||
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = this.dropdownReadPlatformService.retrievewithdrawalFeeTypeOptions();
|
||||
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
|
||||
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, transactions);
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions);
|
||||
} else {
|
||||
|
||||
String clientName = null;
|
||||
@@ -262,11 +278,13 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
|
||||
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
|
||||
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
|
||||
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
|
||||
template = SavingsAccountData.withTemplateOptions(template, productOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, transactions);
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions);
|
||||
}
|
||||
|
||||
return template;
|
||||
@@ -404,8 +422,10 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
sqlBuilder.append("sp.interest_calculation_type_enum as interestCalculationType, ");
|
||||
sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
|
||||
sqlBuilder.append("sp.min_required_opening_balance as minRequiredOpeningBalance, ");
|
||||
sqlBuilder.append("sp.lockin_period_frequency as lockinPeriodFrequency, ");
|
||||
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType ");
|
||||
sqlBuilder.append("sp.lockin_period_frequency as lockinPeriodFrequency,");
|
||||
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
sqlBuilder.append("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum ");
|
||||
sqlBuilder.append("from m_savings_product sp ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
||||
|
||||
@@ -456,6 +476,14 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodType);
|
||||
}
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
|
||||
EnumOptionData withdrawalFeeType = null;
|
||||
final Integer withdrawalFeeTypeValue = JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum");
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
Long clientId = null;
|
||||
String clientName = null;
|
||||
if (client != null) {
|
||||
@@ -476,7 +504,7 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
return SavingsAccountData.instance(null, null, null, status, activationDate, groupId, groupName, clientId, clientName,
|
||||
productId, productName, currency, nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, summary);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -137,7 +137,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
.build();
|
||||
} catch (DataAccessException dve) {
|
||||
handleDataIntegrityIssues(command, dve);
|
||||
return new CommandProcessingResult(Long.valueOf(-1));
|
||||
return CommandProcessingResult.empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -15,4 +15,6 @@ public interface SavingsDropdownReadPlatformService {
|
||||
Collection<EnumOptionData> retrieveInterestCalculationTypeOptions();
|
||||
|
||||
Collection<EnumOptionData> retrieveInterestCalculationDaysInYearTypeOptions();
|
||||
|
||||
Collection<EnumOptionData> retrievewithdrawalFeeTypeOptions();
|
||||
}
|
||||
+11
@@ -10,11 +10,22 @@ import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDays
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPostingPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsWithdrawalFeesType;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SavingsDropdownReadPlatformServiceImpl implements SavingsDropdownReadPlatformService {
|
||||
|
||||
@Override
|
||||
public Collection<EnumOptionData> retrievewithdrawalFeeTypeOptions() {
|
||||
List<EnumOptionData> allowedOptions = Arrays.asList( //
|
||||
SavingsEnumerations.withdrawalFeeType(SavingsWithdrawalFeesType.FLAT), //
|
||||
SavingsEnumerations.withdrawalFeeType(SavingsWithdrawalFeesType.PERCENT_OF_AMOUNT) //
|
||||
);
|
||||
|
||||
return allowedOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveLockinPeriodFrequencyTypeOptions() {
|
||||
List<EnumOptionData> allowedLockinPeriodFrequencyTypeOptions = Arrays.asList( //
|
||||
|
||||
+31
-1
@@ -15,6 +15,7 @@ import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDays
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPostingPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsWithdrawalFeesType;
|
||||
|
||||
public class SavingsEnumerations {
|
||||
|
||||
@@ -75,6 +76,11 @@ public class SavingsEnumerations {
|
||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.INTEREST_POSTING.getValue().longValue(),
|
||||
SavingsAccountTransactionType.INTEREST_POSTING.getCode(), "Interest posting");
|
||||
break;
|
||||
case WITHDRAWAL_FEE:
|
||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue().longValue(),
|
||||
SavingsAccountTransactionType.WITHDRAWAL_FEE.getCode(), "Withdrawal fee");
|
||||
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
@@ -144,7 +150,7 @@ public class SavingsEnumerations {
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData interestPeriodType(final Integer type) {
|
||||
public static EnumOptionData compoundingInterestPeriodType(final Integer type) {
|
||||
return compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(type));
|
||||
}
|
||||
|
||||
@@ -243,4 +249,28 @@ public class SavingsEnumerations {
|
||||
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData withdrawalFeeType(final Integer type) {
|
||||
return withdrawalFeeType(SavingsWithdrawalFeesType.fromInt(type));
|
||||
}
|
||||
|
||||
public static EnumOptionData withdrawalFeeType(final SavingsWithdrawalFeesType type) {
|
||||
EnumOptionData optionData = new EnumOptionData(SavingsWithdrawalFeesType.INVALID.getValue().longValue(),
|
||||
SavingsWithdrawalFeesType.INVALID.getCode(), "Invalid");
|
||||
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
break;
|
||||
case FLAT:
|
||||
optionData = new EnumOptionData(SavingsWithdrawalFeesType.FLAT.getValue().longValue(),
|
||||
SavingsWithdrawalFeesType.FLAT.getCode(), "Flat");
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT:
|
||||
optionData = new EnumOptionData(SavingsWithdrawalFeesType.PERCENT_OF_AMOUNT.getValue().longValue(),
|
||||
SavingsWithdrawalFeesType.PERCENT_OF_AMOUNT.getCode(), "% of Amount");
|
||||
break;
|
||||
}
|
||||
|
||||
return optionData;
|
||||
}
|
||||
}
|
||||
+20
-18
@@ -16,11 +16,6 @@ import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSourc
|
||||
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
import org.mifosplatform.portfolio.savings.data.SavingsProductData;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsCompoundingInterestPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationDaysInYearType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestCalculationType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsInterestPostingPeriodType;
|
||||
import org.mifosplatform.portfolio.savings.domain.SavingsPeriodFrequencyType;
|
||||
import org.mifosplatform.portfolio.savings.exception.SavingsProductNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
@@ -88,7 +83,9 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum as interestCalculationDaysInYearType, ");
|
||||
sqlBuilder.append("sp.min_required_opening_balance as minRequiredOpeningBalance, ");
|
||||
sqlBuilder.append("sp.lockin_period_frequency as lockinPeriodFrequency,");
|
||||
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType ");
|
||||
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||
sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||
sqlBuilder.append("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum ");
|
||||
sqlBuilder.append("from m_savings_product sp ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
||||
|
||||
@@ -116,23 +113,21 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
currencyNameCode);
|
||||
final BigDecimal nominalAnnualInterestRate = rs.getBigDecimal("nominalAnnualInterestRate");
|
||||
|
||||
final Integer compoundingInterestPeriodTypeValue = JdbcSupport.getInteger(rs, "compoundingInterestPeriodType");
|
||||
EnumOptionData compoundingInterestPeriodType = SavingsEnumerations
|
||||
.compoundingInterestPeriodType(SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
|
||||
"compoundingInterestPeriodType")));
|
||||
.compoundingInterestPeriodType(compoundingInterestPeriodTypeValue);
|
||||
|
||||
SavingsInterestPostingPeriodType interestPostingPeriod = SavingsInterestPostingPeriodType.fromInt(JdbcSupport.getInteger(rs,
|
||||
"interestPostingPeriodType"));
|
||||
EnumOptionData interestPostingPeriodType = SavingsEnumerations.interestPostingPeriodType(interestPostingPeriod);
|
||||
final Integer interestPostingPeriodTypeValue = JdbcSupport.getInteger(rs, "interestPostingPeriodType");
|
||||
EnumOptionData interestPostingPeriodType = SavingsEnumerations.interestPostingPeriodType(interestPostingPeriodTypeValue);
|
||||
|
||||
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(SavingsInterestCalculationType
|
||||
.fromInt(JdbcSupport.getInteger(rs, "interestCalculationType")));
|
||||
final Integer interestCalculationTypeValue = JdbcSupport.getInteger(rs, "interestCalculationType");
|
||||
EnumOptionData interestCalculationType = SavingsEnumerations.interestCalculationType(interestCalculationTypeValue);
|
||||
|
||||
EnumOptionData interestCalculationDaysInYearType = null;
|
||||
final Integer interestCalculationDaysInYearTypeValue = JdbcSupport.getInteger(rs, "interestCalculationDaysInYearType");
|
||||
if (interestCalculationDaysInYearTypeValue != null) {
|
||||
interestCalculationDaysInYearType = SavingsEnumerations
|
||||
.interestCalculationDaysInYearType(SavingsInterestCalculationDaysInYearType
|
||||
.fromInt(interestCalculationDaysInYearTypeValue));
|
||||
.interestCalculationDaysInYearType(interestCalculationDaysInYearTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal minRequiredOpeningBalance = rs.getBigDecimal("minRequiredOpeningBalance");
|
||||
@@ -141,13 +136,20 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final Integer lockinPeriodFrequencyTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodFrequencyType");
|
||||
if (lockinPeriodFrequencyTypeValue != null) {
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(SavingsPeriodFrequencyType
|
||||
.fromInt(lockinPeriodFrequencyTypeValue));
|
||||
lockinPeriodFrequencyType = SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodFrequencyTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal withdrawalFeeAmount = rs.getBigDecimal("withdrawalFeeAmount");
|
||||
|
||||
EnumOptionData withdrawalFeeType = null;
|
||||
final Integer withdrawalFeeTypeValue = JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum");
|
||||
if (withdrawalFeeTypeValue != null) {
|
||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
return SavingsProductData.instance(id, name, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -72,8 +72,6 @@ public class SavingsProductWritePlatformServiceJpaRepositoryImpl implements Savi
|
||||
public CommandProcessingResult create(final JsonCommand command) {
|
||||
|
||||
try {
|
||||
this.context.authenticatedUser();
|
||||
|
||||
this.fromApiJsonDataValidator.validateForCreate(command.json());
|
||||
|
||||
final SavingsProduct product = this.savingsProductAssembler.assemble(command);
|
||||
|
||||
Reference in New Issue
Block a user