MIFOSX-246: add support for annual fees on product and savings account. need to introduce overnight process to check and update annual fees.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
ALTER TABLE `m_savings_product`
|
||||
ADD COLUMN `annual_fee_amount` DECIMAL(19,6) NULL DEFAULT NULL AFTER `withdrawal_fee_type_enum`,
|
||||
ADD COLUMN `annual_fee_on_month` SMALLINT(5) NULL DEFAULT NULL AFTER `annual_fee_amount`,
|
||||
ADD COLUMN `annual_fee_on_day` SMALLINT(5) NULL DEFAULT NULL AFTER `annual_fee_on_month`;
|
||||
|
||||
ALTER TABLE `m_savings_account`
|
||||
ADD COLUMN `annual_fee_amount` DECIMAL(19,6) NULL DEFAULT NULL AFTER `withdrawal_fee_type_enum`,
|
||||
ADD COLUMN `annual_fee_on_month` SMALLINT(5) NULL DEFAULT NULL AFTER `annual_fee_amount`,
|
||||
ADD COLUMN `annual_fee_on_day` SMALLINT(5) NULL DEFAULT NULL AFTER `annual_fee_on_month`,
|
||||
ADD COLUMN `annual_fee_next_due_date` DATE NULL DEFAULT NULL AFTER `annual_fee_on_day`;
|
||||
|
||||
ALTER TABLE `m_savings_account`
|
||||
ADD COLUMN `total_annual_fees_derived` DECIMAL(19,6) NULL DEFAULT NULL AFTER `total_withdrawal_fees_derived`;
|
||||
+1
-1
@@ -22,7 +22,7 @@ public class JodaDateTimeAdapter implements JsonSerializer<DateTime> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public JsonElement serialize(DateTime src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
public JsonElement serialize(final DateTime src, final Type typeOfSrc, final JsonSerializationContext context) {
|
||||
|
||||
JsonElement element = null;
|
||||
if (src != null) {
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ public class JodaLocalDateAdapter implements JsonSerializer<LocalDate> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
public JsonElement serialize(final LocalDate src, final Type typeOfSrc, final JsonSerializationContext context) {
|
||||
|
||||
JsonArray array = null;
|
||||
if (src != null) {
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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.api;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.joda.time.MonthDay;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
/**
|
||||
* Serializer for joda time {@link MonthDay} that returns date in array format
|
||||
* to match previous jackson functionality.
|
||||
*/
|
||||
public class JodaMonthDayAdapter implements JsonSerializer<MonthDay> {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public JsonElement serialize(final MonthDay src, final Type typeOfSrc, final JsonSerializationContext context) {
|
||||
|
||||
JsonArray array = null;
|
||||
if (src != null) {
|
||||
array = new JsonArray();
|
||||
array.add(new JsonPrimitive(src.getMonthOfYear()));
|
||||
array.add(new JsonPrimitive(src.getDayOfMonth()));
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
||||
+5
@@ -13,6 +13,7 @@ import java.util.Locale;
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.mifosplatform.infrastructure.security.domain.BasicPasswordEncodablePlatformUser;
|
||||
import org.mifosplatform.infrastructure.security.domain.PlatformUser;
|
||||
@@ -261,6 +262,10 @@ public final class JsonCommand {
|
||||
return this.fromApiJsonHelper.extractLocalDateNamed(parameterName, parsedCommand);
|
||||
}
|
||||
|
||||
public MonthDay extractMonthDayNamed(final String parameterName) {
|
||||
return this.fromApiJsonHelper.extractMonthDayNamed(parameterName, parsedCommand);
|
||||
}
|
||||
|
||||
public Date DateValueOfParameterNamed(final String parameterName) {
|
||||
LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(parameterName, parsedCommand);
|
||||
if (localDate == null) { return null; }
|
||||
|
||||
+3
@@ -7,8 +7,10 @@ package org.mifosplatform.infrastructure.core.serialization;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaMonthDayAdapter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
@@ -28,6 +30,7 @@ public final class CommandProcessingResultJsonSerializer {
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||
builder.serializeNulls();
|
||||
|
||||
this.gson = builder.create();
|
||||
|
||||
+3
@@ -7,8 +7,10 @@ package org.mifosplatform.infrastructure.core.serialization;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaMonthDayAdapter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
@@ -28,6 +30,7 @@ public final class ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson {
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||
|
||||
this.gson = builder.create();
|
||||
}
|
||||
|
||||
+3
@@ -7,8 +7,10 @@ package org.mifosplatform.infrastructure.core.serialization;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaMonthDayAdapter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
@@ -28,6 +30,7 @@ public final class ExcludeNothingWithPrettyPrintingOnJsonSerializerGoogleGson {
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||
builder.setPrettyPrinting();
|
||||
|
||||
this.gson = builder.create();
|
||||
|
||||
+5
@@ -16,6 +16,7 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -114,6 +115,10 @@ public class FromJsonHelper {
|
||||
return helperDelegator.extractBooleanNamed(parameterName, element, parametersPassedInRequest);
|
||||
}
|
||||
|
||||
public MonthDay extractMonthDayNamed(final String parameterName, final JsonElement element) {
|
||||
return helperDelegator.extractMonthDayNamed(parameterName, element);
|
||||
}
|
||||
|
||||
public LocalDate extractLocalDateNamed(final String parameterName, final JsonElement element) {
|
||||
return helperDelegator.extractLocalDateNamed(parameterName, element, new HashSet<String>());
|
||||
}
|
||||
|
||||
+4
@@ -11,8 +11,10 @@ import java.util.Set;
|
||||
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
||||
import org.mifosplatform.infrastructure.core.api.JodaMonthDayAdapter;
|
||||
import org.mifosplatform.infrastructure.core.api.ParameterListExclusionStrategy;
|
||||
import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -31,6 +33,7 @@ public final class GoogleGsonSerializerHelper {
|
||||
final GsonBuilder builder = new GsonBuilder();
|
||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||
if (prettyPrint) {
|
||||
builder.setPrettyPrinting();
|
||||
}
|
||||
@@ -61,6 +64,7 @@ public final class GoogleGsonSerializerHelper {
|
||||
final GsonBuilder builder = new GsonBuilder().addSerializationExclusionStrategy(strategy);
|
||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||
if (prettyPrint) {
|
||||
builder.setPrettyPrinting();
|
||||
}
|
||||
|
||||
+50
@@ -18,7 +18,9 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.springframework.format.number.NumberFormatter;
|
||||
@@ -181,6 +183,20 @@ public class JsonParserHelper {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String extractMonthDayFormatParameter(final JsonObject element) {
|
||||
String value = null;
|
||||
if (element.isJsonObject()) {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
|
||||
final String monthDayFormatParameter = "monthDayFormat";
|
||||
if (object.has(monthDayFormatParameter) && object.get(monthDayFormatParameter).isJsonPrimitive()) {
|
||||
final JsonPrimitive primitive = object.get(monthDayFormatParameter).getAsJsonPrimitive();
|
||||
value = primitive.getAsString();
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public Locale extractLocaleParameter(final JsonObject element) {
|
||||
Locale clientApplicationLocale = null;
|
||||
if (element.isJsonObject()) {
|
||||
@@ -252,6 +268,40 @@ public class JsonParserHelper {
|
||||
return value;
|
||||
}
|
||||
|
||||
public MonthDay extractMonthDayNamed(final String parameterName, final JsonElement element) {
|
||||
|
||||
MonthDay value = null;
|
||||
|
||||
if (element.isJsonObject()) {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
|
||||
final String monthDayFormat = extractMonthDayFormatParameter(object);
|
||||
final Locale clientApplicationLocale = extractLocaleParameter(object);
|
||||
value = extractMonthDayNamed(parameterName, object, monthDayFormat, clientApplicationLocale);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public MonthDay extractMonthDayNamed(final String parameterName, final JsonObject element, final String dateFormat,
|
||||
final Locale clientApplicationLocale) {
|
||||
MonthDay value = null;
|
||||
if (element.isJsonObject()) {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
|
||||
if (object.has(parameterName) && object.get(parameterName).isJsonPrimitive()) {
|
||||
|
||||
final JsonPrimitive primitive = object.get(parameterName).getAsJsonPrimitive();
|
||||
final String valueAsString = primitive.getAsString();
|
||||
if (StringUtils.isNotBlank(valueAsString)) {
|
||||
DateTimeFormatter formatter = DateTimeFormat.forPattern(dateFormat).withLocale(clientApplicationLocale);
|
||||
value = MonthDay.parse(valueAsString.toLowerCase(clientApplicationLocale), formatter);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public LocalDate extractLocalDateNamed(final String parameterName, final JsonElement element,
|
||||
final Set<String> parametersPassedInCommand) {
|
||||
|
||||
|
||||
+208
-282
@@ -45,335 +45,261 @@ import com.google.gson.JsonArray;
|
||||
@Table(name = "m_product_loan", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name") })
|
||||
public class LoanProduct extends AbstractPersistable<Long> {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fund_id", nullable = true)
|
||||
private Fund fund;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "fund_id", nullable = true)
|
||||
private Fund fund;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
|
||||
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
|
||||
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
|
||||
|
||||
@Column(name = "name", nullable = false, unique = true)
|
||||
private String name;
|
||||
@Column(name = "name", nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "m_product_loan_charge", joinColumns = @JoinColumn(name = "product_loan_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
|
||||
private List<Charge> charges;
|
||||
@ManyToMany
|
||||
@JoinTable(name = "m_product_loan_charge", joinColumns = @JoinColumn(name = "product_loan_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
|
||||
private List<Charge> charges;
|
||||
|
||||
@Embedded
|
||||
private final LoanProductRelatedDetail loanProductRelatedDetail;
|
||||
@Embedded
|
||||
private final LoanProductRelatedDetail loanProductRelatedDetail;
|
||||
|
||||
@Embedded
|
||||
private LoanProductMinMaxConstraints loanProductMinMaxConstraints;
|
||||
@Embedded
|
||||
private LoanProductMinMaxConstraints loanProductMinMaxConstraints;
|
||||
|
||||
@Column(name = "accounting_type", nullable = false)
|
||||
private Integer accountingRule;
|
||||
@Column(name = "accounting_type", nullable = false)
|
||||
private Integer accountingRule;
|
||||
|
||||
public static LoanProduct assembleFromJson(
|
||||
final Fund fund,
|
||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
|
||||
final List<Charge> productCharges, final JsonCommand command,
|
||||
final AprCalculator aprCalculator) {
|
||||
public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
|
||||
final List<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator) {
|
||||
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
final String description = command
|
||||
.stringValueOfParameterNamed("description");
|
||||
final String currencyCode = command
|
||||
.stringValueOfParameterNamed("currencyCode");
|
||||
final Integer digitsAfterDecimal = command
|
||||
.integerValueOfParameterNamed("digitsAfterDecimal");
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
final String description = command.stringValueOfParameterNamed("description");
|
||||
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||
final Integer digitsAfterDecimal = command.integerValueOfParameterNamed("digitsAfterDecimal");
|
||||
|
||||
final MonetaryCurrency currency = new MonetaryCurrency(currencyCode,
|
||||
digitsAfterDecimal);
|
||||
final BigDecimal principal = command
|
||||
.bigDecimalValueOfParameterNamed("principal");
|
||||
final BigDecimal minPrincipal = command
|
||||
.bigDecimalValueOfParameterNamed("minPrincipal");
|
||||
final BigDecimal maxPrincipal = command
|
||||
.bigDecimalValueOfParameterNamed("maxPrincipal");
|
||||
final MonetaryCurrency currency = new MonetaryCurrency(currencyCode, digitsAfterDecimal);
|
||||
final BigDecimal principal = command.bigDecimalValueOfParameterNamed("principal");
|
||||
final BigDecimal minPrincipal = command.bigDecimalValueOfParameterNamed("minPrincipal");
|
||||
final BigDecimal maxPrincipal = command.bigDecimalValueOfParameterNamed("maxPrincipal");
|
||||
|
||||
final InterestMethod interestMethod = InterestMethod.fromInt(command
|
||||
.integerValueOfParameterNamed("interestType"));
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod
|
||||
.fromInt(command
|
||||
.integerValueOfParameterNamed("interestCalculationPeriodType"));
|
||||
final AmortizationMethod amortizationMethod = AmortizationMethod
|
||||
.fromInt(command
|
||||
.integerValueOfParameterNamed("amortizationType"));
|
||||
final PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType
|
||||
.fromInt(command
|
||||
.integerValueOfParameterNamed("repaymentFrequencyType"));
|
||||
final PeriodFrequencyType interestFrequencyType = PeriodFrequencyType
|
||||
.fromInt(command
|
||||
.integerValueOfParameterNamed("interestRateFrequencyType"));
|
||||
final BigDecimal interestRatePerPeriod = command
|
||||
.bigDecimalValueOfParameterNamed("interestRatePerPeriod");
|
||||
final BigDecimal minInterestRatePerPeriod = command
|
||||
.bigDecimalValueOfParameterNamed("minInterestRatePerPeriod");
|
||||
final BigDecimal maxInterestRatePerPeriod = command
|
||||
.bigDecimalValueOfParameterNamed("maxInterestRatePerPeriod");
|
||||
final BigDecimal annualInterestRate = aprCalculator.calculateFrom(
|
||||
interestFrequencyType, interestRatePerPeriod);
|
||||
final InterestMethod interestMethod = InterestMethod.fromInt(command.integerValueOfParameterNamed("interestType"));
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod.fromInt(command
|
||||
.integerValueOfParameterNamed("interestCalculationPeriodType"));
|
||||
final AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(command.integerValueOfParameterNamed("amortizationType"));
|
||||
final PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.fromInt(command
|
||||
.integerValueOfParameterNamed("repaymentFrequencyType"));
|
||||
final PeriodFrequencyType interestFrequencyType = PeriodFrequencyType.fromInt(command
|
||||
.integerValueOfParameterNamed("interestRateFrequencyType"));
|
||||
final BigDecimal interestRatePerPeriod = command.bigDecimalValueOfParameterNamed("interestRatePerPeriod");
|
||||
final BigDecimal minInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("minInterestRatePerPeriod");
|
||||
final BigDecimal maxInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("maxInterestRatePerPeriod");
|
||||
final BigDecimal annualInterestRate = aprCalculator.calculateFrom(interestFrequencyType, interestRatePerPeriod);
|
||||
|
||||
final Integer repaymentEvery = command
|
||||
.integerValueOfParameterNamed("repaymentEvery");
|
||||
final Integer numberOfRepayments = command
|
||||
.integerValueOfParameterNamed("numberOfRepayments");
|
||||
final Integer minNumberOfRepayments = command
|
||||
.integerValueOfParameterNamed("minNumberOfRepayments");
|
||||
final Integer maxNumberOfRepayments = command
|
||||
.integerValueOfParameterNamed("maxNumberOfRepayments");
|
||||
final BigDecimal inArrearsTolerance = command
|
||||
.bigDecimalValueOfParameterNamed("inArrearsTolerance");
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType
|
||||
.fromInt(command.integerValueOfParameterNamed("accountingRule"));
|
||||
final Integer repaymentEvery = command.integerValueOfParameterNamed("repaymentEvery");
|
||||
final Integer numberOfRepayments = command.integerValueOfParameterNamed("numberOfRepayments");
|
||||
final Integer minNumberOfRepayments = command.integerValueOfParameterNamed("minNumberOfRepayments");
|
||||
final Integer maxNumberOfRepayments = command.integerValueOfParameterNamed("maxNumberOfRepayments");
|
||||
final BigDecimal inArrearsTolerance = command.bigDecimalValueOfParameterNamed("inArrearsTolerance");
|
||||
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule"));
|
||||
|
||||
return new LoanProduct(fund, loanTransactionProcessingStrategy, name,
|
||||
description, currency, principal, minPrincipal, maxPrincipal,
|
||||
interestRatePerPeriod, minInterestRatePerPeriod,
|
||||
maxInterestRatePerPeriod, interestFrequencyType,
|
||||
annualInterestRate, interestMethod,
|
||||
interestCalculationPeriodMethod, repaymentEvery,
|
||||
repaymentFrequencyType, numberOfRepayments,
|
||||
minNumberOfRepayments, maxNumberOfRepayments,
|
||||
amortizationMethod, inArrearsTolerance, productCharges,
|
||||
accountingRuleType);
|
||||
}
|
||||
return new LoanProduct(fund, loanTransactionProcessingStrategy, name, description, currency, principal, minPrincipal, maxPrincipal,
|
||||
interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType, annualInterestRate,
|
||||
interestMethod, interestCalculationPeriodMethod, repaymentEvery, repaymentFrequencyType, numberOfRepayments,
|
||||
minNumberOfRepayments, maxNumberOfRepayments, amortizationMethod, inArrearsTolerance, productCharges, accountingRuleType);
|
||||
}
|
||||
|
||||
protected LoanProduct() {
|
||||
this.loanProductRelatedDetail = null;
|
||||
this.loanProductMinMaxConstraints = null;
|
||||
}
|
||||
protected LoanProduct() {
|
||||
this.loanProductRelatedDetail = null;
|
||||
this.loanProductMinMaxConstraints = null;
|
||||
}
|
||||
|
||||
public LoanProduct(
|
||||
final Fund fund,
|
||||
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
||||
final String name,
|
||||
final String description,
|
||||
final MonetaryCurrency currency,
|
||||
final BigDecimal defaultPrincipal,
|
||||
final BigDecimal defaultMinPrincipal,
|
||||
final BigDecimal defaultMaxPrincipal,
|
||||
final BigDecimal defaultNominalInterestRatePerPeriod,
|
||||
final BigDecimal defaultMinNominalInterestRatePerPeriod,
|
||||
final BigDecimal defaultMaxNominalInterestRatePerPeriod,
|
||||
final PeriodFrequencyType interestPeriodFrequencyType,
|
||||
final BigDecimal defaultAnnualNominalInterestRate,
|
||||
final InterestMethod interestMethod,
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod,
|
||||
final Integer repayEvery,
|
||||
final PeriodFrequencyType repaymentFrequencyType,
|
||||
final Integer defaultNumberOfInstallments,
|
||||
final Integer defaultMinNumberOfInstallments,
|
||||
final Integer defaultMaxNumberOfInstallments,
|
||||
final AmortizationMethod amortizationMethod,
|
||||
final BigDecimal inArrearsTolerance, final List<Charge> charges,
|
||||
final AccountingRuleType accountingRuleType) {
|
||||
this.fund = fund;
|
||||
this.transactionProcessingStrategy = transactionProcessingStrategy;
|
||||
this.name = name.trim();
|
||||
if (StringUtils.isNotBlank(description)) {
|
||||
this.description = description.trim();
|
||||
} else {
|
||||
this.description = null;
|
||||
}
|
||||
public LoanProduct(final Fund fund, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final String name,
|
||||
final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
|
||||
final BigDecimal defaultMinPrincipal, final BigDecimal defaultMaxPrincipal,
|
||||
final BigDecimal defaultNominalInterestRatePerPeriod, final BigDecimal defaultMinNominalInterestRatePerPeriod,
|
||||
final BigDecimal defaultMaxNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType,
|
||||
final BigDecimal defaultAnnualNominalInterestRate, final InterestMethod interestMethod,
|
||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Integer repayEvery,
|
||||
final PeriodFrequencyType repaymentFrequencyType, final Integer defaultNumberOfInstallments,
|
||||
final Integer defaultMinNumberOfInstallments, final Integer defaultMaxNumberOfInstallments,
|
||||
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List<Charge> charges,
|
||||
final AccountingRuleType accountingRuleType) {
|
||||
this.fund = fund;
|
||||
this.transactionProcessingStrategy = transactionProcessingStrategy;
|
||||
this.name = name.trim();
|
||||
if (StringUtils.isNotBlank(description)) {
|
||||
this.description = description.trim();
|
||||
} else {
|
||||
this.description = null;
|
||||
}
|
||||
|
||||
if (charges != null) {
|
||||
this.charges = charges;
|
||||
}
|
||||
if (charges != null) {
|
||||
this.charges = charges;
|
||||
}
|
||||
|
||||
this.loanProductRelatedDetail = new LoanProductRelatedDetail(currency,
|
||||
defaultPrincipal, defaultNominalInterestRatePerPeriod,
|
||||
interestPeriodFrequencyType, defaultAnnualNominalInterestRate,
|
||||
interestMethod, interestCalculationPeriodMethod, repayEvery,
|
||||
repaymentFrequencyType, defaultNumberOfInstallments,
|
||||
amortizationMethod, inArrearsTolerance);
|
||||
this.loanProductRelatedDetail = new LoanProductRelatedDetail(currency, defaultPrincipal, defaultNominalInterestRatePerPeriod,
|
||||
interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery,
|
||||
repaymentFrequencyType, defaultNumberOfInstallments, amortizationMethod, inArrearsTolerance);
|
||||
|
||||
this.loanProductMinMaxConstraints = new LoanProductMinMaxConstraints(
|
||||
defaultMinPrincipal, defaultMaxPrincipal,
|
||||
defaultMinNominalInterestRatePerPeriod,
|
||||
defaultMaxNominalInterestRatePerPeriod,
|
||||
defaultMinNumberOfInstallments, defaultMaxNumberOfInstallments);
|
||||
this.loanProductMinMaxConstraints = new LoanProductMinMaxConstraints(defaultMinPrincipal, defaultMaxPrincipal,
|
||||
defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod, defaultMinNumberOfInstallments,
|
||||
defaultMaxNumberOfInstallments);
|
||||
|
||||
if (accountingRuleType != null) {
|
||||
this.accountingRule = accountingRuleType.getValue();
|
||||
}
|
||||
}
|
||||
if (accountingRuleType != null) {
|
||||
this.accountingRule = accountingRuleType.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
public MonetaryCurrency getCurrency() {
|
||||
return this.loanProductRelatedDetail.getCurrency();
|
||||
}
|
||||
public MonetaryCurrency getCurrency() {
|
||||
return this.loanProductRelatedDetail.getCurrency();
|
||||
}
|
||||
|
||||
public void update(final Fund fund) {
|
||||
this.fund = fund;
|
||||
}
|
||||
public void update(final Fund fund) {
|
||||
this.fund = fund;
|
||||
}
|
||||
|
||||
public void update(final LoanTransactionProcessingStrategy strategy) {
|
||||
this.transactionProcessingStrategy = strategy;
|
||||
}
|
||||
public void update(final LoanTransactionProcessingStrategy strategy) {
|
||||
this.transactionProcessingStrategy = strategy;
|
||||
}
|
||||
|
||||
public boolean update(final List<Charge> newProductCharges) {
|
||||
if (newProductCharges == null)
|
||||
return false;
|
||||
public boolean update(final List<Charge> newProductCharges) {
|
||||
if (newProductCharges == null) return false;
|
||||
|
||||
boolean updated = false;
|
||||
if (this.charges != null) {
|
||||
final Set<Charge> currentSetOfCharges = new HashSet<Charge>(
|
||||
this.charges);
|
||||
final Set<Charge> newSetOfCharges = new HashSet<Charge>(
|
||||
newProductCharges);
|
||||
boolean updated = false;
|
||||
if (this.charges != null) {
|
||||
final Set<Charge> currentSetOfCharges = new HashSet<Charge>(this.charges);
|
||||
final Set<Charge> newSetOfCharges = new HashSet<Charge>(newProductCharges);
|
||||
|
||||
if (!(currentSetOfCharges.equals(newSetOfCharges))) {
|
||||
updated = true;
|
||||
this.charges = newProductCharges;
|
||||
}
|
||||
} else {
|
||||
updated = true;
|
||||
this.charges = newProductCharges;
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
if (!(currentSetOfCharges.equals(newSetOfCharges))) {
|
||||
updated = true;
|
||||
this.charges = newProductCharges;
|
||||
}
|
||||
} else {
|
||||
updated = true;
|
||||
this.charges = newProductCharges;
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
public Integer getAccountingType() {
|
||||
return this.accountingRule;
|
||||
}
|
||||
public Integer getAccountingType() {
|
||||
return this.accountingRule;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command,
|
||||
final AprCalculator aprCalculator) {
|
||||
public Map<String, Object> update(final JsonCommand command, final AprCalculator aprCalculator) {
|
||||
|
||||
final Map<String, Object> actualChanges = this.loanProductRelatedDetail
|
||||
.update(command, aprCalculator);
|
||||
actualChanges.putAll(this.loanProductMinMaxConstraints()
|
||||
.update(command));
|
||||
final Map<String, Object> actualChanges = this.loanProductRelatedDetail.update(command, aprCalculator);
|
||||
actualChanges.putAll(this.loanProductMinMaxConstraints().update(command));
|
||||
|
||||
final String accountingTypeParamName = "accountingRule";
|
||||
if (command.isChangeInIntegerParameterNamed(accountingTypeParamName,
|
||||
this.accountingRule)) {
|
||||
final Integer newValue = command
|
||||
.integerValueOfParameterNamed(accountingTypeParamName);
|
||||
actualChanges.put(accountingTypeParamName, newValue);
|
||||
this.accountingRule = newValue;
|
||||
}
|
||||
final String accountingTypeParamName = "accountingRule";
|
||||
if (command.isChangeInIntegerParameterNamed(accountingTypeParamName, this.accountingRule)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(accountingTypeParamName);
|
||||
actualChanges.put(accountingTypeParamName, newValue);
|
||||
this.accountingRule = newValue;
|
||||
}
|
||||
|
||||
final String nameParamName = "name";
|
||||
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
|
||||
final String newValue = command
|
||||
.stringValueOfParameterNamed(nameParamName);
|
||||
actualChanges.put(nameParamName, newValue);
|
||||
this.name = newValue;
|
||||
}
|
||||
final String nameParamName = "name";
|
||||
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(nameParamName);
|
||||
actualChanges.put(nameParamName, newValue);
|
||||
this.name = newValue;
|
||||
}
|
||||
|
||||
final String descriptionParamName = "description";
|
||||
if (command.isChangeInStringParameterNamed(descriptionParamName,
|
||||
this.description)) {
|
||||
final String newValue = command
|
||||
.stringValueOfParameterNamed(descriptionParamName);
|
||||
actualChanges.put(descriptionParamName, newValue);
|
||||
this.description = newValue;
|
||||
}
|
||||
final String descriptionParamName = "description";
|
||||
if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
|
||||
actualChanges.put(descriptionParamName, newValue);
|
||||
this.description = newValue;
|
||||
}
|
||||
|
||||
Long existingFundId = null;
|
||||
if (this.fund != null) {
|
||||
existingFundId = this.fund.getId();
|
||||
}
|
||||
final String fundIdParamName = "fundId";
|
||||
if (command.isChangeInLongParameterNamed(fundIdParamName,
|
||||
existingFundId)) {
|
||||
final Long newValue = command
|
||||
.longValueOfParameterNamed(fundIdParamName);
|
||||
actualChanges.put(fundIdParamName, newValue);
|
||||
}
|
||||
Long existingFundId = null;
|
||||
if (this.fund != null) {
|
||||
existingFundId = this.fund.getId();
|
||||
}
|
||||
final String fundIdParamName = "fundId";
|
||||
if (command.isChangeInLongParameterNamed(fundIdParamName, existingFundId)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(fundIdParamName);
|
||||
actualChanges.put(fundIdParamName, newValue);
|
||||
}
|
||||
|
||||
Long existingStrategyId = null;
|
||||
if (this.transactionProcessingStrategy != null) {
|
||||
existingStrategyId = this.transactionProcessingStrategy.getId();
|
||||
}
|
||||
final String transactionProcessingStrategyParamName = "transactionProcessingStrategyId";
|
||||
if (command.isChangeInLongParameterNamed(
|
||||
transactionProcessingStrategyParamName, existingStrategyId)) {
|
||||
final Long newValue = command
|
||||
.longValueOfParameterNamed(transactionProcessingStrategyParamName);
|
||||
actualChanges.put(transactionProcessingStrategyParamName, newValue);
|
||||
}
|
||||
Long existingStrategyId = null;
|
||||
if (this.transactionProcessingStrategy != null) {
|
||||
existingStrategyId = this.transactionProcessingStrategy.getId();
|
||||
}
|
||||
final String transactionProcessingStrategyParamName = "transactionProcessingStrategyId";
|
||||
if (command.isChangeInLongParameterNamed(transactionProcessingStrategyParamName, existingStrategyId)) {
|
||||
final Long newValue = command.longValueOfParameterNamed(transactionProcessingStrategyParamName);
|
||||
actualChanges.put(transactionProcessingStrategyParamName, newValue);
|
||||
}
|
||||
|
||||
final String chargesParamName = "charges";
|
||||
if (command.hasParameter(chargesParamName)) {
|
||||
JsonArray jsonArray = command
|
||||
.arrayOfParameterNamed(chargesParamName);
|
||||
if (jsonArray != null) {
|
||||
final String chargesParamName = "charges";
|
||||
if (command.hasParameter(chargesParamName)) {
|
||||
JsonArray jsonArray = command.arrayOfParameterNamed(chargesParamName);
|
||||
if (jsonArray != null) {
|
||||
|
||||
}
|
||||
actualChanges.put(chargesParamName,
|
||||
command.jsonFragment(chargesParamName));
|
||||
}
|
||||
}
|
||||
actualChanges.put(chargesParamName, command.jsonFragment(chargesParamName));
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
public boolean isCashBasedAccountingEnabled() {
|
||||
return AccountingRuleType.CASH_BASED.getValue().equals(
|
||||
this.accountingRule);
|
||||
}
|
||||
public boolean isCashBasedAccountingEnabled() {
|
||||
return AccountingRuleType.CASH_BASED.getValue().equals(this.accountingRule);
|
||||
}
|
||||
|
||||
public boolean isAccrualBasedAccountingEnabled() {
|
||||
return AccountingRuleType.ACCRUAL_BASED.getValue().equals(
|
||||
this.accountingRule);
|
||||
}
|
||||
public boolean isAccrualBasedAccountingEnabled() {
|
||||
return AccountingRuleType.ACCRUAL_BASED.getValue().equals(this.accountingRule);
|
||||
}
|
||||
|
||||
public Money getPrincipalAmount() {
|
||||
return this.loanProductRelatedDetail.getPrincipal();
|
||||
}
|
||||
public Money getPrincipalAmount() {
|
||||
return this.loanProductRelatedDetail.getPrincipal();
|
||||
}
|
||||
|
||||
public Money getMinPrincipalAmount() {
|
||||
return Money.of(this.loanProductRelatedDetail.getCurrency(), this
|
||||
.loanProductMinMaxConstraints().getMinPrincipal());
|
||||
}
|
||||
public Money getMinPrincipalAmount() {
|
||||
return Money.of(this.loanProductRelatedDetail.getCurrency(), this.loanProductMinMaxConstraints().getMinPrincipal());
|
||||
}
|
||||
|
||||
public Money getMaxPrincipalAmount() {
|
||||
return Money.of(this.loanProductRelatedDetail.getCurrency(), this
|
||||
.loanProductMinMaxConstraints().getMaxPrincipal());
|
||||
}
|
||||
public Money getMaxPrincipalAmount() {
|
||||
return Money.of(this.loanProductRelatedDetail.getCurrency(), this.loanProductMinMaxConstraints().getMaxPrincipal());
|
||||
}
|
||||
|
||||
public BigDecimal getNominalInterestRatePerPeriod() {
|
||||
return this.loanProductRelatedDetail.getNominalInterestRatePerPeriod();
|
||||
}
|
||||
public BigDecimal getNominalInterestRatePerPeriod() {
|
||||
return this.loanProductRelatedDetail.getNominalInterestRatePerPeriod();
|
||||
}
|
||||
|
||||
public BigDecimal getMinNominalInterestRatePerPeriod() {
|
||||
return this.loanProductMinMaxConstraints()
|
||||
.getMinNominalInterestRatePerPeriod();
|
||||
}
|
||||
public BigDecimal getMinNominalInterestRatePerPeriod() {
|
||||
return this.loanProductMinMaxConstraints().getMinNominalInterestRatePerPeriod();
|
||||
}
|
||||
|
||||
public BigDecimal getMaxNominalInterestRatePerPeriod() {
|
||||
return this.loanProductMinMaxConstraints()
|
||||
.getMaxNominalInterestRatePerPeriod();
|
||||
}
|
||||
public BigDecimal getMaxNominalInterestRatePerPeriod() {
|
||||
return this.loanProductMinMaxConstraints().getMaxNominalInterestRatePerPeriod();
|
||||
}
|
||||
|
||||
public Integer getNumberOfRepayments() {
|
||||
return this.loanProductRelatedDetail().getNumberOfRepayments();
|
||||
}
|
||||
public Integer getNumberOfRepayments() {
|
||||
return this.loanProductRelatedDetail().getNumberOfRepayments();
|
||||
}
|
||||
|
||||
public Integer getMinNumberOfRepayments() {
|
||||
return this.loanProductMinMaxConstraints().getMinNumberOfRepayments();
|
||||
}
|
||||
public Integer getMinNumberOfRepayments() {
|
||||
return this.loanProductMinMaxConstraints().getMinNumberOfRepayments();
|
||||
}
|
||||
|
||||
public Integer getMaxNumberOfRepayments() {
|
||||
return this.loanProductMinMaxConstraints().getMaxNumberOfRepayments();
|
||||
}
|
||||
public Integer getMaxNumberOfRepayments() {
|
||||
return this.loanProductMinMaxConstraints().getMaxNumberOfRepayments();
|
||||
}
|
||||
|
||||
public LoanProductRelatedDetail loanProductRelatedDetail() {
|
||||
return this.loanProductRelatedDetail;
|
||||
}
|
||||
public LoanProductRelatedDetail loanProductRelatedDetail() {
|
||||
return this.loanProductRelatedDetail;
|
||||
}
|
||||
|
||||
public LoanProductMinMaxConstraints loanProductMinMaxConstraints() {
|
||||
// If all min and max fields are null then loanProductMinMaxConstraints
|
||||
// initialising to null
|
||||
// Reset LoanProductMinMaxConstraints with null values.
|
||||
this.loanProductMinMaxConstraints = (this.loanProductMinMaxConstraints == null) ? new LoanProductMinMaxConstraints(
|
||||
null, null, null, null, null, null)
|
||||
: this.loanProductMinMaxConstraints;
|
||||
return loanProductMinMaxConstraints;
|
||||
}
|
||||
public LoanProductMinMaxConstraints loanProductMinMaxConstraints() {
|
||||
// If all min and max fields are null then loanProductMinMaxConstraints
|
||||
// initialising to null
|
||||
// Reset LoanProductMinMaxConstraints with null values.
|
||||
this.loanProductMinMaxConstraints = (this.loanProductMinMaxConstraints == null) ? new LoanProductMinMaxConstraints(null, null,
|
||||
null, null, null, null) : this.loanProductMinMaxConstraints;
|
||||
return loanProductMinMaxConstraints;
|
||||
}
|
||||
}
|
||||
+22
-15
@@ -16,6 +16,7 @@ public class SavingsApiConstants {
|
||||
// general
|
||||
public static final String localeParamName = "locale";
|
||||
public static final String dateFormatParamName = "dateFormat";
|
||||
public static final String monthDayFormatParamName = "monthDayFormat";
|
||||
|
||||
// savings product and account parameters
|
||||
public static final String idParamName = "id";
|
||||
@@ -41,16 +42,19 @@ public class SavingsApiConstants {
|
||||
public static final String lockinPeriodFrequencyTypeParamName = "lockinPeriodFrequencyType";
|
||||
public static final String withdrawalFeeAmountParamName = "withdrawalFeeAmount";
|
||||
public static final String withdrawalFeeTypeParamName = "withdrawalFeeType";
|
||||
public static final String annualFeeAmountParamName = "annualFeeAmount";
|
||||
public static final String annualFeeOnMonthDayParamName = "annualFeeOnMonthDay";
|
||||
|
||||
// transaction parameters
|
||||
public static final String transactionDateParamName = "transactionDate";
|
||||
public static final String transactionAmountParamName = "transactionAmount";
|
||||
|
||||
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||
nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
|
||||
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName));
|
||||
monthDayFormatParamName, nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName,
|
||||
nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName,
|
||||
interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
|
||||
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
|
||||
annualFeeAmountParamName, annualFeeOnMonthDayParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
@@ -61,16 +65,18 @@ public class SavingsApiConstants {
|
||||
nameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
|
||||
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, "currencyOptions",
|
||||
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
|
||||
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions"));
|
||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, annualFeeAmountParamName,
|
||||
annualFeeOnMonthDayParamName, "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,
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName));
|
||||
dateFormatParamName, monthDayFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName,
|
||||
productIdParamName, activeParamName, activationDateParamName, nominalAnnualInterestRateParamName,
|
||||
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, annualFeeAmountParamName,
|
||||
annualFeeOnMonthDayParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of
|
||||
@@ -82,9 +88,10 @@ public class SavingsApiConstants {
|
||||
groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", nominalAnnualInterestRateParamName,
|
||||
interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
|
||||
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, "summary", "transactions", "productOptions",
|
||||
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
|
||||
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions"));
|
||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, annualFeeAmountParamName, annualFeeOnMonthDayParamName, "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));
|
||||
|
||||
+25
-10
@@ -9,6 +9,7 @@ import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
|
||||
@@ -39,6 +40,9 @@ public class SavingsAccountData {
|
||||
private final EnumOptionData lockinPeriodFrequencyType;
|
||||
private final BigDecimal withdrawalFeeAmount;
|
||||
private final EnumOptionData withdrawalFeeType;
|
||||
private final BigDecimal annualFeeAmount;
|
||||
private final MonthDay annualFeeOnMonthDay;
|
||||
private final LocalDate annualFeeNextDueDate;
|
||||
|
||||
// associations
|
||||
private final SavingsAccountSummaryData summary;
|
||||
@@ -68,7 +72,8 @@ public class SavingsAccountData {
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||
final EnumOptionData withdrawalFeeType, final SavingsAccountSummaryData summary) {
|
||||
final EnumOptionData withdrawalFeeType, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
||||
final LocalDate annualFeeNextDueDate, final SavingsAccountSummaryData summary) {
|
||||
|
||||
final Collection<SavingsProductData> productOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
@@ -83,9 +88,10 @@ public class SavingsAccountData {
|
||||
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
||||
productId, productName, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, summary, transactions, productOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
||||
annualFeeNextDueDate, summary, transactions, productOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||
@@ -101,9 +107,10 @@ public class SavingsAccountData {
|
||||
account.savingsProductName, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
|
||||
account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType,
|
||||
account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType,
|
||||
account.withdrawalFeeAmount, account.withdrawalFeeType, account.summary, transactions, productOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
account.withdrawalFeeAmount, account.withdrawalFeeType, account.annualFeeAmount, account.annualFeeOnMonthDay,
|
||||
account.annualFeeNextDueDate, account.summary, transactions, productOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
||||
@@ -127,6 +134,9 @@ public class SavingsAccountData {
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final BigDecimal withdrawalFeeAmount = null;
|
||||
final EnumOptionData withdrawalFeeType = null;
|
||||
final BigDecimal annualFeeAmount = null;
|
||||
final MonthDay annualFeeOnMonthDay = null;
|
||||
final LocalDate annualFeeNextDueDate = null;
|
||||
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
final Collection<SavingsAccountTransactionData> transactions = null;
|
||||
@@ -142,9 +152,10 @@ public class SavingsAccountData {
|
||||
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
||||
productId, productName, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, summary, transactions, productOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
||||
annualFeeNextDueDate, summary, transactions, productOptions, interestCompoundingPeriodTypeOptions,
|
||||
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
private SavingsAccountData(final Long id, final String accountNo, final String externalId, final SavingsAccountStatusEnumData status,
|
||||
@@ -154,6 +165,7 @@ public class SavingsAccountData {
|
||||
final EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
|
||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
||||
final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount, final EnumOptionData withdrawalFeeType,
|
||||
final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay, final LocalDate annualFeeNextDueDate,
|
||||
final SavingsAccountSummaryData summary, final Collection<SavingsAccountTransactionData> transactions,
|
||||
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||
@@ -182,6 +194,9 @@ public class SavingsAccountData {
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
this.withdrawalFeeType = withdrawalFeeType;
|
||||
this.annualFeeAmount = annualFeeAmount;
|
||||
this.annualFeeOnMonthDay = annualFeeOnMonthDay;
|
||||
this.annualFeeNextDueDate = annualFeeNextDueDate;
|
||||
|
||||
this.summary = summary;
|
||||
this.transactions = transactions;
|
||||
|
||||
+24
-5
@@ -3,6 +3,8 @@ package org.mifosplatform.portfolio.savings.data;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.accountNoParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activationDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.clientIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.externalIdParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.groupIdParamName;
|
||||
@@ -26,6 +28,7 @@ import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
@@ -173,6 +176,16 @@ public class SavingsAccountDataValidator {
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).notNull().positiveAmount();
|
||||
|
||||
if (annualFeeAmount != null) {
|
||||
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(monthDayOfAnnualFee).notNull();
|
||||
}
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -316,15 +329,21 @@ public class SavingsAccountDataValidator {
|
||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).ignoreIfNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(monthDayOfAnnualFee).ignoreIfNull();
|
||||
}
|
||||
|
||||
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); }
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -19,17 +19,19 @@ public class SavingsAccountSummaryData {
|
||||
private final BigDecimal totalDeposits;
|
||||
private final BigDecimal totalWithdrawals;
|
||||
private final BigDecimal totalWithdrawalFees;
|
||||
private final BigDecimal totalAnnualFees;
|
||||
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 totalWithdrawalFees, final BigDecimal totalInterestEarned, final BigDecimal totalInterestPosted,
|
||||
final BigDecimal accountBalance) {
|
||||
final BigDecimal totalWithdrawalFees, final BigDecimal totalAnnualFees, final BigDecimal totalInterestEarned,
|
||||
final BigDecimal totalInterestPosted, final BigDecimal accountBalance) {
|
||||
this.currency = currency;
|
||||
this.totalDeposits = totalDeposits;
|
||||
this.totalWithdrawals = totalWithdrawals;
|
||||
this.totalWithdrawalFees = totalWithdrawalFees;
|
||||
this.totalAnnualFees = totalAnnualFees;
|
||||
this.totalInterestEarned = totalInterestEarned;
|
||||
this.totalInterestPosted = totalInterestPosted;
|
||||
this.accountBalance = accountBalance;
|
||||
|
||||
+28
-17
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.savings.data;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||
|
||||
@@ -30,6 +31,8 @@ public class SavingsProductData {
|
||||
private final EnumOptionData lockinPeriodFrequencyType;
|
||||
private final BigDecimal withdrawalFeeAmount;
|
||||
private final EnumOptionData withdrawalFeeType;
|
||||
private final BigDecimal annualFeeAmount;
|
||||
private final MonthDay annualFeeOnMonthDay;
|
||||
|
||||
// template
|
||||
@SuppressWarnings("unused")
|
||||
@@ -65,12 +68,15 @@ public class SavingsProductData {
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final BigDecimal withdrawalFeeAmount = null;
|
||||
final EnumOptionData withdrawalFeeType = null;
|
||||
final BigDecimal annualFeeAmount = null;
|
||||
final MonthDay annualFeeMonthDay = null;
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, currencyOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||
annualFeeMonthDay, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,9 +95,9 @@ public class SavingsProductData {
|
||||
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||
existingProduct.interestCalculationDaysInYearType, existingProduct.minRequiredOpeningBalance,
|
||||
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.withdrawalFeeAmount,
|
||||
existingProduct.withdrawalFeeType, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions);
|
||||
existingProduct.withdrawalFeeType, existingProduct.annualFeeAmount, existingProduct.annualFeeOnMonthDay, currencyOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
public static SavingsProductData instance(final Long id, final String name, final String description, final CurrencyData currency,
|
||||
@@ -99,7 +105,7 @@ public class SavingsProductData {
|
||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||
final EnumOptionData withdrawalFeeType) {
|
||||
final EnumOptionData withdrawalFeeType, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay) {
|
||||
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
@@ -111,9 +117,10 @@ public class SavingsProductData {
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, currencyOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||
annualFeeOnMonthDay, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||
withdrawalFeeTypeOptions);
|
||||
}
|
||||
|
||||
public static SavingsProductData lookup(final Long id, final String name) {
|
||||
@@ -130,6 +137,8 @@ public class SavingsProductData {
|
||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||
final BigDecimal withdrawalFeeAmount = null;
|
||||
final EnumOptionData withdrawalFeeType = null;
|
||||
final BigDecimal annualFeeAmount = null;
|
||||
final MonthDay annualFeeMonthDay = null;
|
||||
|
||||
final Collection<CurrencyData> currencyOptions = null;
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||
@@ -141,19 +150,19 @@ public class SavingsProductData {
|
||||
|
||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, currencyOptions,
|
||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||
annualFeeMonthDay, 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 BigDecimal withdrawalFeeAmount, final EnumOptionData withdrawalFeeType,
|
||||
final Collection<CurrencyData> currencyOptions,
|
||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||
final EnumOptionData withdrawalFeeType, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
||||
final Collection<CurrencyData> currencyOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||
@@ -172,6 +181,8 @@ public class SavingsProductData {
|
||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||
this.withdrawalFeeType = withdrawalFeeType;
|
||||
this.annualFeeAmount = annualFeeAmount;
|
||||
this.annualFeeOnMonthDay = annualFeeOnMonthDay;
|
||||
|
||||
this.currencyOptions = currencyOptions;
|
||||
this.interestCompoundingPeriodTypeOptions = interestCompoundingPeriodTypeOptions;
|
||||
|
||||
+23
@@ -2,6 +2,8 @@ package org.mifosplatform.portfolio.savings.data;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||
@@ -24,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||
@@ -136,6 +139,16 @@ public class SavingsProductDataValidator {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).notNull().positiveAmount();
|
||||
|
||||
if (annualFeeAmount != null) {
|
||||
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(monthDayOfAnnualFee).notNull();
|
||||
}
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
@@ -222,6 +235,16 @@ public class SavingsProductDataValidator {
|
||||
.isOneOfTheseValues(1, 2);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) {
|
||||
final BigDecimal annualFeeAmount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed(annualFeeAmountParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeAmountParamName).value(annualFeeAmount).ignoreIfNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(annualFeeOnMonthDayParamName, element)) {
|
||||
MonthDay monthDayOfAnnualFee = fromApiJsonHelper.extractMonthDayNamed(annualFeeOnMonthDayParamName, element);
|
||||
baseDataValidator.reset().parameter(annualFeeOnMonthDayParamName).value(monthDayOfAnnualFee).ignoreIfNull();
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
|
||||
+155
-3
@@ -5,6 +5,12 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.localeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdrawalFeeTypeParamName;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
@@ -34,6 +40,7 @@ import org.hibernate.annotations.LazyCollection;
|
||||
import org.hibernate.annotations.LazyCollectionOption;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||
@@ -142,6 +149,19 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
@Column(name = "withdrawal_fee_type_enum", nullable = true)
|
||||
private Integer withdrawalFeeType;
|
||||
|
||||
@Column(name = "annual_fee_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal annualFeeAmount;
|
||||
|
||||
@Column(name = "annual_fee_on_month", nullable = true)
|
||||
private Integer annualFeeOnMonth;
|
||||
|
||||
@Column(name = "annual_fee_on_day", nullable = true)
|
||||
private Integer annualFeeOnDay;
|
||||
|
||||
@Temporal(TemporalType.DATE)
|
||||
@Column(name = "annual_fee_next_due_date", nullable = true)
|
||||
private Date annualFeeNextDueDate;
|
||||
|
||||
@Embedded
|
||||
private SavingsAccountSummary summary;
|
||||
|
||||
@@ -165,13 +185,15 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||
final MonthDay annualFeeOnMonthDay) {
|
||||
|
||||
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, withdrawalFeeAmount, withdrawalFeeType);
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType,
|
||||
annualFeeAmount, annualFeeOnMonthDay);
|
||||
}
|
||||
|
||||
private SavingsAccount(final Client client, final Group group, final SavingsProduct product, final String accountNo,
|
||||
@@ -180,7 +202,8 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||
final MonthDay annualFeeOnMonthDay) {
|
||||
this.client = client;
|
||||
this.group = group;
|
||||
this.product = product;
|
||||
@@ -210,9 +233,27 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
if (withdrawalFeeType != null) {
|
||||
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
||||
}
|
||||
|
||||
this.annualFeeAmount = annualFeeAmount;
|
||||
if (annualFeeOnMonthDay != null) {
|
||||
this.annualFeeOnMonth = annualFeeOnMonthDay.getMonthOfYear();
|
||||
this.annualFeeOnDay = annualFeeOnMonthDay.getDayOfMonth();
|
||||
|
||||
updateAnnualFeeNextDueDate();
|
||||
}
|
||||
|
||||
this.summary = new SavingsAccountSummary();
|
||||
}
|
||||
|
||||
private void updateAnnualFeeNextDueDate() {
|
||||
LocalDate nextDueLocalDate = new LocalDate().withMonthOfYear(this.annualFeeOnMonth).withDayOfMonth(this.annualFeeOnDay);
|
||||
if (nextDueLocalDate.isBefore(DateUtils.getLocalDateOfTenant())) {
|
||||
nextDueLocalDate = nextDueLocalDate.plusYears(1);
|
||||
}
|
||||
|
||||
this.annualFeeNextDueDate = nextDueLocalDate.toDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used after fetching/hydrating a {@link SavingsAccount} object to inject
|
||||
* helper services/components used for update summary details after
|
||||
@@ -834,6 +875,10 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
}
|
||||
}
|
||||
|
||||
final Money annualFee = Money.of(this.currency, this.annualFeeAmount);
|
||||
SavingsAccountTransaction annualFeeTransaction = SavingsAccountTransaction.annualFee(this, transactionDate, annualFee);
|
||||
this.transactions.add(annualFeeTransaction);
|
||||
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
@@ -842,6 +887,71 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public SavingsAccountTransaction addAnnualFee(final DateTimeFormatter formatter, final LocalDate transactionDate) {
|
||||
|
||||
if (isNotActive()) {
|
||||
|
||||
final String defaultUserMessage = "Transaction is not allowed. Account is not active.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.savingsaccount.transaction.account.is.not.active",
|
||||
defaultUserMessage, "transactionDate", transactionDate.toString(formatter));
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (isDateInTheFuture(transactionDate)) {
|
||||
final String defaultUserMessage = "Transaction date cannot be in the future.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.savingsaccount.transaction.in.the.future",
|
||||
defaultUserMessage, "transactionDate", transactionDate.toString(formatter));
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (transactionDate.isBefore(getActivationLocalDate())) {
|
||||
final Object[] defaultUserArgs = Arrays.asList(transactionDate.toString(formatter),
|
||||
getActivationLocalDate().toString(formatter)).toArray();
|
||||
final String defaultUserMessage = "Transaction date cannot be before accounts activation date.";
|
||||
final ApiParameterError error = ApiParameterError.parameterError("error.msg.savingsaccount.transaction.before.activation.date",
|
||||
defaultUserMessage, "transactionDate", defaultUserArgs);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
if (isAccountLocked(transactionDate)) {
|
||||
final String defaultUserMessage = "Withdrawal is not allowed. No withdrawals are allowed until after "
|
||||
+ getLockedInUntilLocalDate().toString(formatter);
|
||||
final ApiParameterError error = ApiParameterError.parameterError(
|
||||
"error.msg.savingsaccount.transaction.withdrawals.blocked.during.lockin.period", defaultUserMessage, "transactionDate",
|
||||
transactionDate.toString(formatter), getLockedInUntilLocalDate().toString(formatter));
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
|
||||
dataValidationErrors.add(error);
|
||||
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
final Money annualFee = Money.of(this.currency, this.annualFeeAmount);
|
||||
SavingsAccountTransaction annualFeeTransaction = SavingsAccountTransaction.annualFee(this, transactionDate, annualFee);
|
||||
this.transactions.add(annualFeeTransaction);
|
||||
|
||||
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||
|
||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||
calculateInterest(today);
|
||||
|
||||
updateAnnualFeeNextDueDate();
|
||||
|
||||
return annualFeeTransaction;
|
||||
}
|
||||
|
||||
private boolean isAutomaticWithdrawalFee() {
|
||||
return this.withdrawalFeeType != null;
|
||||
}
|
||||
@@ -942,6 +1052,48 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
||||
this.lockinPeriodFrequencyType = null;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamed(annualFeeAmountParamName, this.annualFeeAmount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(annualFeeAmountParamName);
|
||||
actualChanges.put(annualFeeAmountParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeAmount = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(annualFeeOnMonthDayParamName, this.annualFeeOnDay)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
||||
final Integer newValue = monthDay.getDayOfMonth();
|
||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeOnDay = newValue;
|
||||
|
||||
updateAnnualFeeNextDueDate();
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(annualFeeOnMonthDayParamName, this.annualFeeOnMonth)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
||||
final Integer newValue = monthDay.getMonthOfYear();
|
||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeOnMonth = newValue;
|
||||
|
||||
updateAnnualFeeNextDueDate();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(final Client client) {
|
||||
|
||||
+19
-2
@@ -7,6 +7,8 @@ package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activationDateParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationDaysInYearTypeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||
@@ -22,6 +24,7 @@ import java.math.BigDecimal;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
@@ -161,7 +164,7 @@ public class SavingsAccountAssembler {
|
||||
} else {
|
||||
withdrawalFeeAmount = product.withdrawalFeeAmount();
|
||||
}
|
||||
|
||||
|
||||
SavingsWithdrawalFeesType withdrawalFeeType = null;
|
||||
if (command.parameterExists(withdrawalFeeAmountParamName)) {
|
||||
final Integer withdrawalFeeTypeValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
||||
@@ -172,10 +175,24 @@ public class SavingsAccountAssembler {
|
||||
withdrawalFeeType = product.withdrawalFeeType();
|
||||
}
|
||||
|
||||
BigDecimal annualFeeAmount = null;
|
||||
if (command.parameterExists(annualFeeAmountParamName)) {
|
||||
annualFeeAmount = command.bigDecimalValueOfParameterNamed(annualFeeAmountParamName);
|
||||
} else {
|
||||
annualFeeAmount = product.annualFeeAmount();
|
||||
}
|
||||
|
||||
MonthDay monthDayOfAnnualFee = null;
|
||||
if (command.parameterExists(annualFeeOnMonthDayParamName)) {
|
||||
monthDayOfAnnualFee = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
} else {
|
||||
monthDayOfAnnualFee = product.monthDayOfAnnualFee();
|
||||
}
|
||||
|
||||
final SavingsAccount account = SavingsAccount.createNewAccount(client, group, product, accountNo, externalId, interestRate,
|
||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType,
|
||||
annualFeeAmount, monthDayOfAnnualFee);
|
||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper);
|
||||
|
||||
if (active) {
|
||||
|
||||
+5
-1
@@ -32,6 +32,9 @@ public final class SavingsAccountSummary {
|
||||
@Column(name = "total_withdrawal_fees_derived", scale = 6, precision = 19)
|
||||
private BigDecimal totalWithdrawalFees;
|
||||
|
||||
@Column(name = "total_annual_fees_derived", scale = 6, precision = 19)
|
||||
private BigDecimal totalAnnualFees;
|
||||
|
||||
@Column(name = "account_balance_derived", scale = 6, precision = 19)
|
||||
private BigDecimal accountBalance = BigDecimal.ZERO;
|
||||
|
||||
@@ -46,9 +49,10 @@ public final class SavingsAccountSummary {
|
||||
this.totalWithdrawals = wrapper.calculateTotalWithdrawals(currency, transactions);
|
||||
this.totalInterestPosted = wrapper.calculateTotalInterestPosted(currency, transactions);
|
||||
this.totalWithdrawalFees = wrapper.calculateTotalWithdrawalFees(currency, transactions);
|
||||
this.totalAnnualFees = wrapper.calculateTotalAnnualFees(currency, transactions);
|
||||
|
||||
this.accountBalance = Money.of(currency, this.totalDeposits).plus(this.totalInterestPosted).minus(this.totalWithdrawals)
|
||||
.minus(this.totalWithdrawalFees).getAmount();
|
||||
.minus(this.totalWithdrawalFees).minus(this.totalAnnualFees).getAmount();
|
||||
}
|
||||
|
||||
public void updateFromInterestPeriodSummaries(final MonetaryCurrency currency,
|
||||
|
||||
+10
@@ -88,6 +88,12 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
isReversed);
|
||||
}
|
||||
|
||||
public static SavingsAccountTransaction annualFee(final SavingsAccount savingsAccount, final LocalDate date, final Money amount) {
|
||||
final boolean isReversed = false;
|
||||
return new SavingsAccountTransaction(savingsAccount, SavingsAccountTransactionType.ANNUAL_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;
|
||||
@@ -125,6 +131,10 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawalFee() && isNotReversed();
|
||||
}
|
||||
|
||||
public boolean isAnnualFee() {
|
||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isAnnualFee() && isNotReversed();
|
||||
}
|
||||
|
||||
public boolean isNotReversed() {
|
||||
return !isReversed();
|
||||
}
|
||||
|
||||
+10
@@ -53,4 +53,14 @@ public final class SavingsAccountTransactionSummaryWrapper {
|
||||
}
|
||||
return total.getAmountDefaultedToNullIfZero();
|
||||
}
|
||||
|
||||
public BigDecimal calculateTotalAnnualFees(final MonetaryCurrency currency, final List<SavingsAccountTransaction> transactions) {
|
||||
Money total = Money.zero(currency);
|
||||
for (SavingsAccountTransaction transaction : transactions) {
|
||||
if (transaction.isAnnualFee() && transaction.isNotReversed()) {
|
||||
total = total.plus(transaction.getAmount(currency));
|
||||
}
|
||||
}
|
||||
return total.getAmountDefaultedToNullIfZero();
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -15,7 +15,8 @@ public enum SavingsAccountTransactionType {
|
||||
DEPOSIT(1, "savingsAccountTransactionType.deposit"), //
|
||||
WITHDRAWAL(2, "savingsAccountTransactionType.withdrawal"), //
|
||||
INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), //
|
||||
WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee");
|
||||
WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee"), //
|
||||
ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
@@ -51,6 +52,9 @@ public enum SavingsAccountTransactionType {
|
||||
case 4:
|
||||
loanTransactionType = SavingsAccountTransactionType.WITHDRAWAL_FEE;
|
||||
break;
|
||||
case 5:
|
||||
loanTransactionType = SavingsAccountTransactionType.ANNUAL_FEE;
|
||||
break;
|
||||
}
|
||||
return loanTransactionType;
|
||||
}
|
||||
@@ -70,4 +74,8 @@ public enum SavingsAccountTransactionType {
|
||||
public boolean isWithdrawalFee() {
|
||||
return this.value.equals(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue());
|
||||
}
|
||||
|
||||
public boolean isAnnualFee() {
|
||||
return this.value.equals(SavingsAccountTransactionType.ANNUAL_FEE.getValue());
|
||||
}
|
||||
}
|
||||
+76
-5
@@ -5,6 +5,8 @@
|
||||
*/
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||
@@ -30,6 +32,7 @@ import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
@@ -55,7 +58,7 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
/**
|
||||
* The interest period is the span of time at the end of which savings in a
|
||||
* client's account earn interest.
|
||||
*
|
||||
*
|
||||
* A value from the {@link SavingsCompoundingInterestPeriodType}
|
||||
* enumeration.
|
||||
*/
|
||||
@@ -96,16 +99,26 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
@Column(name = "withdrawal_fee_type_enum", nullable = true)
|
||||
private Integer withdrawalFeeType;
|
||||
|
||||
@Column(name = "annual_fee_amount", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal annualFeeAmount;
|
||||
|
||||
@Column(name = "annual_fee_on_month", nullable = true)
|
||||
private Integer annualFeeOnMonth;
|
||||
|
||||
@Column(name = "annual_fee_on_day", nullable = true)
|
||||
private Integer annualFeeOnDay;
|
||||
|
||||
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 BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||
final MonthDay annualFeeOnMonthDay) {
|
||||
|
||||
return new SavingsProduct(name, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay);
|
||||
}
|
||||
|
||||
protected SavingsProduct() {
|
||||
@@ -118,7 +131,8 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||
final MonthDay annualFeeOnMonthDay) {
|
||||
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
@@ -143,9 +157,15 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
if (withdrawalFeeType != null) {
|
||||
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
||||
}
|
||||
this.annualFeeAmount = annualFeeAmount;
|
||||
if (annualFeeOnMonthDay != null) {
|
||||
this.annualFeeOnMonth = annualFeeOnMonthDay.getMonthOfYear();
|
||||
this.annualFeeOnDay = annualFeeOnMonthDay.getDayOfMonth();
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
validateWithdrawalFeeDetails();
|
||||
validateAnnualFeeDetails();
|
||||
}
|
||||
|
||||
public MonetaryCurrency currency() {
|
||||
@@ -200,6 +220,18 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
return type;
|
||||
}
|
||||
|
||||
public BigDecimal annualFeeAmount() {
|
||||
return this.annualFeeAmount;
|
||||
}
|
||||
|
||||
public MonthDay monthDayOfAnnualFee() {
|
||||
MonthDay monthDay = null;
|
||||
if (this.annualFeeOnMonth != null && this.annualFeeOnDay != null) {
|
||||
monthDay = new MonthDay(this.annualFeeOnMonth, this.annualFeeOnDay);
|
||||
}
|
||||
return monthDay;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(10);
|
||||
@@ -299,12 +331,51 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
this.withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(newValue).getValue();
|
||||
}
|
||||
|
||||
if (command.isChangeInBigDecimalParameterNamed(annualFeeAmountParamName, this.annualFeeAmount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(annualFeeAmountParamName);
|
||||
actualChanges.put(annualFeeAmountParamName, newValue);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeAmount = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(annualFeeOnMonthDayParamName, this.annualFeeOnDay)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
||||
final Integer newValue = monthDay.getDayOfMonth();
|
||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeOnDay = newValue;
|
||||
}
|
||||
|
||||
if (command.isChangeInIntegerParameterNamed(annualFeeOnMonthDayParamName, this.annualFeeOnMonth)) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed(annualFeeOnMonthDayParamName);
|
||||
final Integer newValue = monthDay.getMonthOfYear();
|
||||
actualChanges.put(annualFeeOnMonthDayParamName, actualValueEntered);
|
||||
actualChanges.put(localeParamName, localeAsInput);
|
||||
this.annualFeeOnMonth = newValue;
|
||||
}
|
||||
|
||||
validateLockinDetails();
|
||||
validateWithdrawalFeeDetails();
|
||||
validateAnnualFeeDetails();
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
private void validateAnnualFeeDetails() {
|
||||
if (isInvalidConfigurationOfAnnualFeeSettings()) {
|
||||
Object[] defaultUserMessageArgs = new Object[] { annualFeeAmountParamName };
|
||||
throw new GeneralPlatformDomainRuleException("error.msg.product.savings.invalid.annualfee.settings",
|
||||
"Invalid configuration of annual fee settings.", defaultUserMessageArgs);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInvalidConfigurationOfAnnualFeeSettings() {
|
||||
return (this.annualFeeAmount == null && (this.annualFeeOnDay != null || this.annualFeeOnMonth != null))
|
||||
|| ((this.annualFeeOnDay == null || this.annualFeeOnMonth == null) && this.annualFeeAmount != null);
|
||||
}
|
||||
|
||||
private void validateWithdrawalFeeDetails() {
|
||||
if (isInvalidConfigurationOfWithdrawalFeeSettings()) {
|
||||
Object[] defaultUserMessageArgs = new Object[] { withdrawalFeeAmountParamName };
|
||||
@@ -330,4 +401,4 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
||||
return (this.lockinPeriodFrequency == null && this.lockinPeriodFrequencyType != null)
|
||||
|| (this.lockinPeriodFrequencyType == null && this.lockinPeriodFrequency != null);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-1
@@ -1,5 +1,7 @@
|
||||
package org.mifosplatform.portfolio.savings.domain;
|
||||
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeAmountParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.annualFeeOnMonthDayParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.currencyCodeParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||
@@ -17,6 +19,7 @@ import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.withdr
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -76,8 +79,12 @@ public class SavingsProductAssembler {
|
||||
withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal annualFeeAmount = command.bigDecimalValueOfParameterNamed(annualFeeAmountParamName);
|
||||
final MonthDay monthDayOfAnnualFee = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||
|
||||
return SavingsProduct.createNew(name, description, currency, interestRate, interestCompoundingPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||
monthDayOfAnnualFee);
|
||||
}
|
||||
}
|
||||
+38
-4
@@ -11,6 +11,7 @@ import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
||||
@@ -114,9 +115,14 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
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.annual_fee_amount as annualFeeAmount,");
|
||||
sqlBuilder.append("sa.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
sqlBuilder.append("sa.annual_fee_on_day as annualFeeOnDay, ");
|
||||
sqlBuilder.append("sa.annual_fee_next_due_date as annualFeeNextDueDate, ");
|
||||
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_annual_fees_derived as totalAnnualFees, ");
|
||||
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 ");
|
||||
@@ -195,21 +201,34 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
|
||||
MonthDay annualFeeOnMonthDay = null;
|
||||
final Integer annualFeeOnMonth = JdbcSupport.getInteger(rs, "annualFeeOnMonth");
|
||||
final Integer annualFeeOnDay = JdbcSupport.getInteger(rs, "annualFeeOnDay");
|
||||
if (annualFeeAmount != null && annualFeeOnDay != null) {
|
||||
annualFeeOnMonthDay = new MonthDay(annualFeeOnMonth, annualFeeOnDay);
|
||||
}
|
||||
|
||||
final LocalDate annualFeeNextDueDate = JdbcSupport.getLocalDate(rs, "annualFeeNextDueDate");
|
||||
|
||||
final BigDecimal totalDeposits = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalDeposits");
|
||||
final BigDecimal totalWithdrawals = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawals");
|
||||
final BigDecimal totalWithdrawalFees = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawalFees");
|
||||
final BigDecimal totalAnnualFees = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalAnnualFees");
|
||||
|
||||
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,
|
||||
totalWithdrawalFees, totalInterestEarned, totalInterestPosted, accountBalance);
|
||||
totalWithdrawalFees, totalAnnualFees, 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, withdrawalFeeAmount, withdrawalFeeType, summary);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
||||
annualFeeNextDueDate, summary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +444,10 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
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("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
|
||||
sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay ");
|
||||
sqlBuilder.append("from m_savings_product sp ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
||||
|
||||
@@ -484,6 +506,15 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
|
||||
MonthDay annualFeeOnMonthDay = null;
|
||||
final Integer annualFeeOnMonth = JdbcSupport.getInteger(rs, "annualFeeOnMonth");
|
||||
final Integer annualFeeOnDay = JdbcSupport.getInteger(rs, "annualFeeOnDay");
|
||||
if (annualFeeAmount != null && annualFeeOnDay != null) {
|
||||
annualFeeOnMonthDay = new MonthDay(annualFeeOnMonth, annualFeeOnDay);
|
||||
}
|
||||
|
||||
Long clientId = null;
|
||||
String clientName = null;
|
||||
if (client != null) {
|
||||
@@ -500,11 +531,14 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
||||
|
||||
final SavingsAccountStatusEnumData status = null;
|
||||
final LocalDate activationDate = null;
|
||||
final LocalDate annualFeeNextDueDate = null;
|
||||
final SavingsAccountSummaryData summary = null;
|
||||
|
||||
return SavingsAccountData.instance(null, null, null, status, activationDate, groupId, groupName, clientId, clientName,
|
||||
productId, productName, currency, nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, summary);
|
||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
||||
annualFeeNextDueDate, summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -79,7 +79,10 @@ public class SavingsEnumerations {
|
||||
case WITHDRAWAL_FEE:
|
||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue().longValue(),
|
||||
SavingsAccountTransactionType.WITHDRAWAL_FEE.getCode(), "Withdrawal fee");
|
||||
|
||||
break;
|
||||
case ANNUAL_FEE:
|
||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.ANNUAL_FEE.getValue().longValue(),
|
||||
SavingsAccountTransactionType.ANNUAL_FEE.getCode(), "Annual fee");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
|
||||
+16
-2
@@ -10,6 +10,7 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joda.time.MonthDay;
|
||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
||||
@@ -85,7 +86,10 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
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("sp.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
||||
sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
|
||||
sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth, ");
|
||||
sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay ");
|
||||
sqlBuilder.append("from m_savings_product sp ");
|
||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
||||
|
||||
@@ -147,9 +151,19 @@ public class SavingsProductReadPlatformServiceImpl implements SavingsProductRead
|
||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
||||
}
|
||||
|
||||
final BigDecimal annualFeeAmount = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "annualFeeAmount");
|
||||
|
||||
MonthDay annualFeeOnMonthDay = null;
|
||||
final Integer annualFeeOnMonth = JdbcSupport.getInteger(rs, "annualFeeOnMonth");
|
||||
final Integer annualFeeOnDay = JdbcSupport.getInteger(rs, "annualFeeOnDay");
|
||||
if (annualFeeAmount != null && annualFeeOnDay != null) {
|
||||
annualFeeOnMonthDay = new MonthDay(annualFeeOnMonth, annualFeeOnDay);
|
||||
}
|
||||
|
||||
return SavingsProductData.instance(id, name, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType,
|
||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||
annualFeeOnMonthDay);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user