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")
|
@SuppressWarnings("unused")
|
||||||
@Override
|
@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;
|
JsonElement element = null;
|
||||||
if (src != null) {
|
if (src != null) {
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ public class JodaLocalDateAdapter implements JsonSerializer<LocalDate> {
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Override
|
@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;
|
JsonArray array = null;
|
||||||
if (src != 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.ObjectUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
|
||||||
import org.mifosplatform.infrastructure.security.domain.BasicPasswordEncodablePlatformUser;
|
import org.mifosplatform.infrastructure.security.domain.BasicPasswordEncodablePlatformUser;
|
||||||
import org.mifosplatform.infrastructure.security.domain.PlatformUser;
|
import org.mifosplatform.infrastructure.security.domain.PlatformUser;
|
||||||
@@ -261,6 +262,10 @@ public final class JsonCommand {
|
|||||||
return this.fromApiJsonHelper.extractLocalDateNamed(parameterName, parsedCommand);
|
return this.fromApiJsonHelper.extractLocalDateNamed(parameterName, parsedCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MonthDay extractMonthDayNamed(final String parameterName) {
|
||||||
|
return this.fromApiJsonHelper.extractMonthDayNamed(parameterName, parsedCommand);
|
||||||
|
}
|
||||||
|
|
||||||
public Date DateValueOfParameterNamed(final String parameterName) {
|
public Date DateValueOfParameterNamed(final String parameterName) {
|
||||||
LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(parameterName, parsedCommand);
|
LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(parameterName, parsedCommand);
|
||||||
if (localDate == null) { return null; }
|
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.DateTime;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
||||||
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JodaMonthDayAdapter;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
@@ -28,6 +30,7 @@ public final class CommandProcessingResultJsonSerializer {
|
|||||||
GsonBuilder builder = new GsonBuilder();
|
GsonBuilder builder = new GsonBuilder();
|
||||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||||
|
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||||
builder.serializeNulls();
|
builder.serializeNulls();
|
||||||
|
|
||||||
this.gson = builder.create();
|
this.gson = builder.create();
|
||||||
|
|||||||
+3
@@ -7,8 +7,10 @@ package org.mifosplatform.infrastructure.core.serialization;
|
|||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
||||||
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JodaMonthDayAdapter;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
@@ -28,6 +30,7 @@ public final class ExcludeNothingWithPrettyPrintingOffJsonSerializerGoogleGson {
|
|||||||
GsonBuilder builder = new GsonBuilder();
|
GsonBuilder builder = new GsonBuilder();
|
||||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||||
|
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||||
|
|
||||||
this.gson = builder.create();
|
this.gson = builder.create();
|
||||||
}
|
}
|
||||||
|
|||||||
+3
@@ -7,8 +7,10 @@ package org.mifosplatform.infrastructure.core.serialization;
|
|||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
||||||
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
||||||
|
import org.mifosplatform.infrastructure.core.api.JodaMonthDayAdapter;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
@@ -28,6 +30,7 @@ public final class ExcludeNothingWithPrettyPrintingOnJsonSerializerGoogleGson {
|
|||||||
GsonBuilder builder = new GsonBuilder();
|
GsonBuilder builder = new GsonBuilder();
|
||||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||||
|
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||||
builder.setPrettyPrinting();
|
builder.setPrettyPrinting();
|
||||||
|
|
||||||
this.gson = builder.create();
|
this.gson = builder.create();
|
||||||
|
|||||||
+5
@@ -16,6 +16,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||||
import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
|
import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -114,6 +115,10 @@ public class FromJsonHelper {
|
|||||||
return helperDelegator.extractBooleanNamed(parameterName, element, parametersPassedInRequest);
|
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) {
|
public LocalDate extractLocalDateNamed(final String parameterName, final JsonElement element) {
|
||||||
return helperDelegator.extractLocalDateNamed(parameterName, element, new HashSet<String>());
|
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.DateTime;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
import org.mifosplatform.infrastructure.core.api.JodaDateTimeAdapter;
|
||||||
import org.mifosplatform.infrastructure.core.api.JodaLocalDateAdapter;
|
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.api.ParameterListExclusionStrategy;
|
||||||
import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
|
import org.mifosplatform.infrastructure.core.exception.UnsupportedParameterException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -31,6 +33,7 @@ public final class GoogleGsonSerializerHelper {
|
|||||||
final GsonBuilder builder = new GsonBuilder();
|
final GsonBuilder builder = new GsonBuilder();
|
||||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||||
|
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||||
if (prettyPrint) {
|
if (prettyPrint) {
|
||||||
builder.setPrettyPrinting();
|
builder.setPrettyPrinting();
|
||||||
}
|
}
|
||||||
@@ -61,6 +64,7 @@ public final class GoogleGsonSerializerHelper {
|
|||||||
final GsonBuilder builder = new GsonBuilder().addSerializationExclusionStrategy(strategy);
|
final GsonBuilder builder = new GsonBuilder().addSerializationExclusionStrategy(strategy);
|
||||||
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
builder.registerTypeAdapter(LocalDate.class, new JodaLocalDateAdapter());
|
||||||
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
builder.registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter());
|
||||||
|
builder.registerTypeAdapter(MonthDay.class, new JodaMonthDayAdapter());
|
||||||
if (prettyPrint) {
|
if (prettyPrint) {
|
||||||
builder.setPrettyPrinting();
|
builder.setPrettyPrinting();
|
||||||
}
|
}
|
||||||
|
|||||||
+50
@@ -18,7 +18,9 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||||
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||||
import org.springframework.format.number.NumberFormatter;
|
import org.springframework.format.number.NumberFormatter;
|
||||||
@@ -181,6 +183,20 @@ public class JsonParserHelper {
|
|||||||
return value;
|
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) {
|
public Locale extractLocaleParameter(final JsonObject element) {
|
||||||
Locale clientApplicationLocale = null;
|
Locale clientApplicationLocale = null;
|
||||||
if (element.isJsonObject()) {
|
if (element.isJsonObject()) {
|
||||||
@@ -252,6 +268,40 @@ public class JsonParserHelper {
|
|||||||
return value;
|
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,
|
public LocalDate extractLocalDateNamed(final String parameterName, final JsonElement element,
|
||||||
final Set<String> parametersPassedInCommand) {
|
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") })
|
@Table(name = "m_product_loan", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "unq_name") })
|
||||||
public class LoanProduct extends AbstractPersistable<Long> {
|
public class LoanProduct extends AbstractPersistable<Long> {
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "fund_id", nullable = true)
|
@JoinColumn(name = "fund_id", nullable = true)
|
||||||
private Fund fund;
|
private Fund fund;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
|
@JoinColumn(name = "loan_transaction_strategy_id", nullable = true)
|
||||||
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
|
private LoanTransactionProcessingStrategy transactionProcessingStrategy;
|
||||||
|
|
||||||
@Column(name = "name", nullable = false, unique = true)
|
@Column(name = "name", nullable = false, unique = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Column(name = "description")
|
@Column(name = "description")
|
||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@ManyToMany
|
@ManyToMany
|
||||||
@JoinTable(name = "m_product_loan_charge", joinColumns = @JoinColumn(name = "product_loan_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
|
@JoinTable(name = "m_product_loan_charge", joinColumns = @JoinColumn(name = "product_loan_id"), inverseJoinColumns = @JoinColumn(name = "charge_id"))
|
||||||
private List<Charge> charges;
|
private List<Charge> charges;
|
||||||
|
|
||||||
@Embedded
|
@Embedded
|
||||||
private final LoanProductRelatedDetail loanProductRelatedDetail;
|
private final LoanProductRelatedDetail loanProductRelatedDetail;
|
||||||
|
|
||||||
@Embedded
|
@Embedded
|
||||||
private LoanProductMinMaxConstraints loanProductMinMaxConstraints;
|
private LoanProductMinMaxConstraints loanProductMinMaxConstraints;
|
||||||
|
|
||||||
@Column(name = "accounting_type", nullable = false)
|
@Column(name = "accounting_type", nullable = false)
|
||||||
private Integer accountingRule;
|
private Integer accountingRule;
|
||||||
|
|
||||||
public static LoanProduct assembleFromJson(
|
public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
|
||||||
final Fund fund,
|
final List<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator) {
|
||||||
final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
|
|
||||||
final List<Charge> productCharges, final JsonCommand command,
|
|
||||||
final AprCalculator aprCalculator) {
|
|
||||||
|
|
||||||
final String name = command.stringValueOfParameterNamed("name");
|
final String name = command.stringValueOfParameterNamed("name");
|
||||||
final String description = command
|
final String description = command.stringValueOfParameterNamed("description");
|
||||||
.stringValueOfParameterNamed("description");
|
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||||
final String currencyCode = command
|
final Integer digitsAfterDecimal = command.integerValueOfParameterNamed("digitsAfterDecimal");
|
||||||
.stringValueOfParameterNamed("currencyCode");
|
|
||||||
final Integer digitsAfterDecimal = command
|
|
||||||
.integerValueOfParameterNamed("digitsAfterDecimal");
|
|
||||||
|
|
||||||
final MonetaryCurrency currency = new MonetaryCurrency(currencyCode,
|
final MonetaryCurrency currency = new MonetaryCurrency(currencyCode, digitsAfterDecimal);
|
||||||
digitsAfterDecimal);
|
final BigDecimal principal = command.bigDecimalValueOfParameterNamed("principal");
|
||||||
final BigDecimal principal = command
|
final BigDecimal minPrincipal = command.bigDecimalValueOfParameterNamed("minPrincipal");
|
||||||
.bigDecimalValueOfParameterNamed("principal");
|
final BigDecimal maxPrincipal = command.bigDecimalValueOfParameterNamed("maxPrincipal");
|
||||||
final BigDecimal minPrincipal = command
|
|
||||||
.bigDecimalValueOfParameterNamed("minPrincipal");
|
|
||||||
final BigDecimal maxPrincipal = command
|
|
||||||
.bigDecimalValueOfParameterNamed("maxPrincipal");
|
|
||||||
|
|
||||||
final InterestMethod interestMethod = InterestMethod.fromInt(command
|
final InterestMethod interestMethod = InterestMethod.fromInt(command.integerValueOfParameterNamed("interestType"));
|
||||||
.integerValueOfParameterNamed("interestType"));
|
final InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod.fromInt(command
|
||||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod = InterestCalculationPeriodMethod
|
.integerValueOfParameterNamed("interestCalculationPeriodType"));
|
||||||
.fromInt(command
|
final AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(command.integerValueOfParameterNamed("amortizationType"));
|
||||||
.integerValueOfParameterNamed("interestCalculationPeriodType"));
|
final PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType.fromInt(command
|
||||||
final AmortizationMethod amortizationMethod = AmortizationMethod
|
.integerValueOfParameterNamed("repaymentFrequencyType"));
|
||||||
.fromInt(command
|
final PeriodFrequencyType interestFrequencyType = PeriodFrequencyType.fromInt(command
|
||||||
.integerValueOfParameterNamed("amortizationType"));
|
.integerValueOfParameterNamed("interestRateFrequencyType"));
|
||||||
final PeriodFrequencyType repaymentFrequencyType = PeriodFrequencyType
|
final BigDecimal interestRatePerPeriod = command.bigDecimalValueOfParameterNamed("interestRatePerPeriod");
|
||||||
.fromInt(command
|
final BigDecimal minInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("minInterestRatePerPeriod");
|
||||||
.integerValueOfParameterNamed("repaymentFrequencyType"));
|
final BigDecimal maxInterestRatePerPeriod = command.bigDecimalValueOfParameterNamed("maxInterestRatePerPeriod");
|
||||||
final PeriodFrequencyType interestFrequencyType = PeriodFrequencyType
|
final BigDecimal annualInterestRate = aprCalculator.calculateFrom(interestFrequencyType, interestRatePerPeriod);
|
||||||
.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
|
final Integer repaymentEvery = command.integerValueOfParameterNamed("repaymentEvery");
|
||||||
.integerValueOfParameterNamed("repaymentEvery");
|
final Integer numberOfRepayments = command.integerValueOfParameterNamed("numberOfRepayments");
|
||||||
final Integer numberOfRepayments = command
|
final Integer minNumberOfRepayments = command.integerValueOfParameterNamed("minNumberOfRepayments");
|
||||||
.integerValueOfParameterNamed("numberOfRepayments");
|
final Integer maxNumberOfRepayments = command.integerValueOfParameterNamed("maxNumberOfRepayments");
|
||||||
final Integer minNumberOfRepayments = command
|
final BigDecimal inArrearsTolerance = command.bigDecimalValueOfParameterNamed("inArrearsTolerance");
|
||||||
.integerValueOfParameterNamed("minNumberOfRepayments");
|
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule"));
|
||||||
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,
|
return new LoanProduct(fund, loanTransactionProcessingStrategy, name, description, currency, principal, minPrincipal, maxPrincipal,
|
||||||
description, currency, principal, minPrincipal, maxPrincipal,
|
interestRatePerPeriod, minInterestRatePerPeriod, maxInterestRatePerPeriod, interestFrequencyType, annualInterestRate,
|
||||||
interestRatePerPeriod, minInterestRatePerPeriod,
|
interestMethod, interestCalculationPeriodMethod, repaymentEvery, repaymentFrequencyType, numberOfRepayments,
|
||||||
maxInterestRatePerPeriod, interestFrequencyType,
|
minNumberOfRepayments, maxNumberOfRepayments, amortizationMethod, inArrearsTolerance, productCharges, accountingRuleType);
|
||||||
annualInterestRate, interestMethod,
|
}
|
||||||
interestCalculationPeriodMethod, repaymentEvery,
|
|
||||||
repaymentFrequencyType, numberOfRepayments,
|
|
||||||
minNumberOfRepayments, maxNumberOfRepayments,
|
|
||||||
amortizationMethod, inArrearsTolerance, productCharges,
|
|
||||||
accountingRuleType);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected LoanProduct() {
|
protected LoanProduct() {
|
||||||
this.loanProductRelatedDetail = null;
|
this.loanProductRelatedDetail = null;
|
||||||
this.loanProductMinMaxConstraints = null;
|
this.loanProductMinMaxConstraints = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanProduct(
|
public LoanProduct(final Fund fund, final LoanTransactionProcessingStrategy transactionProcessingStrategy, final String name,
|
||||||
final Fund fund,
|
final String description, final MonetaryCurrency currency, final BigDecimal defaultPrincipal,
|
||||||
final LoanTransactionProcessingStrategy transactionProcessingStrategy,
|
final BigDecimal defaultMinPrincipal, final BigDecimal defaultMaxPrincipal,
|
||||||
final String name,
|
final BigDecimal defaultNominalInterestRatePerPeriod, final BigDecimal defaultMinNominalInterestRatePerPeriod,
|
||||||
final String description,
|
final BigDecimal defaultMaxNominalInterestRatePerPeriod, final PeriodFrequencyType interestPeriodFrequencyType,
|
||||||
final MonetaryCurrency currency,
|
final BigDecimal defaultAnnualNominalInterestRate, final InterestMethod interestMethod,
|
||||||
final BigDecimal defaultPrincipal,
|
final InterestCalculationPeriodMethod interestCalculationPeriodMethod, final Integer repayEvery,
|
||||||
final BigDecimal defaultMinPrincipal,
|
final PeriodFrequencyType repaymentFrequencyType, final Integer defaultNumberOfInstallments,
|
||||||
final BigDecimal defaultMaxPrincipal,
|
final Integer defaultMinNumberOfInstallments, final Integer defaultMaxNumberOfInstallments,
|
||||||
final BigDecimal defaultNominalInterestRatePerPeriod,
|
final AmortizationMethod amortizationMethod, final BigDecimal inArrearsTolerance, final List<Charge> charges,
|
||||||
final BigDecimal defaultMinNominalInterestRatePerPeriod,
|
final AccountingRuleType accountingRuleType) {
|
||||||
final BigDecimal defaultMaxNominalInterestRatePerPeriod,
|
this.fund = fund;
|
||||||
final PeriodFrequencyType interestPeriodFrequencyType,
|
this.transactionProcessingStrategy = transactionProcessingStrategy;
|
||||||
final BigDecimal defaultAnnualNominalInterestRate,
|
this.name = name.trim();
|
||||||
final InterestMethod interestMethod,
|
if (StringUtils.isNotBlank(description)) {
|
||||||
final InterestCalculationPeriodMethod interestCalculationPeriodMethod,
|
this.description = description.trim();
|
||||||
final Integer repayEvery,
|
} else {
|
||||||
final PeriodFrequencyType repaymentFrequencyType,
|
this.description = null;
|
||||||
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) {
|
if (charges != null) {
|
||||||
this.charges = charges;
|
this.charges = charges;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loanProductRelatedDetail = new LoanProductRelatedDetail(currency,
|
this.loanProductRelatedDetail = new LoanProductRelatedDetail(currency, defaultPrincipal, defaultNominalInterestRatePerPeriod,
|
||||||
defaultPrincipal, defaultNominalInterestRatePerPeriod,
|
interestPeriodFrequencyType, defaultAnnualNominalInterestRate, interestMethod, interestCalculationPeriodMethod, repayEvery,
|
||||||
interestPeriodFrequencyType, defaultAnnualNominalInterestRate,
|
repaymentFrequencyType, defaultNumberOfInstallments, amortizationMethod, inArrearsTolerance);
|
||||||
interestMethod, interestCalculationPeriodMethod, repayEvery,
|
|
||||||
repaymentFrequencyType, defaultNumberOfInstallments,
|
|
||||||
amortizationMethod, inArrearsTolerance);
|
|
||||||
|
|
||||||
this.loanProductMinMaxConstraints = new LoanProductMinMaxConstraints(
|
this.loanProductMinMaxConstraints = new LoanProductMinMaxConstraints(defaultMinPrincipal, defaultMaxPrincipal,
|
||||||
defaultMinPrincipal, defaultMaxPrincipal,
|
defaultMinNominalInterestRatePerPeriod, defaultMaxNominalInterestRatePerPeriod, defaultMinNumberOfInstallments,
|
||||||
defaultMinNominalInterestRatePerPeriod,
|
defaultMaxNumberOfInstallments);
|
||||||
defaultMaxNominalInterestRatePerPeriod,
|
|
||||||
defaultMinNumberOfInstallments, defaultMaxNumberOfInstallments);
|
|
||||||
|
|
||||||
if (accountingRuleType != null) {
|
if (accountingRuleType != null) {
|
||||||
this.accountingRule = accountingRuleType.getValue();
|
this.accountingRule = accountingRuleType.getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MonetaryCurrency getCurrency() {
|
public MonetaryCurrency getCurrency() {
|
||||||
return this.loanProductRelatedDetail.getCurrency();
|
return this.loanProductRelatedDetail.getCurrency();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(final Fund fund) {
|
public void update(final Fund fund) {
|
||||||
this.fund = fund;
|
this.fund = fund;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(final LoanTransactionProcessingStrategy strategy) {
|
public void update(final LoanTransactionProcessingStrategy strategy) {
|
||||||
this.transactionProcessingStrategy = strategy;
|
this.transactionProcessingStrategy = strategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean update(final List<Charge> newProductCharges) {
|
public boolean update(final List<Charge> newProductCharges) {
|
||||||
if (newProductCharges == null)
|
if (newProductCharges == null) return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
boolean updated = false;
|
boolean updated = false;
|
||||||
if (this.charges != null) {
|
if (this.charges != null) {
|
||||||
final Set<Charge> currentSetOfCharges = new HashSet<Charge>(
|
final Set<Charge> currentSetOfCharges = new HashSet<Charge>(this.charges);
|
||||||
this.charges);
|
final Set<Charge> newSetOfCharges = new HashSet<Charge>(newProductCharges);
|
||||||
final Set<Charge> newSetOfCharges = new HashSet<Charge>(
|
|
||||||
newProductCharges);
|
|
||||||
|
|
||||||
if (!(currentSetOfCharges.equals(newSetOfCharges))) {
|
if (!(currentSetOfCharges.equals(newSetOfCharges))) {
|
||||||
updated = true;
|
updated = true;
|
||||||
this.charges = newProductCharges;
|
this.charges = newProductCharges;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
updated = true;
|
updated = true;
|
||||||
this.charges = newProductCharges;
|
this.charges = newProductCharges;
|
||||||
}
|
}
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getAccountingType() {
|
public Integer getAccountingType() {
|
||||||
return this.accountingRule;
|
return this.accountingRule;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Object> update(final JsonCommand command,
|
public Map<String, Object> update(final JsonCommand command, final AprCalculator aprCalculator) {
|
||||||
final AprCalculator aprCalculator) {
|
|
||||||
|
|
||||||
final Map<String, Object> actualChanges = this.loanProductRelatedDetail
|
final Map<String, Object> actualChanges = this.loanProductRelatedDetail.update(command, aprCalculator);
|
||||||
.update(command, aprCalculator);
|
actualChanges.putAll(this.loanProductMinMaxConstraints().update(command));
|
||||||
actualChanges.putAll(this.loanProductMinMaxConstraints()
|
|
||||||
.update(command));
|
|
||||||
|
|
||||||
final String accountingTypeParamName = "accountingRule";
|
final String accountingTypeParamName = "accountingRule";
|
||||||
if (command.isChangeInIntegerParameterNamed(accountingTypeParamName,
|
if (command.isChangeInIntegerParameterNamed(accountingTypeParamName, this.accountingRule)) {
|
||||||
this.accountingRule)) {
|
final Integer newValue = command.integerValueOfParameterNamed(accountingTypeParamName);
|
||||||
final Integer newValue = command
|
actualChanges.put(accountingTypeParamName, newValue);
|
||||||
.integerValueOfParameterNamed(accountingTypeParamName);
|
this.accountingRule = newValue;
|
||||||
actualChanges.put(accountingTypeParamName, newValue);
|
}
|
||||||
this.accountingRule = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String nameParamName = "name";
|
final String nameParamName = "name";
|
||||||
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
|
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
|
||||||
final String newValue = command
|
final String newValue = command.stringValueOfParameterNamed(nameParamName);
|
||||||
.stringValueOfParameterNamed(nameParamName);
|
actualChanges.put(nameParamName, newValue);
|
||||||
actualChanges.put(nameParamName, newValue);
|
this.name = newValue;
|
||||||
this.name = newValue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
final String descriptionParamName = "description";
|
final String descriptionParamName = "description";
|
||||||
if (command.isChangeInStringParameterNamed(descriptionParamName,
|
if (command.isChangeInStringParameterNamed(descriptionParamName, this.description)) {
|
||||||
this.description)) {
|
final String newValue = command.stringValueOfParameterNamed(descriptionParamName);
|
||||||
final String newValue = command
|
actualChanges.put(descriptionParamName, newValue);
|
||||||
.stringValueOfParameterNamed(descriptionParamName);
|
this.description = newValue;
|
||||||
actualChanges.put(descriptionParamName, newValue);
|
}
|
||||||
this.description = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Long existingFundId = null;
|
Long existingFundId = null;
|
||||||
if (this.fund != null) {
|
if (this.fund != null) {
|
||||||
existingFundId = this.fund.getId();
|
existingFundId = this.fund.getId();
|
||||||
}
|
}
|
||||||
final String fundIdParamName = "fundId";
|
final String fundIdParamName = "fundId";
|
||||||
if (command.isChangeInLongParameterNamed(fundIdParamName,
|
if (command.isChangeInLongParameterNamed(fundIdParamName, existingFundId)) {
|
||||||
existingFundId)) {
|
final Long newValue = command.longValueOfParameterNamed(fundIdParamName);
|
||||||
final Long newValue = command
|
actualChanges.put(fundIdParamName, newValue);
|
||||||
.longValueOfParameterNamed(fundIdParamName);
|
}
|
||||||
actualChanges.put(fundIdParamName, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
Long existingStrategyId = null;
|
Long existingStrategyId = null;
|
||||||
if (this.transactionProcessingStrategy != null) {
|
if (this.transactionProcessingStrategy != null) {
|
||||||
existingStrategyId = this.transactionProcessingStrategy.getId();
|
existingStrategyId = this.transactionProcessingStrategy.getId();
|
||||||
}
|
}
|
||||||
final String transactionProcessingStrategyParamName = "transactionProcessingStrategyId";
|
final String transactionProcessingStrategyParamName = "transactionProcessingStrategyId";
|
||||||
if (command.isChangeInLongParameterNamed(
|
if (command.isChangeInLongParameterNamed(transactionProcessingStrategyParamName, existingStrategyId)) {
|
||||||
transactionProcessingStrategyParamName, existingStrategyId)) {
|
final Long newValue = command.longValueOfParameterNamed(transactionProcessingStrategyParamName);
|
||||||
final Long newValue = command
|
actualChanges.put(transactionProcessingStrategyParamName, newValue);
|
||||||
.longValueOfParameterNamed(transactionProcessingStrategyParamName);
|
}
|
||||||
actualChanges.put(transactionProcessingStrategyParamName, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String chargesParamName = "charges";
|
final String chargesParamName = "charges";
|
||||||
if (command.hasParameter(chargesParamName)) {
|
if (command.hasParameter(chargesParamName)) {
|
||||||
JsonArray jsonArray = command
|
JsonArray jsonArray = command.arrayOfParameterNamed(chargesParamName);
|
||||||
.arrayOfParameterNamed(chargesParamName);
|
if (jsonArray != null) {
|
||||||
if (jsonArray != null) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
actualChanges.put(chargesParamName,
|
actualChanges.put(chargesParamName, command.jsonFragment(chargesParamName));
|
||||||
command.jsonFragment(chargesParamName));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return actualChanges;
|
return actualChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCashBasedAccountingEnabled() {
|
public boolean isCashBasedAccountingEnabled() {
|
||||||
return AccountingRuleType.CASH_BASED.getValue().equals(
|
return AccountingRuleType.CASH_BASED.getValue().equals(this.accountingRule);
|
||||||
this.accountingRule);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAccrualBasedAccountingEnabled() {
|
public boolean isAccrualBasedAccountingEnabled() {
|
||||||
return AccountingRuleType.ACCRUAL_BASED.getValue().equals(
|
return AccountingRuleType.ACCRUAL_BASED.getValue().equals(this.accountingRule);
|
||||||
this.accountingRule);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Money getPrincipalAmount() {
|
public Money getPrincipalAmount() {
|
||||||
return this.loanProductRelatedDetail.getPrincipal();
|
return this.loanProductRelatedDetail.getPrincipal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Money getMinPrincipalAmount() {
|
public Money getMinPrincipalAmount() {
|
||||||
return Money.of(this.loanProductRelatedDetail.getCurrency(), this
|
return Money.of(this.loanProductRelatedDetail.getCurrency(), this.loanProductMinMaxConstraints().getMinPrincipal());
|
||||||
.loanProductMinMaxConstraints().getMinPrincipal());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Money getMaxPrincipalAmount() {
|
public Money getMaxPrincipalAmount() {
|
||||||
return Money.of(this.loanProductRelatedDetail.getCurrency(), this
|
return Money.of(this.loanProductRelatedDetail.getCurrency(), this.loanProductMinMaxConstraints().getMaxPrincipal());
|
||||||
.loanProductMinMaxConstraints().getMaxPrincipal());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getNominalInterestRatePerPeriod() {
|
public BigDecimal getNominalInterestRatePerPeriod() {
|
||||||
return this.loanProductRelatedDetail.getNominalInterestRatePerPeriod();
|
return this.loanProductRelatedDetail.getNominalInterestRatePerPeriod();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getMinNominalInterestRatePerPeriod() {
|
public BigDecimal getMinNominalInterestRatePerPeriod() {
|
||||||
return this.loanProductMinMaxConstraints()
|
return this.loanProductMinMaxConstraints().getMinNominalInterestRatePerPeriod();
|
||||||
.getMinNominalInterestRatePerPeriod();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getMaxNominalInterestRatePerPeriod() {
|
public BigDecimal getMaxNominalInterestRatePerPeriod() {
|
||||||
return this.loanProductMinMaxConstraints()
|
return this.loanProductMinMaxConstraints().getMaxNominalInterestRatePerPeriod();
|
||||||
.getMaxNominalInterestRatePerPeriod();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public Integer getNumberOfRepayments() {
|
public Integer getNumberOfRepayments() {
|
||||||
return this.loanProductRelatedDetail().getNumberOfRepayments();
|
return this.loanProductRelatedDetail().getNumberOfRepayments();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getMinNumberOfRepayments() {
|
public Integer getMinNumberOfRepayments() {
|
||||||
return this.loanProductMinMaxConstraints().getMinNumberOfRepayments();
|
return this.loanProductMinMaxConstraints().getMinNumberOfRepayments();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getMaxNumberOfRepayments() {
|
public Integer getMaxNumberOfRepayments() {
|
||||||
return this.loanProductMinMaxConstraints().getMaxNumberOfRepayments();
|
return this.loanProductMinMaxConstraints().getMaxNumberOfRepayments();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanProductRelatedDetail loanProductRelatedDetail() {
|
public LoanProductRelatedDetail loanProductRelatedDetail() {
|
||||||
return this.loanProductRelatedDetail;
|
return this.loanProductRelatedDetail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanProductMinMaxConstraints loanProductMinMaxConstraints() {
|
public LoanProductMinMaxConstraints loanProductMinMaxConstraints() {
|
||||||
// If all min and max fields are null then loanProductMinMaxConstraints
|
// If all min and max fields are null then loanProductMinMaxConstraints
|
||||||
// initialising to null
|
// initialising to null
|
||||||
// Reset LoanProductMinMaxConstraints with null values.
|
// Reset LoanProductMinMaxConstraints with null values.
|
||||||
this.loanProductMinMaxConstraints = (this.loanProductMinMaxConstraints == null) ? new LoanProductMinMaxConstraints(
|
this.loanProductMinMaxConstraints = (this.loanProductMinMaxConstraints == null) ? new LoanProductMinMaxConstraints(null, null,
|
||||||
null, null, null, null, null, null)
|
null, null, null, null) : this.loanProductMinMaxConstraints;
|
||||||
: this.loanProductMinMaxConstraints;
|
return loanProductMinMaxConstraints;
|
||||||
return loanProductMinMaxConstraints;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+22
-15
@@ -16,6 +16,7 @@ public class SavingsApiConstants {
|
|||||||
// general
|
// general
|
||||||
public static final String localeParamName = "locale";
|
public static final String localeParamName = "locale";
|
||||||
public static final String dateFormatParamName = "dateFormat";
|
public static final String dateFormatParamName = "dateFormat";
|
||||||
|
public static final String monthDayFormatParamName = "monthDayFormat";
|
||||||
|
|
||||||
// savings product and account parameters
|
// savings product and account parameters
|
||||||
public static final String idParamName = "id";
|
public static final String idParamName = "id";
|
||||||
@@ -41,16 +42,19 @@ public class SavingsApiConstants {
|
|||||||
public static final String lockinPeriodFrequencyTypeParamName = "lockinPeriodFrequencyType";
|
public static final String lockinPeriodFrequencyTypeParamName = "lockinPeriodFrequencyType";
|
||||||
public static final String withdrawalFeeAmountParamName = "withdrawalFeeAmount";
|
public static final String withdrawalFeeAmountParamName = "withdrawalFeeAmount";
|
||||||
public static final String withdrawalFeeTypeParamName = "withdrawalFeeType";
|
public static final String withdrawalFeeTypeParamName = "withdrawalFeeType";
|
||||||
|
public static final String annualFeeAmountParamName = "annualFeeAmount";
|
||||||
|
public static final String annualFeeOnMonthDayParamName = "annualFeeOnMonthDay";
|
||||||
|
|
||||||
// transaction parameters
|
// transaction parameters
|
||||||
public static final String transactionDateParamName = "transactionDate";
|
public static final String transactionDateParamName = "transactionDate";
|
||||||
public static final String transactionAmountParamName = "transactionAmount";
|
public static final String transactionAmountParamName = "transactionAmount";
|
||||||
|
|
||||||
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||||
nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
|
monthDayFormatParamName, nameParamName, descriptionParamName, currencyCodeParamName, digitsAfterDecimalParamName,
|
||||||
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName,
|
||||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
|
||||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName));
|
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
|
||||||
|
annualFeeAmountParamName, annualFeeOnMonthDayParamName));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These parameters will match the class level parameters of
|
* These parameters will match the class level parameters of
|
||||||
@@ -61,16 +65,18 @@ public class SavingsApiConstants {
|
|||||||
nameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
|
nameParamName, descriptionParamName, "currency", digitsAfterDecimalParamName, nominalAnnualInterestRateParamName,
|
||||||
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||||
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
||||||
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, "currencyOptions",
|
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, annualFeeAmountParamName,
|
||||||
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
|
annualFeeOnMonthDayParamName, "currencyOptions", "interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions",
|
||||||
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions"));
|
"interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions",
|
||||||
|
"withdrawalFeeTypeOptions"));
|
||||||
|
|
||||||
public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
public static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
|
||||||
dateFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName,
|
dateFormatParamName, monthDayFormatParamName, accountNoParamName, externalIdParamName, clientIdParamName, groupIdParamName,
|
||||||
activeParamName, activationDateParamName, nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName,
|
productIdParamName, activeParamName, activationDateParamName, nominalAnnualInterestRateParamName,
|
||||||
interestPostingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
|
interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName, interestCalculationTypeParamName,
|
||||||
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName,
|
||||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName));
|
lockinPeriodFrequencyTypeParamName, withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, annualFeeAmountParamName,
|
||||||
|
annualFeeOnMonthDayParamName));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These parameters will match the class level parameters of
|
* These parameters will match the class level parameters of
|
||||||
@@ -82,9 +88,10 @@ public class SavingsApiConstants {
|
|||||||
groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", nominalAnnualInterestRateParamName,
|
groupIdParamName, "groupName", "savingsProductId", "savingsProductName", "currency", nominalAnnualInterestRateParamName,
|
||||||
interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
|
interestCompoundingPeriodTypeParamName, interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName,
|
||||||
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
minRequiredOpeningBalanceParamName, lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||||
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, "summary", "transactions", "productOptions",
|
withdrawalFeeAmountParamName, withdrawalFeeTypeParamName, annualFeeAmountParamName, annualFeeOnMonthDayParamName, "summary",
|
||||||
"interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions", "interestCalculationTypeOptions",
|
"transactions", "productOptions", "interestCompoundingPeriodTypeOptions", "interestPostingPeriodTypeOptions",
|
||||||
"interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions", "withdrawalFeeTypeOptions"));
|
"interestCalculationTypeOptions", "interestCalculationDaysInYearTypeOptions", "lockinPeriodFrequencyTypeOptions",
|
||||||
|
"withdrawalFeeTypeOptions"));
|
||||||
|
|
||||||
public static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
|
public static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(
|
||||||
localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName));
|
localeParamName, dateFormatParamName, transactionDateParamName, transactionAmountParamName));
|
||||||
|
|||||||
+25
-10
@@ -9,6 +9,7 @@ import java.math.BigDecimal;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||||
|
|
||||||
@@ -39,6 +40,9 @@ public class SavingsAccountData {
|
|||||||
private final EnumOptionData lockinPeriodFrequencyType;
|
private final EnumOptionData lockinPeriodFrequencyType;
|
||||||
private final BigDecimal withdrawalFeeAmount;
|
private final BigDecimal withdrawalFeeAmount;
|
||||||
private final EnumOptionData withdrawalFeeType;
|
private final EnumOptionData withdrawalFeeType;
|
||||||
|
private final BigDecimal annualFeeAmount;
|
||||||
|
private final MonthDay annualFeeOnMonthDay;
|
||||||
|
private final LocalDate annualFeeNextDueDate;
|
||||||
|
|
||||||
// associations
|
// associations
|
||||||
private final SavingsAccountSummaryData summary;
|
private final SavingsAccountSummaryData summary;
|
||||||
@@ -68,7 +72,8 @@ public class SavingsAccountData {
|
|||||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
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<SavingsProductData> productOptions = null;
|
||||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = 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,
|
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
||||||
productId, productName, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
productId, productName, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, summary, transactions, productOptions,
|
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
||||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
annualFeeNextDueDate, summary, transactions, productOptions, interestCompoundingPeriodTypeOptions,
|
||||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||||
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
public static SavingsAccountData withTemplateOptions(final SavingsAccountData account,
|
||||||
@@ -101,9 +107,10 @@ public class SavingsAccountData {
|
|||||||
account.savingsProductName, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
|
account.savingsProductName, account.currency, account.nominalAnnualInterestRate, account.interestCompoundingPeriodType,
|
||||||
account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType,
|
account.interestPostingPeriodType, account.interestCalculationType, account.interestCalculationDaysInYearType,
|
||||||
account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType,
|
account.minRequiredOpeningBalance, account.lockinPeriodFrequency, account.lockinPeriodFrequencyType,
|
||||||
account.withdrawalFeeAmount, account.withdrawalFeeType, account.summary, transactions, productOptions,
|
account.withdrawalFeeAmount, account.withdrawalFeeType, account.annualFeeAmount, account.annualFeeOnMonthDay,
|
||||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
account.annualFeeNextDueDate, account.summary, transactions, productOptions, interestCompoundingPeriodTypeOptions,
|
||||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||||
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
|
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 EnumOptionData lockinPeriodFrequencyType = null;
|
||||||
final BigDecimal withdrawalFeeAmount = null;
|
final BigDecimal withdrawalFeeAmount = null;
|
||||||
final EnumOptionData withdrawalFeeType = null;
|
final EnumOptionData withdrawalFeeType = null;
|
||||||
|
final BigDecimal annualFeeAmount = null;
|
||||||
|
final MonthDay annualFeeOnMonthDay = null;
|
||||||
|
final LocalDate annualFeeNextDueDate = null;
|
||||||
|
|
||||||
final SavingsAccountSummaryData summary = null;
|
final SavingsAccountSummaryData summary = null;
|
||||||
final Collection<SavingsAccountTransactionData> transactions = 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,
|
return new SavingsAccountData(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
||||||
productId, productName, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType,
|
productId, productName, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType,
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, summary, transactions, productOptions,
|
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay,
|
||||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
annualFeeNextDueDate, summary, transactions, productOptions, interestCompoundingPeriodTypeOptions,
|
||||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
|
||||||
|
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SavingsAccountData(final Long id, final String accountNo, final String externalId, final SavingsAccountStatusEnumData status,
|
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 EnumOptionData interestCalculationType, final EnumOptionData interestCalculationDaysInYearType,
|
||||||
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
final BigDecimal minRequiredOpeningBalance, final Integer lockinPeriodFrequency,
|
||||||
final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount, final EnumOptionData withdrawalFeeType,
|
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 SavingsAccountSummaryData summary, final Collection<SavingsAccountTransactionData> transactions,
|
||||||
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
final Collection<SavingsProductData> productOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||||
@@ -182,6 +194,9 @@ public class SavingsAccountData {
|
|||||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
||||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||||
this.withdrawalFeeType = withdrawalFeeType;
|
this.withdrawalFeeType = withdrawalFeeType;
|
||||||
|
this.annualFeeAmount = annualFeeAmount;
|
||||||
|
this.annualFeeOnMonthDay = annualFeeOnMonthDay;
|
||||||
|
this.annualFeeNextDueDate = annualFeeNextDueDate;
|
||||||
|
|
||||||
this.summary = summary;
|
this.summary = summary;
|
||||||
this.transactions = transactions;
|
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.accountNoParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activationDateParamName;
|
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.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.clientIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.externalIdParamName;
|
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.externalIdParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.groupIdParamName;
|
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.apache.commons.lang.StringUtils;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
||||||
@@ -173,6 +176,16 @@ public class SavingsAccountDataValidator {
|
|||||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
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);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,15 +329,21 @@ public class SavingsAccountDataValidator {
|
|||||||
baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).isOneOfTheseValues(1, 2);
|
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);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||||
if (!dataValidationErrors.isEmpty()) {
|
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
|
||||||
//
|
|
||||||
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.",
|
|
||||||
dataValidationErrors);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+4
-2
@@ -19,17 +19,19 @@ public class SavingsAccountSummaryData {
|
|||||||
private final BigDecimal totalDeposits;
|
private final BigDecimal totalDeposits;
|
||||||
private final BigDecimal totalWithdrawals;
|
private final BigDecimal totalWithdrawals;
|
||||||
private final BigDecimal totalWithdrawalFees;
|
private final BigDecimal totalWithdrawalFees;
|
||||||
|
private final BigDecimal totalAnnualFees;
|
||||||
private final BigDecimal totalInterestEarned;
|
private final BigDecimal totalInterestEarned;
|
||||||
private final BigDecimal totalInterestPosted;
|
private final BigDecimal totalInterestPosted;
|
||||||
private final BigDecimal accountBalance;
|
private final BigDecimal accountBalance;
|
||||||
|
|
||||||
public SavingsAccountSummaryData(final CurrencyData currency, final BigDecimal totalDeposits, final BigDecimal totalWithdrawals,
|
public SavingsAccountSummaryData(final CurrencyData currency, final BigDecimal totalDeposits, final BigDecimal totalWithdrawals,
|
||||||
final BigDecimal totalWithdrawalFees, final BigDecimal totalInterestEarned, final BigDecimal totalInterestPosted,
|
final BigDecimal totalWithdrawalFees, final BigDecimal totalAnnualFees, final BigDecimal totalInterestEarned,
|
||||||
final BigDecimal accountBalance) {
|
final BigDecimal totalInterestPosted, final BigDecimal accountBalance) {
|
||||||
this.currency = currency;
|
this.currency = currency;
|
||||||
this.totalDeposits = totalDeposits;
|
this.totalDeposits = totalDeposits;
|
||||||
this.totalWithdrawals = totalWithdrawals;
|
this.totalWithdrawals = totalWithdrawals;
|
||||||
this.totalWithdrawalFees = totalWithdrawalFees;
|
this.totalWithdrawalFees = totalWithdrawalFees;
|
||||||
|
this.totalAnnualFees = totalAnnualFees;
|
||||||
this.totalInterestEarned = totalInterestEarned;
|
this.totalInterestEarned = totalInterestEarned;
|
||||||
this.totalInterestPosted = totalInterestPosted;
|
this.totalInterestPosted = totalInterestPosted;
|
||||||
this.accountBalance = accountBalance;
|
this.accountBalance = accountBalance;
|
||||||
|
|||||||
+28
-17
@@ -8,6 +8,7 @@ package org.mifosplatform.portfolio.savings.data;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||||
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
import org.mifosplatform.organisation.monetary.data.CurrencyData;
|
||||||
|
|
||||||
@@ -30,6 +31,8 @@ public class SavingsProductData {
|
|||||||
private final EnumOptionData lockinPeriodFrequencyType;
|
private final EnumOptionData lockinPeriodFrequencyType;
|
||||||
private final BigDecimal withdrawalFeeAmount;
|
private final BigDecimal withdrawalFeeAmount;
|
||||||
private final EnumOptionData withdrawalFeeType;
|
private final EnumOptionData withdrawalFeeType;
|
||||||
|
private final BigDecimal annualFeeAmount;
|
||||||
|
private final MonthDay annualFeeOnMonthDay;
|
||||||
|
|
||||||
// template
|
// template
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@@ -65,12 +68,15 @@ public class SavingsProductData {
|
|||||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||||
final BigDecimal withdrawalFeeAmount = null;
|
final BigDecimal withdrawalFeeAmount = null;
|
||||||
final EnumOptionData withdrawalFeeType = null;
|
final EnumOptionData withdrawalFeeType = null;
|
||||||
|
final BigDecimal annualFeeAmount = null;
|
||||||
|
final MonthDay annualFeeMonthDay = null;
|
||||||
|
|
||||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, currencyOptions,
|
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
annualFeeMonthDay, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||||
|
withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,9 +95,9 @@ public class SavingsProductData {
|
|||||||
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
existingProduct.interestPostingPeriodType, existingProduct.interestCalculationType,
|
||||||
existingProduct.interestCalculationDaysInYearType, existingProduct.minRequiredOpeningBalance,
|
existingProduct.interestCalculationDaysInYearType, existingProduct.minRequiredOpeningBalance,
|
||||||
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.withdrawalFeeAmount,
|
existingProduct.lockinPeriodFrequency, existingProduct.lockinPeriodFrequencyType, existingProduct.withdrawalFeeAmount,
|
||||||
existingProduct.withdrawalFeeType, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
existingProduct.withdrawalFeeType, existingProduct.annualFeeAmount, existingProduct.annualFeeOnMonthDay, currencyOptions,
|
||||||
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
||||||
withdrawalFeeTypeOptions);
|
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsProductData instance(final Long id, final String name, final String description, final CurrencyData currency,
|
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 interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
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<CurrencyData> currencyOptions = null;
|
||||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||||
@@ -111,9 +117,10 @@ public class SavingsProductData {
|
|||||||
|
|
||||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, currencyOptions,
|
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
annualFeeOnMonthDay, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||||
|
withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SavingsProductData lookup(final Long id, final String name) {
|
public static SavingsProductData lookup(final Long id, final String name) {
|
||||||
@@ -130,6 +137,8 @@ public class SavingsProductData {
|
|||||||
final EnumOptionData lockinPeriodFrequencyType = null;
|
final EnumOptionData lockinPeriodFrequencyType = null;
|
||||||
final BigDecimal withdrawalFeeAmount = null;
|
final BigDecimal withdrawalFeeAmount = null;
|
||||||
final EnumOptionData withdrawalFeeType = null;
|
final EnumOptionData withdrawalFeeType = null;
|
||||||
|
final BigDecimal annualFeeAmount = null;
|
||||||
|
final MonthDay annualFeeMonthDay = null;
|
||||||
|
|
||||||
final Collection<CurrencyData> currencyOptions = null;
|
final Collection<CurrencyData> currencyOptions = null;
|
||||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
|
||||||
@@ -141,19 +150,19 @@ public class SavingsProductData {
|
|||||||
|
|
||||||
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
return new SavingsProductData(id, name, description, currency, nominalAnnualInterestRate, interestCompoundingPeriodType,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, currencyOptions,
|
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||||
interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
|
annualFeeMonthDay, currencyOptions, interestCompoundingPeriodTypeOptions, interestPostingPeriodTypeOptions,
|
||||||
interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions);
|
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
|
||||||
|
withdrawalFeeTypeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SavingsProductData(final Long id, final String name, final String description, final CurrencyData currency,
|
private SavingsProductData(final Long id, final String name, final String description, final CurrencyData currency,
|
||||||
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
|
final BigDecimal nominalAnnualInterestRate, final EnumOptionData interestCompoundingPeriodType,
|
||||||
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
final EnumOptionData interestPostingPeriodType, final EnumOptionData interestCalculationType,
|
||||||
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final EnumOptionData interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType,
|
final Integer lockinPeriodFrequency, final EnumOptionData lockinPeriodFrequencyType, final BigDecimal withdrawalFeeAmount,
|
||||||
final BigDecimal withdrawalFeeAmount, final EnumOptionData withdrawalFeeType,
|
final EnumOptionData withdrawalFeeType, final BigDecimal annualFeeAmount, final MonthDay annualFeeOnMonthDay,
|
||||||
final Collection<CurrencyData> currencyOptions,
|
final Collection<CurrencyData> currencyOptions, final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
||||||
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions,
|
|
||||||
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
final Collection<EnumOptionData> interestPostingPeriodTypeOptions,
|
||||||
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
final Collection<EnumOptionData> interestCalculationTypeOptions,
|
||||||
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions,
|
||||||
@@ -172,6 +181,8 @@ public class SavingsProductData {
|
|||||||
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
this.lockinPeriodFrequencyType = lockinPeriodFrequencyType;
|
||||||
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
this.withdrawalFeeAmount = withdrawalFeeAmount;
|
||||||
this.withdrawalFeeType = withdrawalFeeType;
|
this.withdrawalFeeType = withdrawalFeeType;
|
||||||
|
this.annualFeeAmount = annualFeeAmount;
|
||||||
|
this.annualFeeOnMonthDay = annualFeeOnMonthDay;
|
||||||
|
|
||||||
this.currencyOptions = currencyOptions;
|
this.currencyOptions = currencyOptions;
|
||||||
this.interestCompoundingPeriodTypeOptions = interestCompoundingPeriodTypeOptions;
|
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_REQUEST_DATA_PARAMETERS;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.SAVINGS_PRODUCT_RESOURCE_NAME;
|
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.currencyCodeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||||
@@ -24,6 +26,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
||||||
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
|
||||||
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
|
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);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +235,16 @@ public class SavingsProductDataValidator {
|
|||||||
.isOneOfTheseValues(1, 2);
|
.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);
|
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+155
-3
@@ -5,6 +5,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.mifosplatform.portfolio.savings.domain;
|
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.BigDecimal;
|
||||||
import java.math.MathContext;
|
import java.math.MathContext;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
@@ -34,6 +40,7 @@ import org.hibernate.annotations.LazyCollection;
|
|||||||
import org.hibernate.annotations.LazyCollectionOption;
|
import org.hibernate.annotations.LazyCollectionOption;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
|
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)
|
@Column(name = "withdrawal_fee_type_enum", nullable = true)
|
||||||
private Integer withdrawalFeeType;
|
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
|
@Embedded
|
||||||
private SavingsAccountSummary summary;
|
private SavingsAccountSummary summary;
|
||||||
|
|
||||||
@@ -165,13 +185,15 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||||
|
final MonthDay annualFeeOnMonthDay) {
|
||||||
|
|
||||||
final SavingsAccountStatusType status = SavingsAccountStatusType.UNACTIVATED;
|
final SavingsAccountStatusType status = SavingsAccountStatusType.UNACTIVATED;
|
||||||
final LocalDate activationDate = null;
|
final LocalDate activationDate = null;
|
||||||
return new SavingsAccount(client, group, product, accountNo, externalId, status, activationDate, interestRate,
|
return new SavingsAccount(client, group, product, accountNo, externalId, status, activationDate, interestRate,
|
||||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
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,
|
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 SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||||
|
final MonthDay annualFeeOnMonthDay) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.group = group;
|
this.group = group;
|
||||||
this.product = product;
|
this.product = product;
|
||||||
@@ -210,9 +233,27 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
if (withdrawalFeeType != null) {
|
if (withdrawalFeeType != null) {
|
||||||
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.annualFeeAmount = annualFeeAmount;
|
||||||
|
if (annualFeeOnMonthDay != null) {
|
||||||
|
this.annualFeeOnMonth = annualFeeOnMonthDay.getMonthOfYear();
|
||||||
|
this.annualFeeOnDay = annualFeeOnMonthDay.getDayOfMonth();
|
||||||
|
|
||||||
|
updateAnnualFeeNextDueDate();
|
||||||
|
}
|
||||||
|
|
||||||
this.summary = new SavingsAccountSummary();
|
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
|
* Used after fetching/hydrating a {@link SavingsAccount} object to inject
|
||||||
* helper services/components used for update summary details after
|
* 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);
|
this.summary.updateSummary(this.currency, this.savingsAccountTransactionSummaryWrapper, this.transactions);
|
||||||
|
|
||||||
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
final LocalDate today = DateUtils.getLocalDateOfTenant();
|
||||||
@@ -842,6 +887,71 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
return transaction;
|
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() {
|
private boolean isAutomaticWithdrawalFee() {
|
||||||
return this.withdrawalFeeType != null;
|
return this.withdrawalFeeType != null;
|
||||||
}
|
}
|
||||||
@@ -942,6 +1052,48 @@ public class SavingsAccount extends AbstractPersistable<Long> {
|
|||||||
this.lockinPeriodFrequencyType = null;
|
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) {
|
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.activationDateParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.activeParamName;
|
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.interestCalculationDaysInYearTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
|
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCalculationTypeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.interestCompoundingPeriodTypeParamName;
|
||||||
@@ -22,6 +24,7 @@ import java.math.BigDecimal;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
@@ -161,7 +164,7 @@ public class SavingsAccountAssembler {
|
|||||||
} else {
|
} else {
|
||||||
withdrawalFeeAmount = product.withdrawalFeeAmount();
|
withdrawalFeeAmount = product.withdrawalFeeAmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
SavingsWithdrawalFeesType withdrawalFeeType = null;
|
SavingsWithdrawalFeesType withdrawalFeeType = null;
|
||||||
if (command.parameterExists(withdrawalFeeAmountParamName)) {
|
if (command.parameterExists(withdrawalFeeAmountParamName)) {
|
||||||
final Integer withdrawalFeeTypeValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
final Integer withdrawalFeeTypeValue = command.integerValueOfParameterNamed(withdrawalFeeTypeParamName);
|
||||||
@@ -172,10 +175,24 @@ public class SavingsAccountAssembler {
|
|||||||
withdrawalFeeType = product.withdrawalFeeType();
|
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,
|
final SavingsAccount account = SavingsAccount.createNewAccount(client, group, product, accountNo, externalId, interestRate,
|
||||||
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
interestCompoundingPeriodType, interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType,
|
||||||
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType,
|
||||||
|
annualFeeAmount, monthDayOfAnnualFee);
|
||||||
account.setHelpers(this.savingsAccountTransactionSummaryWrapper);
|
account.setHelpers(this.savingsAccountTransactionSummaryWrapper);
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
|
|||||||
+5
-1
@@ -32,6 +32,9 @@ public final class SavingsAccountSummary {
|
|||||||
@Column(name = "total_withdrawal_fees_derived", scale = 6, precision = 19)
|
@Column(name = "total_withdrawal_fees_derived", scale = 6, precision = 19)
|
||||||
private BigDecimal totalWithdrawalFees;
|
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)
|
@Column(name = "account_balance_derived", scale = 6, precision = 19)
|
||||||
private BigDecimal accountBalance = BigDecimal.ZERO;
|
private BigDecimal accountBalance = BigDecimal.ZERO;
|
||||||
|
|
||||||
@@ -46,9 +49,10 @@ public final class SavingsAccountSummary {
|
|||||||
this.totalWithdrawals = wrapper.calculateTotalWithdrawals(currency, transactions);
|
this.totalWithdrawals = wrapper.calculateTotalWithdrawals(currency, transactions);
|
||||||
this.totalInterestPosted = wrapper.calculateTotalInterestPosted(currency, transactions);
|
this.totalInterestPosted = wrapper.calculateTotalInterestPosted(currency, transactions);
|
||||||
this.totalWithdrawalFees = wrapper.calculateTotalWithdrawalFees(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)
|
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,
|
public void updateFromInterestPeriodSummaries(final MonetaryCurrency currency,
|
||||||
|
|||||||
+10
@@ -88,6 +88,12 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
|||||||
isReversed);
|
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,
|
private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Integer typeOf, final LocalDate transactionLocalDate,
|
||||||
final Money amount, final boolean isReversed) {
|
final Money amount, final boolean isReversed) {
|
||||||
this.savingsAccount = savingsAccount;
|
this.savingsAccount = savingsAccount;
|
||||||
@@ -125,6 +131,10 @@ public final class SavingsAccountTransaction extends AbstractPersistable<Long> {
|
|||||||
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawalFee() && isNotReversed();
|
return SavingsAccountTransactionType.fromInt(this.typeOf).isWithdrawalFee() && isNotReversed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAnnualFee() {
|
||||||
|
return SavingsAccountTransactionType.fromInt(this.typeOf).isAnnualFee() && isNotReversed();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isNotReversed() {
|
public boolean isNotReversed() {
|
||||||
return !isReversed();
|
return !isReversed();
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -53,4 +53,14 @@ public final class SavingsAccountTransactionSummaryWrapper {
|
|||||||
}
|
}
|
||||||
return total.getAmountDefaultedToNullIfZero();
|
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"), //
|
DEPOSIT(1, "savingsAccountTransactionType.deposit"), //
|
||||||
WITHDRAWAL(2, "savingsAccountTransactionType.withdrawal"), //
|
WITHDRAWAL(2, "savingsAccountTransactionType.withdrawal"), //
|
||||||
INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), //
|
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 Integer value;
|
||||||
private final String code;
|
private final String code;
|
||||||
@@ -51,6 +52,9 @@ public enum SavingsAccountTransactionType {
|
|||||||
case 4:
|
case 4:
|
||||||
loanTransactionType = SavingsAccountTransactionType.WITHDRAWAL_FEE;
|
loanTransactionType = SavingsAccountTransactionType.WITHDRAWAL_FEE;
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
|
loanTransactionType = SavingsAccountTransactionType.ANNUAL_FEE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return loanTransactionType;
|
return loanTransactionType;
|
||||||
}
|
}
|
||||||
@@ -70,4 +74,8 @@ public enum SavingsAccountTransactionType {
|
|||||||
public boolean isWithdrawalFee() {
|
public boolean isWithdrawalFee() {
|
||||||
return this.value.equals(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue());
|
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;
|
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.currencyCodeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
||||||
@@ -30,6 +32,7 @@ import javax.persistence.Embedded;
|
|||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
import org.mifosplatform.infrastructure.core.exception.GeneralPlatformDomainRuleException;
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
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
|
* The interest period is the span of time at the end of which savings in a
|
||||||
* client's account earn interest.
|
* client's account earn interest.
|
||||||
*
|
*
|
||||||
* A value from the {@link SavingsCompoundingInterestPeriodType}
|
* A value from the {@link SavingsCompoundingInterestPeriodType}
|
||||||
* enumeration.
|
* enumeration.
|
||||||
*/
|
*/
|
||||||
@@ -96,16 +99,26 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
@Column(name = "withdrawal_fee_type_enum", nullable = true)
|
@Column(name = "withdrawal_fee_type_enum", nullable = true)
|
||||||
private Integer withdrawalFeeType;
|
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,
|
public static SavingsProduct createNew(final String name, final String description, final MonetaryCurrency currency,
|
||||||
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
final BigDecimal interestRate, final SavingsCompoundingInterestPeriodType interestCompoundingPeriodType,
|
||||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||||
|
final MonthDay annualFeeOnMonthDay) {
|
||||||
|
|
||||||
return new SavingsProduct(name, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
return new SavingsProduct(name, description, currency, interestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
||||||
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount, annualFeeOnMonthDay);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SavingsProduct() {
|
protected SavingsProduct() {
|
||||||
@@ -118,7 +131,8 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
final SavingsInterestPostingPeriodType interestPostingPeriodType, final SavingsInterestCalculationType interestCalculationType,
|
||||||
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
final SavingsInterestCalculationDaysInYearType interestCalculationDaysInYearType, final BigDecimal minRequiredOpeningBalance,
|
||||||
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
final Integer lockinPeriodFrequency, final SavingsPeriodFrequencyType lockinPeriodFrequencyType,
|
||||||
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType) {
|
final BigDecimal withdrawalFeeAmount, final SavingsWithdrawalFeesType withdrawalFeeType, final BigDecimal annualFeeAmount,
|
||||||
|
final MonthDay annualFeeOnMonthDay) {
|
||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
@@ -143,9 +157,15 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
if (withdrawalFeeType != null) {
|
if (withdrawalFeeType != null) {
|
||||||
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
this.withdrawalFeeType = withdrawalFeeType.getValue();
|
||||||
}
|
}
|
||||||
|
this.annualFeeAmount = annualFeeAmount;
|
||||||
|
if (annualFeeOnMonthDay != null) {
|
||||||
|
this.annualFeeOnMonth = annualFeeOnMonthDay.getMonthOfYear();
|
||||||
|
this.annualFeeOnDay = annualFeeOnMonthDay.getDayOfMonth();
|
||||||
|
}
|
||||||
|
|
||||||
validateLockinDetails();
|
validateLockinDetails();
|
||||||
validateWithdrawalFeeDetails();
|
validateWithdrawalFeeDetails();
|
||||||
|
validateAnnualFeeDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MonetaryCurrency currency() {
|
public MonetaryCurrency currency() {
|
||||||
@@ -200,6 +220,18 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
return type;
|
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) {
|
public Map<String, Object> update(final JsonCommand command) {
|
||||||
|
|
||||||
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(10);
|
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();
|
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();
|
validateLockinDetails();
|
||||||
validateWithdrawalFeeDetails();
|
validateWithdrawalFeeDetails();
|
||||||
|
validateAnnualFeeDetails();
|
||||||
|
|
||||||
return actualChanges;
|
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() {
|
private void validateWithdrawalFeeDetails() {
|
||||||
if (isInvalidConfigurationOfWithdrawalFeeSettings()) {
|
if (isInvalidConfigurationOfWithdrawalFeeSettings()) {
|
||||||
Object[] defaultUserMessageArgs = new Object[] { withdrawalFeeAmountParamName };
|
Object[] defaultUserMessageArgs = new Object[] { withdrawalFeeAmountParamName };
|
||||||
@@ -330,4 +401,4 @@ public class SavingsProduct extends AbstractPersistable<Long> {
|
|||||||
return (this.lockinPeriodFrequency == null && this.lockinPeriodFrequencyType != null)
|
return (this.lockinPeriodFrequency == null && this.lockinPeriodFrequencyType != null)
|
||||||
|| (this.lockinPeriodFrequencyType == null && this.lockinPeriodFrequency != null);
|
|| (this.lockinPeriodFrequencyType == null && this.lockinPeriodFrequency != null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+8
-1
@@ -1,5 +1,7 @@
|
|||||||
package org.mifosplatform.portfolio.savings.domain;
|
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.currencyCodeParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.descriptionParamName;
|
||||||
import static org.mifosplatform.portfolio.savings.api.SavingsApiConstants.digitsAfterDecimalParamName;
|
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 java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
import org.mifosplatform.infrastructure.core.api.JsonCommand;
|
||||||
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -76,8 +79,12 @@ public class SavingsProductAssembler {
|
|||||||
withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(withdrawalFeeTypeValue);
|
withdrawalFeeType = SavingsWithdrawalFeesType.fromInt(withdrawalFeeTypeValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final BigDecimal annualFeeAmount = command.bigDecimalValueOfParameterNamed(annualFeeAmountParamName);
|
||||||
|
final MonthDay monthDayOfAnnualFee = command.extractMonthDayNamed(annualFeeOnMonthDayParamName);
|
||||||
|
|
||||||
return SavingsProduct.createNew(name, description, currency, interestRate, interestCompoundingPeriodType,
|
return SavingsProduct.createNew(name, description, currency, interestRate, interestCompoundingPeriodType,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
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 java.util.Collection;
|
||||||
|
|
||||||
import org.joda.time.LocalDate;
|
import org.joda.time.LocalDate;
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||||
import org.mifosplatform.infrastructure.core.service.DateUtils;
|
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.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||||
sqlBuilder.append("sa.withdrawal_fee_amount as withdrawalFeeAmount,");
|
sqlBuilder.append("sa.withdrawal_fee_amount as withdrawalFeeAmount,");
|
||||||
sqlBuilder.append("sa.withdrawal_fee_type_enum as withdrawalFeeTypeEnum, ");
|
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_deposits_derived as totalDeposits, ");
|
||||||
sqlBuilder.append("sa.total_withdrawals_derived as totalWithdrawals, ");
|
sqlBuilder.append("sa.total_withdrawals_derived as totalWithdrawals, ");
|
||||||
sqlBuilder.append("sa.total_withdrawal_fees_derived as totalWithdrawalFees, ");
|
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_earned_derived as totalInterestEarned, ");
|
||||||
sqlBuilder.append("sa.total_interest_posted_derived as totalInterestPosted, ");
|
sqlBuilder.append("sa.total_interest_posted_derived as totalInterestPosted, ");
|
||||||
sqlBuilder.append("sa.account_balance_derived as accountBalance ");
|
sqlBuilder.append("sa.account_balance_derived as accountBalance ");
|
||||||
@@ -195,21 +201,34 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
withdrawalFeeType = SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue);
|
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 totalDeposits = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalDeposits");
|
||||||
final BigDecimal totalWithdrawals = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawals");
|
final BigDecimal totalWithdrawals = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawals");
|
||||||
final BigDecimal totalWithdrawalFees = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawalFees");
|
final BigDecimal totalWithdrawalFees = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalWithdrawalFees");
|
||||||
|
final BigDecimal totalAnnualFees = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalAnnualFees");
|
||||||
|
|
||||||
final BigDecimal totalInterestEarned = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalInterestEarned");
|
final BigDecimal totalInterestEarned = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalInterestEarned");
|
||||||
final BigDecimal totalInterestPosted = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalInterestPosted");
|
final BigDecimal totalInterestPosted = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalInterestPosted");
|
||||||
final BigDecimal accountBalance = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "accountBalance");
|
final BigDecimal accountBalance = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "accountBalance");
|
||||||
|
|
||||||
final SavingsAccountSummaryData summary = new SavingsAccountSummaryData(currency, totalDeposits, totalWithdrawals,
|
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,
|
return SavingsAccountData.instance(id, accountNo, externalId, status, activationDate, groupId, groupName, clientId, clientName,
|
||||||
productId, productName, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
productId, productName, currency, nominalAnnualInterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
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 as lockinPeriodFrequency,");
|
||||||
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||||
sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
sqlBuilder.append("sp.withdrawal_fee_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("from m_savings_product sp ");
|
||||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
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);
|
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;
|
Long clientId = null;
|
||||||
String clientName = null;
|
String clientName = null;
|
||||||
if (client != null) {
|
if (client != null) {
|
||||||
@@ -500,11 +531,14 @@ public class SavingsAccountReadPlatformServiceImpl implements SavingsAccountRead
|
|||||||
|
|
||||||
final SavingsAccountStatusEnumData status = null;
|
final SavingsAccountStatusEnumData status = null;
|
||||||
final LocalDate activationDate = null;
|
final LocalDate activationDate = null;
|
||||||
|
final LocalDate annualFeeNextDueDate = null;
|
||||||
final SavingsAccountSummaryData summary = null;
|
final SavingsAccountSummaryData summary = null;
|
||||||
|
|
||||||
return SavingsAccountData.instance(null, null, null, status, activationDate, groupId, groupName, clientId, clientName,
|
return SavingsAccountData.instance(null, null, null, status, activationDate, groupId, groupName, clientId, clientName,
|
||||||
productId, productName, currency, nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
productId, productName, currency, nominalAnnualIterestRate, interestCompoundingPeriodType, interestPostingPeriodType,
|
||||||
interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency,
|
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:
|
case WITHDRAWAL_FEE:
|
||||||
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue().longValue(),
|
optionData = new SavingsAccountTransactionEnumData(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue().longValue(),
|
||||||
SavingsAccountTransactionType.WITHDRAWAL_FEE.getCode(), "Withdrawal fee");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return optionData;
|
return optionData;
|
||||||
|
|||||||
+16
-2
@@ -10,6 +10,7 @@ import java.sql.ResultSet;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.joda.time.MonthDay;
|
||||||
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
|
||||||
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
|
||||||
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
|
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 as lockinPeriodFrequency,");
|
||||||
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
sqlBuilder.append("sp.lockin_period_frequency_enum as lockinPeriodFrequencyType, ");
|
||||||
sqlBuilder.append("sp.withdrawal_fee_amount as withdrawalFeeAmount,");
|
sqlBuilder.append("sp.withdrawal_fee_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("from m_savings_product sp ");
|
||||||
sqlBuilder.append("join m_currency curr on curr.code = sp.currency_code ");
|
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);
|
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,
|
return SavingsProductData.instance(id, name, description, currency, nominalAnnualInterestRate, compoundingInterestPeriodType,
|
||||||
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
interestPostingPeriodType, interestCalculationType, interestCalculationDaysInYearType, minRequiredOpeningBalance,
|
||||||
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType);
|
lockinPeriodFrequency, lockinPeriodFrequencyType, withdrawalFeeAmount, withdrawalFeeType, annualFeeAmount,
|
||||||
|
annualFeeOnMonthDay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user