MIFOSX-97: repackage remaining savings related code.

This commit is contained in:
Keith Woodlock
2012-12-03 00:20:43 +00:00
parent 082d77f5b6
commit f73d42857e
125 changed files with 4790 additions and 4882 deletions
@@ -1,269 +0,0 @@
package org.mifosng.platform.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.api.commands.DepositAccountCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawInterestCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawalCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionCommand;
import org.mifosng.platform.api.data.DepositAccountData;
import org.mifosng.platform.api.data.DepositPermissionData;
import org.mifosng.platform.api.data.DepositProductLookup;
import org.mifosng.platform.saving.service.DepositAccountReadPlatformService;
import org.mifosng.platform.saving.service.DepositAccountWritePlatformService;
import org.mifosng.platform.savingproduct.service.DepositProductReadPlatformService;
import org.mifosng.platform.savingproduct.service.SavingsDepositEnumerations;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService;
import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/depositaccounts")
@Component
@Scope("singleton")
public class DepositAccountsApiResource {
@Autowired
private DepositAccountReadPlatformService depositAccountReadPlatformService;
@Autowired
private DepositProductReadPlatformService depositProductReadPlatformService;
@Autowired
private DepositAccountWritePlatformService depositAccountWritePlatformService;
@Autowired
private PortfolioApiDataConversionService apiDataConversionService;
@Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService;
private final String entityType = "DEPOSITACCOUNT";
@Autowired
private PlatformSecurityContext context;
private static final Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("id", "externalId", "clientId", "clientName",
"productId", "productName", "status", "currency",
"deposit", "maturityInterestRate", "tenureInMonths",
"interestCompoundedEvery","interestCompoundingAllowed",
"interestCompoundedEveryPeriodType", "renewalAllowed",
"preClosureAllowed", "preClosureInterestRate",
"withdrawnonDate","rejectedonDate","closedonDate","transactions","interestPaid","isInterestWithdrawable",
"availableInterestForWithdrawal","availableWithdrawalAmount","todaysDate",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType"));
@POST
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response createDepositAccount(final String jsonRequestBody){
final DepositAccountCommand command = this.apiDataConversionService.convertJsonToDepositAccountCommand(null, jsonRequestBody);
EntityIdentifier entityIdentifier = this.depositAccountWritePlatformService.createDepositAccount(command);
return Response.ok().entity(entityIdentifier).build();
}
@PUT
@Path("{accountId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response updateDepositAccount(@PathParam("accountId") final Long accountId,final String jsonRequestBody){
final DepositAccountCommand command = this.apiDataConversionService.convertJsonToDepositAccountCommand(accountId, jsonRequestBody);
EntityIdentifier entityIdentifier = this.depositAccountWritePlatformService.updateDepositAccount(command);
return Response.ok().entity(entityIdentifier).build();
}
@GET
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveAllDepositAccounts(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
Collection<DepositAccountData> accounts = this.depositAccountReadPlatformService.retrieveAllDepositAccounts();
return this.apiJsonSerializerService.serializeDepositAccountDataToJson(prettyPrint, responseParameters, accounts);
}
@GET
@Path("{accountId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveDepositAccount(@PathParam("accountId") final Long accountId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
DepositPermissionData permissions = null;
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
DepositAccountData account = this.depositAccountReadPlatformService.retrieveDepositAccount(accountId);
boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
if (template) {
account = handleTemplateRelatedData(responseParameters, account);
}
Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
if (!associationParameters.isEmpty()) {
if (associationParameters.contains("all")) {
responseParameters.addAll(Arrays.asList("permissions"));
} else {
responseParameters.addAll(associationParameters);
}
permissions = this.depositAccountReadPlatformService.retrieveDepositAccountsPermissions(account);
account = new DepositAccountData(account, permissions, account.getTransactions());
}
return this.apiJsonSerializerService.serializeDepositAccountDataToJson(prettyPrint, responseParameters, account);
}
@GET
@Path("template")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveNewDepositAccountDetails(
@QueryParam("clientId") final Long clientId,
@QueryParam("productId") final Long productId,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
DepositAccountData account = this.depositAccountReadPlatformService.retrieveNewDepositAccountDetails(clientId,productId);
account = handleTemplateRelatedData(responseParameters, account);
return this.apiJsonSerializerService.serializeDepositAccountDataToJson(prettyPrint, responseParameters, account);
}
@DELETE
@Path("{accountId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response deleteProduct(@PathParam("accountId") final Long accountId) {
this.depositAccountWritePlatformService.deleteDepositAccount(accountId);
return Response.ok(new EntityIdentifier(accountId)).build();
}
private DepositAccountData handleTemplateRelatedData(
final Set<String> responseParameters,
final DepositAccountData account) {
responseParameters.addAll(Arrays.asList("interestCompoundedEveryPeriodTypeOptions", "productOptions"));
Collection<DepositProductLookup> productOptions = depositProductReadPlatformService.retrieveAllDepositProductsForLookup();
EnumOptionData monthly = SavingsDepositEnumerations.interestCompoundingPeriodType(PeriodFrequencyType.MONTHS);
List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions = Arrays.asList(monthly);
return new DepositAccountData(account, interestCompoundedEveryPeriodTypeOptions, productOptions);
}
@POST
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response SubmitDepositApplication(@PathParam("accountId") final Long accountId,
@QueryParam("command") final String commandParam, final String jsonRequestBody) {
Response response=null;
if (is(commandParam, "approve")) {
DepositStateTransitionApprovalCommand command=apiDataConversionService.convertJsonToDepositStateTransitionApprovalCommand(accountId, jsonRequestBody);
EntityIdentifier identifier = this.depositAccountWritePlatformService.approveDepositApplication(command);
response = Response.ok().entity(identifier).build();
} else if(is(commandParam, "withdrawal")){
DepositAccountWithdrawalCommand command = apiDataConversionService.convertJsonToDepositWithdrawalCommand(accountId, jsonRequestBody);
EntityIdentifier identifier = this.depositAccountWritePlatformService.withdrawDepositAccountMoney(command);
response = Response.ok().entity(identifier).build();
} else if(is(commandParam, "interestwithdraw")){
DepositAccountWithdrawInterestCommand command = apiDataConversionService.convertJsonToDepositAccountWithdrawInterestCommand(accountId, jsonRequestBody);
EntityIdentifier identifier = this.depositAccountWritePlatformService.withdrawDepositAccountInterestMoney(command);
response = Response.ok().entity(identifier).build();
} else if(is(commandParam, "renew")){
DepositAccountCommand command = apiDataConversionService.convertJsonToDepositAccountCommand(accountId, jsonRequestBody);
EntityIdentifier entityIdentifier = this.depositAccountWritePlatformService.renewDepositAccount(command);
return Response.ok().entity(entityIdentifier).build();
} else {
DepositStateTransitionCommand command=apiDataConversionService.convertJsonToDepositStateTransitionCommand(accountId, jsonRequestBody);
if (is(commandParam, "reject")) {
EntityIdentifier identifier = this.depositAccountWritePlatformService.rejectDepositApplication(command);
response = Response.ok().entity(identifier).build();
} else if (is(commandParam, "withdrewbyclient")) {
EntityIdentifier identifier = this.depositAccountWritePlatformService.withdrawDepositApplication(command);
response = Response.ok().entity(identifier).build();
}
UndoStateTransitionCommand undoCommand = new UndoStateTransitionCommand(accountId, command.getNote());
if (is(commandParam, "undoapproval")) {
EntityIdentifier identifier = this.depositAccountWritePlatformService.undoDepositApproval(undoCommand);
response = Response.ok().entity(identifier).build();
}
}
if (response == null) {
throw new UnrecognizedQueryParamException("command", commandParam);
}
return response;
}
private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam)
&& commandParam.trim().equalsIgnoreCase(commandValue);
}
}
@@ -1,197 +0,0 @@
package org.mifosng.platform.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.mifosng.platform.api.commands.DepositProductCommand;
import org.mifosng.platform.api.data.DepositProductData;
import org.mifosng.platform.savingproduct.service.DepositProductReadPlatformService;
import org.mifosng.platform.savingproduct.service.DepositProductWritePlatformService;
import org.mifosng.platform.savingproduct.service.SavingsDepositEnumerations;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.service.CurrencyReadPlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService;
import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/depositproducts")
@Component
@Scope("singleton")
public class DepositProductsApiResource {
@Autowired
private DepositProductReadPlatformService depositProductReadPlatformService;
@Autowired
private CurrencyReadPlatformService currencyReadPlatformService;
@Autowired
private DepositProductWritePlatformService depositProductWritePlatformService;
@Autowired
private PortfolioApiDataConversionService apiDataConversionService;
@Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService;
private final String entityType = "DEPOSITPRODUCT";
@Autowired
private PlatformSecurityContext context;
@POST
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response createDepositProduct(final String jsonRequestBody){
final DepositProductCommand command=this.apiDataConversionService.convertJsonToDepositProductCommand(null, jsonRequestBody);
EntityIdentifier entityIdentifier=this.depositProductWritePlatformService.createDepositProduct(command);
return Response.ok().entity(entityIdentifier).build();
}
@PUT
@Path("{productId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response updateDepositProduct(@PathParam("productId") final Long productId, final String jsonRequestBody){
final DepositProductCommand command=this.apiDataConversionService.convertJsonToDepositProductCommand(productId, jsonRequestBody);
EntityIdentifier entityIdentifier=this.depositProductWritePlatformService.updateDepositProduct(command);
return Response.ok().entity(entityIdentifier).build();
}
@DELETE
@Path("{productId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response deleteDepositProduct(@PathParam("productId") final Long productId) {
this.depositProductWritePlatformService.deleteDepositProduct(productId);
return Response.ok(new EntityIdentifier(productId)).build();
}
@GET
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveAllDepositProducts(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("id", "externalId", "name", "description", "createdOn", "lastModifedOn",
"currencyCode","digitsAfterDecimal","minimumBalance","maximumBalance","tenureInMonths",
"maturityDefaultInterestRate","maturityMinInterestRate","maturityMaxInterestRate",
"interestCompoundedEvery", "interestCompoundedEveryPeriodType",
"renewalAllowed","preClosureAllowed","preClosureInterestRate","interestCompoundingAllowed",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType"));
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
Collection<DepositProductData> products=this.depositProductReadPlatformService.retrieveAllDepositProducts();
return this.apiJsonSerializerService.serializeDepositProductDataToJson(prettyPrint, responseParameters, products);
}
@GET
@Path("{productId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveDepositProductDetails(@PathParam("productId") final Long productId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("id", "externalId", "name", "description", "createdOn", "lastModifedOn",
"currencyCode","digitsAfterDecimal","minimumBalance","maximumBalance","tenureInMonths",
"maturityDefaultInterestRate","maturityMinInterestRate","maturityMaxInterestRate",
"interestCompoundedEvery", "interestCompoundedEveryPeriodType",
"renewalAllowed","preClosureAllowed","preClosureInterestRate","interestCompoundingAllowed",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType"));
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
DepositProductData productData = this.depositProductReadPlatformService.retrieveDepositProductData(productId);
boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
if (template) {
productData = handleTemplateRelatedData(responseParameters, productData);
}
return this.apiJsonSerializerService.serializeDepositProductDataToJson(prettyPrint, responseParameters, productData);
}
@GET
@Path("template")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveNewDepositProductDetails(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("currencyOptions", "interestCompoundedEveryPeriodTypeOptions",
"id", "externalId", "name", "description", "createdOn", "lastModifedOn",
"currencyCode","digitsAfterDecimal","minimumBalance","maximumBalance","tenureInMonths",
"maturityDefaultInterestRate","maturityMinInterestRate","maturityMaxInterestRate",
"interestCompoundedEvery", "interestCompoundedEveryPeriodType",
"renewalAllowed","preClosureAllowed","preClosureInterestRate",
"isLockinPeriodAllowed","lockinPeriod","lockinPeriodType"));
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
DepositProductData depositProduct = this.depositProductReadPlatformService.retrieveNewDepositProductDetails();
depositProduct = handleTemplateRelatedData(responseParameters, depositProduct);
return this.apiJsonSerializerService.serializeDepositProductDataToJson(prettyPrint, responseParameters, depositProduct);
}
private DepositProductData handleTemplateRelatedData(
final Set<String> responseParameters,
final DepositProductData productData) {
responseParameters.addAll(Arrays.asList("currencyOptions", "interestCompoundedEveryPeriodTypeOptions"));
List<CurrencyData> allowedCurrencies = this.currencyReadPlatformService.retrieveAllowedCurrencies();
EnumOptionData monthly = SavingsDepositEnumerations.interestCompoundingPeriodType(PeriodFrequencyType.MONTHS);
List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions = Arrays.asList(monthly);
return new DepositProductData(productData, allowedCurrencies, interestCompoundedEveryPeriodTypeOptions);
}
}
@@ -1,147 +0,0 @@
package org.mifosng.platform.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.mifosng.platform.api.commands.SavingAccountCommand;
import org.mifosng.platform.api.data.SavingAccountData;
import org.mifosng.platform.saving.service.SavingAccountReadPlatformService;
import org.mifosng.platform.saving.service.SavingAccountWritePlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService;
import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/savingaccounts")
@Component
@Scope("singleton")
public class SavingsAccountApiResource {
@Autowired
private SavingAccountWritePlatformService savingAccountWritePlatformService;
@Autowired
private SavingAccountReadPlatformService savingAccountReadPlatformService;
@Autowired
private PortfolioApiDataConversionService apiDataConversionService;
@Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService;
private final String entityType = "SAVINGSACCOUNT";
@Autowired
private PlatformSecurityContext context;
private static final Set<String> typicalResponseParameters = new HashSet<String>(
Arrays.asList("id", "status", "externalId", "clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod", "savingsFrequencyType",
"totalDepositAmount", "reccuringInterestRate", "savingInterestRate", "interestType", "interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate",
"actualCommencementDate", "maturesOnDate", "projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount", "preClosureAllowed",
"preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed", "lockinPeriod", "lockinPeriodType"));
@POST
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response createSavingAccount(final String jsonRequestBody){
final SavingAccountCommand command = this.apiDataConversionService.convertJsonToSavingAccountCommand(null, jsonRequestBody);
EntityIdentifier entityIdentifier = this.savingAccountWritePlatformService.createSavingAccount(command);
return Response.ok().entity(entityIdentifier).build();
}
@PUT
@Path("{accountId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Response updateSavingAccount(@PathParam("accountId") final Long accountId,final String jsonRequestBody){
final SavingAccountCommand command = this.apiDataConversionService.convertJsonToSavingAccountCommand(accountId, jsonRequestBody);
EntityIdentifier entityIdentifier = this.savingAccountWritePlatformService.updateSavingAccount(command);
return Response.ok().entity(entityIdentifier).build();
}
@GET
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveAllDepositAccounts(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
Collection<SavingAccountData> accounts = this.savingAccountReadPlatformService.retrieveAllSavingsAccounts();
return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, accounts);
}
@GET
@Path("{accountId}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveDepositAccount(@PathParam("accountId") final Long accountId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
SavingAccountData account = this.savingAccountReadPlatformService.retrieveSavingsAccount(accountId);
return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, account);
}
@SuppressWarnings("unused")
@GET
@Path("template")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public String retrieveNewDepositAccountDetails(
@QueryParam("clientId") final Long clientId,
@QueryParam("productId") final Long productId,
@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
SavingAccountData account = null;
// this.savingAccountReadPlatformService.retrieveNewSavingsAccountDetails(clientId, productId);
return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, account);
}
}
@@ -1,199 +0,0 @@
package org.mifosng.platform.api.commands;
import java.math.BigDecimal;
import java.util.Set;
import org.joda.time.LocalDate;
/**
* Immutable command used when create/renewing deposit accounts
*/
public class DepositAccountCommand {
private final Long id;
private final Long clientId;
private final Long productId;
private final String externalId;
private final BigDecimal depositAmount;
private final BigDecimal maturityInterestRate;
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;
private final boolean renewalAllowed;
private final boolean preClosureAllowed;
private final boolean isInterestWithdrawable;
private final boolean interestCompoundingAllowed;
private final Set<String> modifiedParameters;
public DepositAccountCommand(final Set<String> modifiedParameters,
final Long id,
final Long clientId,
final Long productId,
final String externalId,
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 isLockinPeriodAllowed, final Integer lockInPeriod, final Integer lockinPeriodType) {
this.id = id;
this.clientId = clientId;
this.productId = productId;
this.externalId = externalId;
this.depositAmount = depositAmount;
this.maturityInterestRate = interestRate;
this.preClosureInterestRate = preClosureInterestRate;
this.tenureInMonths = tenureInMonths;
this.modifiedParameters = modifiedParameters;
this.interestCompoundedEvery = compoundingInterestFrequency;
this.interestCompoundedEveryPeriodType = compoundingInterestFrequencyType;
this.commencementDate = commencementDate;
this.renewalAllowed = renewalAllowed;
this.preClosureAllowed = preClosureAllowed;
this.isInterestWithdrawable = isInterstWithdrawable;
this.interestCompoundingAllowed = interestCompoundingAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockInPeriod;
this.lockinPeriodType = lockinPeriodType;
}
public Long getId() {
return id;
}
public Long getClientId() {
return clientId;
}
public Long getProductId() {
return productId;
}
public String getExternalId() {
return externalId;
}
public BigDecimal getDepositAmount() {
return depositAmount;
}
public BigDecimal getMaturityInterestRate() {
return maturityInterestRate;
}
public BigDecimal getPreClosureInterestRate() {
return preClosureInterestRate;
}
public Integer getTenureInMonths() {
return tenureInMonths;
}
public Integer getInterestCompoundedEvery() {
return interestCompoundedEvery;
}
public Integer getInterestCompoundedEveryPeriodType() {
return interestCompoundedEveryPeriodType;
}
public LocalDate getCommencementDate() {
return commencementDate;
}
public boolean isInterestWithdrawable() {
return isInterestWithdrawable;
}
public boolean isRenewalAllowed() {
return renewalAllowed;
}
public boolean isPreClosureAllowed() {
return preClosureAllowed;
}
public boolean isInterestCompoundingAllowed() {
return interestCompoundingAllowed;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public Integer getLockinPeriodType() {
return lockinPeriodType;
}
public boolean isNoFieldChanged() {
return this.modifiedParameters.isEmpty();
}
public boolean isExternalIdChanged(){
return this.modifiedParameters.contains("externalId");
}
public boolean isDepositAmountChanged(){
return this.modifiedParameters.contains("deposit");
}
public boolean isTenureInMonthsChanged() {
return this.modifiedParameters.contains("tenureInMonths");
}
public boolean isLockinPeriodChanged() {
return this.modifiedParameters.contains("lockinPeriod");
}
public boolean isMaturityActualInterestRateChanged() {
return this.modifiedParameters.contains("maturityInterestRate");
}
public boolean isPreClosureInterestRateChanged(){
return this.modifiedParameters.contains("preClosureInterestRate");
}
public boolean isCompoundingInterestEveryChanged(){
return this.modifiedParameters.contains("interestCompoundedEvery");
}
public boolean isInterestCompoundedEveryPeriodTypeChaged(){
return this.modifiedParameters.contains("interestCompoundedEveryPeriodType");
}
public boolean isRenewalAllowedChanged() {
return this.modifiedParameters.contains("renewalAllowed");
}
public boolean isPreClosureAllowedChanged() {
return this.modifiedParameters.contains("preClosureAllowed");
}
public boolean isInterestWithdrawableChanged(){
return this.modifiedParameters.contains("isInterestWithdrawable");
}
public boolean isInterestCompoundingAllowedChanged(){
return this.modifiedParameters.contains("interestCompoundingAllowed");
}
public boolean isCommencementDateChanged() {
return this.modifiedParameters.contains("commencementDate");
}
}
@@ -1,26 +0,0 @@
package org.mifosng.platform.api.commands;
import java.math.BigDecimal;
public class DepositAccountWithdrawInterestCommand {
private final Long accountId;
private final BigDecimal withdrawInterest;
private final String note;
public DepositAccountWithdrawInterestCommand(final Long accountId, BigDecimal withdrawInterest, String note){
this.accountId=accountId;
this.withdrawInterest=withdrawInterest;
this.note=note;
}
public Long getAccountId() {
return accountId;
}
public BigDecimal getWithdrawInterest() {
return withdrawInterest;
}
public String getNote() {
return note;
}
}
@@ -1,29 +0,0 @@
package org.mifosng.platform.api.commands;
import org.joda.time.LocalDate;
public class DepositAccountWithdrawalCommand {
private final Long accountId;
private final String note;
private final LocalDate maturesOnDate;
public DepositAccountWithdrawalCommand(final Long accountId, final String note, final LocalDate maturesOnDate) {
this.accountId = accountId;
this.note = note;
this.maturesOnDate=maturesOnDate;
}
public Long getAccountId() {
return accountId;
}
public String getNote() {
return note;
}
public LocalDate getMaturesOnDate() {
return maturesOnDate;
}
}
@@ -1,250 +0,0 @@
package org.mifosng.platform.api.commands;
import java.math.BigDecimal;
import java.util.Set;
public class DepositProductCommand {
private final Long id;
private final String externalId;
private final String name;
private final String description;
private final String currencyCode;
private final Integer digitsAfterDecimal;
private final BigDecimal minimumBalance;
private final BigDecimal maximumBalance;
private final Integer tenureInMonths;
private final BigDecimal maturityDefaultInterestRate;
private final BigDecimal maturityMinInterestRate;
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;
private final BigDecimal preClosureInterestRate;
private final boolean interestCompoundingAllowed;
private final Set<String> modifiedParameters;
public DepositProductCommand(final Set<String> modifiedParameters,
final Long id, final String externalId, final String name, final String description,
final String currencyCode, final Integer digitsAfterDecimal,
final BigDecimal minimumBalance, final BigDecimal maximumBalance,
final Integer tenureInMonths, final BigDecimal maturityDefaultInterestRate,
final BigDecimal maturityMinInterestRate, final BigDecimal maturityMaxInterestRate,
final Integer interestCompoundedEvery,
final Integer interestCompoundedEveryPeriodType,
final boolean renewalAllowed, final boolean preClosureAllowed,
final BigDecimal preClosureInterestRate, final boolean interestCompoundingAllowed,
final boolean isLockinPeriodAllowed,final Integer lockinPeriod,final Integer lockinPeriodType ) {
this.id = id;
this.externalId = externalId;
this.name = name;
this.description = description;
this.currencyCode = currencyCode;
this.digitsAfterDecimal = digitsAfterDecimal;
this.minimumBalance=minimumBalance;
this.maximumBalance=maximumBalance;
this.tenureInMonths=tenureInMonths;
this.maturityDefaultInterestRate = maturityDefaultInterestRate;
this.maturityMinInterestRate = maturityMinInterestRate;
this.maturityMaxInterestRate = maturityMaxInterestRate;
this.interestCompoundedEvery = interestCompoundedEvery;
this.interestCompoundedEveryPeriodType = interestCompoundedEveryPeriodType;
this.preClosureInterestRate = preClosureInterestRate;
this.renewalAllowed = renewalAllowed;
this.preClosureAllowed = preClosureAllowed;
this.interestCompoundingAllowed = interestCompoundingAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
this.modifiedParameters = modifiedParameters;
}
public Long getId() {
return id;
}
public String getExternalId() {
return externalId;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String getCurrencyCode() {
return currencyCode;
}
public Integer getDigitsAfterDecimal() {
return digitsAfterDecimal;
}
public BigDecimal getMinimumBalance() {
return minimumBalance;
}
public BigDecimal getMaximumBalance() {
return maximumBalance;
}
public Integer getTenureInMonths() {
return tenureInMonths;
}
public BigDecimal getMaturityDefaultInterestRate() {
return maturityDefaultInterestRate;
}
public BigDecimal getMaturityMinInterestRate() {
return maturityMinInterestRate;
}
public BigDecimal getMaturityMaxInterestRate() {
return maturityMaxInterestRate;
}
public Integer getInterestCompoundedEvery() {
return interestCompoundedEvery;
}
public Integer getInterestCompoundedEveryPeriodType() {
return interestCompoundedEveryPeriodType;
}
public boolean isRenewalAllowed() {
return renewalAllowed;
}
public boolean isPreClosureAllowed() {
return preClosureAllowed;
}
public BigDecimal getPreClosureInterestRate() {
return preClosureInterestRate;
}
public boolean isInterestCompoundingAllowed() {
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");
}
public boolean isNameChanged() {
return this.modifiedParameters.contains("name");
}
public boolean isDescriptionChanged() {
return this.modifiedParameters.contains("description");
}
public boolean isCurrencyCodeChanged() {
return this.modifiedParameters.contains("currencyCode");
}
public boolean isDigitsAfterDecimalChanged() {
return this.modifiedParameters.contains("digitsAfterDecimal");
}
public boolean isInterestRateChanged() {
return this.modifiedParameters.contains("interestRate");
}
public boolean isMinimumBalanceChanged(){
return this.modifiedParameters.contains("minimumBalance");
}
public boolean isMaximumBalanceChanged(){
return this.modifiedParameters.contains("maximumBalance");
}
public boolean isTenureMonthsChanged() {
return this.modifiedParameters.contains("tenureMonths");
}
public boolean isMaturityDefaultInterestRateChanged() {
return this.modifiedParameters.contains("maturityDefaultInterestRate");
}
public boolean isMaturityMinInterestRateChanged() {
return this.modifiedParameters.contains("maturityMinInterestRate");
}
public boolean isMaturityMaxInterestRateChanged() {
return this.modifiedParameters.contains("maturityMaxInterestRate");
}
public boolean isInterestCompoundedEveryChanged() {
return this.modifiedParameters.contains("interestCompoundedEvery");
}
public boolean isInterestCompoundedEveryPeriodTypeChanged() {
return this.modifiedParameters.contains("interestCompoundedEveryPeriodType");
}
public boolean isRenewalAllowedChanged() {
return this.modifiedParameters.contains("renewalAllowed");
}
public boolean isPreClosureAllowedChanged() {
return this.modifiedParameters.contains("preClosureAllowed");
}
public boolean isPreClosureInterestRateChanged() {
return this.modifiedParameters.contains("preClosureInterestRate");
}
public boolean isNoFieldChanged() {
return this.modifiedParameters.isEmpty();
}
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");
}
}
@@ -1,72 +0,0 @@
package org.mifosng.platform.api.commands;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
public class DepositStateTransitionApprovalCommand {
private final Long accountId;
private final Long productId;
private final LocalDate eventDate;
private final BigDecimal depositAmount;
private final BigDecimal maturityInterestRate;
private final Integer tenureInMonths;
private final Integer interestCompoundedEveryPeriodType;
private final Integer interestCompoundedEvery;
private final String note;
public DepositStateTransitionApprovalCommand(final Long resourceIdentifier,final Long productId,final LocalDate eventDate,final Integer tenureInMonths,
final BigDecimal depositAmount,final Integer interestCompoundedEveryPeriodType,final Integer interestCompoundedEvery,final String note,final BigDecimal maturityInterestRate) {
this.accountId=resourceIdentifier;
this.eventDate=eventDate;
this.depositAmount=depositAmount;
this.maturityInterestRate=maturityInterestRate;
this.tenureInMonths=tenureInMonths;
this.interestCompoundedEveryPeriodType=interestCompoundedEveryPeriodType;
this.productId=productId;
this.interestCompoundedEvery=interestCompoundedEvery;
this.note = note;
}
public Long getAccountId() {
return accountId;
}
public LocalDate getEventDate() {
return eventDate;
}
public BigDecimal getDepositAmount() {
return depositAmount;
}
public BigDecimal getMaturityInterestRate() {
return maturityInterestRate;
}
public Integer getTenureInMonths() {
return tenureInMonths;
}
public Integer getInterestCompoundedEveryPeriodType() {
return interestCompoundedEveryPeriodType;
}
public Long getProductId() {
return productId;
}
public Integer getInterestCompoundedEvery() {
return interestCompoundedEvery;
}
public String getNote() {
return note;
}
}
@@ -1,30 +0,0 @@
package org.mifosng.platform.api.commands;
import org.joda.time.LocalDate;
public class DepositStateTransitionCommand {
private final Long accountId;
private final LocalDate eventDate;
private final String note;
public DepositStateTransitionCommand(final Long accountId, final LocalDate enentDate, final String note) {
this.accountId=accountId;
this.eventDate=enentDate;
this.note = note;
}
public Long getAccountId() {
return accountId;
}
public LocalDate getEventDate() {
return eventDate;
}
public String getNote() {
return note;
}
}
@@ -1,235 +0,0 @@
package org.mifosng.platform.api.commands;
import java.math.BigDecimal;
import java.util.Set;
import org.joda.time.LocalDate;
public class SavingAccountCommand {
private final Long id;
private final Long clientId;
private final Long productId;
private final String externalId;
private final String currencyCode;
private final Integer digitsAfterDecimal;
private final BigDecimal savingsDepositAmount;
private final BigDecimal recurringInterestRate;
private final BigDecimal savingInterestRate;
private final Integer tenure;
private final boolean isLockinPeriodAllowed;
private final Integer lockinPeriod;
private final Integer lockinPeriodType;
private final LocalDate commencementDate;
private final Integer savingProductType;
private final Integer tenureType;
private final Integer frequency;
private final Integer interestType;
private final Integer interestCalculationMethod;
private final BigDecimal minimumBalanceForWithdrawal;
private final boolean isPartialDepositAllowed;
private final Set<String> modifiedParameters;
public SavingAccountCommand(final Set<String> modifiedParameters,
final Long id,
final Long clientId,
final Long productId,
final String externalId,final String currencyCode, final Integer digitsAfterDecimal,
final BigDecimal savingsDepositAmount,
final BigDecimal recurringInterestRate, final BigDecimal savingInterestRate,
final Integer tenure, final LocalDate commencementDate,
final Integer savingProductType, final Integer tenureType, final Integer frequency, final Integer interestType,
final BigDecimal minimumBalanceForWithdrawal, final Integer interestCalculationMethod,
final boolean isLockinPeriodAllowed, final boolean isPartialDepositAllowed, final Integer lockInPeriod, final Integer lockinPeriodType) {
this.id = id;
this.clientId = clientId;
this.productId = productId;
this.externalId = externalId;
this.currencyCode = currencyCode;
this.digitsAfterDecimal = digitsAfterDecimal;
this.savingsDepositAmount = savingsDepositAmount;
this.recurringInterestRate = recurringInterestRate;
this.savingInterestRate = savingInterestRate;
this.tenure = tenure;
this.modifiedParameters = modifiedParameters;
this.commencementDate = commencementDate;
this.savingProductType=savingProductType;
this.tenureType=tenureType;
this.frequency=frequency;
this.interestType=interestType;
this.isPartialDepositAllowed=isPartialDepositAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockInPeriod;
this.lockinPeriodType = lockinPeriodType;
this.minimumBalanceForWithdrawal=minimumBalanceForWithdrawal;
this.interestCalculationMethod=interestCalculationMethod;
}
public Long getId() {
return id;
}
public Long getClientId() {
return clientId;
}
public Long getProductId() {
return productId;
}
public String getExternalId() {
return externalId;
}
public String getCurrencyCode() {
return currencyCode;
}
public Integer getDigitsAfterDecimal() {
return digitsAfterDecimal;
}
public BigDecimal getSavingsDepositAmount() {
return savingsDepositAmount;
}
public BigDecimal getRecurringInterestRate() {
return recurringInterestRate;
}
public BigDecimal getSavingInterestRate() {
return savingInterestRate;
}
public Integer getTenure() {
return tenure;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public Integer getLockinPeriodType() {
return lockinPeriodType;
}
public LocalDate getCommencementDate() {
return commencementDate;
}
public Integer getSavingProductType() {
return savingProductType;
}
public Integer getTenureType() {
return tenureType;
}
public Integer getFrequency() {
return frequency;
}
public Integer getInterestType() {
return interestType;
}
public Integer getInterestCalculationMethod() {
return interestCalculationMethod;
}
public BigDecimal getMinimumBalanceForWithdrawal() {
return minimumBalanceForWithdrawal;
}
public boolean isPartialDepositAllowed() {
return isPartialDepositAllowed;
}
public boolean isNoFieldChanged() {
return this.modifiedParameters.isEmpty();
}
public boolean isProductIdChanged(){
return this.modifiedParameters.contains("productId");
}
public boolean isExternalIdChanged(){
return this.modifiedParameters.contains("externalId");
}
public boolean isDepositAmountChanged(){
return this.modifiedParameters.contains("deposit");
}
public boolean isTenureInMonthsChanged() {
return this.modifiedParameters.contains("tenureInMonths");
}
public boolean isLockinPeriodChanged() {
return this.modifiedParameters.contains("lockinPeriod");
}
public boolean isPreClosureInterestRateChanged(){
return this.modifiedParameters.contains("preClosureInterestRate");
}
public boolean isPreClosureAllowedChanged() {
return this.modifiedParameters.contains("preClosureAllowed");
}
public boolean isCommencementDateChanged() {
return this.modifiedParameters.contains("commencementDate");
}
public boolean isTenureTypeEnumChanged() {
return this.modifiedParameters.contains("tenureType");
}
public boolean isSavingProductTypeChanged() {
return this.modifiedParameters.contains("savingProductType");
}
public boolean isSavingFrequencyTypeChanged() {
return this.modifiedParameters.contains("frequency");
}
public boolean isSavingInterestCalculationMethodChanged() {
return this.modifiedParameters.contains("interestCalculationMethod");
}
public boolean isReccuringInterestRateChanged() {
return this.modifiedParameters.contains("recurringInterestRate");
}
public boolean isSavingInterestRateChanged() {
return this.modifiedParameters.contains("savingInterestRate");
}
public boolean isLockinPeriodAllowedChanged() {
return this.modifiedParameters.contains("isLockinPeriodAllowed");
}
public boolean isLockinPeriodTypeChanged() {
return this.modifiedParameters.contains("lockinPeriodType");
}
public boolean isPartialDepositAllowedChanged() {
return this.modifiedParameters.contains("isPartialDepositAllowed");
}
}
@@ -1,567 +0,0 @@
package org.mifosng.platform.api.data;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
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;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/**
* Immutable data object for deposit accounts.
*/
public class DepositAccountData {
private final Long id;
private final String externalId;
private final EnumOptionData status;
private final Long clientId;
private final String clientName;
private final Long productId;
private final String productName;
private final CurrencyData currency;
private final BigDecimal deposit;
private final BigDecimal maturityInterestRate;
private final Integer tenureInMonths;
private final LocalDate projectedCommencementDate;
private final LocalDate actualCommencementDate;
private final LocalDate maturedOn;
private final LocalDate withdrawnonDate;
private final LocalDate rejectedonDate;
private final LocalDate closedonDate;
private final BigDecimal projectedInterestAccrued;
private final BigDecimal actualInterestAccrued;
private final BigDecimal projectedMaturityAmount;
private final BigDecimal actualMaturityAmount;
private final Integer interestCompoundedEvery;
private final EnumOptionData interestCompoundedEveryPeriodType;
private final boolean renewalAllowed;
private final boolean preClosureAllowed;
private final BigDecimal preClosureInterestRate;
private final boolean isInterestWithdrawable;
private final BigDecimal interestPaid;
private final boolean interestCompoundingAllowed;
private final List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions;
private final List<DepositProductLookup> productOptions;
private final Collection<DepositAccountTransactionData> transactions;
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.
*/
public static DepositAccountData createFrom(final Long clientId, final String clientDisplayName) {
return new DepositAccountData(clientId, clientDisplayName);
}
private DepositAccountData(
final Long clientId,
final String clientName) {
this.id=null;
this.externalId = null;
this.status = null;
this.clientId = clientId;
this.clientName = clientName;
this.productId = null;
this.productName = null;
this.currency = null;
this.deposit = null;
this.maturityInterestRate=null;
this.tenureInMonths = null;
this.projectedCommencementDate = null;
this.actualCommencementDate = null;
this.maturedOn = null;
this.projectedInterestAccrued = null;
this.actualInterestAccrued = null;
this.projectedMaturityAmount = null;
this.actualMaturityAmount = null;
this.interestCompoundedEvery = null;
this.interestCompoundedEveryPeriodType = null;
this.renewalAllowed = false;
this.preClosureAllowed = false;
this.preClosureInterestRate = null;
this.interestCompoundedEveryPeriodTypeOptions = new ArrayList<EnumOptionData>();
this.productOptions = new ArrayList<DepositProductLookup>();
this.withdrawnonDate=null;
this.closedonDate=null;
this.rejectedonDate=null;
this.transactions=null;
this.permissions=null;
this.interestPaid=null;
this.isInterestWithdrawable=false;
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(
final DepositAccountData account,
final List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions,
final Collection<DepositProductLookup> productOptions) {
this.id = account.getId();
this.externalId = account.getExternalId();
this.status = account.getStatus();
this.clientId = account.getClientId();
this.clientName = account.getClientName();
this.productId = account.getProductId();
this.productName = account.getProductName();
this.currency = account.getCurrency();
this.deposit = account.getDeposit();
this.maturityInterestRate = account.getMaturityInterestRate();
this.tenureInMonths = account.getTenureInMonths();
this.projectedCommencementDate = account.getProjectedCommencementDate();
this.actualCommencementDate = account.getActualCommencementDate();
this.maturedOn = account.getMaturedOn();
this.projectedInterestAccrued = account.getProjectedInterestAccrued();
this.actualInterestAccrued = account.getActualInterestAccrued();
this.projectedMaturityAmount = account.getProjectedMaturityAmount();
this.actualMaturityAmount = account.getActualMaturityAmount();
this.interestCompoundedEvery = account.getInterestCompoundedEvery();
this.interestCompoundedEveryPeriodType = account.getInterestCompoundedEveryPeriodType();
this.renewalAllowed = account.isRenewalAllowed();
this.preClosureAllowed = account.isPreClosureAllowed();
this.preClosureInterestRate = account.getPreClosureInterestRate();
this.interestCompoundedEveryPeriodTypeOptions = interestCompoundedEveryPeriodTypeOptions;
this.productOptions = new ArrayList<DepositProductLookup>(productOptions);
this.withdrawnonDate=account.getWithdrawnonDate();
this.rejectedonDate=account.getRejectedonDate();
this.closedonDate=account.getClosedonDate();
this.transactions=account.getTransactions();
this.permissions=account.getPermissions();
this.interestPaid=account.getInterestPaid();
this.isInterestWithdrawable=account.isInterestWithdrawable();
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) {
this.id = account.getId();
this.externalId = account.getExternalId();
this.status = account.getStatus();
this.clientId = account.getClientId();
this.clientName = account.getClientName();
this.productId = account.getProductId();
this.productName = account.getProductName();
this.currency = account.getCurrency();
this.deposit = account.getDeposit();
this.maturityInterestRate = account.getMaturityInterestRate();
this.tenureInMonths = account.getTenureInMonths();
this.projectedCommencementDate = account.getProjectedCommencementDate();
this.actualCommencementDate = account.getActualCommencementDate();
this.maturedOn = account.getMaturedOn();
this.projectedInterestAccrued = account.getProjectedInterestAccrued();
this.actualInterestAccrued = account.getActualInterestAccrued();
this.projectedMaturityAmount = account.getProjectedMaturityAmount();
this.actualMaturityAmount = account.getActualMaturityAmount();
this.interestCompoundedEvery = account.getInterestCompoundedEvery();
this.interestCompoundedEveryPeriodType = account.getInterestCompoundedEveryPeriodType();
this.renewalAllowed = account.isRenewalAllowed();
this.preClosureAllowed = account.isPreClosureAllowed();
this.preClosureInterestRate = account.getPreClosureInterestRate();
this.interestCompoundedEveryPeriodTypeOptions = account.getInterestCompoundedEveryPeriodTypeOptions();
this.productOptions = account.getProductOptions();
this.withdrawnonDate=account.getWithdrawnonDate();
this.rejectedonDate=account.getRejectedonDate();
this.closedonDate=account.getClosedonDate();
this.transactions=transactions;
this.permissions=permissions;
this.interestPaid=account.getInterestPaid();
this.isInterestWithdrawable=account.isInterestWithdrawable();
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 Long id,
final String externalId,
final EnumOptionData status,
final Long clientId,
final String clientName,
final Long productId,
final String productName,
final CurrencyData currency,
final BigDecimal deposit, final BigDecimal interestRate,
final Integer tenureInMonths,
final LocalDate projectedCommencementDate,
final LocalDate actualCommencementDate,
final LocalDate maturedOn,
final BigDecimal projectedInterestAccrued,
final BigDecimal actualInterestAccrued,
final BigDecimal projectedMaturityAmount,
final BigDecimal actualMaturityAmount,
final Integer interestCompoundedEvery,
final EnumOptionData interestCompoundedEveryPeriodType,
final boolean renewalAllowed,
final boolean preClosureAllowed,
final BigDecimal preClosureInterestRate,
final LocalDate withdrawnonDate,
final LocalDate rejectedonDate,
final LocalDate closedonDate,
final boolean isInterestWithdrawable,
final BigDecimal interestPaid,
final boolean interestCompoundingAllowed,
final boolean isLockinPeriodAllowed,
final Integer lockinPeriod,
final EnumOptionData lockinPeriodType) {
this.id=id;
this.externalId = externalId;
this.status = status;
this.clientId = clientId;
this.clientName = clientName;
this.productId = productId;
this.productName = productName;
this.currency = currency;
this.deposit = deposit;
this.maturityInterestRate=interestRate;
this.tenureInMonths = tenureInMonths;
this.projectedCommencementDate = projectedCommencementDate;
this.actualCommencementDate = actualCommencementDate;
this.maturedOn = maturedOn;
this.projectedInterestAccrued = projectedInterestAccrued;
this.actualInterestAccrued = actualInterestAccrued;
this.projectedMaturityAmount = projectedMaturityAmount;
this.actualMaturityAmount = actualMaturityAmount;
this.interestCompoundedEvery = interestCompoundedEvery;
this.interestCompoundedEveryPeriodType = interestCompoundedEveryPeriodType;
this.renewalAllowed = renewalAllowed;
this.preClosureAllowed = preClosureAllowed;
this.preClosureInterestRate = preClosureInterestRate;
this.interestCompoundedEveryPeriodTypeOptions = new ArrayList<EnumOptionData>();
this.productOptions = new ArrayList<DepositProductLookup>();
this.withdrawnonDate = withdrawnonDate;
this.rejectedonDate = rejectedonDate;
this.closedonDate = closedonDate;
this.transactions = null;
this.permissions = null;
this.interestPaid =interestPaid;
this.isInterestWithdrawable=isInterestWithdrawable;
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(
final Long clientId,
final String clientName,
final Long productId,
final String productName,
final CurrencyData currency,
final BigDecimal deposit, final BigDecimal interestRate,
final Integer tenureInMonths,
final Integer interestCompoundedEvery,
final EnumOptionData interestCompoundedEveryPeriodType,
final boolean renewalAllowed,
final boolean preClosureAllowed,
final BigDecimal preClosureInterestRate,
final boolean interestCompoundingAllowed) {
this.id=null;
this.externalId = null;
this.status = null;
this.clientId = clientId;
this.clientName = clientName;
this.productId = productId;
this.productName = productName;
this.currency = currency;
this.deposit = deposit;
this.maturityInterestRate=interestRate;
this.tenureInMonths = tenureInMonths;
this.projectedCommencementDate = new LocalDate();
this.actualCommencementDate = null;
this.maturedOn = null;
this.projectedInterestAccrued = null;
this.actualInterestAccrued = null;
this.projectedMaturityAmount = null;
this.actualMaturityAmount = null;
this.interestCompoundedEvery = interestCompoundedEvery;
this.interestCompoundedEveryPeriodType = interestCompoundedEveryPeriodType;
this.renewalAllowed = renewalAllowed;
this.preClosureAllowed = preClosureAllowed;
this.preClosureInterestRate = preClosureInterestRate;
this.interestCompoundedEveryPeriodTypeOptions = new ArrayList<EnumOptionData>();
this.productOptions = new ArrayList<DepositProductLookup>();
this.withdrawnonDate=null;
this.closedonDate=null;
this.rejectedonDate=null;
this.transactions = null;
this.permissions = null;
this.interestPaid=null;
this.isInterestWithdrawable=false;
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() {
return id;
}
public String getExternalId() {
return externalId;
}
public EnumOptionData getStatus() {
return status;
}
public Long getClientId() {
return clientId;
}
public String getClientName() {
return clientName;
}
public Long getProductId() {
return productId;
}
public String getProductName() {
return productName;
}
public CurrencyData getCurrency() {
return currency;
}
public BigDecimal getDeposit() {
return deposit;
}
public BigDecimal getMaturityInterestRate() {
return maturityInterestRate;
}
public Integer getTenureInMonths() {
return tenureInMonths;
}
public LocalDate getProjectedCommencementDate() {
return projectedCommencementDate;
}
public LocalDate getActualCommencementDate() {
return actualCommencementDate;
}
public LocalDate getMaturedOn() {
return maturedOn;
}
public BigDecimal getProjectedInterestAccrued() {
return projectedInterestAccrued;
}
public BigDecimal getActualInterestAccrued() {
return actualInterestAccrued;
}
public BigDecimal getProjectedMaturityAmount() {
return projectedMaturityAmount;
}
public BigDecimal getActualMaturityAmount() {
return actualMaturityAmount;
}
public Integer getInterestCompoundedEvery() {
return interestCompoundedEvery;
}
public EnumOptionData getInterestCompoundedEveryPeriodType() {
return interestCompoundedEveryPeriodType;
}
public boolean isRenewalAllowed() {
return renewalAllowed;
}
public boolean isPreClosureAllowed() {
return preClosureAllowed;
}
public BigDecimal getPreClosureInterestRate() {
return preClosureInterestRate;
}
public List<EnumOptionData> getInterestCompoundedEveryPeriodTypeOptions() {
return interestCompoundedEveryPeriodTypeOptions;
}
public List<DepositProductLookup> getProductOptions() {
return productOptions;
}
public LocalDate getWithdrawnonDate() {
return withdrawnonDate;
}
public LocalDate getRejectedonDate() {
return rejectedonDate;
}
public LocalDate getClosedonDate() {
return closedonDate;
}
public Collection<DepositAccountTransactionData> getTransactions() {
return transactions;
}
public DepositPermissionData getPermissions() {
return permissions;
}
public boolean isInterestWithdrawable() {
return isInterestWithdrawable;
}
public BigDecimal getInterestPaid() {
return interestPaid;
}
public boolean isInterestCompoundingAllowed() {
return interestCompoundingAllowed;
}
public BigDecimal getAvailableInterestForWithdrawal() {
return availableInterestForWithdrawal;
}
public BigDecimal getAvailableWithdrawalAmount() {
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()));
LocalDate interestWithdrawingDate= new LocalDate().isBefore(getMaturedOn())?new LocalDate():getMaturedOn().plusDays(1);
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());
}else {
return BigDecimal.ZERO;
}
}else return BigDecimal.ZERO;
return availableInterestForWithdrawal;
}
private BigDecimal determineAvalableWithdrawalAmount(final DepositAccountData account) {
BigDecimal avalablePreclosureWithdrawalAmount = BigDecimal.ZERO;
if(this.status != null){
if (account.getStatus().getId() == 300) {
if(new LocalDate().isBefore(account.getMaturedOn()) || new LocalDate().isEqual(account.getMaturedOn())){
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
Integer monthsInYear = 12;
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()).add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days));
}else if(new LocalDate().isAfter(account.getMaturedOn())){
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();
}
}
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());
}
}
@@ -1,271 +0,0 @@
package org.mifosng.platform.api.data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.joda.time.DateTime;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/**
* Immutable data object representing details of a deposit product.
*/
public class DepositProductData {
private final Long id;
private final String externalId;
private final String name;
private final String description;
private final String currencyCode;
private final Integer digitsAfterDecimal;
private final BigDecimal minimumBalance;
private final BigDecimal maximumBalance;
private final Integer tenureInMonths;
private final BigDecimal maturityDefaultInterestRate;
private final BigDecimal maturityMinInterestRate;
private final BigDecimal maturityMaxInterestRate;
private final Integer interestCompoundedEvery;
private final EnumOptionData interestCompoundedEveryPeriodType;
private final boolean renewalAllowed;
private final boolean preClosureAllowed;
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;
private final List<CurrencyData> currencyOptions;
private final List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions;
public DepositProductData(
final DateTime createdOn,
final DateTime lastModifedOn,
final Long id,
final String externalId,
final String name,
final String description,
final String currencyCode,
final Integer digitsAfterDecimal,
final BigDecimal minimumBalance,
final BigDecimal maximumBalance,
final Integer tenureMonths,
final BigDecimal maturityDefaultInterestRate,
final BigDecimal maturityMinInterestRate,
final BigDecimal maturityMaxInterestRate,
final Integer interestCompoundedEvery,
final EnumOptionData interestCompoundedEveryPeriodType,
final boolean renewalAllowed,
final boolean preClosureAllowed,
final BigDecimal preClosureInterestRate,
final boolean interestCompoundingAllowed,
final boolean isLockinPeriodAllowed,
final Integer lockinPeriod,
final EnumOptionData lockinPeriodType) {
this.createdOn=createdOn;
this.lastModifedOn=lastModifedOn;
this.id=id;
this.externalId = externalId;
this.name=name;
this.description=description;
this.currencyCode=currencyCode;
this.digitsAfterDecimal=digitsAfterDecimal;
this.minimumBalance=minimumBalance;
this.maximumBalance=maximumBalance;
this.tenureInMonths=tenureMonths;
this.maturityDefaultInterestRate = maturityDefaultInterestRate;
this.maturityMinInterestRate=maturityMinInterestRate;
this.maturityMaxInterestRate=maturityMaxInterestRate;
this.interestCompoundedEvery = interestCompoundedEvery;
this.interestCompoundedEveryPeriodType = interestCompoundedEveryPeriodType;
this.renewalAllowed=renewalAllowed;
this.preClosureAllowed=preClosureAllowed;
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>();
}
public DepositProductData(
final List<CurrencyData> currencyOptions,
final EnumOptionData defaultInterestCompoundedEveryPeriodType,
final List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions) {
this.createdOn=null;
this.lastModifedOn=null;
this.id=null;
this.externalId = null;
this.name=null;
this.description=null;
this.currencyCode=null;
this.digitsAfterDecimal=Integer.valueOf(0);
this.minimumBalance=BigDecimal.ZERO;
this.maximumBalance=BigDecimal.ZERO;
this.tenureInMonths=Integer.valueOf(0);
this.maturityDefaultInterestRate = BigDecimal.ZERO;
this.maturityMinInterestRate=BigDecimal.ZERO;
this.maturityMaxInterestRate=BigDecimal.ZERO;
this.interestCompoundedEvery = Integer.valueOf(1);
this.interestCompoundedEveryPeriodType = defaultInterestCompoundedEveryPeriodType;
this.renewalAllowed=true;
this.preClosureAllowed=true;
this.preClosureInterestRate=BigDecimal.ZERO;
this.interestCompoundingAllowed=true;
this.isLockinPeriodAllowed=true;
this.lockinPeriod=Integer.valueOf(0);
this.lockinPeriodType=defaultInterestCompoundedEveryPeriodType;
this.currencyOptions = currencyOptions;
this.interestCompoundedEveryPeriodTypeOptions = interestCompoundedEveryPeriodTypeOptions;
}
public DepositProductData(
final DepositProductData product,
final List<CurrencyData> currencyOptions,
final List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions) {
this.createdOn=product.getCreatedOn();
this.lastModifedOn=product.getLastModifedOn();
this.id=product.getId();
this.externalId = product.getExternalId();
this.name=product.getName();
this.description=product.getDescription();
this.currencyCode=product.getCurrencyCode();
this.digitsAfterDecimal=product.getDigitsAfterDecimal();
this.minimumBalance=product.getMinimumBalance();
this.maximumBalance=product.getMaximumBalance();
this.tenureInMonths=product.getTenureInMonths();
this.maturityDefaultInterestRate = product.getMaturityDefaultInterestRate();
this.maturityMinInterestRate=product.getMaturityMinInterestRate();
this.maturityMaxInterestRate=product.getMaturityMaxInterestRate();
this.interestCompoundedEvery = product.getInterestCompoundedEvery();
this.interestCompoundedEveryPeriodType = product.getInterestCompoundedEveryPeriodType();
this.renewalAllowed=product.isRenewalAllowed();
this.preClosureAllowed=product.isPreClosureAllowed();
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;
}
public Long getId() {
return id;
}
public String getExternalId() {
return externalId;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public String getCurrencyCode() {
return currencyCode;
}
public Integer getDigitsAfterDecimal() {
return digitsAfterDecimal;
}
public BigDecimal getMinimumBalance() {
return minimumBalance;
}
public BigDecimal getMaximumBalance() {
return maximumBalance;
}
public Integer getTenureInMonths() {
return tenureInMonths;
}
public BigDecimal getMaturityDefaultInterestRate() {
return maturityDefaultInterestRate;
}
public BigDecimal getMaturityMinInterestRate() {
return maturityMinInterestRate;
}
public BigDecimal getMaturityMaxInterestRate() {
return maturityMaxInterestRate;
}
public Integer getInterestCompoundedEvery() {
return interestCompoundedEvery;
}
public EnumOptionData getInterestCompoundedEveryPeriodType() {
return interestCompoundedEveryPeriodType;
}
public boolean isRenewalAllowed() {
return renewalAllowed;
}
public boolean isPreClosureAllowed() {
return preClosureAllowed;
}
public BigDecimal getPreClosureInterestRate() {
return preClosureInterestRate;
}
public DateTime getCreatedOn() {
return createdOn;
}
public DateTime getLastModifedOn() {
return lastModifedOn;
}
public List<CurrencyData> getCurrencyOptions() {
return currencyOptions;
}
public List<EnumOptionData> getInterestCompoundedEveryPeriodTypeOptions() {
return interestCompoundedEveryPeriodTypeOptions;
}
public boolean isInterestCompoundingAllowed() {
return interestCompoundingAllowed;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public EnumOptionData getLockinPeriodType() {
return lockinPeriodType;
}
}
@@ -1,20 +0,0 @@
package org.mifosng.platform.api.data;
public class DepositProductLookup {
private final Long id;
private final String name;
public DepositProductLookup(final Long id, final String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
}
@@ -1,134 +0,0 @@
package org.mifosng.platform.api.data;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/**
* Immutable data object reprsenting a savings account.
*/
public class SavingAccountData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final EnumOptionData status;
@SuppressWarnings("unused")
private final String externalId;
@SuppressWarnings("unused")
private final Long clientId;
@SuppressWarnings("unused")
private final String clientName;
@SuppressWarnings("unused")
private final Long productId;
@SuppressWarnings("unused")
private final String productName;
@SuppressWarnings("unused")
private final EnumOptionData productType;
@SuppressWarnings("unused")
private final CurrencyData currencyData;
@SuppressWarnings("unused")
private final BigDecimal savingsDepostiAmountPerPeriod;
@SuppressWarnings("unused")
private final EnumOptionData savingsFrequencyType;
@SuppressWarnings("unused")
private final BigDecimal totalDepositAmount;
@SuppressWarnings("unused")
private final BigDecimal reccuringInterestRate;
@SuppressWarnings("unused")
private final BigDecimal savingInterestRate;
@SuppressWarnings("unused")
private final EnumOptionData interestType;
@SuppressWarnings("unused")
private final EnumOptionData interestCalculationMethod;
@SuppressWarnings("unused")
private final Integer tenure;
@SuppressWarnings("unused")
private final EnumOptionData tenureType;
@SuppressWarnings("unused")
private final LocalDate projectedCommencementDate;
@SuppressWarnings("unused")
private final LocalDate actualCommencementDate;
@SuppressWarnings("unused")
private final LocalDate maturesOnDate;
@SuppressWarnings("unused")
private final BigDecimal projectedInterestAccuredOnMaturity;
@SuppressWarnings("unused")
private final BigDecimal actualInterestAccured;
@SuppressWarnings("unused")
private final BigDecimal projectedMaturityAmount;
@SuppressWarnings("unused")
private final BigDecimal actualMaturityAmount;
@SuppressWarnings("unused")
private final boolean preClosureAllowed;
@SuppressWarnings("unused")
private final BigDecimal preClosureInterestRate;
@SuppressWarnings("unused")
private final LocalDate withdrawnonDate;
@SuppressWarnings("unused")
private final LocalDate rejectedonDate;
@SuppressWarnings("unused")
private final LocalDate closedonDate;
@SuppressWarnings("unused")
private final boolean isLockinPeriodAllowed;
@SuppressWarnings("unused")
private final Integer lockinPeriod;
@SuppressWarnings("unused")
private final EnumOptionData lockinPeriodType;
public SavingAccountData(Long id, EnumOptionData status, String externalId,
Long clientId, String clientName, Long productId,
String productName, EnumOptionData productType,
CurrencyData currencyData,
BigDecimal savingsDepostiAmountPerPeriod,
EnumOptionData savingsFrequencyType, BigDecimal totalDepositAmount,
BigDecimal reccuringInterestRate, BigDecimal savingInterestRate,
EnumOptionData interestType,
EnumOptionData interestCalculationMethod, Integer tenure,
EnumOptionData tenureType, LocalDate projectedCommencementDate,
LocalDate actualCommencementDate, LocalDate maturesOnDate,
BigDecimal projectedInterestAccuredOnMaturity,
BigDecimal actualInterestAccured,
BigDecimal projectedMaturityAmount,
BigDecimal actualMaturityAmount, boolean preClosureAllowed,
BigDecimal preClosureInterestRate, LocalDate withdrawnonDate,
LocalDate rejectedonDate, LocalDate closedonDate,
boolean isLockinPeriodAllowed, Integer lockinPeriod,
EnumOptionData lockinPeriodType) {
this.id = id;
this.status = status;
this.externalId = externalId;
this.clientId = clientId;
this.clientName = clientName;
this.productId = productId;
this.productName = productName;
this.productType = productType;
this.currencyData = currencyData;
this.savingsDepostiAmountPerPeriod = savingsDepostiAmountPerPeriod;
this.savingsFrequencyType = savingsFrequencyType;
this.totalDepositAmount = totalDepositAmount;
this.reccuringInterestRate = reccuringInterestRate;
this.savingInterestRate = savingInterestRate;
this.interestType =interestType;
this.interestCalculationMethod = interestCalculationMethod;
this.tenure = tenure;
this.tenureType = tenureType;
this.projectedCommencementDate = projectedCommencementDate;
this.actualCommencementDate = actualCommencementDate;
this.maturesOnDate = maturesOnDate;
this.projectedInterestAccuredOnMaturity = projectedInterestAccuredOnMaturity;
this.actualInterestAccured = actualInterestAccured;
this.projectedMaturityAmount = projectedMaturityAmount;
this.actualMaturityAmount =actualMaturityAmount;
this.preClosureAllowed = preClosureAllowed;
this.preClosureInterestRate = preClosureInterestRate;
this.withdrawnonDate = withdrawnonDate;
this.rejectedonDate = rejectedonDate;
this.closedonDate = closedonDate;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
}
}
@@ -1,12 +0,0 @@
package org.mifosng.platform.exceptions;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;
public class InvalidDepositStateTransitionException extends
AbstractPlatformDomainRuleException {
public InvalidDepositStateTransitionException(final String action, String postFix, String defaultUserMessage, Object... defaultUserMessageArgs) {
super("error.msg.deposit." + action + "." + postFix, defaultUserMessage, defaultUserMessageArgs);
}
}
@@ -1,76 +0,0 @@
package org.mifosng.platform.saving.domain;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import org.joda.time.LocalDate;
import org.mifosng.platform.savingproduct.domain.SavingFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod;
import org.mifosng.platform.savingproduct.domain.TenureTypeEnum;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.springframework.stereotype.Service;
@Service
public class ReccuringDepositInterestCalculator {
// FIXME - MADHUKAR - Are the unused field here needed?
public Money calculateInterestOnMaturityFor(Money savingsDepositPerPeriod,
Integer tenure, BigDecimal reccuringInterestRate,
LocalDate commencementDate, TenureTypeEnum tenureTypeEnum,
SavingFrequencyType savingFrequencyType,
SavingInterestCalculationMethod savingInterestCalculationMethod) {
/*
// Assuming tenure in months
// see http://www.onemint.com/2012/04/03/how-to-calculate-interest-on-recurring-deposits/
A=P(1+r/n)^nt
A = final amount
P = principal amount (initial investment)
r = annual nominal interest rate (as a decimal, not in percentage)
n = number of times the interest is compounded per year
t = number of years
*/
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
Integer monthsInYear = 12;
BigDecimal interestRateAsFraction = reccuringInterestRate.divide(BigDecimal.valueOf(100), mc);
Integer noofTimesInterestCompoundPerYear = Integer.valueOf(0);
switch (savingFrequencyType) {
case MONTHLY:
noofTimesInterestCompoundPerYear = monthsInYear;
break;
case QUATERLY:
noofTimesInterestCompoundPerYear = monthsInYear/3;
break;
case HALFYEARLY:
noofTimesInterestCompoundPerYear = monthsInYear/6;
break;
case YEARLY:
noofTimesInterestCompoundPerYear = monthsInYear/12;
break;
default:
throw new RuntimeException("The specified frequency not supported");
}
BigDecimal interestRatePerPeriod = BigDecimal.valueOf(interestRateAsFraction.doubleValue()/noofTimesInterestCompoundPerYear.doubleValue());
BigDecimal onePlusInterestRatePerPeriod = BigDecimal.ONE.add(interestRatePerPeriod);
BigDecimal monthsExpressedInYears;
BigDecimal timeforOneCalculationPeriod;
BigDecimal amountPerPeriod;
BigDecimal finalAmount = BigDecimal.ZERO;
while (tenure > 0) {
monthsExpressedInYears = BigDecimal.valueOf(tenure.doubleValue()/monthsInYear.doubleValue());
timeforOneCalculationPeriod = BigDecimal.valueOf(noofTimesInterestCompoundPerYear*monthsExpressedInYears.doubleValue());
amountPerPeriod = savingsDepositPerPeriod.getAmount().multiply(BigDecimal.valueOf(Math.pow(onePlusInterestRatePerPeriod.doubleValue(), timeforOneCalculationPeriod.doubleValue())));
finalAmount=finalAmount.add(amountPerPeriod);
tenure--;
}
return Money.of(savingsDepositPerPeriod.getCurrency(), finalAmount);
}
}
@@ -1,359 +0,0 @@
package org.mifosng.platform.saving.domain;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import org.joda.time.LocalDate;
import org.mifosng.platform.savingproduct.domain.SavingFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod;
import org.mifosng.platform.savingproduct.domain.SavingProduct;
import org.mifosng.platform.savingproduct.domain.SavingProductType;
import org.mifosng.platform.savingproduct.domain.SavingsInterestType;
import org.mifosng.platform.savingproduct.domain.TenureTypeEnum;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
@Entity
@Table(name = "m_saving_account", uniqueConstraints = @UniqueConstraint(name="saving_acc_external_id", columnNames = { "external_id" }))
public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
@ManyToOne
@JoinColumn(name = "client_id", nullable = false)
private Client client;
@ManyToOne
@JoinColumn(name = "product_id")
private SavingProduct product;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use Integer e.g. private Integer savingProductType;
@Column(name = "savings_product_type", nullable=false)
private SavingProductType savingProductType;
@Column(name = "external_id")
private String externalId;
@SuppressWarnings("unused")
@Embedded
private MonetaryCurrency currency;
@Column(name = "deposit_amount_per_period", scale = 6, precision = 19, nullable = false)
private BigDecimal savingsDepositAmountPerPeriod;
@SuppressWarnings("unused")
@Column(name = "total_deposit_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal totalSavingsAmount;
@Column(name = "reccuring_nominal_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal reccuringInterestRate;
@Column(name = "regular_saving_nominal_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal savingInterestRate;
@Column(name = "tenure", nullable=false)
private Integer tenure;
@Column(name = "tenure_type", nullable=false)
private TenureTypeEnum tenureType;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use Integer e.g. private Integer savingProductType;
@Column(name = "frequency", nullable=false)
private SavingFrequencyType frequency;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use Integer e.g. private Integer savingProductType;
@Column(name = "interest_type", nullable=false)
private SavingsInterestType interestType;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use Integer e.g. private Integer savingProductType;
@Column(name = "interest_calculation_method")
private SavingInterestCalculationMethod interestCalculationMethod;
@Temporal(TemporalType.DATE)
@Column(name = "projected_commencement_date")
private Date projectedCommencementDate;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "actual_commencement_date")
private Date actualCommencementDate;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "matures_on_date")
private Date maturesOnDate;
@SuppressWarnings("unused")
@Column(name = "projected_interest_accrued_on_maturity", scale = 6, precision = 19, nullable = false)
private BigDecimal projectedInterestAccruedOnMaturity;
@SuppressWarnings("unused")
@Column(name = "actual_interest_accrued", scale = 6, precision = 19, nullable = false)
private BigDecimal interestAccrued;
@SuppressWarnings("unused")
@Column(name = "projected_total_maturity_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal projectedTotalOnMaturity;
@SuppressWarnings("unused")
@Column(name = "actual_total_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal total;
@Column(name = "pre_closure_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal preClosureInterestRate;
@Column(name = "is_preclosure_allowed", nullable = false)
private boolean preClosureAllowed = false;
@Column(name = "is_deleted", nullable=false)
private boolean deleted = false;
@Column(name = "status_enum", nullable = false)
private Integer accountStatus;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "closedon_date")
private Date closedOnDate;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "rejectedon_date")
private Date rejectedOnDate;
@Temporal(TemporalType.DATE)
@Column(name = "withdrawnon_date")
private Date withdrawnOnDate;
@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 static SavingAccount openNew(
Client client,
SavingProduct product,
String externalId,
Money savingsDeposit,
BigDecimal reccuringInterestRate,
BigDecimal savingInterestRate,
Integer tenure,
LocalDate commencementDate,
TenureTypeEnum tenureTypeEnum,
SavingProductType savingProductType,
SavingFrequencyType savingFrequencyType,
SavingsInterestType interestType,
SavingInterestCalculationMethod savingInterestCalculationMethod,
boolean isLockinPeriodAllowed,
Integer lockinPeriod,
PeriodFrequencyType lockinPeriodType,
ReccuringDepositInterestCalculator reccuringDepositInterestCalculator,
final DepositLifecycleStateMachine lifecycleStateMachine) {
Money futureValueOnMaturity = null;
if(savingProductType.isReccuring()){
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure, reccuringInterestRate,
commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
} else if(savingProductType.isRegular()){
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure, savingInterestRate,
commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
}
return new SavingAccount(client, externalId, product, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure,
commencementDate, tenureTypeEnum, savingProductType, savingFrequencyType, interestType, savingInterestCalculationMethod,
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, futureValueOnMaturity, lifecycleStateMachine);
}
public SavingAccount(Client client, String externalId,
SavingProduct product, Money savingsDeposit,
BigDecimal reccuringInterestRate, BigDecimal savingInterestRate,
Integer tenure, LocalDate commencementDate,
TenureTypeEnum tenureTypeEnum,
SavingProductType savingProductType,
SavingFrequencyType savingFrequencyType, SavingsInterestType interestType,
SavingInterestCalculationMethod savingInterestCalculationMethod,
boolean isLockinPeriodAllowed, Integer lockinPeriod,
PeriodFrequencyType lockinPeriodType, Money futureValueOnMaturity,
final DepositLifecycleStateMachine lifecycleStateMachine) {
DepositAccountStatus from = null;
if (accountStatus != null) {
from = DepositAccountStatus.fromInt(accountStatus);
}
DepositAccountStatus statusEnum = lifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_CREATED, from);
accountStatus = statusEnum.getValue();
this.total=BigDecimal.ZERO;
this.preClosureInterestRate=BigDecimal.ZERO;
this.totalSavingsAmount = BigDecimal.ZERO;
this.interestAccrued = BigDecimal.ZERO;
this.client = client;
this.externalId = externalId;
this.product = product;
this.savingsDepositAmountPerPeriod = savingsDeposit.getAmount();
this.currency = savingsDeposit.getCurrency();
this.reccuringInterestRate = reccuringInterestRate;
this.savingInterestRate = savingInterestRate;
this.tenure =tenure;
this.projectedCommencementDate=commencementDate.toDate();
this.tenureType = tenureTypeEnum;
this.savingProductType = savingProductType;
this.frequency = savingFrequencyType;
this.interestType = interestType;
this.interestCalculationMethod= savingInterestCalculationMethod;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
this.projectedInterestAccruedOnMaturity =futureValueOnMaturity.getAmount().subtract(BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue()*tenure.doubleValue()));
}
public void modifyAccount(
SavingProduct product,
String externalId,
Money savingsDeposit,
BigDecimal reccuringInterestRate,
BigDecimal savingInterestRate,
Integer tenure,
LocalDate commencementDate,
TenureTypeEnum tenureTypeEnum,
SavingProductType savingProductType,
SavingFrequencyType savingFrequencyType,
SavingInterestCalculationMethod savingInterestCalculationMethod,
boolean isLockinPeriodAllowed,
Integer lockinPeriod,
PeriodFrequencyType lockinPeriodType,
ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) {
Money futureValueOnMaturity = null;
if(savingProductType.isReccuring()){
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure, reccuringInterestRate,
commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
} else if(savingProductType.isRegular()){
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure, savingInterestRate,
commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
}
this.product = product;
this.externalId=externalId;
this.savingsDepositAmountPerPeriod=savingsDeposit.getAmount();
this.reccuringInterestRate=reccuringInterestRate;
this.savingInterestRate = savingInterestRate;
this.tenure = tenure;
this.projectedCommencementDate = commencementDate.toDate();
this.tenureType = tenureTypeEnum;
this.savingProductType = savingProductType;
this.frequency =savingFrequencyType;
this.interestCalculationMethod = savingInterestCalculationMethod;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
// FIXME - MADHUKAR - futureValueOnMaturity is possibly null
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
this.projectedInterestAccruedOnMaturity =futureValueOnMaturity.getAmount().subtract(BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue()*tenure.doubleValue()));
}
public boolean isDeleted() {
return this.deleted;
}
public boolean isPendingApproval() {
return this.accountStatus.equals(100);
}
public Client getClient() {
return client;
}
public SavingProduct getProduct() {
return product;
}
public SavingProductType getSavingProductType() {
return savingProductType;
}
public String getExternalId() {
return externalId;
}
public BigDecimal getSavingsDepositAmountPerPeriod() {
return savingsDepositAmountPerPeriod;
}
public BigDecimal getReccuringInterestRate() {
return reccuringInterestRate;
}
public BigDecimal getSavingInterestRate() {
return savingInterestRate;
}
public Integer getTenure() {
return tenure;
}
public TenureTypeEnum getTenureType() {
return tenureType;
}
public SavingFrequencyType getFrequency() {
return frequency;
}
public SavingsInterestType getInterestType() {
return interestType;
}
public SavingInterestCalculationMethod getInterestCalculationMethod() {
return interestCalculationMethod;
}
public Date getProjectedCommencementDate() {
return projectedCommencementDate;
}
public BigDecimal getPreClosureInterestRate() {
return preClosureInterestRate;
}
public boolean isPreClosureAllowed() {
return preClosureAllowed;
}
public Date getWithdrawnOnDate() {
return withdrawnOnDate;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public PeriodFrequencyType getLockinPeriodType() {
return lockinPeriodType;
}
}
@@ -1,73 +0,0 @@
package org.mifosng.platform.saving.service;
import java.util.ArrayList;
import java.util.List;
import org.mifosng.platform.api.commands.DepositAccountCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class DepositAccountCommandValidator {
private final DepositAccountCommand command;
public DepositAccountCommandValidator(final DepositAccountCommand command) {
this.command=command;
}
public void validateForUpdate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.account");
baseDataValidator.reset().parameter("id").value(command.getId()).notNull();
baseDataValidator.reset().parameter("clientId").value(command.getClientId()).ignoreIfNull().notNull();
baseDataValidator.reset().parameter("productId").value(command.getProductId()).ignoreIfNull().notNull();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
baseDataValidator.reset().parameter("deposit").value(command.getDepositAmount()).ignoreIfNull().notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("maturityInterestRate").value(command.getMaturityInterestRate()).ignoreIfNull().notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("tenureInMonths").value(command.getTenureInMonths()).ignoreIfNull().notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEvery").value(command.getInterestCompoundedEvery()).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType()).ignoreIfNull().inMinMaxRange(2, 2);
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).ignoreIfNull();
if (command.isNoFieldChanged()) {
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append("deposit.account").append(".no.parameters.for.update");
StringBuilder defaultEnglishMessage = new StringBuilder("No parameters passed for update.");
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(), "id");
dataValidationErrors.add(error);
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
public void validateForCreate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.account");
baseDataValidator.reset().parameter("clientId").value(command.getClientId()).notNull();
baseDataValidator.reset().parameter("productId").value(command.getProductId()).notNull();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
baseDataValidator.reset().parameter("deposit").value(command.getDepositAmount()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("maturityInterestRate").value(command.getMaturityInterestRate()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("preClosureInterestRate").value(command.getPreClosureInterestRate()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("tenureInMonths").value(command.getTenureInMonths()).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEvery").value(command.getInterestCompoundedEvery()).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType()).ignoreIfNull().inMinMaxRange(2, 2);
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).notNull();
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
}
@@ -1,20 +0,0 @@
package org.mifosng.platform.saving.service;
import java.math.BigDecimal;
import java.util.Collection;
import org.mifosng.platform.api.data.DepositAccountData;
import org.mifosng.platform.api.data.DepositPermissionData;
public interface DepositAccountReadPlatformService {
Collection<DepositAccountData> retrieveAllDepositAccounts();
DepositAccountData retrieveDepositAccount(Long accountId);
DepositAccountData retrieveNewDepositAccountDetails(Long clientId, Long productId);
DepositPermissionData retrieveDepositAccountsPermissions(DepositAccountData depositAccountData);
BigDecimal retrieveAvailableInterestForWithdrawal(DepositAccountData account);
}
@@ -1,267 +0,0 @@
package org.mifosng.platform.saving.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import org.joda.time.LocalDate;
import org.joda.time.Months;
import org.mifosng.platform.api.data.DepositAccountData;
import org.mifosng.platform.api.data.DepositAccountTransactionData;
import org.mifosng.platform.api.data.DepositPermissionData;
import org.mifosng.platform.api.data.DepositProductData;
import org.mifosng.platform.api.data.DepositProductLookup;
import org.mifosng.platform.savingproduct.service.DepositProductReadPlatformService;
import org.mifosng.platform.savingproduct.service.SavingsDepositEnumerations;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.data.ClientData;
import org.mifosplatform.portfolio.client.service.ClientReadPlatformService;
import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class DepositAccountReadPlatformServiceImpl implements DepositAccountReadPlatformService {
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
private final DepositProductReadPlatformService depositProductReadPlatformService;
private final ClientReadPlatformService clientReadPlatformService;
@Autowired
public DepositAccountReadPlatformServiceImpl(final PlatformSecurityContext context,final TenantAwareRoutingDataSource dataSource, final DepositProductReadPlatformService depositProductReadPlatformService,final ClientReadPlatformService clientReadPlatformService) {
this.context=context;
jdbcTemplate=new JdbcTemplate(dataSource);
this.depositProductReadPlatformService=depositProductReadPlatformService;
this.clientReadPlatformService=clientReadPlatformService;
}
@Override
public Collection<DepositAccountData> retrieveAllDepositAccounts() {
this.context.authenticatedUser();
DepositAccountMapper mapper = new DepositAccountMapper();
String sql = "select " + mapper.schema() + " where da.is_deleted=0";
return this.jdbcTemplate.query(sql,mapper, new Object[]{});
}
@Override
public DepositAccountData retrieveDepositAccount(final Long accountId) {
try{
DepositAccountMapper mapper = new DepositAccountMapper();
String sql = "select " + mapper.schema() + " where da.id = ? and da.is_deleted=0";
DepositAccountData depositAccountData = this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { accountId });
// FIXME - kw - the call to find transactions for deposit account to add to the deposit account payload can be decided at the api level
// depending on whether the requester wants them or not instead of always getting the transactions
DepositAccountTransactionMapper transactionMapper = new DepositAccountTransactionMapper();
String transactionSchema = "select " + transactionMapper.schema() + " where txn.deposit_account_id = ? ";
Collection<DepositAccountTransactionData> depositAccountTransactions = this.jdbcTemplate.query(transactionSchema, transactionMapper, new Object[]{accountId});
if (!depositAccountTransactions.isEmpty()) {
DepositPermissionData permissions = null;
depositAccountData = new DepositAccountData(depositAccountData, permissions, depositAccountTransactions);
}
return depositAccountData;
} catch (EmptyResultDataAccessException e) {
throw new LoanProductNotFoundException(accountId);
}
}
@Override
public DepositAccountData retrieveNewDepositAccountDetails(final Long clientId, final Long productId) {
context.authenticatedUser();
ClientData clientAccount = this.clientReadPlatformService.retrieveIndividualClient(clientId);
DepositAccountData accountData = null;
Collection<DepositProductLookup> depositProducts = this.depositProductReadPlatformService.retrieveAllDepositProductsForLookup();
if (productId != null) {
DepositProductData selectedProduct = findDepositProductById(depositProducts,productId);
CurrencyData currency = new CurrencyData(selectedProduct.getCurrencyCode(), "", selectedProduct.getDigitsAfterDecimal(), "", "");
accountData = new DepositAccountData(
clientAccount.id(), clientAccount.displayName(), selectedProduct.getId(), selectedProduct.getName(),
currency, selectedProduct.getMinimumBalance(), selectedProduct.getMaturityDefaultInterestRate(),
selectedProduct.getTenureInMonths(), selectedProduct.getInterestCompoundedEvery(), selectedProduct.getInterestCompoundedEveryPeriodType(),
selectedProduct.isRenewalAllowed(), selectedProduct.isPreClosureAllowed(),
selectedProduct.getPreClosureInterestRate(),selectedProduct.isInterestCompoundingAllowed());
} else {
accountData = DepositAccountData.createFrom(clientAccount.id(), clientAccount.displayName());
}
return accountData;
}
private DepositProductData findDepositProductById(
final Collection<DepositProductLookup> depositProducts,
final Long productId) {
DepositProductData match= this.depositProductReadPlatformService.retrieveNewDepositProductDetails();
for(DepositProductLookup depositProductLookup : depositProducts){
if (depositProductLookup.getId().equals(productId)) {
match=this.depositProductReadPlatformService.retrieveDepositProductData(depositProductLookup.getId());
break;
}
}
return match;
}
private static final class DepositAccountMapper implements RowMapper<DepositAccountData> {
public String schema() {
return "da.id as id, da.external_id as externalId, da.client_id as clientId, da.product_id as productId, "
+ " da.currency_code as currencyCode, da.currency_digits as currencyDigits, "
+ " da.deposit_amount as depositAmount, da.status_enum as statusId, "
+ " da.maturity_nominal_interest_rate as interestRate, da.tenure_months as termInMonths, da.projected_commencement_date as projectedCommencementDate,"
+ " da.actual_commencement_date as actualCommencementDate, da.matures_on_date as maturedOn,"
+ " da.projected_interest_accrued_on_maturity as projectedInterestAccrued, da.actual_interest_accrued as actualInterestAccrued, "
+ " da.projected_total_maturity_amount as projectedMaturityAmount, da.actual_total_amount as actualMaturityAmount, "
+ " da.interest_compounded_every as interestCompoundedEvery, da.interest_compounded_every_period_enum as interestCompoundedEveryPeriodType, "
+ " 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 "
+ " join m_currency curr on curr.code = da.currency_code "
+ " join m_client c on c.id = da.client_id "
+ " join m_product_deposit pd on pd.id = da.product_id";
}
@Override
public DepositAccountData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum)
throws SQLException {
Long id = rs.getLong("id");
String externalId = rs.getString("externalId");
Long clientId = rs.getLong("clientId");
String clientName = rs.getString("firstname") + " " + rs.getString("lastname");
Long productId = rs.getLong("productId");
String productName = rs.getString("productName");
Integer statusId = JdbcSupport.getInteger(rs, "statusId");
EnumOptionData status = DepositAccountEnumerations.status(statusId);
String currencyCode = rs.getString("currencyCode");
String currencyName = rs.getString("currencyName");
String currencyNameCode = rs.getString("currencyNameCode");
String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
Integer currencyDigits = JdbcSupport.getInteger(rs,"currencyDigits");
CurrencyData currencyData = new CurrencyData(currencyCode,currencyName, currencyDigits, currencyDisplaySymbol,currencyNameCode);
BigDecimal depositAmount = rs.getBigDecimal("depositAmount");
BigDecimal interestRate = rs.getBigDecimal("interestRate");
Integer termInMonths = JdbcSupport.getInteger(rs,"termInMonths");
LocalDate projectedCommencementDate = JdbcSupport.getLocalDate(rs, "projectedCommencementDate");
LocalDate actualCommencementDate = JdbcSupport.getLocalDate(rs, "actualCommencementDate");
LocalDate maturedOn = JdbcSupport.getLocalDate(rs, "maturedOn");
BigDecimal projectedInterestAccrued = rs.getBigDecimal("projectedInterestAccrued");
BigDecimal actualInterestAccrued = rs.getBigDecimal("actualInterestAccrued");
BigDecimal projectedMaturityAmount = rs.getBigDecimal("projectedMaturityAmount");
BigDecimal actualMaturityAmount = rs.getBigDecimal("actualMaturityAmount");
Integer interestCompoundedEvery = JdbcSupport.getInteger(rs, "interestCompoundedEvery");
Integer interestCompoundedEveryPeriodTypeValue = JdbcSupport.getInteger(rs, "interestCompoundedEveryPeriodType");
EnumOptionData interestCompoundedEveryPeriodType = SavingsDepositEnumerations.interestCompoundingPeriodType(interestCompoundedEveryPeriodTypeValue);
boolean renewalAllowed = rs.getBoolean("renewalAllowed");
boolean preClosureAllowed = rs.getBoolean("preClosureAllowed");
boolean interestCompoundingAllowed = rs.getBoolean("interestCompoundingAllowed");
BigDecimal preClosureInterestRate = rs.getBigDecimal("preClosureInterestRate");
LocalDate withdrawnonDate = JdbcSupport.getLocalDate(rs, "withdrawnonDate");
LocalDate rejectedonDate = JdbcSupport.getLocalDate(rs, "rejectedonDate");
LocalDate closedonDate = JdbcSupport.getLocalDate(rs, "closedonDate");
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,
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType);
}
}
private static final class DepositAccountTransactionMapper implements RowMapper<DepositAccountTransactionData>{
public String schema() {
return " txn.id as transactionId, txn.deposit_account_id as accountId, txn.transaction_type_enum as transactionType, txn.transaction_date as transactionDate, txn.amount as transactionAmount, txn.interest as interestAmount "
+ " from m_deposit_account_transaction txn";
}
@Override
public DepositAccountTransactionData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum)
throws SQLException {
Long transactionId = rs.getLong("transactionId");
Long accountId = rs.getLong("accountId");
Integer transactionTypeValue = JdbcSupport.getInteger(rs, "transactionType");
EnumOptionData transactionType=DepositAccountTransactionEnumerations.depositType(transactionTypeValue);
LocalDate transactionDate = JdbcSupport.getLocalDate(rs, "transactionDate");
BigDecimal transactionAmount = rs.getBigDecimal("transactionAmount");
BigDecimal interestAmount = rs.getBigDecimal("interestAmount");
BigDecimal total = transactionAmount.add(interestAmount);
return new DepositAccountTransactionData(transactionId, accountId, transactionType, transactionDate, transactionAmount, interestAmount, total);
}
}
@Override
public DepositPermissionData retrieveDepositAccountsPermissions(DepositAccountData depositAccountData) {
boolean pendingApproval = (depositAccountData.getStatus().getId().equals(100L));
boolean undoApprovalAllowed = (depositAccountData.getStatus().getId().equals(300L));
boolean renewelAllowed = false;
if(depositAccountData.getMaturedOn()!=null){
if(new LocalDate().isAfter(depositAccountData.getMaturedOn())/*||depositAccountData.getMaturedOn().isEqual(new LocalDate())*/){
renewelAllowed = depositAccountData.isRenewalAllowed();
}
}
boolean rejectAllowed = pendingApproval;
boolean withdrawnByApplicantAllowed = pendingApproval;
boolean interestWithdrawAllowed = depositAccountData.isInterestWithdrawable();
boolean isMaturedDepositAccount = (depositAccountData.getStatus().getId().equals(700L));
return new DepositPermissionData(rejectAllowed, withdrawnByApplicantAllowed, undoApprovalAllowed, pendingApproval, interestWithdrawAllowed, renewelAllowed, isMaturedDepositAccount);
}
@Override
public BigDecimal retrieveAvailableInterestForWithdrawal(DepositAccountData account) {
BigDecimal interstGettingForPeriod = BigDecimal.valueOf(account.getActualInterestAccrued().doubleValue()/new Double(account.getTenureInMonths()));
Integer noOfMonthsforInterestCal = Months.monthsBetween(account.getActualCommencementDate(), new LocalDate()).getMonths();
Integer noOfPeriods = noOfMonthsforInterestCal / account.getInterestCompoundedEvery();
return BigDecimal.valueOf(interstGettingForPeriod.multiply(new BigDecimal(noOfPeriods)).doubleValue()-account.getInterestPaid().doubleValue());
}
}
@@ -1,31 +0,0 @@
package org.mifosng.platform.saving.service;
import java.util.ArrayList;
import java.util.List;
import org.mifosng.platform.api.commands.DepositAccountWithdrawalCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class DepositAccountWithdrawalCommandValidator {
private final DepositAccountWithdrawalCommand command;
public DepositAccountWithdrawalCommandValidator(final DepositAccountWithdrawalCommand command) {
this.command=command;
}
public void validate(){
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.transaction");
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("note").value(command.getNote()).notNull();
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
}
@@ -1,55 +0,0 @@
package org.mifosng.platform.saving.service;
import org.mifosng.platform.api.commands.DepositAccountCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawInterestCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawalCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionCommand;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand;
import org.springframework.security.access.prepost.PreAuthorize;
public interface DepositAccountWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'CREATE_DEPOSITACCOUNT')")
EntityIdentifier createDepositAccount(DepositAccountCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'UPDATE_DEPOSITACCOUNT')")
EntityIdentifier updateDepositAccount(DepositAccountCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'DELETE_DEPOSITACCOUNT')")
EntityIdentifier deleteDepositAccount(Long productId);
// NOTE - took out permissions relating to doing things with deposit
// accounts in the past as doesn't appear to be code for it
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'APPROVE_DEPOSITACCOUNT')")
EntityIdentifier approveDepositApplication(
DepositStateTransitionApprovalCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'REJECT_DEPOSITACCOUNT')")
EntityIdentifier rejectDepositApplication(
DepositStateTransitionCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'WITHDRAW_DEPOSITACCOUNT')")
EntityIdentifier withdrawDepositApplication(
DepositStateTransitionCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'APPROVALUNDO_DEPOSITACCOUNT')")
EntityIdentifier undoDepositApproval(UndoStateTransitionCommand undoCommand);
/*
* @PreAuthorize(value =
* "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', '')"
* ) EntityIdentifier matureDepositApplication(DepositStateTransitionCommand
* command);
*/
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'WITHDRAWAL_DEPOSITACCOUNT')")
EntityIdentifier withdrawDepositAccountMoney(DepositAccountWithdrawalCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'INTEREST_DEPOSITACCOUNT')")
EntityIdentifier withdrawDepositAccountInterestMoney(DepositAccountWithdrawInterestCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'RENEW_DEPOSITACCOUNT')")
EntityIdentifier renewDepositAccount(DepositAccountCommand command);
}
@@ -1,422 +0,0 @@
package org.mifosng.platform.saving.service;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.Months;
import org.mifosng.platform.api.commands.DepositAccountCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawInterestCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawalCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionCommand;
import org.mifosng.platform.exceptions.DepositAccountNotFoundException;
import org.mifosng.platform.exceptions.DepositAccountReopenException;
import org.mifosng.platform.exceptions.DepositAccountTransactionsException;
import org.mifosng.platform.exceptions.SavingsProductNotFoundException;
import org.mifosng.platform.saving.domain.DepositAccount;
import org.mifosng.platform.saving.domain.DepositAccountRepository;
import org.mifosng.platform.saving.domain.DepositAccountStatus;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachine;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachineImpl;
import org.mifosng.platform.saving.domain.FixedTermDepositInterestCalculator;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.domain.Note;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements DepositAccountWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(DepositAccountWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final DepositAccountRepository depositAccountRepository;
private final DepositAccountAssembler depositAccountAssembler;
private final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator;
private final NoteRepository noteRepository;
@Autowired
public DepositAccountWritePlatformServiceJpaRepositoryImpl(
final PlatformSecurityContext context,
final DepositAccountRepository depositAccountRepository,
final DepositAccountAssembler depositAccountAssembler,
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,
final NoteRepository noteRepository) {
this.context=context;
this.depositAccountRepository = depositAccountRepository;
this.depositAccountAssembler = depositAccountAssembler;
this.fixedTermDepositInterestCalculator = fixedTermDepositInterestCalculator;
this.noteRepository = noteRepository;
}
/*
* Guaranteed to throw an exception no matter what the data integrity issue is.
*/
private void handleDataIntegrityIssues(final DepositAccountCommand command, DataIntegrityViolationException dve) {
Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("deposit_acc_external_id")) {
throw new PlatformDataIntegrityException("error.msg.desposit.account.duplicate.externalId", "Deposit account with externalId " + command.getExternalId() + " already exists", "externalId", command.getExternalId());
}
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.deposit.account.unknown.data.integrity.issue", "Unknown data integrity issue with resource.");
}
@Transactional
@Override
public EntityIdentifier createDepositAccount(final DepositAccountCommand command) {
try {
this.context.authenticatedUser();
DepositAccountCommandValidator validator = new DepositAccountCommandValidator(command);
validator.validateForCreate();
final DepositAccount account = this.depositAccountAssembler.assembleFrom(command);
this.depositAccountRepository.save(account);
return new EntityIdentifier(account.getId());
} catch (DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return new EntityIdentifier(Long.valueOf(-1));
}
}
@Transactional
@Override
public EntityIdentifier deleteDepositAccount(final Long accountId) {
this.context.authenticatedUser();
DepositAccount account = this.depositAccountRepository.findOne(accountId);
if (account==null || account.isDeleted()) {
throw new SavingsProductNotFoundException(accountId);
}
account.delete();
this.depositAccountRepository.save(account);
return new EntityIdentifier(accountId);
}
@Transactional
@Override
public EntityIdentifier approveDepositApplication(final DepositStateTransitionApprovalCommand command) {
//AppUser currentUser = context.authenticatedUser();
DepositStateTransitionApprovalCommandValidator validator = new DepositStateTransitionApprovalCommandValidator(command);
validator.validate();
DepositAccount account = this.depositAccountRepository.findOne(command.getAccountId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getAccountId());
}
// FIXME - madhukar - you are checking for loan permission here instead of some specific deposit account permission.
// removing check for now until rules dealing with creating and maintaining deposit accounts in the past is clarified
LocalDate eventDate = command.getEventDate();
//if (this.isBeforeToday(eventDate) && currentUser.canNotApproveLoanInPast()) {
// throw new NoAuthorizationException("User has no authority to approve deposit with a date in the past.");
//}
account.approve(eventDate, defaultDepositLifecycleStateMachine(), command, this.fixedTermDepositInterestCalculator);
this.depositAccountRepository.save(account);
String noteText = command.getNote();
if (StringUtils.isNotBlank(noteText)) {
Note note = Note.depositNote(account, noteText);
this.noteRepository.save(note);
}
return new EntityIdentifier(account.getId());
}
//private boolean isBeforeToday(final LocalDate date) {
// return date.isBefore(new LocalDate());
//}
private DepositLifecycleStateMachine defaultDepositLifecycleStateMachine() {
List<DepositAccountStatus> allowedDepositStatuses = Arrays.asList(DepositAccountStatus.values());
return new DepositLifecycleStateMachineImpl(allowedDepositStatuses);
}
@Transactional
@Override
public EntityIdentifier rejectDepositApplication(DepositStateTransitionCommand command) {
//AppUser currentUser = context.authenticatedUser();
DepositStateTransitionCommandValidator validator = new DepositStateTransitionCommandValidator(command);
validator.validate();
DepositAccount account = this.depositAccountRepository.findOne(command.getAccountId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getAccountId());
}
// removing check for now until rules dealing with creating and maintaining deposit accounts in the past is clarified
LocalDate eventDate = command.getEventDate();
//if (this.isBeforeToday(eventDate) && currentUser.canNotApproveLoanInPast()) {
// throw new NoAuthorizationException("User has no authority to approve deposit with a date in the past.");
//}
account.reject(eventDate, defaultDepositLifecycleStateMachine());
this.depositAccountRepository.save(account);
String noteText = command.getNote();
if (StringUtils.isNotBlank(noteText)) {
Note note = Note.depositNote(account, noteText);
this.noteRepository.save(note);
}
return new EntityIdentifier(account.getId());
}
@Transactional
@Override
public EntityIdentifier withdrawDepositApplication(DepositStateTransitionCommand command) {
//AppUser currentUser = context.authenticatedUser();
DepositStateTransitionCommandValidator validator = new DepositStateTransitionCommandValidator(command);
validator.validate();
DepositAccount account = this.depositAccountRepository.findOne(command.getAccountId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getAccountId());
}
// removing check for now until rules dealing with creating and maintaining deposit accounts in the past is clarified
LocalDate eventDate = command.getEventDate();
//if (this.isBeforeToday(eventDate) && currentUser.canNotApproveLoanInPast()) {
// throw new NoAuthorizationException("User has no authority to approve deposit with a date in the past.");
//}
account.withdrawnByApplicant(eventDate, defaultDepositLifecycleStateMachine());
this.depositAccountRepository.save(account);
String noteText = command.getNote();
if (StringUtils.isNotBlank(noteText)) {
Note note = Note.depositNote(account, noteText);
this.noteRepository.save(note);
}
return new EntityIdentifier(account.getId());
}
@Transactional
@Override
public EntityIdentifier undoDepositApproval(UndoStateTransitionCommand command) {
context.authenticatedUser();
DepositAccount account = this.depositAccountRepository.findOne(command.getLoanId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getLoanId());
}
account.undoDepositApproval(defaultDepositLifecycleStateMachine());
this.depositAccountRepository.save(account);
String noteText = command.getNote();
if (StringUtils.isNotBlank(noteText)) {
Note note = Note.depositNote(account, noteText);
this.noteRepository.save(note);
}
return new EntityIdentifier(account.getId());
}
/*@Transactional
@Override
public EntityIdentifier matureDepositApplication(DepositStateTransitionCommand command) {
AppUser currentUser = context.authenticatedUser();
DepositStateTransitionCommandValidator validator = new DepositStateTransitionCommandValidator(command);
validator.validate();
DepositAccount account = this.depositAccountRepository.findOne(command.getAccountId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getAccountId());
}
LocalDate eventDate = command.getEventDate();
if (this.isBeforeToday(eventDate) && currentUser.canNotApproveLoanInPast()) {
throw new NoAuthorizationException("User has no authority to mature deposit with a date in the past.");
}
account.matureDepositApplication(eventDate, defaultDepositLifecycleStateMachine());
this.depositAccountRepository.save(account);
if(account.isRenewalAllowed()){
final DepositAccount renewedAccount = this.depositAccountAssembler.assembleFrom(account);
this.depositAccountRepository.save(renewedAccount);
return new EntityIdentifier(renewedAccount.getId()); //returns the new deposit application id
}
String noteText = command.getNote();
if (StringUtils.isNotBlank(noteText)) {
Note note = Note.depositNote(account, noteText);
this.noteRepository.save(note);
}
return new EntityIdentifier(account.getId());
}*/
@Transactional
@Override
public EntityIdentifier withdrawDepositAccountMoney(final DepositAccountWithdrawalCommand command) {
context.authenticatedUser();
DepositAccountWithdrawalCommandValidator validator = new DepositAccountWithdrawalCommandValidator(command);
validator.validate();
DepositAccount account = this.depositAccountRepository.findOne(command.getAccountId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getAccountId());
}
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);
this.noteRepository.save(note);
}
return new EntityIdentifier(account.getId());
}
@Transactional
@Override
public EntityIdentifier withdrawDepositAccountInterestMoney(DepositAccountWithdrawInterestCommand command) {
context.authenticatedUser();
WithDrawDepositAccountInterestCommandValidator validator = new WithDrawDepositAccountInterestCommandValidator(command);
validator.validate();
DepositAccount account = this.depositAccountRepository.findOne(command.getAccountId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getAccountId());
}
if(account.isInterestWithdrawable() && !account.isInterestCompoundingAllowed()){
BigDecimal totalAvailableInterestForWithdrawal = getTotalWithdrawableInterestAvailable(account);
BigDecimal interestPaid = account.getInterstPaid();
BigDecimal remainInterestForWithdrawal = totalAvailableInterestForWithdrawal.subtract(interestPaid);
if(remainInterestForWithdrawal.doubleValue() > 0){
if(remainInterestForWithdrawal.doubleValue() >= command.getWithdrawInterest().doubleValue()&&command.getWithdrawInterest().doubleValue()>0){
account.withdrawInterest(Money.of(account.getDeposit().getCurrency(), command.getWithdrawInterest()));
this.depositAccountRepository.save(account);
}else {
throw new DepositAccountTransactionsException("deposit.transaction.interest.withdrawal.exceed","You can Withdraw "+remainInterestForWithdrawal+" only");
}
}else {
throw new DepositAccountTransactionsException("deposit.transaction.interest.withdrawal.insufficient.amount","You don't have enough money for withdrawal");
}
}else{
throw new DepositAccountTransactionsException("deposit.transaction.interest.withdrawal.cannot.withdraw","You can not withdraw interst for this account");
}
return new EntityIdentifier(account.getId());
}
private BigDecimal getTotalWithdrawableInterestAvailable(DepositAccount account){
BigDecimal interstGettingForPeriod = BigDecimal.valueOf(account.getAccuredInterest().getAmount().doubleValue()/new Double(account.getTenureInMonths()));
Integer noOfMonthsforInterestCal = Months.monthsBetween(account.getActualCommencementDate(), new LocalDate()).getMonths();
Integer noOfPeriods = noOfMonthsforInterestCal / account.getInterestCompoundedEvery();
return interstGettingForPeriod.multiply(new BigDecimal(noOfPeriods));
}
@Transactional
@Override
public EntityIdentifier renewDepositAccount(DepositAccountCommand command) {
this.context.authenticatedUser();
RenewDepositAccountCommandValidator validator = new RenewDepositAccountCommandValidator(command);
validator.validateForCreate();
DepositAccount account = this.depositAccountRepository.findOne(command.getId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getId());
}
// FIXME - KW - extract whats in this if into a method that naturally describes what you are checking.
if (account.isRenewalAllowed()
&& (new LocalDate().isAfter(account.maturesOnDate()) || new LocalDate()
.isEqual(account.maturesOnDate()))) {
if (account.isActive()) {
final DepositAccount renewedAccount = this.depositAccountAssembler.assembleFrom(account, command);
this.depositAccountRepository.save(renewedAccount);
account.closeDepositAccount(defaultDepositLifecycleStateMachine());
this.depositAccountRepository.save(account);
return new EntityIdentifier(renewedAccount.getId());
}
throw new DepositAccountReopenException(account.getMaturityDate());
}
throw new DepositAccountReopenException(account.getMaturityDate());
}
@Override
public EntityIdentifier updateDepositAccount(DepositAccountCommand command) {
try {
this.context.authenticatedUser();
DepositAccountCommandValidator validator = new DepositAccountCommandValidator(command);
validator.validateForUpdate();
final DepositAccount account = this.depositAccountRepository.findOne(command.getId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(command.getId());
}
if (account.isSubmittedAndPendingApproval()) {
this.depositAccountAssembler.assembleUpdatedDepositAccount(account, command);
} else if (account.isActive()) {
this.depositAccountAssembler.updateApprovedDepositAccount(account, command);
}
this.depositAccountRepository.save(account);
return new EntityIdentifier(account.getId());
} catch (DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return new EntityIdentifier(Long.valueOf(-1));
}
}
}
@@ -1,42 +0,0 @@
package org.mifosng.platform.saving.service;
import java.util.ArrayList;
import java.util.List;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class DepositStateTransitionApprovalCommandValidator {
private final DepositStateTransitionApprovalCommand command;
public DepositStateTransitionApprovalCommandValidator(final DepositStateTransitionApprovalCommand command) {
this.command=command;
}
public void validate(){
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.transition");
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("commencementDate").value(command.getEventDate()).notNull();
baseDataValidator.reset().parameter("deposit").value(command.getDepositAmount()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("maturityInterestRate").value(command.getMaturityInterestRate()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("tenureInMonths").value(command.getTenureInMonths()).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType()).ignoreIfNull().inMinMaxRange(2, 2);
baseDataValidator.reset().parameter("note").value(command.getNote()).notNull();
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
}
@@ -1,207 +0,0 @@
package org.mifosng.platform.saving.service;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.commands.SavingAccountCommand;
import org.mifosng.platform.exceptions.SavingsProductNotFoundException;
import org.mifosng.platform.saving.domain.DepositAccountStatus;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachine;
import org.mifosng.platform.saving.domain.DepositLifecycleStateMachineImpl;
import org.mifosng.platform.saving.domain.ReccuringDepositInterestCalculator;
import org.mifosng.platform.saving.domain.SavingAccount;
import org.mifosng.platform.savingproduct.domain.SavingFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod;
import org.mifosng.platform.savingproduct.domain.SavingProduct;
import org.mifosng.platform.savingproduct.domain.SavingProductRepository;
import org.mifosng.platform.savingproduct.domain.SavingProductType;
import org.mifosng.platform.savingproduct.domain.SavingsInterestType;
import org.mifosng.platform.savingproduct.domain.TenureTypeEnum;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SavingAccountAssembler {
private final ClientRepository clientRepository;
private final SavingProductRepository savingProductRepository;
private final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator;
@Autowired
public SavingAccountAssembler(final ClientRepository clientRepository,final SavingProductRepository savingProductRepository,
final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) {
this.clientRepository=clientRepository;
this.savingProductRepository=savingProductRepository;
this.reccuringDepositInterestCalculator=reccuringDepositInterestCalculator;
}
//minimumBalanceForWithdrawal,isPartialDepositAllowed
public SavingAccount assembleFrom(SavingAccountCommand command){
Client client = this.clientRepository.findOne(command.getClientId());
if (client == null || client.isDeleted()) {
throw new ClientNotFoundException(command.getClientId());
}
SavingProduct product=this.savingProductRepository.findOne(command.getProductId());
if(product == null || product.isDeleted()){
throw new SavingsProductNotFoundException(command.getProductId());
}
MonetaryCurrency currency = product.getCurrency();
if(command.getCurrencyCode() != null && command.getDigitsAfterDecimal() != null){
currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal());
}
Money savingsDeposit = Money.of(currency, command.getSavingsDepositAmount());
Integer tenure = product.getSavingProductRelatedDetail().getTenure();
if(command.getTenure() != null){
tenure=command.getTenure();
}
TenureTypeEnum tenureTypeEnum=product.getSavingProductRelatedDetail().getTenureType();
if (command.getTenureType() != null) {
tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType());
}
SavingProductType savingProductType= product.getSavingProductRelatedDetail().getSavingProductType();
if(command.getSavingProductType() != null){
savingProductType = SavingProductType.fromInt(command.getSavingProductType());
}
SavingFrequencyType savingFrequencyType = product.getSavingProductRelatedDetail().getFrequency();
if (command.getFrequency() != null) {
savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency());
}
SavingInterestCalculationMethod savingInterestCalculationMethod = product.getSavingProductRelatedDetail().getInterestCalculationMethod();
if (command.getInterestCalculationMethod() != null) {
savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
}
SavingsInterestType interestType = product.getSavingProductRelatedDetail().getInterestType();
if (command.getInterestType() != null) {
interestType = SavingsInterestType.fromInt(command.getInterestType());
}
BigDecimal reccuringInterestRate = command.getRecurringInterestRate();
BigDecimal savingInterestRate = product.getInterestRate();
if(command.getSavingInterestRate() != null)
savingInterestRate = command.getSavingInterestRate();
boolean isLockinPeriodAllowed = product.getSavingProductRelatedDetail().isLockinPeriodAllowed();
if(command.isLockinPeriodChanged()){
isLockinPeriodAllowed = command.isLockinPeriodAllowed();
}
Integer lockinPeriod = product.getSavingProductRelatedDetail().getLockinPeriod();
if(command.getLockinPeriod() != null){
lockinPeriod = command.getLockinPeriod();
}
PeriodFrequencyType lockinPeriodType = product.getSavingProductRelatedDetail().getLockinPeriodType();
if(command.getLockinPeriodType() != null){
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
}
SavingAccount account = SavingAccount.openNew(client, product, command.getExternalId(),savingsDeposit,
reccuringInterestRate,savingInterestRate,tenure,command.getCommencementDate(),tenureTypeEnum, savingProductType,
savingFrequencyType, interestType, savingInterestCalculationMethod, isLockinPeriodAllowed,lockinPeriod, lockinPeriodType,
this.reccuringDepositInterestCalculator, defaultDepositLifecycleStateMachine());
return account;
}
public void assembleFrom(SavingAccountCommand command, SavingAccount account) {
SavingProduct product=account.getProduct();
if(command.isProductIdChanged()){
if(product.getId() != command.getProductId()){
product = this.savingProductRepository.findOne(command.getProductId());
if(product == null || product.isDeleted())
throw new SavingsProductNotFoundException(command.getProductId());
}
}
String externalId = account.getExternalId();
if(command.isExternalIdChanged()){
externalId = command.getExternalId();
}
Money savingsDeposit = Money.of(product.getCurrency(), account.getSavingsDepositAmountPerPeriod());
if(command.isDepositAmountChanged()){
savingsDeposit = Money.of(product.getCurrency(), command.getSavingsDepositAmount());
}
Integer tenure = account.getTenure();
if(command.isTenureInMonthsChanged()){
tenure = command.getTenure();
}
LocalDate commencementDate = new LocalDate(account.getProjectedCommencementDate());
if (command.isCommencementDateChanged()) {
commencementDate = command.getCommencementDate();
}
TenureTypeEnum tenureTypeEnum=account.getTenureType();
if(command.isTenureTypeEnumChanged()){
tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType());
}
SavingProductType savingProductType= account.getSavingProductType();
if (command.isSavingProductTypeChanged()) {
savingProductType = SavingProductType.fromInt(command.getSavingProductType());
}
SavingFrequencyType savingFrequencyType = account.getFrequency();
if (command.isSavingFrequencyTypeChanged()) {
savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency());
}
SavingInterestCalculationMethod savingInterestCalculationMethod =account.getInterestCalculationMethod();
if (command.isSavingInterestCalculationMethodChanged()) {
savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
}
BigDecimal reccuringInterestRate = account.getReccuringInterestRate();
if (command.isReccuringInterestRateChanged()) {
reccuringInterestRate = command.getRecurringInterestRate();
}
BigDecimal savingInterestRate = account.getSavingInterestRate();
if (command.isSavingInterestRateChanged()) {
savingInterestRate = command.getSavingInterestRate();
}
boolean isLockinPeriodAllowed = account.isLockinPeriodAllowed();
if (command.isLockinPeriodAllowedChanged()) {
isLockinPeriodAllowed = command.isLockinPeriodAllowed();
}
Integer lockinPeriod =account.getLockinPeriod();
if (command.isLockinPeriodChanged()) {
lockinPeriod = command.getLockinPeriod();
}
PeriodFrequencyType lockinPeriodType = account.getLockinPeriodType();
if (command.isLockinPeriodTypeChanged()) {
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
}
account.modifyAccount(product, externalId, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure,
commencementDate, tenureTypeEnum, savingProductType, savingFrequencyType, savingInterestCalculationMethod,
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, this.reccuringDepositInterestCalculator);
}
private DepositLifecycleStateMachine defaultDepositLifecycleStateMachine() {
List<DepositAccountStatus> allowedDepositStatuses = Arrays.asList(DepositAccountStatus.values());
return new DepositLifecycleStateMachineImpl(allowedDepositStatuses);
}
}
@@ -1,94 +0,0 @@
package org.mifosng.platform.saving.service;
import java.util.ArrayList;
import java.util.List;
import org.mifosng.platform.api.commands.SavingAccountCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class SavingAccountCommandValidator {
private final SavingAccountCommand command;
public SavingAccountCommandValidator(final SavingAccountCommand command) {
this.command = command;
}
public void validateForCreate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("saving.account");
baseDataValidator.reset().parameter("clientId").value(command.getClientId()).notNull();
baseDataValidator.reset().parameter("productId").value(command.getProductId()).notNull();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank();
baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).notNull().inMinMaxRange(0, 6);
baseDataValidator.reset().parameter("savingsDepositAmountPerPeriod").value(command.getSavingsDepositAmount()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("recurringInterestRate").value(command.getRecurringInterestRate()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("savingInterestRate").value(command.getSavingInterestRate()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("savingInterestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getSavingInterestRate(), command.getRecurringInterestRate());
baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).notNull();
baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).notNull();
baseDataValidator.reset().parameter("tenure").value(command.getTenure()).notNull();
baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).notNull();
baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).notNull();
baseDataValidator.reset().parameter("interestCalculationMethod").value(command.getInterestCalculationMethod()).notNull();
baseDataValidator.reset().parameter("minimumBalanceForWithdrawal").value(command.getMinimumBalanceForWithdrawal()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("isPartialDepositAllowed").value(command.isPartialDepositAllowed()).trueOrFalseRequired(command.isPartialDepositAllowedChanged()).notNull();
baseDataValidator.reset().parameter("isLockinPeriodAllowed").value(command.isLockinPeriodAllowed()).trueOrFalseRequired(command.isLockinPeriodAllowedChanged()).notNull();
baseDataValidator.reset().parameter("lockinPeriod").value(command.getLockinPeriod()).notNull();
baseDataValidator.reset().parameter("lockinPeriodType").value(command.getLockinPeriodType()).notNull();
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).notNull();
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
public void validateForUpdate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("saving.account");
baseDataValidator.reset().parameter("id").value(command.getId()).notNull();
baseDataValidator.reset().parameter("clientId").value(command.getClientId()).ignoreIfNull().notNull();
baseDataValidator.reset().parameter("productId").value(command.getProductId()).ignoreIfNull().notNull();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank();
baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).ignoreIfNull().inMinMaxRange(0, 6);
baseDataValidator.reset().parameter("savingsDepositAmountPerPeriod").value(command.getSavingsDepositAmount()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("recurringInterestRate").value(command.getRecurringInterestRate()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("savingInterestRate").value(command.getSavingInterestRate()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("savingInterestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getSavingInterestRate(), command.getRecurringInterestRate());
baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).ignoreIfNull();
baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).ignoreIfNull();
baseDataValidator.reset().parameter("tenure").value(command.getTenure()).ignoreIfNull();
baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).ignoreIfNull();
baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).ignoreIfNull();
baseDataValidator.reset().parameter("interestCalculationMethod").value(command.getInterestCalculationMethod()).ignoreIfNull();
baseDataValidator.reset().parameter("minimumBalanceForWithdrawal").value(command.getMinimumBalanceForWithdrawal()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("isPartialDepositAllowed").value(command.isPartialDepositAllowed()).trueOrFalseRequired(command.isPartialDepositAllowedChanged()).ignoreIfNull();
baseDataValidator.reset().parameter("isLockinPeriodAllowed").value(command.isLockinPeriodAllowed()).trueOrFalseRequired(command.isLockinPeriodAllowedChanged()).ignoreIfNull();
baseDataValidator.reset().parameter("lockinPeriod").value(command.getLockinPeriod()).ignoreIfNull();
baseDataValidator.reset().parameter("lockinPeriodType").value(command.getLockinPeriodType()).ignoreIfNull();
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).ignoreIfNull();
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).ignoreIfNull();
if (command.isNoFieldChanged()) {
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append("deposit.account").append(".no.parameters.for.update");
StringBuilder defaultEnglishMessage = new StringBuilder("No parameters passed for update.");
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(), "id");
dataValidationErrors.add(error);
}
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
}
@@ -1,12 +0,0 @@
package org.mifosng.platform.saving.service;
import java.util.Collection;
import org.mifosng.platform.api.data.SavingAccountData;
public interface SavingAccountReadPlatformService {
Collection<SavingAccountData> retrieveAllSavingsAccounts();
SavingAccountData retrieveSavingsAccount(Long accountId);
}
@@ -1,150 +0,0 @@
package org.mifosng.platform.saving.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import org.joda.time.LocalDate;
import org.mifosng.platform.api.data.SavingAccountData;
import org.mifosng.platform.savingproduct.service.SavingProductEnumerations;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class SavingAccountReadPlatformServiceImpl implements
SavingAccountReadPlatformService {
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
// private final SavingProductReadPlatformService savingProductReadPlatformService;
// private final ClientReadPlatformService clientReadPlatformService;
@Autowired
public SavingAccountReadPlatformServiceImpl(
final PlatformSecurityContext context,
final TenantAwareRoutingDataSource dataSource
// final SavingProductReadPlatformService savingProductReadPlatformService,
// final ClientReadPlatformService clientReadPlatformService
) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
// this.savingProductReadPlatformService = savingProductReadPlatformService;
// this.clientReadPlatformService = clientReadPlatformService;
}
@Override
public Collection<SavingAccountData> retrieveAllSavingsAccounts() {
this.context.authenticatedUser();
SavingAccountMapper mapper = new SavingAccountMapper();
String sql = "select " + mapper.schema() + " where sa.is_deleted=0";
return this.jdbcTemplate.query(sql,mapper, new Object[]{});
}
@Override
public SavingAccountData retrieveSavingsAccount(Long accountId) {
this.context.authenticatedUser();
SavingAccountMapper mapper = new SavingAccountMapper();
String sql = "select " + mapper.schema() + " where sa.id = ? and sa.is_deleted=0";
SavingAccountData savingAccountData = this.jdbcTemplate.queryForObject(sql,mapper, new Object[]{accountId});
return savingAccountData;
}
private static final class SavingAccountMapper implements RowMapper<SavingAccountData> {
public String schema() {
return "sa.id AS id, sa.status_enum AS status, sa.external_id AS externalId,"
+ " sa.client_id AS clientId, sa.product_id AS productId, sa.deposit_amount_per_period AS savingsDepostiAmountPerPeriod,"
+ " sa.savings_product_type AS savingsProductType, sa.currency_code AS currencyCode, sa.currency_digits AS currencyDigits,"
+ " sa.total_deposit_amount AS totalDepositAmount, sa.reccuring_nominal_interest_rate AS reccuringInterestRate,"
+ " sa.regular_saving_nominal_interest_rate AS savingInterestRate, sa.tenure AS tenure, sa.tenure_type AS tenureType,"
+ " sa.frequency AS savingsFrequencyType, sa.interest_type AS interestType, sa.interest_calculation_method AS interestCalculationMethod,"
+ " sa.projected_commencement_date AS projectedCommencementDate, sa.actual_commencement_date AS actualCommencementDate,"
+ " sa.matures_on_date AS maturesOnDate, sa.projected_interest_accrued_on_maturity AS projectedInterestAccuredOnMaturity,"
+ " sa.actual_interest_accrued AS actualInterestAccured, sa.projected_total_maturity_amount AS projectedTotalMaturityAmount,"
+ " sa.actual_total_amount AS actualTotalAmount, sa.is_preclosure_allowed AS isPreclosureAllowed,"
+ " sa.pre_closure_interest_rate AS preClosureInterestRate, sa.is_lock_in_period_allowed AS isLockinPeriodAllowed,"
+ " sa.lock_in_period AS lockinPeriod, sa.lock_in_period_type AS lockinPeriodType, sa.withdrawnon_date AS withdrawnonDate,"
+ " sa.rejectedon_date AS rejectedonDate, sa.closedon_date AS closedonDate, ps.name AS productName,"
+ " c.firstname AS firstname, c.lastname AS lastname, curr.name AS currencyName, "
+ " curr.internationalized_name_code AS currencyNameCode, curr.display_symbol AS currencyDisplaySymbol "
+ " FROM m_saving_account sa "
+ " JOIN m_client c ON c.id = sa.client_id"
+ " JOIN m_currency curr ON curr.code = sa.currency_code "
+ " JOIN m_product_savings ps ON sa.product_id = ps.id ";
}
@Override
public SavingAccountData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
Long id = rs.getLong("id");
String externalId = rs.getString("externalId");
Long clientId = rs.getLong("clientId");
String clientName = rs.getString("firstname") + " " + rs.getString("lastname");
Long productId = rs.getLong("productId");
String productName = rs.getString("productName");
EnumOptionData productType = SavingProductEnumerations.savingProductType(JdbcSupport.getInteger(rs, "savingsProductType"));
Integer statusId = JdbcSupport.getInteger(rs, "status");
EnumOptionData status = DepositAccountEnumerations.status(statusId);
String currencyCode = rs.getString("currencyCode");
String currencyName = rs.getString("currencyName");
String currencyNameCode = rs.getString("currencyNameCode");
String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
Integer currencyDigits = JdbcSupport.getInteger(rs,"currencyDigits");
CurrencyData currencyData = new CurrencyData(currencyCode,currencyName, currencyDigits, currencyDisplaySymbol,currencyNameCode);
BigDecimal savingsDepostiAmountPerPeriod = rs.getBigDecimal("savingsDepostiAmountPerPeriod");
EnumOptionData savingsFrequencyType = SavingProductEnumerations.interestFrequencyType(JdbcSupport.getInteger(rs, "savingsFrequencyType"));
BigDecimal totalDepositAmount = rs.getBigDecimal("totalDepositAmount");
BigDecimal reccuringInterestRate = rs.getBigDecimal("reccuringInterestRate");
BigDecimal savingInterestRate = rs.getBigDecimal("savingInterestRate");
EnumOptionData interestType = SavingProductEnumerations.savingInterestType(JdbcSupport.getInteger(rs, "interestType"));
EnumOptionData interestCalculationMethod = SavingProductEnumerations.savingInterestCalculationMethod(JdbcSupport.getInteger(rs, "interestCalculationMethod"));
Integer tenure = JdbcSupport.getInteger(rs,"tenure");
EnumOptionData tenureType = SavingProductEnumerations.tenureTypeEnum(JdbcSupport.getInteger(rs, "tenureType"));
LocalDate projectedCommencementDate = JdbcSupport.getLocalDate(rs, "projectedCommencementDate");
LocalDate actualCommencementDate = JdbcSupport.getLocalDate(rs, "actualCommencementDate");
LocalDate maturesOnDate = JdbcSupport.getLocalDate(rs, "maturesOnDate");
BigDecimal projectedInterestAccuredOnMaturity = rs.getBigDecimal("projectedInterestAccuredOnMaturity");
BigDecimal actualInterestAccured = rs.getBigDecimal("actualInterestAccured");
BigDecimal projectedMaturityAmount = rs.getBigDecimal("projectedTotalMaturityAmount");
BigDecimal actualMaturityAmount = rs.getBigDecimal("actualTotalAmount");
boolean preClosureAllowed = rs.getBoolean("isPreclosureAllowed");
BigDecimal preClosureInterestRate = rs.getBigDecimal("preClosureInterestRate");
LocalDate withdrawnonDate = JdbcSupport.getLocalDate(rs, "withdrawnonDate");
LocalDate rejectedonDate = JdbcSupport.getLocalDate(rs, "rejectedonDate");
LocalDate closedonDate = JdbcSupport.getLocalDate(rs, "closedonDate");
boolean isLockinPeriodAllowed = rs.getBoolean("isLockinPeriodAllowed");
Integer lockinPeriod = JdbcSupport.getInteger(rs, "lockinPeriod");
Integer lockinPeriodTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodType");
EnumOptionData lockinPeriodType = SavingProductEnumerations.savingsLockinPeriod(lockinPeriodTypeValue);
return new SavingAccountData(id, status, externalId, clientId, clientName, productId, productName, productType, currencyData,
savingsDepostiAmountPerPeriod, savingsFrequencyType, totalDepositAmount, reccuringInterestRate, savingInterestRate,
interestType, interestCalculationMethod, tenure, tenureType, projectedCommencementDate, actualCommencementDate,
maturesOnDate,projectedInterestAccuredOnMaturity, actualInterestAccured,
projectedMaturityAmount, actualMaturityAmount, preClosureAllowed, preClosureInterestRate, withdrawnonDate,
rejectedonDate, closedonDate, isLockinPeriodAllowed, lockinPeriod, lockinPeriodType);
}
}
}
@@ -1,14 +0,0 @@
package org.mifosng.platform.saving.service;
import org.mifosng.platform.api.commands.SavingAccountCommand;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.springframework.security.access.prepost.PreAuthorize;
public interface SavingAccountWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'CREATE_SAVINGSACCOUNT')")
EntityIdentifier createSavingAccount(SavingAccountCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'UPDATE_SAVINGSACCOUNT')")
EntityIdentifier updateSavingAccount(SavingAccountCommand command);
}
@@ -1,93 +0,0 @@
package org.mifosng.platform.saving.service;
import org.mifosng.platform.api.commands.SavingAccountCommand;
import org.mifosng.platform.exceptions.SavingAccountNotFoundException;
import org.mifosng.platform.saving.domain.SavingAccount;
import org.mifosng.platform.saving.domain.SavingAccountRepository;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class SavingAccountWritePlatformServiceJpaRepositoryImpl implements SavingAccountWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(SavingAccountWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final SavingAccountRepository savingAccountRepository;
private final SavingAccountAssembler savingAccountAssembler;
@SuppressWarnings("unused")
private final NoteRepository noteRepository;
@Autowired
public SavingAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,final SavingAccountRepository savingAccountRepository,
SavingAccountAssembler savingAccountAssembler,NoteRepository noteRepository) {
this.context=context;
this.savingAccountRepository=savingAccountRepository;
this.savingAccountAssembler=savingAccountAssembler;
this.noteRepository=noteRepository;
}
@Transactional
@Override
public EntityIdentifier createSavingAccount(SavingAccountCommand command) {
try {
this.context.authenticatedUser();
SavingAccountCommandValidator validator=new SavingAccountCommandValidator(command);
validator.validateForCreate();
SavingAccount account=this.savingAccountAssembler.assembleFrom(command);
this.savingAccountRepository.save(account);
return new EntityIdentifier(account.getId());
} catch (DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return new EntityIdentifier(Long.valueOf(-1));
}
}
@Override
public EntityIdentifier updateSavingAccount(SavingAccountCommand command) {
try {
this.context.authenticatedUser();
SavingAccountCommandValidator validator=new SavingAccountCommandValidator(command);
validator.validateForUpdate();
SavingAccount account=this.savingAccountRepository.findOne(command.getId());
if (account == null || account.isDeleted()) {
throw new SavingAccountNotFoundException(command.getId());
}
if(account.isPendingApproval()){
this.savingAccountAssembler.assembleFrom(command,account);
this.savingAccountRepository.save(account);
}
return new EntityIdentifier(account.getId());
} catch (DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return new EntityIdentifier(Long.valueOf(-1));
}
}
/*
* Guaranteed to throw an exception no matter what the data integrity issue is.
*/
private void handleDataIntegrityIssues(final SavingAccountCommand command, DataIntegrityViolationException dve) {
Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("saving_acc_external_id")) {
throw new PlatformDataIntegrityException("error.msg.saving.account.duplicate.externalId", "Saving account with externalId " + command.getExternalId() + " already exists", "externalId", command.getExternalId());
}
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.saving.account.unknown.data.integrity.issue", "Unknown data integrity issue with resource.");
}
}
@@ -1,32 +0,0 @@
package org.mifosng.platform.saving.service;
import java.util.ArrayList;
import java.util.List;
import org.mifosng.platform.api.commands.DepositAccountWithdrawInterestCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class WithDrawDepositAccountInterestCommandValidator {
private final DepositAccountWithdrawInterestCommand command;
public WithDrawDepositAccountInterestCommandValidator(final DepositAccountWithdrawInterestCommand command) {
this.command=command;
}
public void validate(){
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.transaction");
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("amount").value(command.getWithdrawInterest()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("note").value(command.getNote()).notNull();
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors);
}
}
}
@@ -1,42 +0,0 @@
package org.mifosng.platform.savingproduct.domain;
public enum TenureTypeEnum {
INVALID(0,"tenureTypeEnum.invalid"),
FIXED_PERIOD(1,"tenureTypeEnum.fixedPeriod"),
PERPETUAL(2,"tenureTypeEnum.perpetual");
private final Integer value;
private final String code;
private TenureTypeEnum(final Integer value,final String code) {
this.value=value;
this.code=code;
}
public Integer getValue() {
return value;
}
public String getCode() {
return code;
}
public static TenureTypeEnum fromInt(final Integer frequency) {
TenureTypeEnum tenureTypeEnum = TenureTypeEnum.INVALID;
switch (frequency) {
case 1:
tenureTypeEnum = TenureTypeEnum.FIXED_PERIOD;
break;
case 2:
tenureTypeEnum = TenureTypeEnum.PERPETUAL;
break;
default:
tenureTypeEnum = TenureTypeEnum.INVALID;
break;
}
return tenureTypeEnum;
}
}
@@ -1,18 +0,0 @@
package org.mifosng.platform.savingproduct.service;
import java.util.Collection;
import org.mifosng.platform.api.data.DepositProductData;
import org.mifosng.platform.api.data.DepositProductLookup;
public interface DepositProductReadPlatformService {
Collection<DepositProductData> retrieveAllDepositProducts();
Collection<DepositProductLookup> retrieveAllDepositProductsForLookup();
DepositProductData retrieveDepositProductData(Long productId);
DepositProductData retrieveNewDepositProductDetails();
}
@@ -1,146 +0,0 @@
package org.mifosng.platform.savingproduct.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import org.joda.time.DateTime;
import org.mifosng.platform.api.data.DepositProductData;
import org.mifosng.platform.api.data.DepositProductLookup;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class DepositProductReadPlatformServiceImpl implements DepositProductReadPlatformService {
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
@Autowired
public DepositProductReadPlatformServiceImpl(final PlatformSecurityContext context,final TenantAwareRoutingDataSource dataSource) {
this.context=context;
jdbcTemplate=new JdbcTemplate(dataSource);
}
@Override
public Collection<DepositProductData> retrieveAllDepositProducts() {
this.context.authenticatedUser();
DepositProductMapper depositProductMapper= new DepositProductMapper();
String sql="select "+depositProductMapper.depositProductSchema() + " where dp.is_deleted=0";
return this.jdbcTemplate.query(sql,depositProductMapper, new Object[]{});
}
@Override
public Collection<DepositProductLookup> retrieveAllDepositProductsForLookup() {
this.context.authenticatedUser();
DepositProductLookupMapper depositProductLookupMapper=new DepositProductLookupMapper();
String sql = "select "+depositProductLookupMapper.depositProductLookupSchema();
return this.jdbcTemplate.query(sql, depositProductLookupMapper, new Object[]{});
}
@Override
public DepositProductData retrieveDepositProductData(Long productId) {
DepositProductMapper depositProductMapper=new DepositProductMapper();
String sql = "select "+ depositProductMapper.depositProductSchema() +" where dp.id = ? and dp.is_deleted=0";
return this.jdbcTemplate.queryForObject(sql, depositProductMapper, new Object[]{productId});
}
@Override
public DepositProductData retrieveNewDepositProductDetails() {
List<CurrencyData> currencyOptions = null;
List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions = null;
EnumOptionData monthly = SavingsDepositEnumerations.interestCompoundingPeriodType(PeriodFrequencyType.MONTHS);
return new DepositProductData(currencyOptions, monthly, interestCompoundedEveryPeriodTypeOptions);
}
private static final class DepositProductMapper implements RowMapper<DepositProductData>{
public String depositProductSchema(){
return " dp.id as id, dp.external_id as exernalId, dp.name as name, dp.description as description,dp.currency_code as currencyCode, dp.currency_digits as currencyDigits,dp.minimum_balance as minimumBalance,dp.maximum_balance as maximumBalance," +
"dp.created_date as createdon, dp.lastmodified_date as modifiedon,dp.tenure_months as tenureMonths, " +
"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 ";
}
@Override
public DepositProductData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum)
throws SQLException {
Long id = rs.getLong("id");
String exernalId = rs.getString("exernalId");
String name = rs.getString("name");
String description = rs.getString("description");
String currencyCode = rs.getString("currencyCode");
Integer currencyDigits = JdbcSupport.getInteger(rs,"currencyDigits");
DateTime createdOn = JdbcSupport.getDateTime(rs, "createdon");
DateTime lastModifedOn = JdbcSupport.getDateTime(rs, "modifiedon");
BigDecimal minimumBalance=rs.getBigDecimal("minimumBalance");
BigDecimal maximumBalance=rs.getBigDecimal("maximumBalance");
Integer tenureMonths = JdbcSupport.getInteger(rs, "tenureMonths");
Integer interestCompoundedEvery = JdbcSupport.getInteger(rs, "interestCompoundedEvery");
Integer interestCompoundedEveryPeriodTypeValue = JdbcSupport.getInteger(rs, "interestCompoundedEveryPeriodType");
EnumOptionData interestCompoundedEveryPeriodType = SavingsDepositEnumerations.interestCompoundingPeriodType(interestCompoundedEveryPeriodTypeValue);
BigDecimal maturityDefaultInterestRate=rs.getBigDecimal("maturityDefaultInterestRate");
BigDecimal maturityMinInterestRate= rs.getBigDecimal("maturityMinInterestRate");
BigDecimal maturityMaxInterestRate = rs.getBigDecimal("maturityMaxInterestRate");
Boolean canRenew = rs.getBoolean("canRenew");
Boolean canPreClose=rs.getBoolean("canPreClose");
Boolean interestCompoundingAllowed= rs.getBoolean("interestCompoundingAllowed");
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,isLockinPeriodAllowed,lockinPeriod,lockinPeriodType);
}
}
private static final class DepositProductLookupMapper implements RowMapper<DepositProductLookup> {
public String depositProductLookupSchema() {
return "dp.id as id, dp.name as name from m_product_deposit dp";
}
@Override
public DepositProductLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum)
throws SQLException {
Long id = rs.getLong("id");
String name = rs.getString("name");
return new DepositProductLookup(id, name);
}
}
}
@@ -1,18 +0,0 @@
package org.mifosng.platform.savingproduct.service;
import org.mifosng.platform.api.commands.DepositProductCommand;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.springframework.security.access.prepost.PreAuthorize;
public interface DepositProductWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'CREATE_DEPOSITPRODUCT')")
EntityIdentifier createDepositProduct(DepositProductCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'UPDATE_DEPOSITPRODUCT')")
EntityIdentifier updateDepositProduct(DepositProductCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'DELETE_DEPOSITPRODUCT')")
EntityIdentifier deleteDepositProduct(Long productId);
}
@@ -1,123 +0,0 @@
package org.mifosng.platform.savingproduct.service;
import org.mifosng.platform.api.commands.DepositProductCommand;
import org.mifosng.platform.exceptions.DepositProductNotFoundException;
import org.mifosng.platform.savingproduct.domain.DepositProduct;
import org.mifosng.platform.savingproduct.domain.DepositProductRepository;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class DepositProductWritePlatformServiceJpaRepositoryImpl implements DepositProductWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(DepositProductWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final DepositProductRepository depositProductRepository;
@Autowired
public DepositProductWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final DepositProductRepository depositProductRepository){
this.context=context;
this.depositProductRepository=depositProductRepository;
}
/*
* Guaranteed to throw an exception no matter what the data integrity issue is.
*/
private void handleDataIntegrityIssues(final DepositProductCommand command, final DataIntegrityViolationException dve) {
Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("name_deposit_product")) {
throw new PlatformDataIntegrityException("error.msg.desposit.product.duplicate.name", "Deposit product with name: " + command.getName() + " already exists", "name", command.getName());
}
if (realCause.getMessage().contains("externalid_deposit_product")) {
throw new PlatformDataIntegrityException("error.msg.desposit.product.duplicate.externalId", "Deposit product with externalId " + command.getExternalId() + " already exists", "externalId", command.getExternalId());
}
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.deposit.product.unknown.data.integrity.issue", "Unknown data integrity issue with resource.");
}
@Transactional
@Override
public EntityIdentifier createDepositProduct(final DepositProductCommand command) {
try {
this.context.authenticatedUser();
DepositProductCommandValidator validator=new DepositProductCommandValidator(command);
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.isLockinPeriodAllowed(),command.getLockinPeriod(),lockinPeriodType);
this.depositProductRepository.save(product);
return new EntityIdentifier(product.getId());
} catch (DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return new EntityIdentifier(Long.valueOf(-1));
}
}
@Transactional
@Override
public EntityIdentifier updateDepositProduct(final DepositProductCommand command) {
try {
this.context.authenticatedUser();
DepositProductCommandValidator validator=new DepositProductCommandValidator(command);
validator.validateForUpdate();
DepositProduct product=this.depositProductRepository.findOne(command.getId());
if(product==null){
throw new DepositProductNotFoundException(command.getId());
}
PeriodFrequencyType interestCompoundingFrequency = null;
if (command.isInterestCompoundedEveryPeriodTypeChanged()) {
interestCompoundingFrequency = PeriodFrequencyType.fromInt(command.getInterestCompoundedEveryPeriodType());
}
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) {
handleDataIntegrityIssues(command, dve);
return new EntityIdentifier(Long.valueOf(-1));
}
}
@Transactional
@Override
public EntityIdentifier deleteDepositProduct(final Long productId) {
this.context.authenticatedUser();
DepositProduct product=this.depositProductRepository.findOne(productId);
if(product==null){
throw new DepositProductNotFoundException(productId);
}
product.delete();
this.depositProductRepository.save(product);
return new EntityIdentifier(Long.valueOf(product.getId()));
}
}
@@ -5,10 +5,6 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.mifosng.platform.api.data.DepositAccountData;
import org.mifosng.platform.api.data.DepositProductData;
import org.mifosng.platform.api.data.SavingAccountData;
import org.mifosng.platform.api.data.SavingProductData;
import org.mifosplatform.commands.api.data.CommandSourceData;
import org.mifosplatform.infrastructure.codes.data.CodeData;
import org.mifosplatform.infrastructure.configuration.data.ConfigurationData;
@@ -39,6 +35,10 @@ import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData;
import org.mifosplatform.portfolio.loanaccount.gaurantor.data.GuarantorData;
import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData;
import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -1,13 +1,5 @@
package org.mifosplatform.infrastructure.core.api;
import org.mifosng.platform.api.commands.DepositAccountCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawInterestCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawalCommand;
import org.mifosng.platform.api.commands.DepositProductCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionCommand;
import org.mifosng.platform.api.commands.SavingAccountCommand;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosplatform.infrastructure.codes.command.CodeCommand;
import org.mifosplatform.infrastructure.configuration.command.CurrencyCommand;
import org.mifosplatform.infrastructure.office.command.BranchMoneyTransferCommand;
@@ -32,6 +24,14 @@ import org.mifosplatform.portfolio.loanaccount.command.LoanStateTransitionComman
import org.mifosplatform.portfolio.loanaccount.command.LoanTransactionCommand;
import org.mifosplatform.portfolio.loanaccount.gaurantor.command.GuarantorCommand;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawInterestCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand;
import org.mifosplatform.portfolio.savingsdepositproduct.command.DepositProductCommand;
public interface PortfolioApiDataConversionService {
@@ -17,14 +17,6 @@ import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.mifosng.platform.api.commands.DepositAccountCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawInterestCommand;
import org.mifosng.platform.api.commands.DepositAccountWithdrawalCommand;
import org.mifosng.platform.api.commands.DepositProductCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand;
import org.mifosng.platform.api.commands.DepositStateTransitionCommand;
import org.mifosng.platform.api.commands.SavingAccountCommand;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosplatform.infrastructure.codes.command.CodeCommand;
import org.mifosplatform.infrastructure.configuration.command.CurrencyCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
@@ -53,6 +45,14 @@ import org.mifosplatform.portfolio.loanaccount.command.LoanStateTransitionComman
import org.mifosplatform.portfolio.loanaccount.command.LoanTransactionCommand;
import org.mifosplatform.portfolio.loanaccount.gaurantor.command.GuarantorCommand;
import org.mifosplatform.portfolio.loanproduct.command.LoanProductCommand;
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawInterestCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand;
import org.mifosplatform.portfolio.savingsdepositproduct.command.DepositProductCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.number.NumberFormatter;
import org.springframework.stereotype.Service;
@@ -3,10 +3,6 @@ package org.mifosplatform.infrastructure.core.api;
import java.util.Collection;
import java.util.Set;
import org.mifosng.platform.api.data.DepositAccountData;
import org.mifosng.platform.api.data.DepositProductData;
import org.mifosng.platform.api.data.SavingAccountData;
import org.mifosng.platform.api.data.SavingProductData;
import org.mifosplatform.commands.api.data.CommandSourceData;
import org.mifosplatform.infrastructure.codes.data.CodeData;
import org.mifosplatform.infrastructure.configuration.data.ConfigurationData;
@@ -37,6 +33,10 @@ import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData;
import org.mifosplatform.portfolio.loanaccount.gaurantor.data.GuarantorData;
import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData;
import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData;
public interface PortfolioApiJsonSerializerService {
@@ -6,11 +6,11 @@ import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.mifosng.platform.saving.domain.DepositAccount;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanTransaction;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccount;
@Entity
@Table(name = "m_note")
@@ -0,0 +1,148 @@
package org.mifosplatform.portfolio.savingsaccount.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService;
import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
import org.mifosplatform.portfolio.savingsaccount.service.SavingAccountReadPlatformService;
import org.mifosplatform.portfolio.savingsaccount.service.SavingAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/savingaccounts")
@Component
@Scope("singleton")
public class SavingsAccountApiResource {
@Autowired
private SavingAccountWritePlatformService savingAccountWritePlatformService;
@Autowired
private SavingAccountReadPlatformService savingAccountReadPlatformService;
@Autowired
private PortfolioApiDataConversionService apiDataConversionService;
@Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService;
private final String entityType = "SAVINGSACCOUNT";
@Autowired
private PlatformSecurityContext context;
private static final Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "status", "externalId",
"clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod",
"savingsFrequencyType", "totalDepositAmount", "reccuringInterestRate", "savingInterestRate", "interestType",
"interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate", "actualCommencementDate", "maturesOnDate",
"projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount",
"preClosureAllowed", "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed",
"lockinPeriod", "lockinPeriodType"));
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response createSavingAccount(final String jsonRequestBody) {
final SavingAccountCommand command = this.apiDataConversionService.convertJsonToSavingAccountCommand(null, jsonRequestBody);
EntityIdentifier entityIdentifier = this.savingAccountWritePlatformService.createSavingAccount(command);
return Response.ok().entity(entityIdentifier).build();
}
@PUT
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response updateSavingAccount(@PathParam("accountId") final Long accountId, final String jsonRequestBody) {
final SavingAccountCommand command = this.apiDataConversionService.convertJsonToSavingAccountCommand(accountId, jsonRequestBody);
EntityIdentifier entityIdentifier = this.savingAccountWritePlatformService.updateSavingAccount(command);
return Response.ok().entity(entityIdentifier).build();
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllDepositAccounts(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
Collection<SavingAccountData> accounts = this.savingAccountReadPlatformService.retrieveAllSavingsAccounts();
return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, accounts);
}
@GET
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveDepositAccount(@PathParam("accountId") final Long accountId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
SavingAccountData account = this.savingAccountReadPlatformService.retrieveSavingsAccount(accountId);
return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, account);
}
@SuppressWarnings("unused")
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveNewDepositAccountDetails(@QueryParam("clientId") final Long clientId,
@QueryParam("productId") final Long productId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
SavingAccountData account = null;
// this.savingAccountReadPlatformService.retrieveNewSavingsAccountDetails(clientId,
// productId);
return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, account);
}
}
@@ -0,0 +1,229 @@
package org.mifosplatform.portfolio.savingsaccount.command;
import java.math.BigDecimal;
import java.util.Set;
import org.joda.time.LocalDate;
public class SavingAccountCommand {
private final Long id;
private final Long clientId;
private final Long productId;
private final String externalId;
private final String currencyCode;
private final Integer digitsAfterDecimal;
private final BigDecimal savingsDepositAmount;
private final BigDecimal recurringInterestRate;
private final BigDecimal savingInterestRate;
private final Integer tenure;
private final boolean isLockinPeriodAllowed;
private final Integer lockinPeriod;
private final Integer lockinPeriodType;
private final LocalDate commencementDate;
private final Integer savingProductType;
private final Integer tenureType;
private final Integer frequency;
private final Integer interestType;
private final Integer interestCalculationMethod;
private final BigDecimal minimumBalanceForWithdrawal;
private final boolean isPartialDepositAllowed;
private final Set<String> modifiedParameters;
public SavingAccountCommand(final Set<String> modifiedParameters, final Long id, final Long clientId, final Long productId,
final String externalId, final String currencyCode, final Integer digitsAfterDecimal, final BigDecimal savingsDepositAmount,
final BigDecimal recurringInterestRate, final BigDecimal savingInterestRate, final Integer tenure,
final LocalDate commencementDate, final Integer savingProductType, final Integer tenureType, final Integer frequency,
final Integer interestType, final BigDecimal minimumBalanceForWithdrawal, final Integer interestCalculationMethod,
final boolean isLockinPeriodAllowed, final boolean isPartialDepositAllowed, final Integer lockInPeriod,
final Integer lockinPeriodType) {
this.id = id;
this.clientId = clientId;
this.productId = productId;
this.externalId = externalId;
this.currencyCode = currencyCode;
this.digitsAfterDecimal = digitsAfterDecimal;
this.savingsDepositAmount = savingsDepositAmount;
this.recurringInterestRate = recurringInterestRate;
this.savingInterestRate = savingInterestRate;
this.tenure = tenure;
this.modifiedParameters = modifiedParameters;
this.commencementDate = commencementDate;
this.savingProductType = savingProductType;
this.tenureType = tenureType;
this.frequency = frequency;
this.interestType = interestType;
this.isPartialDepositAllowed = isPartialDepositAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockInPeriod;
this.lockinPeriodType = lockinPeriodType;
this.minimumBalanceForWithdrawal = minimumBalanceForWithdrawal;
this.interestCalculationMethod = interestCalculationMethod;
}
public Long getId() {
return id;
}
public Long getClientId() {
return clientId;
}
public Long getProductId() {
return productId;
}
public String getExternalId() {
return externalId;
}
public String getCurrencyCode() {
return currencyCode;
}
public Integer getDigitsAfterDecimal() {
return digitsAfterDecimal;
}
public BigDecimal getSavingsDepositAmount() {
return savingsDepositAmount;
}
public BigDecimal getRecurringInterestRate() {
return recurringInterestRate;
}
public BigDecimal getSavingInterestRate() {
return savingInterestRate;
}
public Integer getTenure() {
return tenure;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public Integer getLockinPeriodType() {
return lockinPeriodType;
}
public LocalDate getCommencementDate() {
return commencementDate;
}
public Integer getSavingProductType() {
return savingProductType;
}
public Integer getTenureType() {
return tenureType;
}
public Integer getFrequency() {
return frequency;
}
public Integer getInterestType() {
return interestType;
}
public Integer getInterestCalculationMethod() {
return interestCalculationMethod;
}
public BigDecimal getMinimumBalanceForWithdrawal() {
return minimumBalanceForWithdrawal;
}
public boolean isPartialDepositAllowed() {
return isPartialDepositAllowed;
}
public boolean isNoFieldChanged() {
return this.modifiedParameters.isEmpty();
}
public boolean isProductIdChanged() {
return this.modifiedParameters.contains("productId");
}
public boolean isExternalIdChanged() {
return this.modifiedParameters.contains("externalId");
}
public boolean isDepositAmountChanged() {
return this.modifiedParameters.contains("deposit");
}
public boolean isTenureInMonthsChanged() {
return this.modifiedParameters.contains("tenureInMonths");
}
public boolean isLockinPeriodChanged() {
return this.modifiedParameters.contains("lockinPeriod");
}
public boolean isPreClosureInterestRateChanged() {
return this.modifiedParameters.contains("preClosureInterestRate");
}
public boolean isPreClosureAllowedChanged() {
return this.modifiedParameters.contains("preClosureAllowed");
}
public boolean isCommencementDateChanged() {
return this.modifiedParameters.contains("commencementDate");
}
public boolean isTenureTypeEnumChanged() {
return this.modifiedParameters.contains("tenureType");
}
public boolean isSavingProductTypeChanged() {
return this.modifiedParameters.contains("savingProductType");
}
public boolean isSavingFrequencyTypeChanged() {
return this.modifiedParameters.contains("frequency");
}
public boolean isSavingInterestCalculationMethodChanged() {
return this.modifiedParameters.contains("interestCalculationMethod");
}
public boolean isReccuringInterestRateChanged() {
return this.modifiedParameters.contains("recurringInterestRate");
}
public boolean isSavingInterestRateChanged() {
return this.modifiedParameters.contains("savingInterestRate");
}
public boolean isLockinPeriodAllowedChanged() {
return this.modifiedParameters.contains("isLockinPeriodAllowed");
}
public boolean isLockinPeriodTypeChanged() {
return this.modifiedParameters.contains("lockinPeriodType");
}
public boolean isPartialDepositAllowedChanged() {
return this.modifiedParameters.contains("isPartialDepositAllowed");
}
}
@@ -0,0 +1,106 @@
package org.mifosplatform.portfolio.savingsaccount.command;
import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class SavingAccountCommandValidator {
private final SavingAccountCommand command;
public SavingAccountCommandValidator(final SavingAccountCommand command) {
this.command = command;
}
public void validateForCreate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("saving.account");
baseDataValidator.reset().parameter("clientId").value(command.getClientId()).notNull();
baseDataValidator.reset().parameter("productId").value(command.getProductId()).notNull();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank();
baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).notNull().inMinMaxRange(0, 6);
baseDataValidator.reset().parameter("savingsDepositAmountPerPeriod").value(command.getSavingsDepositAmount()).notNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("recurringInterestRate").value(command.getRecurringInterestRate()).notNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("savingInterestRate").value(command.getSavingInterestRate()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("savingInterestRate")
.comapareMinAndMaxOfTwoBigDecmimalNos(command.getSavingInterestRate(), command.getRecurringInterestRate());
baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).notNull();
baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).notNull();
baseDataValidator.reset().parameter("tenure").value(command.getTenure()).notNull();
baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).notNull();
baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).notNull();
baseDataValidator.reset().parameter("interestCalculationMethod").value(command.getInterestCalculationMethod()).notNull();
baseDataValidator.reset().parameter("minimumBalanceForWithdrawal").value(command.getMinimumBalanceForWithdrawal()).notNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("isPartialDepositAllowed").value(command.isPartialDepositAllowed())
.trueOrFalseRequired(command.isPartialDepositAllowedChanged()).notNull();
baseDataValidator.reset().parameter("isLockinPeriodAllowed").value(command.isLockinPeriodAllowed())
.trueOrFalseRequired(command.isLockinPeriodAllowedChanged()).notNull();
baseDataValidator.reset().parameter("lockinPeriod").value(command.getLockinPeriod()).notNull();
baseDataValidator.reset().parameter("lockinPeriodType").value(command.getLockinPeriodType()).notNull();
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).notNull();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
public void validateForUpdate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("saving.account");
baseDataValidator.reset().parameter("id").value(command.getId()).notNull();
baseDataValidator.reset().parameter("clientId").value(command.getClientId()).ignoreIfNull().notNull();
baseDataValidator.reset().parameter("productId").value(command.getProductId()).ignoreIfNull().notNull();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank();
baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).ignoreIfNull().inMinMaxRange(0, 6);
baseDataValidator.reset().parameter("savingsDepositAmountPerPeriod").value(command.getSavingsDepositAmount()).ignoreIfNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("recurringInterestRate").value(command.getRecurringInterestRate()).ignoreIfNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("savingInterestRate").value(command.getSavingInterestRate()).ignoreIfNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("savingInterestRate")
.comapareMinAndMaxOfTwoBigDecmimalNos(command.getSavingInterestRate(), command.getRecurringInterestRate());
baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).ignoreIfNull();
baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).ignoreIfNull();
baseDataValidator.reset().parameter("tenure").value(command.getTenure()).ignoreIfNull();
baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).ignoreIfNull();
baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).ignoreIfNull();
baseDataValidator.reset().parameter("interestCalculationMethod").value(command.getInterestCalculationMethod()).ignoreIfNull();
baseDataValidator.reset().parameter("minimumBalanceForWithdrawal").value(command.getMinimumBalanceForWithdrawal()).ignoreIfNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("isPartialDepositAllowed").value(command.isPartialDepositAllowed())
.trueOrFalseRequired(command.isPartialDepositAllowedChanged()).ignoreIfNull();
baseDataValidator.reset().parameter("isLockinPeriodAllowed").value(command.isLockinPeriodAllowed())
.trueOrFalseRequired(command.isLockinPeriodAllowedChanged()).ignoreIfNull();
baseDataValidator.reset().parameter("lockinPeriod").value(command.getLockinPeriod()).ignoreIfNull();
baseDataValidator.reset().parameter("lockinPeriodType").value(command.getLockinPeriodType()).ignoreIfNull();
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).ignoreIfNull();
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).ignoreIfNull();
if (command.isNoFieldChanged()) {
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append("deposit.account").append(
".no.parameters.for.update");
StringBuilder defaultEnglishMessage = new StringBuilder("No parameters passed for update.");
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
"id");
dataValidationErrors.add(error);
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -0,0 +1,124 @@
package org.mifosplatform.portfolio.savingsaccount.data;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
/**
* Immutable data object reprsenting a savings account.
*/
public class SavingAccountData {
@SuppressWarnings("unused")
private final Long id;
@SuppressWarnings("unused")
private final EnumOptionData status;
@SuppressWarnings("unused")
private final String externalId;
@SuppressWarnings("unused")
private final Long clientId;
@SuppressWarnings("unused")
private final String clientName;
@SuppressWarnings("unused")
private final Long productId;
@SuppressWarnings("unused")
private final String productName;
@SuppressWarnings("unused")
private final EnumOptionData productType;
@SuppressWarnings("unused")
private final CurrencyData currencyData;
@SuppressWarnings("unused")
private final BigDecimal savingsDepostiAmountPerPeriod;
@SuppressWarnings("unused")
private final EnumOptionData savingsFrequencyType;
@SuppressWarnings("unused")
private final BigDecimal totalDepositAmount;
@SuppressWarnings("unused")
private final BigDecimal reccuringInterestRate;
@SuppressWarnings("unused")
private final BigDecimal savingInterestRate;
@SuppressWarnings("unused")
private final EnumOptionData interestType;
@SuppressWarnings("unused")
private final EnumOptionData interestCalculationMethod;
@SuppressWarnings("unused")
private final Integer tenure;
@SuppressWarnings("unused")
private final EnumOptionData tenureType;
@SuppressWarnings("unused")
private final LocalDate projectedCommencementDate;
@SuppressWarnings("unused")
private final LocalDate actualCommencementDate;
@SuppressWarnings("unused")
private final LocalDate maturesOnDate;
@SuppressWarnings("unused")
private final BigDecimal projectedInterestAccuredOnMaturity;
@SuppressWarnings("unused")
private final BigDecimal actualInterestAccured;
@SuppressWarnings("unused")
private final BigDecimal projectedMaturityAmount;
@SuppressWarnings("unused")
private final BigDecimal actualMaturityAmount;
@SuppressWarnings("unused")
private final boolean preClosureAllowed;
@SuppressWarnings("unused")
private final BigDecimal preClosureInterestRate;
@SuppressWarnings("unused")
private final LocalDate withdrawnonDate;
@SuppressWarnings("unused")
private final LocalDate rejectedonDate;
@SuppressWarnings("unused")
private final LocalDate closedonDate;
@SuppressWarnings("unused")
private final boolean isLockinPeriodAllowed;
@SuppressWarnings("unused")
private final Integer lockinPeriod;
@SuppressWarnings("unused")
private final EnumOptionData lockinPeriodType;
public SavingAccountData(Long id, EnumOptionData status, String externalId, Long clientId, String clientName, Long productId,
String productName, EnumOptionData productType, CurrencyData currencyData, BigDecimal savingsDepostiAmountPerPeriod,
EnumOptionData savingsFrequencyType, BigDecimal totalDepositAmount, BigDecimal reccuringInterestRate,
BigDecimal savingInterestRate, EnumOptionData interestType, EnumOptionData interestCalculationMethod, Integer tenure,
EnumOptionData tenureType, LocalDate projectedCommencementDate, LocalDate actualCommencementDate, LocalDate maturesOnDate,
BigDecimal projectedInterestAccuredOnMaturity, BigDecimal actualInterestAccured, BigDecimal projectedMaturityAmount,
BigDecimal actualMaturityAmount, boolean preClosureAllowed, BigDecimal preClosureInterestRate, LocalDate withdrawnonDate,
LocalDate rejectedonDate, LocalDate closedonDate, boolean isLockinPeriodAllowed, Integer lockinPeriod,
EnumOptionData lockinPeriodType) {
this.id = id;
this.status = status;
this.externalId = externalId;
this.clientId = clientId;
this.clientName = clientName;
this.productId = productId;
this.productName = productName;
this.productType = productType;
this.currencyData = currencyData;
this.savingsDepostiAmountPerPeriod = savingsDepostiAmountPerPeriod;
this.savingsFrequencyType = savingsFrequencyType;
this.totalDepositAmount = totalDepositAmount;
this.reccuringInterestRate = reccuringInterestRate;
this.savingInterestRate = savingInterestRate;
this.interestType = interestType;
this.interestCalculationMethod = interestCalculationMethod;
this.tenure = tenure;
this.tenureType = tenureType;
this.projectedCommencementDate = projectedCommencementDate;
this.actualCommencementDate = actualCommencementDate;
this.maturesOnDate = maturesOnDate;
this.projectedInterestAccuredOnMaturity = projectedInterestAccuredOnMaturity;
this.actualInterestAccured = actualInterestAccured;
this.projectedMaturityAmount = projectedMaturityAmount;
this.actualMaturityAmount = actualMaturityAmount;
this.preClosureAllowed = preClosureAllowed;
this.preClosureInterestRate = preClosureInterestRate;
this.withdrawnonDate = withdrawnonDate;
this.rejectedonDate = rejectedonDate;
this.closedonDate = closedonDate;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
}
}
@@ -0,0 +1,74 @@
package org.mifosplatform.portfolio.savingsaccount.domain;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
import org.springframework.stereotype.Service;
@Service
public class ReccuringDepositInterestCalculator {
// FIXME - MADHUKAR - Are the unused field here needed?
public Money calculateInterestOnMaturityFor(Money savingsDepositPerPeriod, Integer tenure, BigDecimal reccuringInterestRate,
LocalDate commencementDate, TenureTypeEnum tenureTypeEnum, SavingFrequencyType savingFrequencyType,
SavingInterestCalculationMethod savingInterestCalculationMethod) {
/*
* // Assuming tenure in months // see
* http://www.onemint.com/2012/04/03/
* how-to-calculate-interest-on-recurring-deposits/
*
* A=P(1+r/n)^nt
*
* A = final amount P = principal amount (initial investment) r = annual
* nominal interest rate (as a decimal, not in percentage) n = number of
* times the interest is compounded per year t = number of years
*/
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
Integer monthsInYear = 12;
BigDecimal interestRateAsFraction = reccuringInterestRate.divide(BigDecimal.valueOf(100), mc);
Integer noofTimesInterestCompoundPerYear = Integer.valueOf(0);
switch (savingFrequencyType) {
case MONTHLY:
noofTimesInterestCompoundPerYear = monthsInYear;
break;
case QUATERLY:
noofTimesInterestCompoundPerYear = monthsInYear / 3;
break;
case HALFYEARLY:
noofTimesInterestCompoundPerYear = monthsInYear / 6;
break;
case YEARLY:
noofTimesInterestCompoundPerYear = monthsInYear / 12;
break;
default:
throw new RuntimeException("The specified frequency not supported");
}
BigDecimal interestRatePerPeriod = BigDecimal.valueOf(interestRateAsFraction.doubleValue()
/ noofTimesInterestCompoundPerYear.doubleValue());
BigDecimal onePlusInterestRatePerPeriod = BigDecimal.ONE.add(interestRatePerPeriod);
BigDecimal monthsExpressedInYears;
BigDecimal timeforOneCalculationPeriod;
BigDecimal amountPerPeriod;
BigDecimal finalAmount = BigDecimal.ZERO;
while (tenure > 0) {
monthsExpressedInYears = BigDecimal.valueOf(tenure.doubleValue() / monthsInYear.doubleValue());
timeforOneCalculationPeriod = BigDecimal.valueOf(noofTimesInterestCompoundPerYear * monthsExpressedInYears.doubleValue());
amountPerPeriod = savingsDepositPerPeriod.getAmount().multiply(
BigDecimal.valueOf(Math.pow(onePlusInterestRatePerPeriod.doubleValue(), timeforOneCalculationPeriod.doubleValue())));
finalAmount = finalAmount.add(amountPerPeriod);
tenure--;
}
return Money.of(savingsDepositPerPeriod.getCurrency(), finalAmount);
}
}
@@ -0,0 +1,337 @@
package org.mifosplatform.portfolio.savingsaccount.domain;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsInterestType;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountEvent;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachine;
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
@Entity
@Table(name = "m_saving_account", uniqueConstraints = @UniqueConstraint(name = "saving_acc_external_id", columnNames = { "external_id" }))
public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
@ManyToOne
@JoinColumn(name = "client_id", nullable = false)
private Client client;
@ManyToOne
@JoinColumn(name = "product_id")
private SavingProduct product;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use
// Integer e.g. private Integer savingProductType;
@Column(name = "savings_product_type", nullable = false)
private SavingProductType savingProductType;
@Column(name = "external_id")
private String externalId;
@SuppressWarnings("unused")
@Embedded
private MonetaryCurrency currency;
@Column(name = "deposit_amount_per_period", scale = 6, precision = 19, nullable = false)
private BigDecimal savingsDepositAmountPerPeriod;
@SuppressWarnings("unused")
@Column(name = "total_deposit_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal totalSavingsAmount;
@Column(name = "reccuring_nominal_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal reccuringInterestRate;
@Column(name = "regular_saving_nominal_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal savingInterestRate;
@Column(name = "tenure", nullable = false)
private Integer tenure;
@Column(name = "tenure_type", nullable = false)
private TenureTypeEnum tenureType;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use
// Integer e.g. private Integer savingProductType;
@Column(name = "frequency", nullable = false)
private SavingFrequencyType frequency;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use
// Integer e.g. private Integer savingProductType;
@Column(name = "interest_type", nullable = false)
private SavingsInterestType interestType;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use
// Integer e.g. private Integer savingProductType;
@Column(name = "interest_calculation_method")
private SavingInterestCalculationMethod interestCalculationMethod;
@Temporal(TemporalType.DATE)
@Column(name = "projected_commencement_date")
private Date projectedCommencementDate;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "actual_commencement_date")
private Date actualCommencementDate;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "matures_on_date")
private Date maturesOnDate;
@SuppressWarnings("unused")
@Column(name = "projected_interest_accrued_on_maturity", scale = 6, precision = 19, nullable = false)
private BigDecimal projectedInterestAccruedOnMaturity;
@SuppressWarnings("unused")
@Column(name = "actual_interest_accrued", scale = 6, precision = 19, nullable = false)
private BigDecimal interestAccrued;
@SuppressWarnings("unused")
@Column(name = "projected_total_maturity_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal projectedTotalOnMaturity;
@SuppressWarnings("unused")
@Column(name = "actual_total_amount", scale = 6, precision = 19, nullable = false)
private BigDecimal total;
@Column(name = "pre_closure_interest_rate", scale = 6, precision = 19, nullable = false)
private BigDecimal preClosureInterestRate;
@Column(name = "is_preclosure_allowed", nullable = false)
private boolean preClosureAllowed = false;
@Column(name = "is_deleted", nullable = false)
private boolean deleted = false;
@Column(name = "status_enum", nullable = false)
private Integer accountStatus;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "closedon_date")
private Date closedOnDate;
@SuppressWarnings("unused")
@Temporal(TemporalType.DATE)
@Column(name = "rejectedon_date")
private Date rejectedOnDate;
@Temporal(TemporalType.DATE)
@Column(name = "withdrawnon_date")
private Date withdrawnOnDate;
@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 static SavingAccount openNew(Client client, SavingProduct product, String externalId, Money savingsDeposit,
BigDecimal reccuringInterestRate, BigDecimal savingInterestRate, Integer tenure, LocalDate commencementDate,
TenureTypeEnum tenureTypeEnum, SavingProductType savingProductType, SavingFrequencyType savingFrequencyType,
SavingsInterestType interestType, SavingInterestCalculationMethod savingInterestCalculationMethod,
boolean isLockinPeriodAllowed, Integer lockinPeriod, PeriodFrequencyType lockinPeriodType,
ReccuringDepositInterestCalculator reccuringDepositInterestCalculator, final DepositLifecycleStateMachine lifecycleStateMachine) {
Money futureValueOnMaturity = null;
if (savingProductType.isReccuring()) {
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
} else if (savingProductType.isRegular()) {
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
}
return new SavingAccount(client, externalId, product, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure,
commencementDate, tenureTypeEnum, savingProductType, savingFrequencyType, interestType, savingInterestCalculationMethod,
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, futureValueOnMaturity, lifecycleStateMachine);
}
public SavingAccount(Client client, String externalId, SavingProduct product, Money savingsDeposit, BigDecimal reccuringInterestRate,
BigDecimal savingInterestRate, Integer tenure, LocalDate commencementDate, TenureTypeEnum tenureTypeEnum,
SavingProductType savingProductType, SavingFrequencyType savingFrequencyType, SavingsInterestType interestType,
SavingInterestCalculationMethod savingInterestCalculationMethod, boolean isLockinPeriodAllowed, Integer lockinPeriod,
PeriodFrequencyType lockinPeriodType, Money futureValueOnMaturity, final DepositLifecycleStateMachine lifecycleStateMachine) {
DepositAccountStatus from = null;
if (accountStatus != null) {
from = DepositAccountStatus.fromInt(accountStatus);
}
DepositAccountStatus statusEnum = lifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_CREATED, from);
accountStatus = statusEnum.getValue();
this.total = BigDecimal.ZERO;
this.preClosureInterestRate = BigDecimal.ZERO;
this.totalSavingsAmount = BigDecimal.ZERO;
this.interestAccrued = BigDecimal.ZERO;
this.client = client;
this.externalId = externalId;
this.product = product;
this.savingsDepositAmountPerPeriod = savingsDeposit.getAmount();
this.currency = savingsDeposit.getCurrency();
this.reccuringInterestRate = reccuringInterestRate;
this.savingInterestRate = savingInterestRate;
this.tenure = tenure;
this.projectedCommencementDate = commencementDate.toDate();
this.tenureType = tenureTypeEnum;
this.savingProductType = savingProductType;
this.frequency = savingFrequencyType;
this.interestType = interestType;
this.interestCalculationMethod = savingInterestCalculationMethod;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.getAmount().subtract(
BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue()));
}
public void modifyAccount(SavingProduct product, String externalId, Money savingsDeposit, BigDecimal reccuringInterestRate,
BigDecimal savingInterestRate, Integer tenure, LocalDate commencementDate, TenureTypeEnum tenureTypeEnum,
SavingProductType savingProductType, SavingFrequencyType savingFrequencyType,
SavingInterestCalculationMethod savingInterestCalculationMethod, boolean isLockinPeriodAllowed, Integer lockinPeriod,
PeriodFrequencyType lockinPeriodType, ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) {
Money futureValueOnMaturity = null;
if (savingProductType.isReccuring()) {
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
} else if (savingProductType.isRegular()) {
futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure,
savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod);
}
this.product = product;
this.externalId = externalId;
this.savingsDepositAmountPerPeriod = savingsDeposit.getAmount();
this.reccuringInterestRate = reccuringInterestRate;
this.savingInterestRate = savingInterestRate;
this.tenure = tenure;
this.projectedCommencementDate = commencementDate.toDate();
this.tenureType = tenureTypeEnum;
this.savingProductType = savingProductType;
this.frequency = savingFrequencyType;
this.interestCalculationMethod = savingInterestCalculationMethod;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType;
// FIXME - MADHUKAR - futureValueOnMaturity is possibly null
this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount();
this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.getAmount().subtract(
BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue()));
}
public boolean isDeleted() {
return this.deleted;
}
public boolean isPendingApproval() {
return this.accountStatus.equals(100);
}
public Client getClient() {
return client;
}
public SavingProduct getProduct() {
return product;
}
public SavingProductType getSavingProductType() {
return savingProductType;
}
public String getExternalId() {
return externalId;
}
public BigDecimal getSavingsDepositAmountPerPeriod() {
return savingsDepositAmountPerPeriod;
}
public BigDecimal getReccuringInterestRate() {
return reccuringInterestRate;
}
public BigDecimal getSavingInterestRate() {
return savingInterestRate;
}
public Integer getTenure() {
return tenure;
}
public TenureTypeEnum getTenureType() {
return tenureType;
}
public SavingFrequencyType getFrequency() {
return frequency;
}
public SavingsInterestType getInterestType() {
return interestType;
}
public SavingInterestCalculationMethod getInterestCalculationMethod() {
return interestCalculationMethod;
}
public Date getProjectedCommencementDate() {
return projectedCommencementDate;
}
public BigDecimal getPreClosureInterestRate() {
return preClosureInterestRate;
}
public boolean isPreClosureAllowed() {
return preClosureAllowed;
}
public Date getWithdrawnOnDate() {
return withdrawnOnDate;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public PeriodFrequencyType getLockinPeriodType() {
return lockinPeriodType;
}
}
@@ -1,4 +1,4 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsaccount.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -1,4 +1,4 @@
package org.mifosng.platform.exceptions;
package org.mifosplatform.portfolio.savingsaccount.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
@@ -0,0 +1,203 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
import org.mifosplatform.portfolio.savingsaccount.domain.ReccuringDepositInterestCalculator;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccount;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductRepository;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsInterestType;
import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingsProductNotFoundException;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachine;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachineImpl;
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SavingAccountAssembler {
private final ClientRepository clientRepository;
private final SavingProductRepository savingProductRepository;
private final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator;
@Autowired
public SavingAccountAssembler(final ClientRepository clientRepository, final SavingProductRepository savingProductRepository,
final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) {
this.clientRepository = clientRepository;
this.savingProductRepository = savingProductRepository;
this.reccuringDepositInterestCalculator = reccuringDepositInterestCalculator;
}
// minimumBalanceForWithdrawal,isPartialDepositAllowed
public SavingAccount assembleFrom(SavingAccountCommand command) {
Client client = this.clientRepository.findOne(command.getClientId());
if (client == null || client.isDeleted()) { throw new ClientNotFoundException(command.getClientId()); }
SavingProduct product = this.savingProductRepository.findOne(command.getProductId());
if (product == null || product.isDeleted()) { throw new SavingsProductNotFoundException(command.getProductId()); }
MonetaryCurrency currency = product.getCurrency();
if (command.getCurrencyCode() != null && command.getDigitsAfterDecimal() != null) {
currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal());
}
Money savingsDeposit = Money.of(currency, command.getSavingsDepositAmount());
Integer tenure = product.getSavingProductRelatedDetail().getTenure();
if (command.getTenure() != null) {
tenure = command.getTenure();
}
TenureTypeEnum tenureTypeEnum = product.getSavingProductRelatedDetail().getTenureType();
if (command.getTenureType() != null) {
tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType());
}
SavingProductType savingProductType = product.getSavingProductRelatedDetail().getSavingProductType();
if (command.getSavingProductType() != null) {
savingProductType = SavingProductType.fromInt(command.getSavingProductType());
}
SavingFrequencyType savingFrequencyType = product.getSavingProductRelatedDetail().getFrequency();
if (command.getFrequency() != null) {
savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency());
}
SavingInterestCalculationMethod savingInterestCalculationMethod = product.getSavingProductRelatedDetail()
.getInterestCalculationMethod();
if (command.getInterestCalculationMethod() != null) {
savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
}
SavingsInterestType interestType = product.getSavingProductRelatedDetail().getInterestType();
if (command.getInterestType() != null) {
interestType = SavingsInterestType.fromInt(command.getInterestType());
}
BigDecimal reccuringInterestRate = command.getRecurringInterestRate();
BigDecimal savingInterestRate = product.getInterestRate();
if (command.getSavingInterestRate() != null) savingInterestRate = command.getSavingInterestRate();
boolean isLockinPeriodAllowed = product.getSavingProductRelatedDetail().isLockinPeriodAllowed();
if (command.isLockinPeriodChanged()) {
isLockinPeriodAllowed = command.isLockinPeriodAllowed();
}
Integer lockinPeriod = product.getSavingProductRelatedDetail().getLockinPeriod();
if (command.getLockinPeriod() != null) {
lockinPeriod = command.getLockinPeriod();
}
PeriodFrequencyType lockinPeriodType = product.getSavingProductRelatedDetail().getLockinPeriodType();
if (command.getLockinPeriodType() != null) {
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
}
SavingAccount account = SavingAccount.openNew(client, product, command.getExternalId(), savingsDeposit, reccuringInterestRate,
savingInterestRate, tenure, command.getCommencementDate(), tenureTypeEnum, savingProductType, savingFrequencyType,
interestType, savingInterestCalculationMethod, isLockinPeriodAllowed, lockinPeriod, lockinPeriodType,
this.reccuringDepositInterestCalculator, defaultDepositLifecycleStateMachine());
return account;
}
public void assembleFrom(SavingAccountCommand command, SavingAccount account) {
SavingProduct product = account.getProduct();
if (command.isProductIdChanged()) {
if (product.getId() != command.getProductId()) {
product = this.savingProductRepository.findOne(command.getProductId());
if (product == null || product.isDeleted()) throw new SavingsProductNotFoundException(command.getProductId());
}
}
String externalId = account.getExternalId();
if (command.isExternalIdChanged()) {
externalId = command.getExternalId();
}
Money savingsDeposit = Money.of(product.getCurrency(), account.getSavingsDepositAmountPerPeriod());
if (command.isDepositAmountChanged()) {
savingsDeposit = Money.of(product.getCurrency(), command.getSavingsDepositAmount());
}
Integer tenure = account.getTenure();
if (command.isTenureInMonthsChanged()) {
tenure = command.getTenure();
}
LocalDate commencementDate = new LocalDate(account.getProjectedCommencementDate());
if (command.isCommencementDateChanged()) {
commencementDate = command.getCommencementDate();
}
TenureTypeEnum tenureTypeEnum = account.getTenureType();
if (command.isTenureTypeEnumChanged()) {
tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType());
}
SavingProductType savingProductType = account.getSavingProductType();
if (command.isSavingProductTypeChanged()) {
savingProductType = SavingProductType.fromInt(command.getSavingProductType());
}
SavingFrequencyType savingFrequencyType = account.getFrequency();
if (command.isSavingFrequencyTypeChanged()) {
savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency());
}
SavingInterestCalculationMethod savingInterestCalculationMethod = account.getInterestCalculationMethod();
if (command.isSavingInterestCalculationMethodChanged()) {
savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
}
BigDecimal reccuringInterestRate = account.getReccuringInterestRate();
if (command.isReccuringInterestRateChanged()) {
reccuringInterestRate = command.getRecurringInterestRate();
}
BigDecimal savingInterestRate = account.getSavingInterestRate();
if (command.isSavingInterestRateChanged()) {
savingInterestRate = command.getSavingInterestRate();
}
boolean isLockinPeriodAllowed = account.isLockinPeriodAllowed();
if (command.isLockinPeriodAllowedChanged()) {
isLockinPeriodAllowed = command.isLockinPeriodAllowed();
}
Integer lockinPeriod = account.getLockinPeriod();
if (command.isLockinPeriodChanged()) {
lockinPeriod = command.getLockinPeriod();
}
PeriodFrequencyType lockinPeriodType = account.getLockinPeriodType();
if (command.isLockinPeriodTypeChanged()) {
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
}
account.modifyAccount(product, externalId, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure, commencementDate,
tenureTypeEnum, savingProductType, savingFrequencyType, savingInterestCalculationMethod, isLockinPeriodAllowed,
lockinPeriod, lockinPeriodType, this.reccuringDepositInterestCalculator);
}
private DepositLifecycleStateMachine defaultDepositLifecycleStateMachine() {
List<DepositAccountStatus> allowedDepositStatuses = Arrays.asList(DepositAccountStatus.values());
return new DepositLifecycleStateMachineImpl(allowedDepositStatuses);
}
}
@@ -0,0 +1,12 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import java.util.Collection;
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
public interface SavingAccountReadPlatformService {
Collection<SavingAccountData> retrieveAllSavingsAccounts();
SavingAccountData retrieveSavingsAccount(Long accountId);
}
@@ -0,0 +1,142 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSource;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingProductEnumerations;
import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountEnumerations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
@Service
public class SavingAccountReadPlatformServiceImpl implements SavingAccountReadPlatformService {
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
@Autowired
public SavingAccountReadPlatformServiceImpl(final PlatformSecurityContext context, final TenantAwareRoutingDataSource dataSource) {
this.context = context;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Collection<SavingAccountData> retrieveAllSavingsAccounts() {
this.context.authenticatedUser();
SavingAccountMapper mapper = new SavingAccountMapper();
String sql = "select " + mapper.schema() + " where sa.is_deleted=0";
return this.jdbcTemplate.query(sql, mapper, new Object[] {});
}
@Override
public SavingAccountData retrieveSavingsAccount(Long accountId) {
this.context.authenticatedUser();
SavingAccountMapper mapper = new SavingAccountMapper();
String sql = "select " + mapper.schema() + " where sa.id = ? and sa.is_deleted=0";
SavingAccountData savingAccountData = this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { accountId });
return savingAccountData;
}
private static final class SavingAccountMapper implements RowMapper<SavingAccountData> {
public String schema() {
return "sa.id AS id, sa.status_enum AS status, sa.external_id AS externalId,"
+ " sa.client_id AS clientId, sa.product_id AS productId, sa.deposit_amount_per_period AS savingsDepostiAmountPerPeriod,"
+ " sa.savings_product_type AS savingsProductType, sa.currency_code AS currencyCode, sa.currency_digits AS currencyDigits,"
+ " sa.total_deposit_amount AS totalDepositAmount, sa.reccuring_nominal_interest_rate AS reccuringInterestRate,"
+ " sa.regular_saving_nominal_interest_rate AS savingInterestRate, sa.tenure AS tenure, sa.tenure_type AS tenureType,"
+ " sa.frequency AS savingsFrequencyType, sa.interest_type AS interestType, sa.interest_calculation_method AS interestCalculationMethod,"
+ " sa.projected_commencement_date AS projectedCommencementDate, sa.actual_commencement_date AS actualCommencementDate,"
+ " sa.matures_on_date AS maturesOnDate, sa.projected_interest_accrued_on_maturity AS projectedInterestAccuredOnMaturity,"
+ " sa.actual_interest_accrued AS actualInterestAccured, sa.projected_total_maturity_amount AS projectedTotalMaturityAmount,"
+ " sa.actual_total_amount AS actualTotalAmount, sa.is_preclosure_allowed AS isPreclosureAllowed,"
+ " sa.pre_closure_interest_rate AS preClosureInterestRate, sa.is_lock_in_period_allowed AS isLockinPeriodAllowed,"
+ " sa.lock_in_period AS lockinPeriod, sa.lock_in_period_type AS lockinPeriodType, sa.withdrawnon_date AS withdrawnonDate,"
+ " sa.rejectedon_date AS rejectedonDate, sa.closedon_date AS closedonDate, ps.name AS productName,"
+ " c.firstname AS firstname, c.lastname AS lastname, curr.name AS currencyName, "
+ " curr.internationalized_name_code AS currencyNameCode, curr.display_symbol AS currencyDisplaySymbol "
+ " FROM m_saving_account sa " + " JOIN m_client c ON c.id = sa.client_id"
+ " JOIN m_currency curr ON curr.code = sa.currency_code " + " JOIN m_product_savings ps ON sa.product_id = ps.id ";
}
@Override
public SavingAccountData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
Long id = rs.getLong("id");
String externalId = rs.getString("externalId");
Long clientId = rs.getLong("clientId");
String clientName = rs.getString("firstname") + " " + rs.getString("lastname");
Long productId = rs.getLong("productId");
String productName = rs.getString("productName");
EnumOptionData productType = SavingProductEnumerations.savingProductType(JdbcSupport.getInteger(rs, "savingsProductType"));
Integer statusId = JdbcSupport.getInteger(rs, "status");
EnumOptionData status = DepositAccountEnumerations.status(statusId);
String currencyCode = rs.getString("currencyCode");
String currencyName = rs.getString("currencyName");
String currencyNameCode = rs.getString("currencyNameCode");
String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
CurrencyData currencyData = new CurrencyData(currencyCode, currencyName, currencyDigits, currencyDisplaySymbol,
currencyNameCode);
BigDecimal savingsDepostiAmountPerPeriod = rs.getBigDecimal("savingsDepostiAmountPerPeriod");
EnumOptionData savingsFrequencyType = SavingProductEnumerations.interestFrequencyType(JdbcSupport.getInteger(rs,
"savingsFrequencyType"));
BigDecimal totalDepositAmount = rs.getBigDecimal("totalDepositAmount");
BigDecimal reccuringInterestRate = rs.getBigDecimal("reccuringInterestRate");
BigDecimal savingInterestRate = rs.getBigDecimal("savingInterestRate");
EnumOptionData interestType = SavingProductEnumerations.savingInterestType(JdbcSupport.getInteger(rs, "interestType"));
EnumOptionData interestCalculationMethod = SavingProductEnumerations.savingInterestCalculationMethod(JdbcSupport.getInteger(rs,
"interestCalculationMethod"));
Integer tenure = JdbcSupport.getInteger(rs, "tenure");
EnumOptionData tenureType = SavingProductEnumerations.tenureTypeEnum(JdbcSupport.getInteger(rs, "tenureType"));
LocalDate projectedCommencementDate = JdbcSupport.getLocalDate(rs, "projectedCommencementDate");
LocalDate actualCommencementDate = JdbcSupport.getLocalDate(rs, "actualCommencementDate");
LocalDate maturesOnDate = JdbcSupport.getLocalDate(rs, "maturesOnDate");
BigDecimal projectedInterestAccuredOnMaturity = rs.getBigDecimal("projectedInterestAccuredOnMaturity");
BigDecimal actualInterestAccured = rs.getBigDecimal("actualInterestAccured");
BigDecimal projectedMaturityAmount = rs.getBigDecimal("projectedTotalMaturityAmount");
BigDecimal actualMaturityAmount = rs.getBigDecimal("actualTotalAmount");
boolean preClosureAllowed = rs.getBoolean("isPreclosureAllowed");
BigDecimal preClosureInterestRate = rs.getBigDecimal("preClosureInterestRate");
LocalDate withdrawnonDate = JdbcSupport.getLocalDate(rs, "withdrawnonDate");
LocalDate rejectedonDate = JdbcSupport.getLocalDate(rs, "rejectedonDate");
LocalDate closedonDate = JdbcSupport.getLocalDate(rs, "closedonDate");
boolean isLockinPeriodAllowed = rs.getBoolean("isLockinPeriodAllowed");
Integer lockinPeriod = JdbcSupport.getInteger(rs, "lockinPeriod");
Integer lockinPeriodTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodType");
EnumOptionData lockinPeriodType = SavingProductEnumerations.savingsLockinPeriod(lockinPeriodTypeValue);
return new SavingAccountData(id, status, externalId, clientId, clientName, productId, productName, productType, currencyData,
savingsDepostiAmountPerPeriod, savingsFrequencyType, totalDepositAmount, reccuringInterestRate, savingInterestRate,
interestType, interestCalculationMethod, tenure, tenureType, projectedCommencementDate, actualCommencementDate,
maturesOnDate, projectedInterestAccuredOnMaturity, actualInterestAccured, projectedMaturityAmount,
actualMaturityAmount, preClosureAllowed, preClosureInterestRate, withdrawnonDate, rejectedonDate, closedonDate,
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType);
}
}
}
@@ -0,0 +1,14 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
import org.springframework.security.access.prepost.PreAuthorize;
public interface SavingAccountWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'CREATE_SAVINGSACCOUNT')")
EntityIdentifier createSavingAccount(SavingAccountCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'UPDATE_SAVINGSACCOUNT')")
EntityIdentifier updateSavingAccount(SavingAccountCommand command);
}
@@ -0,0 +1,94 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommandValidator;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccount;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccountRepository;
import org.mifosplatform.portfolio.savingsaccount.exception.SavingAccountNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class SavingAccountWritePlatformServiceJpaRepositoryImpl implements SavingAccountWritePlatformService {
private final static Logger logger = LoggerFactory.getLogger(SavingAccountWritePlatformServiceJpaRepositoryImpl.class);
private final PlatformSecurityContext context;
private final SavingAccountRepository savingAccountRepository;
private final SavingAccountAssembler savingAccountAssembler;
@SuppressWarnings("unused")
private final NoteRepository noteRepository;
@Autowired
public SavingAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final SavingAccountRepository savingAccountRepository, final SavingAccountAssembler savingAccountAssembler,
final NoteRepository noteRepository) {
this.context = context;
this.savingAccountRepository = savingAccountRepository;
this.savingAccountAssembler = savingAccountAssembler;
this.noteRepository = noteRepository;
}
@Transactional
@Override
public EntityIdentifier createSavingAccount(final SavingAccountCommand command) {
try {
this.context.authenticatedUser();
SavingAccountCommandValidator validator = new SavingAccountCommandValidator(command);
validator.validateForCreate();
SavingAccount account = this.savingAccountAssembler.assembleFrom(command);
this.savingAccountRepository.save(account);
return new EntityIdentifier(account.getId());
} catch (DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return new EntityIdentifier(Long.valueOf(-1));
}
}
@Override
public EntityIdentifier updateSavingAccount(final SavingAccountCommand command) {
try {
this.context.authenticatedUser();
SavingAccountCommandValidator validator = new SavingAccountCommandValidator(command);
validator.validateForUpdate();
SavingAccount account = this.savingAccountRepository.findOne(command.getId());
if (account == null || account.isDeleted()) { throw new SavingAccountNotFoundException(command.getId()); }
if (account.isPendingApproval()) {
this.savingAccountAssembler.assembleFrom(command, account);
this.savingAccountRepository.save(account);
}
return new EntityIdentifier(account.getId());
} catch (DataIntegrityViolationException dve) {
handleDataIntegrityIssues(command, dve);
return new EntityIdentifier(Long.valueOf(-1));
}
}
/*
* Guaranteed to throw an exception no matter what the data integrity issue
* is.
*/
private void handleDataIntegrityIssues(final SavingAccountCommand command, final DataIntegrityViolationException dve) {
Throwable realCause = dve.getMostSpecificCause();
if (realCause.getMessage().contains("saving_acc_external_id")) { throw new PlatformDataIntegrityException(
"error.msg.saving.account.duplicate.externalId", "Saving account with externalId " + command.getExternalId()
+ " already exists", "externalId", command.getExternalId()); }
logger.error(dve.getMessage(), dve);
throw new PlatformDataIntegrityException("error.msg.saving.account.unknown.data.integrity.issue",
"Unknown data integrity issue with resource.");
}
}
@@ -1,4 +1,4 @@
package org.mifosng.platform.api;
package org.mifosplatform.portfolio.savingsaccountproduct.api;
import java.util.Arrays;
import java.util.Collection;
@@ -19,17 +19,6 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosng.platform.api.data.SavingProductData;
import org.mifosng.platform.savingproduct.domain.SavingFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod;
import org.mifosng.platform.savingproduct.domain.SavingProductType;
import org.mifosng.platform.savingproduct.domain.SavingsInterestType;
import org.mifosng.platform.savingproduct.domain.SavingsLockinPeriodEnum;
import org.mifosng.platform.savingproduct.domain.TenureTypeEnum;
import org.mifosng.platform.savingproduct.service.SavingProductEnumerations;
import org.mifosng.platform.savingproduct.service.SavingProductReadPlatformService;
import org.mifosng.platform.savingproduct.service.SavingProductWritePlatformService;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.service.CurrencyReadPlatformService;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
@@ -38,6 +27,17 @@ import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerServi
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsInterestType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsLockinPeriodEnum;
import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingProductEnumerations;
import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingProductReadPlatformService;
import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingProductWritePlatformService;
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@@ -1,4 +1,4 @@
package org.mifosng.platform.api.commands;
package org.mifosplatform.portfolio.savingsaccountproduct.command;
import java.math.BigDecimal;
import java.util.Set;
@@ -1,4 +1,4 @@
package org.mifosng.platform.api.data;
package org.mifosplatform.portfolio.savingsaccountproduct.data;
import java.io.Serializable;
import java.math.BigDecimal;
@@ -1,4 +1,4 @@
package org.mifosng.platform.api.data;
package org.mifosplatform.portfolio.savingsaccountproduct.data;
import java.io.Serializable;
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.domain;
package org.mifosplatform.portfolio.savingsaccountproduct.domain;
public enum SavingFrequencyType {
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.domain;
package org.mifosplatform.portfolio.savingsaccountproduct.domain;
public enum SavingInterestCalculationMethod {
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.domain;
package org.mifosplatform.portfolio.savingsaccountproduct.domain;
import java.math.BigDecimal;
@@ -8,11 +8,12 @@ import javax.persistence.Entity;
import javax.persistence.Table;
import org.apache.commons.lang.StringUtils;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
@Entity
@Table(name = "m_product_savings")
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.domain;
package org.mifosplatform.portfolio.savingsaccountproduct.domain;
import java.math.BigDecimal;
@@ -6,9 +6,10 @@ import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
@Embeddable
public class SavingProductRelatedDetail {
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.domain;
package org.mifosplatform.portfolio.savingsaccountproduct.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.domain;
package org.mifosplatform.portfolio.savingsaccountproduct.domain;
public enum SavingProductType {
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.domain;
package org.mifosplatform.portfolio.savingsaccountproduct.domain;
public enum SavingsInterestType {
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.domain;
package org.mifosplatform.portfolio.savingsaccountproduct.domain;
public enum SavingsLockinPeriodEnum {
@@ -1,4 +1,4 @@
package org.mifosng.platform.exceptions;
package org.mifosplatform.portfolio.savingsaccountproduct.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
@@ -1,4 +1,4 @@
package org.mifosng.platform.exceptions;
package org.mifosplatform.portfolio.savingsaccountproduct.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
@@ -1,12 +1,12 @@
package org.mifosng.platform.savingproduct.service;
package org.mifosplatform.portfolio.savingsaccountproduct.service;
import java.util.ArrayList;
import java.util.List;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
public class SavingProductCommandValidator {
@@ -1,12 +1,12 @@
package org.mifosng.platform.savingproduct.service;
package org.mifosplatform.portfolio.savingsaccountproduct.service;
import org.mifosng.platform.savingproduct.domain.SavingFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod;
import org.mifosng.platform.savingproduct.domain.SavingProductType;
import org.mifosng.platform.savingproduct.domain.SavingsInterestType;
import org.mifosng.platform.savingproduct.domain.SavingsLockinPeriodEnum;
import org.mifosng.platform.savingproduct.domain.TenureTypeEnum;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsInterestType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsLockinPeriodEnum;
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
public class SavingProductEnumerations {
@@ -1,9 +1,9 @@
package org.mifosng.platform.savingproduct.service;
package org.mifosplatform.portfolio.savingsaccountproduct.service;
import java.util.Collection;
import org.mifosng.platform.api.data.SavingProductData;
import org.mifosng.platform.api.data.SavingProductLookup;
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData;
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductLookup;
public interface SavingProductReadPlatformService {
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.service;
package org.mifosplatform.portfolio.savingsaccountproduct.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
@@ -7,9 +7,6 @@ import java.util.Collection;
import java.util.List;
import org.joda.time.DateTime;
import org.mifosng.platform.api.data.SavingProductData;
import org.mifosng.platform.api.data.SavingProductLookup;
import org.mifosng.platform.savingproduct.domain.SavingProductType;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.configuration.service.CurrencyReadPlatformService;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
@@ -18,6 +15,9 @@ import org.mifosplatform.infrastructure.core.service.TenantAwareRoutingDataSourc
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundException;
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData;
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductLookup;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
@@ -1,7 +1,7 @@
package org.mifosng.platform.savingproduct.service;
package org.mifosplatform.portfolio.savingsaccountproduct.service;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
import org.springframework.security.access.prepost.PreAuthorize;
public interface SavingProductWritePlatformService {
@@ -1,19 +1,19 @@
package org.mifosng.platform.savingproduct.service;
package org.mifosplatform.portfolio.savingsaccountproduct.service;
import org.mifosng.platform.api.commands.SavingProductCommand;
import org.mifosng.platform.exceptions.SavingsProductNotFoundException;
import org.mifosng.platform.exceptions.SavingProductNotFoundException;
import org.mifosng.platform.savingproduct.domain.SavingFrequencyType;
import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod;
import org.mifosng.platform.savingproduct.domain.SavingProduct;
import org.mifosng.platform.savingproduct.domain.SavingProductRepository;
import org.mifosng.platform.savingproduct.domain.SavingProductType;
import org.mifosng.platform.savingproduct.domain.SavingsInterestType;
import org.mifosng.platform.savingproduct.domain.TenureTypeEnum;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductRepository;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsInterestType;
import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingProductNotFoundException;
import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingsProductNotFoundException;
import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -1,4 +1,4 @@
package org.mifosng.platform.savingproduct.service;
package org.mifosplatform.portfolio.savingsaccountproduct.service;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
@@ -0,0 +1,261 @@
package org.mifosplatform.portfolio.savingsdepositaccount.api;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.api.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService;
import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingsDepositEnumerations;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawInterestCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositPermissionData;
import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountReadPlatformService;
import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountWritePlatformService;
import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductLookup;
import org.mifosplatform.portfolio.savingsdepositproduct.service.DepositProductReadPlatformService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Path("/depositaccounts")
@Component
@Scope("singleton")
public class DepositAccountsApiResource {
@Autowired
private DepositAccountReadPlatformService depositAccountReadPlatformService;
@Autowired
private DepositProductReadPlatformService depositProductReadPlatformService;
@Autowired
private DepositAccountWritePlatformService depositAccountWritePlatformService;
@Autowired
private PortfolioApiDataConversionService apiDataConversionService;
@Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService;
private final String entityType = "DEPOSITACCOUNT";
@Autowired
private PlatformSecurityContext context;
private static final Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "externalId", "clientId",
"clientName", "productId", "productName", "status", "currency", "deposit", "maturityInterestRate", "tenureInMonths",
"interestCompoundedEvery", "interestCompoundingAllowed", "interestCompoundedEveryPeriodType", "renewalAllowed",
"preClosureAllowed", "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "transactions",
"interestPaid", "isInterestWithdrawable", "availableInterestForWithdrawal", "availableWithdrawalAmount", "todaysDate",
"isLockinPeriodAllowed", "lockinPeriod", "lockinPeriodType"));
@POST
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response createDepositAccount(final String jsonRequestBody) {
final DepositAccountCommand command = this.apiDataConversionService.convertJsonToDepositAccountCommand(null, jsonRequestBody);
EntityIdentifier entityIdentifier = this.depositAccountWritePlatformService.createDepositAccount(command);
return Response.ok().entity(entityIdentifier).build();
}
@PUT
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response updateDepositAccount(@PathParam("accountId") final Long accountId, final String jsonRequestBody) {
final DepositAccountCommand command = this.apiDataConversionService.convertJsonToDepositAccountCommand(accountId, jsonRequestBody);
EntityIdentifier entityIdentifier = this.depositAccountWritePlatformService.updateDepositAccount(command);
return Response.ok().entity(entityIdentifier).build();
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveAllDepositAccounts(@Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
Collection<DepositAccountData> accounts = this.depositAccountReadPlatformService.retrieveAllDepositAccounts();
return this.apiJsonSerializerService.serializeDepositAccountDataToJson(prettyPrint, responseParameters, accounts);
}
@GET
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveDepositAccount(@PathParam("accountId") final Long accountId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
DepositPermissionData permissions = null;
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
DepositAccountData account = this.depositAccountReadPlatformService.retrieveDepositAccount(accountId);
boolean template = ApiParameterHelper.template(uriInfo.getQueryParameters());
if (template) {
account = handleTemplateRelatedData(responseParameters, account);
}
Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
if (!associationParameters.isEmpty()) {
if (associationParameters.contains("all")) {
responseParameters.addAll(Arrays.asList("permissions"));
} else {
responseParameters.addAll(associationParameters);
}
permissions = this.depositAccountReadPlatformService.retrieveDepositAccountsPermissions(account);
account = new DepositAccountData(account, permissions, account.getTransactions());
}
return this.apiJsonSerializerService.serializeDepositAccountDataToJson(prettyPrint, responseParameters, account);
}
@GET
@Path("template")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public String retrieveNewDepositAccountDetails(@QueryParam("clientId") final Long clientId,
@QueryParam("productId") final Long productId, @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(entityType);
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
DepositAccountData account = this.depositAccountReadPlatformService.retrieveNewDepositAccountDetails(clientId, productId);
account = handleTemplateRelatedData(responseParameters, account);
return this.apiJsonSerializerService.serializeDepositAccountDataToJson(prettyPrint, responseParameters, account);
}
@DELETE
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response deleteProduct(@PathParam("accountId") final Long accountId) {
this.depositAccountWritePlatformService.deleteDepositAccount(accountId);
return Response.ok(new EntityIdentifier(accountId)).build();
}
private DepositAccountData handleTemplateRelatedData(final Set<String> responseParameters, final DepositAccountData account) {
responseParameters.addAll(Arrays.asList("interestCompoundedEveryPeriodTypeOptions", "productOptions"));
Collection<DepositProductLookup> productOptions = depositProductReadPlatformService.retrieveAllDepositProductsForLookup();
EnumOptionData monthly = SavingsDepositEnumerations.interestCompoundingPeriodType(PeriodFrequencyType.MONTHS);
List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions = Arrays.asList(monthly);
return new DepositAccountData(account, interestCompoundedEveryPeriodTypeOptions, productOptions);
}
@POST
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response SubmitDepositApplication(@PathParam("accountId") final Long accountId,
@QueryParam("command") final String commandParam, final String jsonRequestBody) {
Response response = null;
if (is(commandParam, "approve")) {
DepositStateTransitionApprovalCommand command = apiDataConversionService.convertJsonToDepositStateTransitionApprovalCommand(
accountId, jsonRequestBody);
EntityIdentifier identifier = this.depositAccountWritePlatformService.approveDepositApplication(command);
response = Response.ok().entity(identifier).build();
} else if (is(commandParam, "withdrawal")) {
DepositAccountWithdrawalCommand command = apiDataConversionService.convertJsonToDepositWithdrawalCommand(accountId,
jsonRequestBody);
EntityIdentifier identifier = this.depositAccountWritePlatformService.withdrawDepositAccountMoney(command);
response = Response.ok().entity(identifier).build();
} else if (is(commandParam, "interestwithdraw")) {
DepositAccountWithdrawInterestCommand command = apiDataConversionService.convertJsonToDepositAccountWithdrawInterestCommand(
accountId, jsonRequestBody);
EntityIdentifier identifier = this.depositAccountWritePlatformService.withdrawDepositAccountInterestMoney(command);
response = Response.ok().entity(identifier).build();
} else if (is(commandParam, "renew")) {
DepositAccountCommand command = apiDataConversionService.convertJsonToDepositAccountCommand(accountId, jsonRequestBody);
EntityIdentifier entityIdentifier = this.depositAccountWritePlatformService.renewDepositAccount(command);
return Response.ok().entity(entityIdentifier).build();
} else {
DepositStateTransitionCommand command = apiDataConversionService.convertJsonToDepositStateTransitionCommand(accountId,
jsonRequestBody);
if (is(commandParam, "reject")) {
EntityIdentifier identifier = this.depositAccountWritePlatformService.rejectDepositApplication(command);
response = Response.ok().entity(identifier).build();
} else if (is(commandParam, "withdrewbyclient")) {
EntityIdentifier identifier = this.depositAccountWritePlatformService.withdrawDepositApplication(command);
response = Response.ok().entity(identifier).build();
}
UndoStateTransitionCommand undoCommand = new UndoStateTransitionCommand(accountId, command.getNote());
if (is(commandParam, "undoapproval")) {
EntityIdentifier identifier = this.depositAccountWritePlatformService.undoDepositApproval(undoCommand);
response = Response.ok().entity(identifier).build();
}
}
if (response == null) { throw new UnrecognizedQueryParamException("command", commandParam); }
return response;
}
private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
}
}
@@ -0,0 +1,195 @@
package org.mifosplatform.portfolio.savingsdepositaccount.command;
import java.math.BigDecimal;
import java.util.Set;
import org.joda.time.LocalDate;
/**
* Immutable command used when create/renewing deposit accounts
*/
public class DepositAccountCommand {
private final Long id;
private final Long clientId;
private final Long productId;
private final String externalId;
private final BigDecimal depositAmount;
private final BigDecimal maturityInterestRate;
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;
private final boolean renewalAllowed;
private final boolean preClosureAllowed;
private final boolean isInterestWithdrawable;
private final boolean interestCompoundingAllowed;
private final Set<String> modifiedParameters;
public DepositAccountCommand(final Set<String> modifiedParameters, final Long id, final Long clientId, final Long productId,
final String externalId, 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 isLockinPeriodAllowed, final Integer lockInPeriod, final Integer lockinPeriodType) {
this.id = id;
this.clientId = clientId;
this.productId = productId;
this.externalId = externalId;
this.depositAmount = depositAmount;
this.maturityInterestRate = interestRate;
this.preClosureInterestRate = preClosureInterestRate;
this.tenureInMonths = tenureInMonths;
this.modifiedParameters = modifiedParameters;
this.interestCompoundedEvery = compoundingInterestFrequency;
this.interestCompoundedEveryPeriodType = compoundingInterestFrequencyType;
this.commencementDate = commencementDate;
this.renewalAllowed = renewalAllowed;
this.preClosureAllowed = preClosureAllowed;
this.isInterestWithdrawable = isInterstWithdrawable;
this.interestCompoundingAllowed = interestCompoundingAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockInPeriod;
this.lockinPeriodType = lockinPeriodType;
}
public Long getId() {
return id;
}
public Long getClientId() {
return clientId;
}
public Long getProductId() {
return productId;
}
public String getExternalId() {
return externalId;
}
public BigDecimal getDepositAmount() {
return depositAmount;
}
public BigDecimal getMaturityInterestRate() {
return maturityInterestRate;
}
public BigDecimal getPreClosureInterestRate() {
return preClosureInterestRate;
}
public Integer getTenureInMonths() {
return tenureInMonths;
}
public Integer getInterestCompoundedEvery() {
return interestCompoundedEvery;
}
public Integer getInterestCompoundedEveryPeriodType() {
return interestCompoundedEveryPeriodType;
}
public LocalDate getCommencementDate() {
return commencementDate;
}
public boolean isInterestWithdrawable() {
return isInterestWithdrawable;
}
public boolean isRenewalAllowed() {
return renewalAllowed;
}
public boolean isPreClosureAllowed() {
return preClosureAllowed;
}
public boolean isInterestCompoundingAllowed() {
return interestCompoundingAllowed;
}
public boolean isLockinPeriodAllowed() {
return isLockinPeriodAllowed;
}
public Integer getLockinPeriod() {
return lockinPeriod;
}
public Integer getLockinPeriodType() {
return lockinPeriodType;
}
public boolean isNoFieldChanged() {
return this.modifiedParameters.isEmpty();
}
public boolean isExternalIdChanged() {
return this.modifiedParameters.contains("externalId");
}
public boolean isDepositAmountChanged() {
return this.modifiedParameters.contains("deposit");
}
public boolean isTenureInMonthsChanged() {
return this.modifiedParameters.contains("tenureInMonths");
}
public boolean isLockinPeriodChanged() {
return this.modifiedParameters.contains("lockinPeriod");
}
public boolean isMaturityActualInterestRateChanged() {
return this.modifiedParameters.contains("maturityInterestRate");
}
public boolean isPreClosureInterestRateChanged() {
return this.modifiedParameters.contains("preClosureInterestRate");
}
public boolean isCompoundingInterestEveryChanged() {
return this.modifiedParameters.contains("interestCompoundedEvery");
}
public boolean isInterestCompoundedEveryPeriodTypeChaged() {
return this.modifiedParameters.contains("interestCompoundedEveryPeriodType");
}
public boolean isRenewalAllowedChanged() {
return this.modifiedParameters.contains("renewalAllowed");
}
public boolean isPreClosureAllowedChanged() {
return this.modifiedParameters.contains("preClosureAllowed");
}
public boolean isInterestWithdrawableChanged() {
return this.modifiedParameters.contains("isInterestWithdrawable");
}
public boolean isInterestCompoundingAllowedChanged() {
return this.modifiedParameters.contains("interestCompoundingAllowed");
}
public boolean isCommencementDateChanged() {
return this.modifiedParameters.contains("commencementDate");
}
}
@@ -0,0 +1,80 @@
package org.mifosplatform.portfolio.savingsdepositaccount.command;
import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class DepositAccountCommandValidator {
private final DepositAccountCommand command;
public DepositAccountCommandValidator(final DepositAccountCommand command) {
this.command = command;
}
public void validateForUpdate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.account");
baseDataValidator.reset().parameter("id").value(command.getId()).notNull();
baseDataValidator.reset().parameter("clientId").value(command.getClientId()).ignoreIfNull().notNull();
baseDataValidator.reset().parameter("productId").value(command.getProductId()).ignoreIfNull().notNull();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
baseDataValidator.reset().parameter("deposit").value(command.getDepositAmount()).ignoreIfNull().notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("maturityInterestRate").value(command.getMaturityInterestRate()).ignoreIfNull().notNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("tenureInMonths").value(command.getTenureInMonths()).ignoreIfNull().notNull()
.integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEvery").value(command.getInterestCompoundedEvery()).ignoreIfNull()
.integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType())
.ignoreIfNull().inMinMaxRange(2, 2);
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).ignoreIfNull();
if (command.isNoFieldChanged()) {
StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append("deposit.account").append(
".no.parameters.for.update");
StringBuilder defaultEnglishMessage = new StringBuilder("No parameters passed for update.");
ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(),
"id");
dataValidationErrors.add(error);
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
public void validateForCreate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.account");
baseDataValidator.reset().parameter("clientId").value(command.getClientId()).notNull();
baseDataValidator.reset().parameter("productId").value(command.getProductId()).notNull();
baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100);
baseDataValidator.reset().parameter("deposit").value(command.getDepositAmount()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("maturityInterestRate").value(command.getMaturityInterestRate()).ignoreIfNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("preClosureInterestRate").value(command.getPreClosureInterestRate()).ignoreIfNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("tenureInMonths").value(command.getTenureInMonths()).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEvery").value(command.getInterestCompoundedEvery()).ignoreIfNull()
.integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType())
.ignoreIfNull().inMinMaxRange(2, 2);
baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).notNull();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -0,0 +1,28 @@
package org.mifosplatform.portfolio.savingsdepositaccount.command;
import java.math.BigDecimal;
public class DepositAccountWithdrawInterestCommand {
private final Long accountId;
private final BigDecimal withdrawInterest;
private final String note;
public DepositAccountWithdrawInterestCommand(final Long accountId, BigDecimal withdrawInterest, String note) {
this.accountId = accountId;
this.withdrawInterest = withdrawInterest;
this.note = note;
}
public Long getAccountId() {
return accountId;
}
public BigDecimal getWithdrawInterest() {
return withdrawInterest;
}
public String getNote() {
return note;
}
}
@@ -0,0 +1,28 @@
package org.mifosplatform.portfolio.savingsdepositaccount.command;
import org.joda.time.LocalDate;
public class DepositAccountWithdrawalCommand {
private final Long accountId;
private final String note;
private final LocalDate maturesOnDate;
public DepositAccountWithdrawalCommand(final Long accountId, final String note, final LocalDate maturesOnDate) {
this.accountId = accountId;
this.note = note;
this.maturesOnDate = maturesOnDate;
}
public Long getAccountId() {
return accountId;
}
public String getNote() {
return note;
}
public LocalDate getMaturesOnDate() {
return maturesOnDate;
}
}
@@ -0,0 +1,30 @@
package org.mifosplatform.portfolio.savingsdepositaccount.command;
import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class DepositAccountWithdrawalCommandValidator {
private final DepositAccountWithdrawalCommand command;
public DepositAccountWithdrawalCommandValidator(final DepositAccountWithdrawalCommand command) {
this.command = command;
}
public void validate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.transaction");
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("note").value(command.getNote()).notNull();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -0,0 +1,72 @@
package org.mifosplatform.portfolio.savingsdepositaccount.command;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
public class DepositStateTransitionApprovalCommand {
private final Long accountId;
private final Long productId;
private final LocalDate eventDate;
private final BigDecimal depositAmount;
private final BigDecimal maturityInterestRate;
private final Integer tenureInMonths;
private final Integer interestCompoundedEveryPeriodType;
private final Integer interestCompoundedEvery;
private final String note;
public DepositStateTransitionApprovalCommand(final Long resourceIdentifier, final Long productId, final LocalDate eventDate,
final Integer tenureInMonths, final BigDecimal depositAmount, final Integer interestCompoundedEveryPeriodType,
final Integer interestCompoundedEvery, final String note, final BigDecimal maturityInterestRate) {
this.accountId = resourceIdentifier;
this.eventDate = eventDate;
this.depositAmount = depositAmount;
this.maturityInterestRate = maturityInterestRate;
this.tenureInMonths = tenureInMonths;
this.interestCompoundedEveryPeriodType = interestCompoundedEveryPeriodType;
this.productId = productId;
this.interestCompoundedEvery = interestCompoundedEvery;
this.note = note;
}
public Long getAccountId() {
return accountId;
}
public LocalDate getEventDate() {
return eventDate;
}
public BigDecimal getDepositAmount() {
return depositAmount;
}
public BigDecimal getMaturityInterestRate() {
return maturityInterestRate;
}
public Integer getTenureInMonths() {
return tenureInMonths;
}
public Integer getInterestCompoundedEveryPeriodType() {
return interestCompoundedEveryPeriodType;
}
public Long getProductId() {
return productId;
}
public Integer getInterestCompoundedEvery() {
return interestCompoundedEvery;
}
public String getNote() {
return note;
}
}
@@ -0,0 +1,37 @@
package org.mifosplatform.portfolio.savingsdepositaccount.command;
import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class DepositStateTransitionApprovalCommandValidator {
private final DepositStateTransitionApprovalCommand command;
public DepositStateTransitionApprovalCommandValidator(final DepositStateTransitionApprovalCommand command) {
this.command = command;
}
public void validate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.transition");
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("commencementDate").value(command.getEventDate()).notNull();
baseDataValidator.reset().parameter("deposit").value(command.getDepositAmount()).ignoreIfNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("maturityInterestRate").value(command.getMaturityInterestRate()).ignoreIfNull()
.zeroOrPositiveAmount();
baseDataValidator.reset().parameter("tenureInMonths").value(command.getTenureInMonths()).ignoreIfNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("interestCompoundedEveryPeriodType").value(command.getInterestCompoundedEveryPeriodType())
.ignoreIfNull().inMinMaxRange(2, 2);
baseDataValidator.reset().parameter("note").value(command.getNote()).notNull();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -0,0 +1,30 @@
package org.mifosplatform.portfolio.savingsdepositaccount.command;
import org.joda.time.LocalDate;
public class DepositStateTransitionCommand {
private final Long accountId;
private final LocalDate eventDate;
private final String note;
public DepositStateTransitionCommand(final Long accountId, final LocalDate enentDate, final String note) {
this.accountId = accountId;
this.eventDate = enentDate;
this.note = note;
}
public Long getAccountId() {
return accountId;
}
public LocalDate getEventDate() {
return eventDate;
}
public String getNote() {
return note;
}
}
@@ -0,0 +1,30 @@
package org.mifosplatform.portfolio.savingsdepositaccount.command;
import java.util.ArrayList;
import java.util.List;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
public class WithDrawDepositAccountInterestCommandValidator {
private final DepositAccountWithdrawInterestCommand command;
public WithDrawDepositAccountInterestCommandValidator(final DepositAccountWithdrawInterestCommand command) {
this.command = command;
}
public void validate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("deposit.transaction");
baseDataValidator.reset().parameter("accountId").value(command.getAccountId()).notNull().integerGreaterThanZero();
baseDataValidator.reset().parameter("amount").value(command.getWithdrawInterest()).notNull().zeroOrPositiveAmount();
baseDataValidator.reset().parameter("note").value(command.getNote()).notNull();
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -0,0 +1,544 @@
package org.mifosplatform.portfolio.savingsdepositaccount.data;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
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;
import org.mifosplatform.infrastructure.configuration.data.CurrencyData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductLookup;
/**
* Immutable data object for deposit accounts.
*/
public class DepositAccountData {
private final Long id;
private final String externalId;
private final EnumOptionData status;
private final Long clientId;
private final String clientName;
private final Long productId;
private final String productName;
private final CurrencyData currency;
private final BigDecimal deposit;
private final BigDecimal maturityInterestRate;
private final Integer tenureInMonths;
private final LocalDate projectedCommencementDate;
private final LocalDate actualCommencementDate;
private final LocalDate maturedOn;
private final LocalDate withdrawnonDate;
private final LocalDate rejectedonDate;
private final LocalDate closedonDate;
private final BigDecimal projectedInterestAccrued;
private final BigDecimal actualInterestAccrued;
private final BigDecimal projectedMaturityAmount;
private final BigDecimal actualMaturityAmount;
private final Integer interestCompoundedEvery;
private final EnumOptionData interestCompoundedEveryPeriodType;
private final boolean renewalAllowed;
private final boolean preClosureAllowed;
private final BigDecimal preClosureInterestRate;
private final boolean isInterestWithdrawable;
private final BigDecimal interestPaid;
private final boolean interestCompoundingAllowed;
private final List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions;
private final List<DepositProductLookup> productOptions;
private final Collection<DepositAccountTransactionData> transactions;
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.
*/
public static DepositAccountData createFrom(final Long clientId, final String clientDisplayName) {
return new DepositAccountData(clientId, clientDisplayName);
}
private DepositAccountData(final Long clientId, final String clientName) {
this.id = null;
this.externalId = null;
this.status = null;
this.clientId = clientId;
this.clientName = clientName;
this.productId = null;
this.productName = null;
this.currency = null;
this.deposit = null;
this.maturityInterestRate = null;
this.tenureInMonths = null;
this.projectedCommencementDate = null;
this.actualCommencementDate = null;
this.maturedOn = null;
this.projectedInterestAccrued = null;
this.actualInterestAccrued = null;
this.projectedMaturityAmount = null;
this.actualMaturityAmount = null;
this.interestCompoundedEvery = null;
this.interestCompoundedEveryPeriodType = null;
this.renewalAllowed = false;
this.preClosureAllowed = false;
this.preClosureInterestRate = null;
this.interestCompoundedEveryPeriodTypeOptions = new ArrayList<EnumOptionData>();
this.productOptions = new ArrayList<DepositProductLookup>();
this.withdrawnonDate = null;
this.closedonDate = null;
this.rejectedonDate = null;
this.transactions = null;
this.permissions = null;
this.interestPaid = null;
this.isInterestWithdrawable = false;
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(final DepositAccountData account, final List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions,
final Collection<DepositProductLookup> productOptions) {
this.id = account.getId();
this.externalId = account.getExternalId();
this.status = account.getStatus();
this.clientId = account.getClientId();
this.clientName = account.getClientName();
this.productId = account.getProductId();
this.productName = account.getProductName();
this.currency = account.getCurrency();
this.deposit = account.getDeposit();
this.maturityInterestRate = account.getMaturityInterestRate();
this.tenureInMonths = account.getTenureInMonths();
this.projectedCommencementDate = account.getProjectedCommencementDate();
this.actualCommencementDate = account.getActualCommencementDate();
this.maturedOn = account.getMaturedOn();
this.projectedInterestAccrued = account.getProjectedInterestAccrued();
this.actualInterestAccrued = account.getActualInterestAccrued();
this.projectedMaturityAmount = account.getProjectedMaturityAmount();
this.actualMaturityAmount = account.getActualMaturityAmount();
this.interestCompoundedEvery = account.getInterestCompoundedEvery();
this.interestCompoundedEveryPeriodType = account.getInterestCompoundedEveryPeriodType();
this.renewalAllowed = account.isRenewalAllowed();
this.preClosureAllowed = account.isPreClosureAllowed();
this.preClosureInterestRate = account.getPreClosureInterestRate();
this.interestCompoundedEveryPeriodTypeOptions = interestCompoundedEveryPeriodTypeOptions;
this.productOptions = new ArrayList<DepositProductLookup>(productOptions);
this.withdrawnonDate = account.getWithdrawnonDate();
this.rejectedonDate = account.getRejectedonDate();
this.closedonDate = account.getClosedonDate();
this.transactions = account.getTransactions();
this.permissions = account.getPermissions();
this.interestPaid = account.getInterestPaid();
this.isInterestWithdrawable = account.isInterestWithdrawable();
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) {
this.id = account.getId();
this.externalId = account.getExternalId();
this.status = account.getStatus();
this.clientId = account.getClientId();
this.clientName = account.getClientName();
this.productId = account.getProductId();
this.productName = account.getProductName();
this.currency = account.getCurrency();
this.deposit = account.getDeposit();
this.maturityInterestRate = account.getMaturityInterestRate();
this.tenureInMonths = account.getTenureInMonths();
this.projectedCommencementDate = account.getProjectedCommencementDate();
this.actualCommencementDate = account.getActualCommencementDate();
this.maturedOn = account.getMaturedOn();
this.projectedInterestAccrued = account.getProjectedInterestAccrued();
this.actualInterestAccrued = account.getActualInterestAccrued();
this.projectedMaturityAmount = account.getProjectedMaturityAmount();
this.actualMaturityAmount = account.getActualMaturityAmount();
this.interestCompoundedEvery = account.getInterestCompoundedEvery();
this.interestCompoundedEveryPeriodType = account.getInterestCompoundedEveryPeriodType();
this.renewalAllowed = account.isRenewalAllowed();
this.preClosureAllowed = account.isPreClosureAllowed();
this.preClosureInterestRate = account.getPreClosureInterestRate();
this.interestCompoundedEveryPeriodTypeOptions = account.getInterestCompoundedEveryPeriodTypeOptions();
this.productOptions = account.getProductOptions();
this.withdrawnonDate = account.getWithdrawnonDate();
this.rejectedonDate = account.getRejectedonDate();
this.closedonDate = account.getClosedonDate();
this.transactions = transactions;
this.permissions = permissions;
this.interestPaid = account.getInterestPaid();
this.isInterestWithdrawable = account.isInterestWithdrawable();
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 Long id, final String externalId, final EnumOptionData status, final Long clientId,
final String clientName, final Long productId, final String productName, final CurrencyData currency, final BigDecimal deposit,
final BigDecimal interestRate, final Integer tenureInMonths, final LocalDate projectedCommencementDate,
final LocalDate actualCommencementDate, final LocalDate maturedOn, final BigDecimal projectedInterestAccrued,
final BigDecimal actualInterestAccrued, final BigDecimal projectedMaturityAmount, final BigDecimal actualMaturityAmount,
final Integer interestCompoundedEvery, final EnumOptionData interestCompoundedEveryPeriodType, final boolean renewalAllowed,
final boolean preClosureAllowed, final BigDecimal preClosureInterestRate, final LocalDate withdrawnonDate,
final LocalDate rejectedonDate, final LocalDate closedonDate, final boolean isInterestWithdrawable,
final BigDecimal interestPaid, final boolean interestCompoundingAllowed, final boolean isLockinPeriodAllowed,
final Integer lockinPeriod, final EnumOptionData lockinPeriodType) {
this.id = id;
this.externalId = externalId;
this.status = status;
this.clientId = clientId;
this.clientName = clientName;
this.productId = productId;
this.productName = productName;
this.currency = currency;
this.deposit = deposit;
this.maturityInterestRate = interestRate;
this.tenureInMonths = tenureInMonths;
this.projectedCommencementDate = projectedCommencementDate;
this.actualCommencementDate = actualCommencementDate;
this.maturedOn = maturedOn;
this.projectedInterestAccrued = projectedInterestAccrued;
this.actualInterestAccrued = actualInterestAccrued;
this.projectedMaturityAmount = projectedMaturityAmount;
this.actualMaturityAmount = actualMaturityAmount;
this.interestCompoundedEvery = interestCompoundedEvery;
this.interestCompoundedEveryPeriodType = interestCompoundedEveryPeriodType;
this.renewalAllowed = renewalAllowed;
this.preClosureAllowed = preClosureAllowed;
this.preClosureInterestRate = preClosureInterestRate;
this.interestCompoundedEveryPeriodTypeOptions = new ArrayList<EnumOptionData>();
this.productOptions = new ArrayList<DepositProductLookup>();
this.withdrawnonDate = withdrawnonDate;
this.rejectedonDate = rejectedonDate;
this.closedonDate = closedonDate;
this.transactions = null;
this.permissions = null;
this.interestPaid = interestPaid;
this.isInterestWithdrawable = isInterestWithdrawable;
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(final Long clientId, final String clientName, final Long productId, final String productName,
final CurrencyData currency, final BigDecimal deposit, final BigDecimal interestRate, final Integer tenureInMonths,
final Integer interestCompoundedEvery, final EnumOptionData interestCompoundedEveryPeriodType, final boolean renewalAllowed,
final boolean preClosureAllowed, final BigDecimal preClosureInterestRate, final boolean interestCompoundingAllowed) {
this.id = null;
this.externalId = null;
this.status = null;
this.clientId = clientId;
this.clientName = clientName;
this.productId = productId;
this.productName = productName;
this.currency = currency;
this.deposit = deposit;
this.maturityInterestRate = interestRate;
this.tenureInMonths = tenureInMonths;
this.projectedCommencementDate = new LocalDate();
this.actualCommencementDate = null;
this.maturedOn = null;
this.projectedInterestAccrued = null;
this.actualInterestAccrued = null;
this.projectedMaturityAmount = null;
this.actualMaturityAmount = null;
this.interestCompoundedEvery = interestCompoundedEvery;
this.interestCompoundedEveryPeriodType = interestCompoundedEveryPeriodType;
this.renewalAllowed = renewalAllowed;
this.preClosureAllowed = preClosureAllowed;
this.preClosureInterestRate = preClosureInterestRate;
this.interestCompoundedEveryPeriodTypeOptions = new ArrayList<EnumOptionData>();
this.productOptions = new ArrayList<DepositProductLookup>();
this.withdrawnonDate = null;
this.closedonDate = null;
this.rejectedonDate = null;
this.transactions = null;
this.permissions = null;
this.interestPaid = null;
this.isInterestWithdrawable = false;
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() {
return id;
}
public String getExternalId() {
return externalId;
}
public EnumOptionData getStatus() {
return status;
}
public Long getClientId() {
return clientId;
}
public String getClientName() {
return clientName;
}
public Long getProductId() {
return productId;
}
public String getProductName() {
return productName;
}
public CurrencyData getCurrency() {
return currency;
}
public BigDecimal getDeposit() {
return deposit;
}
public BigDecimal getMaturityInterestRate() {
return maturityInterestRate;
}
public Integer getTenureInMonths() {
return tenureInMonths;
}
public LocalDate getProjectedCommencementDate() {
return projectedCommencementDate;
}
public LocalDate getActualCommencementDate() {
return actualCommencementDate;
}
public LocalDate getMaturedOn() {
return maturedOn;
}
public BigDecimal getProjectedInterestAccrued() {
return projectedInterestAccrued;
}
public BigDecimal getActualInterestAccrued() {
return actualInterestAccrued;
}
public BigDecimal getProjectedMaturityAmount() {
return projectedMaturityAmount;
}
public BigDecimal getActualMaturityAmount() {
return actualMaturityAmount;
}
public Integer getInterestCompoundedEvery() {
return interestCompoundedEvery;
}
public EnumOptionData getInterestCompoundedEveryPeriodType() {
return interestCompoundedEveryPeriodType;
}
public boolean isRenewalAllowed() {
return renewalAllowed;
}
public boolean isPreClosureAllowed() {
return preClosureAllowed;
}
public BigDecimal getPreClosureInterestRate() {
return preClosureInterestRate;
}
public List<EnumOptionData> getInterestCompoundedEveryPeriodTypeOptions() {
return interestCompoundedEveryPeriodTypeOptions;
}
public List<DepositProductLookup> getProductOptions() {
return productOptions;
}
public LocalDate getWithdrawnonDate() {
return withdrawnonDate;
}
public LocalDate getRejectedonDate() {
return rejectedonDate;
}
public LocalDate getClosedonDate() {
return closedonDate;
}
public Collection<DepositAccountTransactionData> getTransactions() {
return transactions;
}
public DepositPermissionData getPermissions() {
return permissions;
}
public boolean isInterestWithdrawable() {
return isInterestWithdrawable;
}
public BigDecimal getInterestPaid() {
return interestPaid;
}
public boolean isInterestCompoundingAllowed() {
return interestCompoundingAllowed;
}
public BigDecimal getAvailableInterestForWithdrawal() {
return availableInterestForWithdrawal;
}
public BigDecimal getAvailableWithdrawalAmount() {
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()));
LocalDate interestWithdrawingDate = new LocalDate().isBefore(getMaturedOn()) ? new LocalDate() : getMaturedOn().plusDays(1);
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());
} else {
return BigDecimal.ZERO;
}
} else
return BigDecimal.ZERO;
return availableInterestForWithdrawal;
}
private BigDecimal determineAvalableWithdrawalAmount(final DepositAccountData account) {
BigDecimal avalablePreclosureWithdrawalAmount = BigDecimal.ZERO;
if (this.status != null) {
if (account.getStatus().getId() == 300) {
if (new LocalDate().isBefore(account.getMaturedOn()) || new LocalDate().isEqual(account.getMaturedOn())) {
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN);
Integer monthsInYear = 12;
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())
.add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days));
} else if (new LocalDate().isAfter(account.getMaturedOn())) {
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();
}
}
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());
}
}
@@ -1,4 +1,4 @@
package org.mifosng.platform.api.data;
package org.mifosplatform.portfolio.savingsdepositaccount.data;
import java.math.BigDecimal;
@@ -1,4 +1,4 @@
package org.mifosng.platform.api.data;
package org.mifosplatform.portfolio.savingsdepositaccount.data;
public class DepositPermissionData {
@@ -1,4 +1,4 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsdepositaccount.domain;
import java.math.BigDecimal;
import java.util.ArrayList;
@@ -25,15 +25,15 @@ 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;
import org.mifosng.platform.exceptions.InvalidDepositStateTransitionException;
import org.mifosng.platform.savingproduct.domain.DepositProduct;
import org.mifosplatform.infrastructure.configuration.domain.MonetaryCurrency;
import org.mifosplatform.infrastructure.configuration.domain.Money;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.infrastructure.user.domain.AppUser;
import org.mifosplatform.portfolio.client.domain.Client;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.exception.InvalidDepositStateTransitionException;
import org.mifosplatform.portfolio.savingsdepositproduct.domain.DepositProduct;
@Entity
@Table(name = "m_deposit_account", uniqueConstraints = @UniqueConstraint(name="deposit_acc_external_id", columnNames = { "external_id" }))
@@ -1,4 +1,4 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsdepositaccount.domain;
public enum DepositAccountEvent {
@@ -1,4 +1,4 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsdepositaccount.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -1,4 +1,4 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsdepositaccount.domain;
public enum DepositAccountStatus {
@@ -1,4 +1,4 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsdepositaccount.domain;
import java.math.BigDecimal;
import java.util.Date;
@@ -1,4 +1,4 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsdepositaccount.domain;
public enum DepositAccountTransactionType {
@@ -1,4 +1,4 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsdepositaccount.domain;
public interface DepositLifecycleStateMachine {
@@ -1,8 +1,8 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsdepositaccount.domain;
import java.util.List;
import org.mifosng.platform.exceptions.InvalidDepositStateTransitionException;
import org.mifosplatform.portfolio.savingsdepositaccount.exception.InvalidDepositStateTransitionException;
public class DepositLifecycleStateMachineImpl implements
DepositLifecycleStateMachine {
@@ -1,4 +1,4 @@
package org.mifosng.platform.saving.domain;
package org.mifosplatform.portfolio.savingsdepositaccount.domain;
import java.math.BigDecimal;
import java.math.MathContext;
@@ -1,4 +1,4 @@
package org.mifosng.platform.exceptions;
package org.mifosplatform.portfolio.savingsdepositaccount.exception;
import java.math.BigDecimal;
@@ -1,4 +1,4 @@
package org.mifosng.platform.exceptions;
package org.mifosplatform.portfolio.savingsdepositaccount.exception;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
@@ -1,4 +1,4 @@
package org.mifosng.platform.exceptions;
package org.mifosplatform.portfolio.savingsdepositaccount.exception;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.exception.AbstractPlatformDomainRuleException;

Some files were not shown because too many files have changed in this diff Show More