squash madhukars pull request into one commit.

This commit is contained in:
Keith Woodlock
2012-10-09 19:16:48 +01:00
parent b97f02ef8e
commit 79d036d5c9
18 changed files with 416 additions and 74 deletions
@@ -0,0 +1,9 @@
ALTER TABLE `m_product_deposit`
ADD COLUMN `is_lock_in_period_allowed` tinyint(1) NOT NULL DEFAULT '0' AFTER `pre_closure_interest_rate`,
ADD COLUMN `lock_in_period` bigint(20) DEFAULT NULL AFTER `is_lock_in_period_allowed`,
ADD COLUMN `lock_in_period_type` smallint(5) NOT NULL DEFAULT '2' AFTER `lock_in_period`;
ALTER TABLE `m_deposit_account`
ADD COLUMN `is_lock_in_period_allowed` tinyint(1) NOT NULL DEFAULT '0' AFTER `pre_closure_interest_rate`,
ADD COLUMN `lock_in_period` bigint(20) DEFAULT NULL AFTER `is_lock_in_period_allowed`,
ADD COLUMN `lock_in_period_type` smallint(5) NOT NULL DEFAULT '2' AFTER `lock_in_period`;
@@ -73,7 +73,8 @@ public class DepositAccountsApiResource {
"interestCompoundedEveryPeriodType", "renewalAllowed",
"preClosureAllowed", "preClosureInterestRate",
"withdrawnonDate","rejectedonDate","closedonDate","transactions","interestPaid","isInterestWithdrawable",
"availableInterestForWithdrawal","availableWithdrawalAmount"));
"availableInterestForWithdrawal","availableWithdrawalAmount","todaysDate",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType"));
@POST
@@ -100,7 +100,8 @@ public class DepositProductsApiResource {
"currencyCode","digitsAfterDecimal","minimumBalance","maximumBalance","tenureInMonths",
"maturityDefaultInterestRate","maturityMinInterestRate","maturityMaxInterestRate",
"interestCompoundedEvery", "interestCompoundedEveryPeriodType",
"renewalAllowed","preClosureAllowed","preClosureInterestRate","interestCompoundingAllowed"));
"renewalAllowed","preClosureAllowed","preClosureInterestRate","interestCompoundingAllowed",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType"));
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
@@ -123,7 +124,8 @@ public class DepositProductsApiResource {
"currencyCode","digitsAfterDecimal","minimumBalance","maximumBalance","tenureInMonths",
"maturityDefaultInterestRate","maturityMinInterestRate","maturityMaxInterestRate",
"interestCompoundedEvery", "interestCompoundedEveryPeriodType",
"renewalAllowed","preClosureAllowed","preClosureInterestRate","interestCompoundingAllowed"));
"renewalAllowed","preClosureAllowed","preClosureInterestRate","interestCompoundingAllowed",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType"));
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
@@ -153,7 +155,8 @@ public class DepositProductsApiResource {
"currencyCode","digitsAfterDecimal","minimumBalance","maximumBalance","tenureInMonths",
"maturityDefaultInterestRate","maturityMinInterestRate","maturityMaxInterestRate",
"interestCompoundedEvery", "interestCompoundedEveryPeriodType",
"renewalAllowed","preClosureAllowed","preClosureInterestRate"));
"renewalAllowed","preClosureAllowed","preClosureInterestRate",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType"));
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
@@ -20,6 +20,10 @@ public class DepositAccountCommand {
private final BigDecimal preClosureInterestRate;
private final Integer tenureInMonths;
private final boolean isLockinPeriodAllowed;
private final Integer lockinPeriod;
private final Integer lockinPeriodType;
private final Integer interestCompoundedEvery;
private final Integer interestCompoundedEveryPeriodType;
private final LocalDate commencementDate;
@@ -39,7 +43,8 @@ public class DepositAccountCommand {
final BigDecimal depositAmount,
final BigDecimal interestRate, final BigDecimal preClosureInterestRate,
final Integer tenureInMonths, final Integer compoundingInterestFrequency, final Integer compoundingInterestFrequencyType, final LocalDate commencementDate,
final boolean renewalAllowed, final boolean preClosureAllowed,final boolean isInterstWithdrawable, final boolean interestCompoundingAllowed) {
final boolean renewalAllowed, final boolean preClosureAllowed,final boolean isInterstWithdrawable, final boolean interestCompoundingAllowed,
final boolean isLockinPeriodAllowed, final Integer lockInPeriod, final Integer lockinPeriodType) {
this.id = id;
this.clientId = clientId;
this.productId = productId;
@@ -58,6 +63,10 @@ public class DepositAccountCommand {
this.preClosureAllowed = preClosureAllowed;
this.isInterestWithdrawable = isInterstWithdrawable;
this.interestCompoundingAllowed = interestCompoundingAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockInPeriod;
this.lockinPeriodType = lockinPeriodType;
}
public Long getId() {
@@ -120,6 +129,18 @@ public class DepositAccountCommand {
return interestCompoundingAllowed;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public Integer getLockinPeriodType() {
return lockinPeriodType;
}
public boolean isNoFieldChanged() {
return this.modifiedParameters.isEmpty();
}
@@ -136,6 +157,10 @@ public class DepositAccountCommand {
return this.modifiedParameters.contains("tenureInMonths");
}
public boolean isLockinPeriodChanged() {
return this.modifiedParameters.contains("lockinPeriod");
}
public boolean isMaturityActualInterestRateChanged() {
return this.modifiedParameters.contains("maturityInterestRate");
}
@@ -22,6 +22,9 @@ public class DepositProductCommand {
private final BigDecimal maturityMaxInterestRate;
private final Integer interestCompoundedEvery;
private final Integer interestCompoundedEveryPeriodType;
private final boolean isLockinPeriodAllowed;
private final Integer lockinPeriod;
private final Integer lockinPeriodType;
private final boolean renewalAllowed;
private final boolean preClosureAllowed;
@@ -40,7 +43,8 @@ public class DepositProductCommand {
final Integer interestCompoundedEvery,
final Integer interestCompoundedEveryPeriodType,
final boolean renewalAllowed, final boolean preClosureAllowed,
final BigDecimal preClosureInterestRate, final boolean interestCompoundingAllowed ) {
final BigDecimal preClosureInterestRate, final boolean interestCompoundingAllowed,
final boolean isLockinPeriodAllowed,final Integer lockinPeriod,final Integer lockinPeriodType ) {
this.id = id;
this.externalId = externalId;
this.name = name;
@@ -63,6 +67,11 @@ public class DepositProductCommand {
this.renewalAllowed = renewalAllowed;
this.preClosureAllowed = preClosureAllowed;
this.interestCompoundingAllowed = interestCompoundingAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
this.modifiedParameters = modifiedParameters;
}
@@ -139,6 +148,18 @@ public class DepositProductCommand {
return interestCompoundingAllowed;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public Integer getLockinPeriodType() {
return lockinPeriodType;
}
public boolean isExternalIdChanged() {
return this.modifiedParameters.contains("externalId");
}
@@ -214,4 +235,16 @@ public class DepositProductCommand {
public boolean interestCompoundingAllowedChanged(){
return this.modifiedParameters.contains("interestCompoundingAllowed");
}
public boolean isLockinPeriodAllowedChanged() {
return this.modifiedParameters.contains("isLockinPeriodAllowed");
}
public boolean isLockinPeriodChanged() {
return this.modifiedParameters.contains("lockinPeriod");
}
public boolean isLockinPeriodTypeChanged() {
return this.modifiedParameters.contains("lockinPeriodType");
}
}
@@ -7,6 +7,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.joda.time.Months;
@@ -56,6 +57,11 @@ public class DepositAccountData {
private final DepositPermissionData permissions;
private final BigDecimal availableInterestForWithdrawal;
private final BigDecimal availableWithdrawalAmount;
private final LocalDate todaysDate;
private final boolean isLockinPeriodAllowed;
private final Integer lockinPeriod;
private final EnumOptionData lockinPeriodType;
/*
* used when returning account template data but only a clientId is passed, no selected product.
@@ -106,6 +112,11 @@ public class DepositAccountData {
this.interestCompoundingAllowed = true;
this.availableInterestForWithdrawal = new BigDecimal(0);
this.availableWithdrawalAmount= new BigDecimal(0);
this.todaysDate = new LocalDate();
this.isLockinPeriodAllowed =true;
this.lockinPeriod = null;
this.lockinPeriodType = null;
}
public DepositAccountData(
@@ -150,6 +161,11 @@ public class DepositAccountData {
this.interestCompoundingAllowed=account.isInterestCompoundingAllowed();
this.availableInterestForWithdrawal=determineAvailableInterestForWithdrawal(account);
this.availableWithdrawalAmount=determineAvalableWithdrawalAmount(account);
this.todaysDate = new LocalDate();
this.lockinPeriod = account.getLockinPeriod();
this.lockinPeriodType = account.getLockinPeriodType();
this.isLockinPeriodAllowed = account.isLockinPeriodAllowed();
}
public DepositAccountData(final DepositAccountData account, final DepositPermissionData permissions, final Collection<DepositAccountTransactionData> transactions) {
@@ -191,6 +207,11 @@ public class DepositAccountData {
this.interestCompoundingAllowed = account.isInterestCompoundingAllowed();
this.availableInterestForWithdrawal=determineAvailableInterestForWithdrawal(account);
this.availableWithdrawalAmount=determineAvalableWithdrawalAmount(account);
this.todaysDate = new LocalDate();
this.lockinPeriod = account.getLockinPeriod();
this.lockinPeriodType = account.getLockinPeriodType();
this.isLockinPeriodAllowed = account.isLockinPeriodAllowed();
}
public DepositAccountData(
@@ -221,7 +242,10 @@ public class DepositAccountData {
final LocalDate closedonDate,
final boolean isInterestWithdrawable,
final BigDecimal interestPaid,
final boolean interestCompoundingAllowed) {
final boolean interestCompoundingAllowed,
final boolean isLockinPeriodAllowed,
final Integer lockinPeriod,
final EnumOptionData lockinPeriodType) {
this.id=id;
this.externalId = externalId;
this.status = status;
@@ -261,6 +285,11 @@ public class DepositAccountData {
this.interestCompoundingAllowed = interestCompoundingAllowed;
this.availableInterestForWithdrawal = BigDecimal.ZERO;
this.availableWithdrawalAmount = BigDecimal.ZERO;
this.todaysDate = new LocalDate();
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod =lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
}
public DepositAccountData(
@@ -315,6 +344,12 @@ public class DepositAccountData {
this.interestCompoundingAllowed=interestCompoundingAllowed;
this.availableInterestForWithdrawal= BigDecimal.ZERO;
this.availableWithdrawalAmount = BigDecimal.ZERO;
this.todaysDate = new LocalDate();
//need to update in constructor's call method and update it
this.lockinPeriod = Integer.valueOf(0);
this.isLockinPeriodAllowed =true;
this.lockinPeriodType = interestCompoundedEveryPeriodType;
}
public Long getId() {
@@ -457,26 +492,35 @@ public class DepositAccountData {
return availableWithdrawalAmount;
}
public LocalDate getTodaysDate() {
return todaysDate;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public EnumOptionData getLockinPeriodType() {
return lockinPeriodType;
}
private BigDecimal determineAvailableInterestForWithdrawal(final DepositAccountData account) {
BigDecimal availableInterestForWithdrawal = BigDecimal.ZERO;
if(this.status!=null){
if (account.getStatus().getId() == 300) {
BigDecimal interestGettingForPeriod = BigDecimal.valueOf(account
.getActualInterestAccrued().doubleValue()
/ new Double(account.getTenureInMonths()));
Integer noOfMonthsforInterestCal = Months.monthsBetween(
account.getActualCommencementDate(), new LocalDate())
.getMonths();
Integer noOfPeriods = noOfMonthsforInterestCal
/ account.getInterestCompoundedEvery();
BigDecimal interestGettingForPeriod = BigDecimal.valueOf(account.getActualInterestAccrued().doubleValue()/ new Double(account.getTenureInMonths()));
LocalDate interestWithdrawingDate= new LocalDate().isAfter(getMaturedOn())?getMaturedOn().plusDays(1):new LocalDate();
Integer noOfMonthsforInterestCal = Months.monthsBetween(account.getActualCommencementDate(), interestWithdrawingDate).getMonths();
Integer noOfPeriods = noOfMonthsforInterestCal/ account.getInterestCompoundedEvery();
availableInterestForWithdrawal = BigDecimal
.valueOf(interestGettingForPeriod.multiply(
new BigDecimal(noOfPeriods)).doubleValue()
- account.getInterestPaid().doubleValue());
availableInterestForWithdrawal = BigDecimal.valueOf(interestGettingForPeriod.multiply(new BigDecimal(noOfPeriods)).doubleValue()- account.getInterestPaid().doubleValue());
}else {
return new BigDecimal(0);
return BigDecimal.ZERO;
}
}else return BigDecimal.ZERO;
@@ -494,10 +538,12 @@ public class DepositAccountData {
BigDecimal interestRateAsFraction = account.getPreClosureInterestRate().divide(BigDecimal.valueOf(100), mc);
BigDecimal interestRateForOneMonth = interestRateAsFraction.divide(BigDecimal.valueOf(monthsInYear.doubleValue()), mc);
Integer noOfMonthsforInterestCal = Months.monthsBetween(account.getActualCommencementDate(), new LocalDate()).getMonths();
Integer days = Days.daysBetween(account.getActualCommencementDate().plusMonths(noOfMonthsforInterestCal), new LocalDate()).getDays();
BigDecimal interest = BigDecimal.valueOf(account.getDeposit().doubleValue()*new Double(noOfMonthsforInterestCal)*interestRateForOneMonth.doubleValue());
avalablePreclosureWithdrawalAmount = interest.add(account.getDeposit()).subtract(account.getInterestPaid());
avalablePreclosureWithdrawalAmount = interest.add(account.getDeposit()).subtract(account.getInterestPaid()).add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days));
}else if(new LocalDate().isAfter(account.getMaturedOn()) || new LocalDate().isEqual(account.getMaturedOn())){
avalablePreclosureWithdrawalAmount=determineAvailableInterestForWithdrawal(account).add(account.getDeposit());
Integer days = Days.daysBetween(account.getMaturedOn(), new LocalDate()).getDays();
avalablePreclosureWithdrawalAmount=determineAvailableInterestForWithdrawal(account).add(account.getDeposit()).add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days));
}
}else{
avalablePreclosureWithdrawalAmount=account.getDeposit();
@@ -505,5 +551,15 @@ public class DepositAccountData {
}
return avalablePreclosureWithdrawalAmount;
}
private BigDecimal determineRemainInerestAmount(final BigDecimal depsoitAmount, final BigDecimal interstRateApplicable, final Integer days){
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
Integer daysInYear = 365;
BigDecimal interestRateAsFraction = interstRateApplicable.divide(BigDecimal.valueOf(100), mc);
BigDecimal interestRateForOneDay = interestRateAsFraction.divide(BigDecimal.valueOf(daysInYear.doubleValue()), mc);
return BigDecimal.valueOf(depsoitAmount.doubleValue()*days.doubleValue()*interestRateForOneDay.doubleValue());
}
}
@@ -31,6 +31,10 @@ public class DepositProductData {
private final BigDecimal preClosureInterestRate;
private final boolean interestCompoundingAllowed;
private final boolean isLockinPeriodAllowed;
private final Integer lockinPeriod;
private final EnumOptionData lockinPeriodType;
private final DateTime createdOn;
private final DateTime lastModifedOn;
@@ -57,7 +61,10 @@ public class DepositProductData {
final boolean renewalAllowed,
final boolean preClosureAllowed,
final BigDecimal preClosureInterestRate,
final boolean interestCompoundingAllowed) {
final boolean interestCompoundingAllowed,
final boolean isLockinPeriodAllowed,
final Integer lockinPeriod,
final EnumOptionData lockinPeriodType) {
this.createdOn=createdOn;
this.lastModifedOn=lastModifedOn;
@@ -81,6 +88,10 @@ public class DepositProductData {
this.preClosureInterestRate=preClosureInterestRate;
this.interestCompoundingAllowed=interestCompoundingAllowed;
this.lockinPeriod=lockinPeriod;
this.lockinPeriodType=lockinPeriodType;
this.isLockinPeriodAllowed=isLockinPeriodAllowed;
this.currencyOptions = new ArrayList<CurrencyData>();
this.interestCompoundedEveryPeriodTypeOptions = new ArrayList<EnumOptionData>();
}
@@ -112,6 +123,10 @@ public class DepositProductData {
this.preClosureInterestRate=BigDecimal.ZERO;
this.interestCompoundingAllowed=true;
this.isLockinPeriodAllowed=true;
this.lockinPeriod=Integer.valueOf(0);
this.lockinPeriodType=defaultInterestCompoundedEveryPeriodType;
this.currencyOptions = currencyOptions;
this.interestCompoundedEveryPeriodTypeOptions = interestCompoundedEveryPeriodTypeOptions;
}
@@ -143,6 +158,10 @@ public class DepositProductData {
this.preClosureInterestRate=product.getPreClosureInterestRate();
this.interestCompoundingAllowed=product.isInterestCompoundingAllowed();
this.lockinPeriod=product.getLockinPeriod();
this.lockinPeriodType=product.getLockinPeriodType();
this.isLockinPeriodAllowed=product.isLockinPeriodAllowed();
this.currencyOptions = currencyOptions;
this.interestCompoundedEveryPeriodTypeOptions = interestCompoundedEveryPeriodTypeOptions;
}
@@ -234,4 +253,17 @@ public class DepositProductData {
public boolean isInterestCompoundingAllowed() {
return interestCompoundingAllowed;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public EnumOptionData getLockinPeriodType() {
return lockinPeriodType;
}
}
@@ -1262,7 +1262,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
Arrays.asList("clientId", "productId", "externalId", "deposit", "maturityInterestRate", "preClosureInterestRate",
"tenureInMonths", "interestCompoundedEvery", "interestCompoundedEveryPeriodType", "commencementDate",
"renewalAllowed", "preClosureAllowed","interestCompoundingAllowed",
"locale", "dateFormat","isInterestWithdrawable")
"locale", "dateFormat","isInterestWithdrawable","isLockinPeriodAllowed","lockinPeriod","lockinPeriodType")
);
checkForUnsupportedParameters(requestMap, supportedParams);
Set<String> modifiedParameters = new HashSet<String>();
@@ -1275,6 +1275,10 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
BigDecimal preClosureInterestRate = extractBigDecimalParameter("preClosureInterestRate", requestMap, modifiedParameters);
Integer tenureInMonths = extractIntegerParameter("tenureInMonths", requestMap, modifiedParameters);
boolean isLockinPeriodAllowed = extractBooleanParameter("isLockinPeriodAllowed", requestMap, modifiedParameters);
Integer lockinPeriod = extractIntegerParameter("lockinPeriod", requestMap, modifiedParameters);
Integer lockinPeriodType = extractIntegerParameter("lockinPeriodType", requestMap, modifiedParameters);
Integer interestCompoundedEvery = extractIntegerParameter("interestCompoundedEvery", requestMap, modifiedParameters);
Integer interestCompoundedEveryPeriodType = extractIntegerParameter("interestCompoundedEveryPeriodType", requestMap, modifiedParameters);
LocalDate commencementDate = extractLocalDateParameter("commencementDate", requestMap, modifiedParameters);
@@ -1285,9 +1289,10 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
boolean interestCompoundingAllowed = extractBooleanParameter("interestCompoundingAllowed", requestMap, modifiedParameters);
return new DepositAccountCommand(modifiedParameters, resourceIdentifier, clientId, productId,
externalId, deposit, interestRate, preClosureInterestRate, tenureInMonths,
externalId, deposit, interestRate, preClosureInterestRate, tenureInMonths,
interestCompoundedEvery, interestCompoundedEveryPeriodType, commencementDate, renewalAllowed,
preClosureAllowed, isInterestWithdrawable, interestCompoundingAllowed);
preClosureAllowed, isInterestWithdrawable, interestCompoundingAllowed,
isLockinPeriodAllowed,lockinPeriod,lockinPeriodType);
}
@Override
@@ -1304,7 +1309,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
Arrays.asList("locale", "name", "externalId", "description","currencyCode", "digitsAfterDecimal","minimumBalance","maximumBalance","tenureInMonths",
"maturityDefaultInterestRate","maturityMinInterestRate","maturityMaxInterestRate",
"interestCompoundedEvery", "interestCompoundedEveryPeriodType",
"renewalAllowed","preClosureAllowed","preClosureInterestRate","interestCompoundingAllowed")
"renewalAllowed","preClosureAllowed","preClosureInterestRate","interestCompoundingAllowed","isLockinPeriodAllowed","lockinPeriod","lockinPeriodType")
);
checkForUnsupportedParameters(requestMap, supportedParams);
Set<String> modifiedParameters = new HashSet<String>();
@@ -1330,12 +1335,18 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService {
boolean canRenew = extractBooleanParameter("renewalAllowed", requestMap, modifiedParameters);
boolean canPreClose = extractBooleanParameter("preClosureAllowed", requestMap, modifiedParameters);
BigDecimal preClosureInterestRate = extractBigDecimalParameter("preClosureInterestRate", requestMap, modifiedParameters);
boolean isLockinPeriodAllowed = extractBooleanParameter("isLockinPeriodAllowed", requestMap, modifiedParameters);
Integer lockinPeriod = extractIntegerParameter("lockinPeriod", requestMap, modifiedParameters);
Integer lockinPeriodType = extractIntegerParameter("lockinPeriodType", requestMap, modifiedParameters);
return new DepositProductCommand(modifiedParameters, resourceIdentifier, externalId,
name, description, currencyCode, digitsAfterDecimalValue, minimumBalance,maximumBalance,
tenureMonths, maturityDefaultInterestRate, maturityMinInterestRate, maturityMaxInterestRate,
interestCompoundedEvery, interestCompoundedEveryPeriodType,
canRenew, canPreClose, preClosureInterestRate, interestCompoundingAllowed);
canRenew, canPreClose, preClosureInterestRate, interestCompoundingAllowed,isLockinPeriodAllowed,lockinPeriod,lockinPeriodType);
}
@Override
@@ -103,7 +103,8 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ
"maturityDefaultInterestRate", "maturityMinInterestRate",
"maturityMaxInterestRate", "interestCompoundedEvery",
"interestCompoundedEveryPeriodType", "renewalAllowed",
"preClosureAllowed", "preClosureInterestRate", "interestCompoundingAllowed"));
"preClosureAllowed", "preClosureInterestRate", "interestCompoundingAllowed",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType"));
private static final Set<String> SAVINGS_DEPOSIT_ACCOUNT_DATA_PARAMETERS = new HashSet<String>(
Arrays.asList("productOptions", "interestCompoundedEveryPeriodTypeOptions",
@@ -113,7 +114,8 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ
"renewalAllowed","preClosureAllowed","preClosureInterestRate",
"withdrawnonDate","rejectedonDate","closedonDate","transactions",
"permissions","isInterestWithdrawable","interestPaid","interestCompoundingAllowed",
"availableInterestForWithdrawal","availableWithdrawalAmount")
"availableInterestForWithdrawal","availableWithdrawalAmount","todaysDate",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType")
);
private static final Set<String> CLIENT_DATA_PARAMETERS = new HashSet<String>(
@@ -3,8 +3,8 @@ package org.mifosng.platform.exceptions;
public class DepositAccountTransactionsException extends AbstractPlatformDomainRuleException {
public DepositAccountTransactionsException(String remainInterestForWithdrawal) {
super("deposit.transaction.interest.withdrawal.exception", "You can Withdraw "+remainInterestForWithdrawal+" only", remainInterestForWithdrawal);
public DepositAccountTransactionsException(String errorcode, String remainInterestForWithdrawal) {
super(errorcode, "You can Withdraw "+remainInterestForWithdrawal+" only", remainInterestForWithdrawal);
}
}
@@ -22,6 +22,7 @@ import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.joda.time.Months;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
@@ -106,17 +107,14 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "status_enum", nullable = false)
private Integer depositStatus;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "closedon_date")
private Date closedOnDate;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "rejectedon_date")
private Date rejectedOnDate;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "withdrawnon_date")
private Date withdrawnOnDate;
@@ -137,10 +135,19 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "depositAccount", orphanRemoval = true)
private final List<DepositAccountTransaction> depositaccountTransactions = new ArrayList<DepositAccountTransaction>();
@SuppressWarnings("unused")
@OneToOne(optional=true, cascade={CascadeType.PERSIST})
@JoinColumn(name = "renewed_account_id")
private DepositAccount renewdAccount;
@Column(name = "is_lock_in_period_allowed", nullable=false)
private boolean isLockinPeriodAllowed = false;
@Column(name = "lock_in_period", nullable=false)
private Integer lockinPeriod;
@Column(name = "lock_in_period_type", nullable=false)
private PeriodFrequencyType lockinPeriodType;
public DepositAccount openNew(
final Client client, final DepositProduct product,
@@ -152,7 +159,8 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
final boolean preClosureAllowed,
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,
final DepositLifecycleStateMachine depositLifecycleStateMachine,
final boolean isInterstWithdrawable,final boolean interestCompoundingAllowed) {
final boolean isInterstWithdrawable,final boolean interestCompoundingAllowed,
final boolean isLockinPeriodAllowed, final Integer lockinPeriod, final PeriodFrequencyType lockinPeriodType) {
Money futureValueOnMaturity =null;
@@ -179,7 +187,7 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
return new DepositAccount(client, product, externalId, deposit, maturityInterestRate, preClosureInterestRate, tenureInMonths,
interestCompoundedEvery, interestCompoundedFrequencyPeriodType, commencementDate, renewalAllowed, preClosureAllowed,
futureValueOnMaturity,depositStatus,isInterstWithdrawable, interestCompoundingAllowed);
futureValueOnMaturity,depositStatus,isInterstWithdrawable, interestCompoundingAllowed,isLockinPeriodAllowed,lockinPeriod,lockinPeriodType);
}
public DepositAccount() {
@@ -197,7 +205,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
final Money futureValueOnMaturity,
final Integer depositStatus,
final boolean isInterestWithdrawable,
final boolean interestCompoundingAllowed) {
final boolean interestCompoundingAllowed,
final boolean isLockinPeriodAllowed,
final Integer lockinPeriod,
final PeriodFrequencyType lockinPeriodType) {
this.client = client;
this.product = product;
setExternalId(externalId);
@@ -213,7 +224,7 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
this.interestCompoundedFrequencyType = interestCompoundedFrequencyPeriodType.getValue();
if (commencementDate != null) {
this.projectedCommencementDate = commencementDate.toDate();
this.maturesOnDate = commencementDate.plusMonths(this.tenureInMonths).toDate();
this.maturesOnDate = commencementDate.plusMonths(this.tenureInMonths).minusDays(1).toDate();
}
this.renewalAllowed = renewalAllowed;
@@ -222,12 +233,15 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
this.preClosureInterestRate = preClosureInterestRate;
this.isInterestWithdrawable = isInterestWithdrawable;
this.interestCompoundingAllowed = interestCompoundingAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
// derived fields
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.minus(deposit).getAmount();
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
this.depositStatus=depositStatus;
this.interstPaid = new BigDecimal(0);
this.interstPaid = BigDecimal.ZERO;
}
private void setExternalId(final String externalId) {
@@ -275,12 +289,14 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
}
this.product.validateDepositInRange(this.depositAmount);
this.interestCompoundedEvery = command.getInterestCompoundedEvery();
if (command.getInterestCompoundedEveryPeriodType() != null) {
this.interestCompoundedFrequencyType = PeriodFrequencyType.fromInt(command.getInterestCompoundedEveryPeriodType()).getValue();
}
this.actualCommencementDate = actualCommencementDate.toDate();
this.maturesOnDate = getActualCommencementDate().plusMonths(this.tenureInMonths).toDate();
this.maturesOnDate = getActualCommencementDate().plusMonths(this.tenureInMonths).minusDays(1).toDate();
Money futureValueOnMaturity =null;
@@ -354,6 +370,18 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
public boolean isInterestCompoundingAllowed() {
return interestCompoundingAllowed;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public PeriodFrequencyType getLockinPeriodType() {
return lockinPeriodType;
}
public void reject(final LocalDate rejectedOn,
final DepositLifecycleStateMachine depositLifecycleStateMachine) {
@@ -425,7 +453,7 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
this.actualCommencementDate = null;
this.projectedInterestAccruedOnMaturity=this.interestAccrued;
this.projectedTotalOnMaturity = this.depositAmount.add(this.projectedInterestAccruedOnMaturity);
this.maturesOnDate = getProjectedCommencementDate().plusMonths(this.tenureInMonths).toDate();
this.maturesOnDate = getProjectedCommencementDate().plusMonths(this.tenureInMonths).minusDays(1).toDate();
this.total=null;
this.interestAccrued=null;
this.depositaccountTransactions.clear();
@@ -509,18 +537,22 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
}
public void withdrawDepositAccountMoney(DepositLifecycleStateMachine depositLifecycleStateMachine) {
public void withdrawDepositAccountMoney(DepositLifecycleStateMachine depositLifecycleStateMachine, FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,LocalDate eventDate) {
if (new LocalDate().isAfter(maturesOnDate()) || new LocalDate().equals(maturesOnDate())) {
if (eventDate.isAfter(maturesOnDate()) || eventDate.equals(maturesOnDate())) {
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_CLOSED, DepositAccountStatus.fromInt(this.depositStatus));
this.depositStatus = statusEnum.getValue();
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), new LocalDate(),getAccuredInterest());
Integer days = Days.daysBetween(maturesOnDate(), eventDate).getDays();
Money accuredInterestAfterMaturityToTillDate = fixedTermDepositInterestCalculator.calculateRemainInterest(getDeposit(), days, preClosureInterestRate);
this.interestAccrued = this.interestAccrued.add(accuredInterestAfterMaturityToTillDate.getAmount());
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), eventDate,getAccuredInterest());
depositaccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositaccountTransaction);
this.closedOnDate = new LocalDate().toDate();
this.closedOnDate = eventDate.toDate();
this.withdrawnOnDate = null;
this.rejectedOnDate = null;
@@ -529,37 +561,42 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_PRECLOSED, DepositAccountStatus.fromInt(this.depositStatus));
this.depositStatus = statusEnum.getValue();
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), new LocalDate(),getAccuredInterest());
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), eventDate, getAccuredInterest());
depositaccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositaccountTransaction);
this.closedOnDate = new LocalDate().toDate();
this.closedOnDate = eventDate.toDate();
this.withdrawnOnDate = null;
this.rejectedOnDate = null;
}
}
public void adjustTotalAmountForPreclosureInterest(DepositAccount account, FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator) {
public void adjustTotalAmountForPreclosureInterest(DepositAccount account, FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,LocalDate eventDate) {
LocalDate commnencementDate = new LocalDate(this.actualCommencementDate);
LocalDate preClosedDate = new LocalDate();
LocalDate commnencementDate = getActualCommencementDate();
LocalDate preClosedDate = eventDate;
Integer tenure = Months.monthsBetween(commnencementDate, preClosedDate).getMonths();
LocalDate actualPrecloseCalculationDate = commnencementDate.plusMonths(tenure);
Integer missedDays = Days.daysBetween(actualPrecloseCalculationDate, preClosedDate).getDays();
Money deposit = Money.of(account.getDeposit().getCurrency(), account.getDeposit().getAmount());
Money accuredtotalAmount = null;
Money remainDaysAmount = fixedTermDepositInterestCalculator.calculateRemainInterest(deposit, missedDays, preClosureInterestRate);
if (account.isInterestCompoundingAllowed()) {
accuredtotalAmount = fixedTermDepositInterestCalculator
.calculateInterestOnMaturityFor(deposit, tenure,
preClosureInterestRate, interestCompoundedEvery,
this.product.getInterestCompoundedEveryPeriodType());
accuredtotalAmount = accuredtotalAmount.plus(remainDaysAmount);
} else {
accuredtotalAmount = fixedTermDepositInterestCalculator
.calculateInterestOnMaturityForSimpleInterest(deposit,
tenure, preClosureInterestRate,
interestCompoundedEvery,
this.product.getInterestCompoundedEveryPeriodType());
accuredtotalAmount = accuredtotalAmount.plus(remainDaysAmount);
}
this.total = account.isInterestCompoundingAllowed()?accuredtotalAmount.getAmount():BigDecimal.valueOf(accuredtotalAmount.getAmount().doubleValue()-this.interstPaid.doubleValue());
this.interestAccrued = accuredtotalAmount.minus(deposit).getAmount();
@@ -596,7 +633,10 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
final boolean renewalAllowed, final boolean preClosureAllowed,
final boolean isInterestWithdrawable, final boolean isInterestCompoundingAllowed,
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,
final DepositLifecycleStateMachine depositLifecycleStateMachine) {
final DepositLifecycleStateMachine depositLifecycleStateMachine,
final boolean isLockinPeriodAllowed,
final Integer lockinPeriod,
final PeriodFrequencyType lockinPeriodType) {
Money futureValueOnMaturity =null;
@@ -614,7 +654,7 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
setExternalId(externalId);
if (commencementDate != null) {
this.projectedCommencementDate = commencementDate.toDate();
this.maturesOnDate = commencementDate.plusMonths(this.tenureInMonths).toDate();
this.maturesOnDate = commencementDate.plusMonths(this.tenureInMonths).minusDays(1).toDate();
}
this.product = product;
this.depositAmount = deposit.getAmount();
@@ -630,6 +670,9 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
this.interestCompoundingAllowed=isInterestCompoundingAllowed;
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.minus(deposit).getAmount();
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
}
@@ -82,4 +82,16 @@ public class FixedTermDepositInterestCalculator {
return Money.of(deposit.getCurrency(), totalAmount);
}
public Money calculateRemainInterest(Money deposit, Integer days, BigDecimal interestRate){
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
Integer daysInYear = 365;
BigDecimal interestRateAsFraction = interestRate.divide(BigDecimal.valueOf(100), mc);
BigDecimal interestRateForOneDay = interestRateAsFraction.divide(BigDecimal.valueOf(daysInYear.doubleValue()), mc);
BigDecimal interest = BigDecimal.valueOf(deposit.getAmount().doubleValue()*days.doubleValue()*interestRateForOneDay.doubleValue());
return Money.of(deposit.getCurrency(), interest);
}
}
@@ -101,6 +101,21 @@ public class DepositAccountAssembler {
if(command.isInterestCompoundingAllowedChanged()){
interestCompoundingAllowed = command.isInterestCompoundingAllowed();
}
boolean isLockinPeriodAllowed = product.isLockinPeriodAllowed();
if(command.isLockinPeriodChanged()){
isLockinPeriodAllowed = command.isLockinPeriodAllowed();
}
Integer lockinPeriod = product.getLockinPeriod();
if(command.getLockinPeriod() != null){
lockinPeriod = command.getLockinPeriod();
}
PeriodFrequencyType lockinPeriodType = product.getLockinPeriodType();
if(command.getLockinPeriodType() != null){
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
}
// end of details allowed to be overriden from product
DepositAccount account =new DepositAccount().openNew(client, product, command.getExternalId(),
@@ -109,7 +124,8 @@ public class DepositAccountAssembler {
tenureInMonths, compoundingInterestEvery, compoundingInterestFrequency,
command.getCommencementDate(),
renewalAllowed, preClosureAllowed, this.fixedTermDepositInterestCalculator,
defaultDepositLifecycleStateMachine(),isInterestWithdrawable,interestCompoundingAllowed);
defaultDepositLifecycleStateMachine(),isInterestWithdrawable,interestCompoundingAllowed,
isLockinPeriodAllowed,lockinPeriod,lockinPeriodType);
return account;
}
@@ -186,21 +202,36 @@ public class DepositAccountAssembler {
isInterestCompoundingAllowed = command.isInterestCompoundingAllowed();
}
boolean isLockinPeriodAllowed = account.isLockinPeriodAllowed();
if(command.isLockinPeriodChanged()){
isLockinPeriodAllowed = command.isLockinPeriodAllowed();
}
Integer lockinPeriod = account.getLockinPeriod();
if(command.getLockinPeriod() != null){
lockinPeriod = command.getLockinPeriod();
}
PeriodFrequencyType lockinPeriodType = account.getLockinPeriodType();
if(command.getLockinPeriodType() != null){
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
}
DepositAccount newAccount =new DepositAccount().openNew(client, product, null,
deposit,
maturityInterestRate, preClosureInterestRate,
tenureInMonths, compoundingInterestEvery, compoundingInterestFrequency,
account.maturesOnDate(),
account.maturesOnDate().plusDays(1),
renewalAllowed, preClosureAllowed, this.fixedTermDepositInterestCalculator, defaultDepositLifecycleStateMachine(),
isInterestWithdrawable,isInterestCompoundingAllowed);
isInterestWithdrawable,isInterestCompoundingAllowed,isLockinPeriodAllowed,lockinPeriod,lockinPeriodType);
newAccount.updateAccount(account);
return newAccount;
}
public void adjustTotalAmountForPreclosureInterest(DepositAccount account) {
account.adjustTotalAmountForPreclosureInterest(account,this.fixedTermDepositInterestCalculator);
public void adjustTotalAmountForPreclosureInterest(DepositAccount account,LocalDate eventDate) {
account.adjustTotalAmountForPreclosureInterest(account,this.fixedTermDepositInterestCalculator,eventDate);
}
public void assembleUpdatedDepositAccount(DepositAccount account,DepositAccountCommand command) {
@@ -276,8 +307,23 @@ public class DepositAccountAssembler {
if(command.isInterestCompoundingAllowedChanged()){
isInterestCompoundingAllowed = command.isInterestCompoundingAllowed();
}
boolean isLockinPeriodAllowed = account.isLockinPeriodAllowed();
if(command.isLockinPeriodChanged()){
isLockinPeriodAllowed = command.isLockinPeriodAllowed();
}
Integer lockinPeriod = account.getLockinPeriod();
if(command.getLockinPeriod() != null){
lockinPeriod = command.getLockinPeriod();
}
PeriodFrequencyType lockinPeriodType = account.getLockinPeriodType();
if(command.getLockinPeriodType() != null){
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
}
account.update(product,externalId,commencementDate,deposit,tenureInMonths,maturityInterestRate,preClosureInterestRate,compoundingInterestEvery,compoundingInterestFrequency,renewalAllowed,
preClosureAllowed,isInterestWithdrawable,isInterestCompoundingAllowed,this.fixedTermDepositInterestCalculator,defaultDepositLifecycleStateMachine());
preClosureAllowed,isInterestWithdrawable,isInterestCompoundingAllowed,this.fixedTermDepositInterestCalculator,defaultDepositLifecycleStateMachine(),isLockinPeriodAllowed,lockinPeriod,lockinPeriodType);
}
public void updateApprovedDepositAccount(DepositAccount account, DepositAccountCommand command) {
@@ -138,6 +138,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
+ " da.is_renewal_allowed as renewalAllowed, da.is_preclosure_allowed as preClosureAllowed, da.pre_closure_interest_rate as preClosureInterestRate, "
+ " da.withdrawnon_date as withdrawnonDate, da.rejectedon_date as rejectedonDate, da.closedon_date as closedonDate, "
+ " da.interest_paid as interestPaid, da.is_interest_withdrawable as isInterestWithdrawable, da.is_compounding_interest_allowed as interestCompoundingAllowed, "
+ " da.is_lock_in_period_allowed as isLockinPeriodAllowed, da.lock_in_period as lockinPeriod, da.lock_in_period_type lockinPeriodType, "
+ " c.firstname as firstname, c.lastname as lastname, pd.name as productName,"
+ " curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol "
+ " from m_deposit_account da "
@@ -198,12 +199,18 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
boolean isInterestWithdrawable = rs.getBoolean("isInterestWithdrawable");
BigDecimal interestPaid = rs.getBigDecimal("interestPaid");
boolean isLockinPeriodAllowed = rs.getBoolean("isLockinPeriodAllowed");
Integer lockinPeriod = JdbcSupport.getInteger(rs, "lockinPeriod");
Integer lockinPeriodTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodType");
EnumOptionData lockinPeriodType = SavingsDepositEnumerations.interestCompoundingPeriodType(lockinPeriodTypeValue);
return new DepositAccountData(id, externalId, status, clientId, clientName, productId, productName, currencyData, depositAmount,
interestRate, termInMonths, projectedCommencementDate, actualCommencementDate, maturedOn,
projectedInterestAccrued, actualInterestAccrued, projectedMaturityAmount, actualMaturityAmount,
interestCompoundedEvery, interestCompoundedEveryPeriodType,
renewalAllowed, preClosureAllowed, preClosureInterestRate,
withdrawnonDate,rejectedonDate,closedonDate,isInterestWithdrawable,interestPaid,interestCompoundingAllowed);
withdrawnonDate,rejectedonDate,closedonDate,isInterestWithdrawable,interestPaid,interestCompoundingAllowed,
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType);
}
}
@@ -292,12 +292,20 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
throw new DepositAccountNotFoundException(command.getAccountId());
}
if(command.getMaturesOnDate().isBefore(account.maturesOnDate())){
this.depositAccountAssembler.adjustTotalAmountForPreclosureInterest(account);
}
account.withdrawDepositAccountMoney(defaultDepositLifecycleStateMachine());
this.depositAccountRepository.save(account);
LocalDate eventDate = command.getMaturesOnDate();
Integer lockinPeriod = account.getLockinPeriod();
LocalDate lockinPeriodExpDate = account.getActualCommencementDate().plusMonths(Integer.valueOf(lockinPeriod));
if(account.isLockinPeriodAllowed()){
if(eventDate.isBefore(lockinPeriodExpDate)){
throw new DepositAccountTransactionsException("deposit.transaction.canot.withdraw.before.lockinperiod.reached","You can not withdraw your application before maturity date reached");
}
}
if(eventDate.isBefore(account.maturesOnDate())){
this.depositAccountAssembler.adjustTotalAmountForPreclosureInterest(account,eventDate);
}
account.withdrawDepositAccountMoney(defaultDepositLifecycleStateMachine(),fixedTermDepositInterestCalculator,eventDate);
this.depositAccountRepository.save(account);
String noteText = command.getNote();
if (StringUtils.isNotBlank(noteText)) {
Note note = Note.depositNote(account, noteText);
@@ -331,13 +339,13 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
account.withdrawInterest(Money.of(account.getDeposit().getCurrency(), command.getWithdrawInterest()));
this.depositAccountRepository.save(account);
}else {
throw new DepositAccountTransactionsException("You can Withdraw "+remainInterestForWithdrawal+" only");
throw new DepositAccountTransactionsException("deposit.transaction.interest.withdrawal.exceed","You can Withdraw "+remainInterestForWithdrawal+" only");
}
}else {
throw new DepositAccountTransactionsException("You don't have enough money for withdrawal");
throw new DepositAccountTransactionsException("deposit.transaction.interest.withdrawal.insufficient.amount","You don't have enough money for withdrawal");
}
}else{
throw new DepositAccountTransactionsException("You can not withdraw interst for this account");
throw new DepositAccountTransactionsException("deposit.transaction.interest.withdrawal.cannot.withdraw","You can not withdraw interst for this account");
}
return new EntityIdentifier(account.getId());
}
@@ -9,6 +9,7 @@ import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.StringUtils;
import org.hibernate.metamodel.binding.CollectionElementNature;
import org.mifosng.platform.api.commands.DepositProductCommand;
import org.mifosng.platform.currency.domain.MonetaryCurrency;
import org.mifosng.platform.exceptions.ValueOutsideRangeException;
@@ -75,6 +76,15 @@ public class DepositProduct extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "pre_closure_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal preClosureInterestRate;
@Column(name = "is_lock_in_period_allowed", nullable=false)
private boolean isLockinPeriodAllowed = false;
@Column(name = "lock_in_period", nullable=false)
private Integer lockinPeriod;
@Column(name = "lock_in_period_type", nullable=false)
private PeriodFrequencyType lockinPeriodType;
protected DepositProduct() {
//
}
@@ -91,7 +101,10 @@ public class DepositProduct extends AbstractAuditableCustom<AppUser, Long> {
final boolean canRenew,
final boolean canPreClose,
final BigDecimal preClosureInterestRate,
final boolean isInterestCompoundingAllowed) {
final boolean isInterestCompoundingAllowed,
final boolean isLockinPeriodAllowed,
final Integer lockinPeriod,
final PeriodFrequencyType lockinPeriodType) {
this.name = name.trim();
if (StringUtils.isNotBlank(description)) {
this.description = description.trim();
@@ -117,6 +130,9 @@ public class DepositProduct extends AbstractAuditableCustom<AppUser, Long> {
this.preClosureAllowed = canPreClose;
this.preClosureInterestRate = preClosureInterestRate;
this.interestCompoundingAllowed = isInterestCompoundingAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
}
public MonetaryCurrency getCurrency() {
@@ -159,6 +175,18 @@ public class DepositProduct extends AbstractAuditableCustom<AppUser, Long> {
return interestCompoundingAllowed;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public PeriodFrequencyType getLockinPeriodType() {
return lockinPeriodType;
}
public boolean isDeleted() {
return deleted;
}
@@ -174,7 +202,7 @@ public class DepositProduct extends AbstractAuditableCustom<AppUser, Long> {
this.externalId = this.getId() + "_DELETED_" + this.externalId;
}
public void update(final DepositProductCommand command, final PeriodFrequencyType interestCompoundingFrequency){
public void update(final DepositProductCommand command, final PeriodFrequencyType interestCompoundingFrequency, final PeriodFrequencyType lockinPeriodType){
if (command.isExternalIdChanged()) {
this.externalId = command.getExternalId();
@@ -249,6 +277,18 @@ public class DepositProduct extends AbstractAuditableCustom<AppUser, Long> {
if(command.interestCompoundingAllowedChanged()){
this.interestCompoundingAllowed = command.isInterestCompoundingAllowed();
}
if(command.isLockinPeriodAllowedChanged()){
this.isLockinPeriodAllowed = command.isLockinPeriodAllowed();
}
if(command.isLockinPeriodChanged()){
this.lockinPeriod = command.getLockinPeriod();
}
if(command.isLockinPeriodTypeChanged()){
this.lockinPeriodType = lockinPeriodType;
}
}
public void validateInterestRateInRange(final BigDecimal interestRate) {
@@ -74,6 +74,7 @@ public class DepositProductReadPlatformServiceImpl implements DepositProductRead
"dp.interest_compounded_every as interestCompoundedEvery, dp.interest_compounded_every_period_enum as interestCompoundedEveryPeriodType, " +
"dp.maturity_default_interest_rate as maturityDefaultInterestRate, dp.is_compounding_interest_allowed as interestCompoundingAllowed, " +
"dp.maturity_min_interest_rate as maturityMinInterestRate, dp.maturity_max_interest_rate as maturityMaxInterestRate, dp.is_renewal_allowed as canRenew, dp.is_preclosure_allowed as canPreClose, dp.pre_closure_interest_rate as preClosureInterestRate, " +
"dp.is_lock_in_period_allowed as isLockinPeriodAllowed, dp.lock_in_period as lockinPeriod, dp.lock_in_period_type as lockinPeriodType, "+
"curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol " +
"from m_product_deposit dp join m_currency curr on curr.code = dp.currency_code ";
}
@@ -111,10 +112,16 @@ public class DepositProductReadPlatformServiceImpl implements DepositProductRead
BigDecimal preClosureInterestRate=rs.getBigDecimal("preClosureInterestRate");
Boolean isLockinPeriodAllowed=rs.getBoolean("isLockinPeriodAllowed");
Integer lockinPeriod = JdbcSupport.getInteger(rs, "lockinPeriod");
Integer lockinPeriodTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodType");
EnumOptionData lockinPeriodType = SavingsDepositEnumerations.interestCompoundingPeriodType(lockinPeriodTypeValue);
return new DepositProductData(createdOn, lastModifedOn, id, exernalId, name, description, currencyCode, currencyDigits, minimumBalance, maximumBalance,
tenureMonths, maturityDefaultInterestRate,maturityMinInterestRate,maturityMaxInterestRate,
interestCompoundedEvery, interestCompoundedEveryPeriodType,
canRenew,canPreClose,preClosureInterestRate,interestCompoundingAllowed);
canRenew,canPreClose,preClosureInterestRate,interestCompoundingAllowed,isLockinPeriodAllowed,lockinPeriod,lockinPeriodType);
}
}
@@ -57,12 +57,14 @@ public class DepositProductWritePlatformServiceJpaRepositoryImpl implements Depo
validator.validateForCreate();
PeriodFrequencyType interestCompoundingPeriodType = PeriodFrequencyType.fromInt(command.getInterestCompoundedEveryPeriodType());
PeriodFrequencyType lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
MonetaryCurrency currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal());
DepositProduct product = new DepositProduct(command.getName(), command.getExternalId(), command.getDescription(),currency,command.getMinimumBalance(),command.getMaximumBalance(),
command.getTenureInMonths(),command.getMaturityDefaultInterestRate(),command.getMaturityMinInterestRate(),command.getMaturityMaxInterestRate(),
command.getInterestCompoundedEvery(), interestCompoundingPeriodType,
command.isRenewalAllowed(), command.isPreClosureAllowed(),
command.getPreClosureInterestRate(),command.isInterestCompoundingAllowed());
command.getPreClosureInterestRate(),command.isInterestCompoundingAllowed(),
command.isLockinPeriodAllowed(),command.getLockinPeriod(),lockinPeriodType);
this.depositProductRepository.save(product);
return new EntityIdentifier(product.getId());
@@ -91,7 +93,12 @@ public class DepositProductWritePlatformServiceJpaRepositoryImpl implements Depo
interestCompoundingFrequency = PeriodFrequencyType.fromInt(command.getInterestCompoundedEveryPeriodType());
}
product.update(command, interestCompoundingFrequency);
PeriodFrequencyType lockinPeriodType = null;
if (command.isLockinPeriodTypeChanged()) {
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
}
product.update(command, interestCompoundingFrequency, lockinPeriodType);
this.depositProductRepository.save(product);
return new EntityIdentifier(Long.valueOf(product.getId()));
} catch (DataIntegrityViolationException dve) {