Madhukars interest posting for fixed deposit and recurrint deposit work.

This commit is contained in:
Madhukar
2012-12-04 15:10:44 +00:00
committed by Keith Woodlock
parent 2dd5c5a7cd
commit d1a1ed60ab
30 changed files with 1683 additions and 845 deletions
+3
View File
@@ -123,6 +123,9 @@ function getBaseURL(docURL)
<tr><td></td><td>offices/{officeId}</td><td></td><td><a href="#offices_retrieve">Retrieve an Office</a></td><td><a href="#offices_update">Update an Office</a></td><td></td></tr> <tr><td></td><td>offices/{officeId}</td><td></td><td><a href="#offices_retrieve">Retrieve an Office</a></td><td><a href="#offices_update">Update an Office</a></td><td></td></tr>
<tr class="alt"><td><a href="#loanproducts">LOAN PRODUCT</a></td><td>loanproducts</td><td><a href="#loanproducts_create">Create a Loan Product</a></td><td><a href="#loanproducts_list">List Loan Products</a></td><td></td><td></td></tr> <tr class="alt"><td><a href="#loanproducts">LOAN PRODUCT</a></td><td>loanproducts</td><td><a href="#loanproducts_create">Create a Loan Product</a></td><td><a href="#loanproducts_list">List Loan Products</a></td><td></td><td></td></tr>
<tr><td></td><td>loanproducts/{productId}</td><td></td><td><a href="#loanproducts_retrieve">Retrieve a Loan Product</a></td><td><a href="#loanproducts_update">Update a Loan Product</a></td><td></td></tr> <tr><td></td><td>loanproducts/{productId}</td><td></td><td><a href="#loanproducts_retrieve">Retrieve a Loan Product</a></td><td><a href="#loanproducts_update">Update a Loan Product</a></td><td></td></tr>
<tr></tr>
<tr class="alt"><td><a href="#loans">FIXED DEPOSITS</a></td><td>depositaccounts</td><td><a href="#loans_create">Create a New Deposit Application</a></td><td><a href="#loans_create">List Deposit Applications</a></td><td></td><td></td></tr>
<tr><td></td><td>depositaccounts/{accountId}</td><td><a href="#loans_approve_etc">Approve, Undo Approve, Interest withdraw, Reject a Deposit Application or Withdraw a Deposit Application</a></td><td><a href="#loans_retrieve">Retrieve a Deposit Application</a></td><td> <a href="#loans_delete">Update a Deposit Application</a></td><td><a href="#loans_delete">Delete a Deposit Application</a></td></tr>
</table> </table>
</div> </div>
</div> </div>
@@ -0,0 +1,18 @@
DROP TABLE IF EXISTS `m_saving_schedule`
CREATE TABLE `m_saving_schedule` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`saving_account_id` bigint(20) NOT NULL,
`duedate` date NOT NULL,
`installment` smallint(5) NOT NULL,
`deposit` decimal(21,4) NOT NULL,
`payment_date` date DEFAULT NULL,
`deposit_paid` decimal(21,4) DEFAULT NULL,
`completed_derived` bit(1) NOT NULL,
`createdby_id` bigint(20) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`lastmodified_date` datetime DEFAULT NULL,
`lastmodifiedby_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FKSS00000000001` (`saving_account_id`),
CONSTRAINT `FKSS00000000001` FOREIGN KEY (`saving_account_id`) REFERENCES `m_saving_account` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -31,6 +31,7 @@ import org.mifosplatform.portfolio.loanaccount.gaurantor.data.GuarantorData;
import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData; import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData; import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData;
import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData; import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData;
@@ -166,6 +167,9 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi
private static final Set<String> GUARANTOR_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("externalGuarantor", "existingClientId", private static final Set<String> GUARANTOR_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("externalGuarantor", "existingClientId",
"firstname", "lastname", "addressLine1", "addressLine2", "city", "state", "zip", "country", "mobileNumber", "housePhoneNumber", "firstname", "lastname", "addressLine1", "addressLine2", "city", "state", "zip", "country", "mobileNumber", "housePhoneNumber",
"comment", "dob")); "comment", "dob"));
private static final Set<String> SAVING_SCHEDULE_DATA_PARAMETERS = new HashSet<String>(Arrays.asList("periods",
"cumulativeDepositDue"));
private final GoogleGsonSerializerHelper helper; private final GoogleGsonSerializerHelper helper;
@@ -555,4 +559,11 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi
prettyPrint, responseParameters); prettyPrint, responseParameters);
return helper.serializedJsonFrom(gsonDeserializer, guarantorData); return helper.serializedJsonFrom(gsonDeserializer, guarantorData);
} }
@Override
public String serializeSavingScheduleDataToJson(boolean prettyPrint, Set<String> responseParameters, SavingScheduleData savingScheduleData) {
final Gson gsonDeserializer = helper.createGsonBuilderWithParameterExclusionSerializationStrategy(SAVING_SCHEDULE_DATA_PARAMETERS,
prettyPrint, responseParameters);
return helper.serializedJsonFrom(gsonDeserializer, savingScheduleData);
}
} }
@@ -1528,7 +1528,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
"digitsAfterDecimal", "savingsDepositAmountPerPeriod", "recurringInterestRate", "savingInterestRate", "tenure", "digitsAfterDecimal", "savingsDepositAmountPerPeriod", "recurringInterestRate", "savingInterestRate", "tenure",
"commencementDate", "locale", "dateFormat", "isLockinPeriodAllowed", "lockinPeriod", "lockinPeriodType", "commencementDate", "locale", "dateFormat", "isLockinPeriodAllowed", "lockinPeriod", "lockinPeriodType",
"savingProductType", "tenureType", "frequency", "interestType", "interestCalculationMethod", "minimumBalanceForWithdrawal", "savingProductType", "tenureType", "frequency", "interestType", "interestCalculationMethod", "minimumBalanceForWithdrawal",
"isPartialDepositAllowed")); "isPartialDepositAllowed","payEvery"));
checkForUnsupportedParameters(requestMap, supportedParams); checkForUnsupportedParameters(requestMap, supportedParams);
Set<String> modifiedParameters = new HashSet<String>(); Set<String> modifiedParameters = new HashSet<String>();
@@ -1554,11 +1554,12 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo
Integer interestCalculationMethod = extractIntegerParameter("interestCalculationMethod", requestMap, modifiedParameters); Integer interestCalculationMethod = extractIntegerParameter("interestCalculationMethod", requestMap, modifiedParameters);
BigDecimal minimumBalanceForWithdrawal = extractBigDecimalParameter("minimumBalanceForWithdrawal", requestMap, modifiedParameters); BigDecimal minimumBalanceForWithdrawal = extractBigDecimalParameter("minimumBalanceForWithdrawal", requestMap, modifiedParameters);
boolean isPartialDepositAllowed = extractBooleanParameter("isPartialDepositAllowed", requestMap, modifiedParameters); boolean isPartialDepositAllowed = extractBooleanParameter("isPartialDepositAllowed", requestMap, modifiedParameters);
Integer payEvery = extractIntegerParameter("payEvery", requestMap, modifiedParameters);
return new SavingAccountCommand(modifiedParameters, resourceIdentifier, clientId, productId, externalId, currencyCode, return new SavingAccountCommand(modifiedParameters, resourceIdentifier, clientId, productId, externalId, currencyCode,
digitsAfterDecimalValue, savingsDepositAmount, recurringInterestRate, savingInterestRate, tenure, commencementDate, digitsAfterDecimalValue, savingsDepositAmount, recurringInterestRate, savingInterestRate, tenure, commencementDate,
savingProductType, tenureType, frequency, interestType, minimumBalanceForWithdrawal, interestCalculationMethod, savingProductType, tenureType, frequency, interestType, minimumBalanceForWithdrawal, interestCalculationMethod,
isLockinPeriodAllowed, isPartialDepositAllowed, lockinPeriod, lockinPeriodType); isLockinPeriodAllowed, isPartialDepositAllowed, lockinPeriod, lockinPeriodType,payEvery);
} }
@Override @Override
@@ -5,6 +5,7 @@ import java.util.Set;
import org.mifosplatform.commands.data.CommandSourceData; import org.mifosplatform.commands.data.CommandSourceData;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.dataqueries.data.DatatableData; import org.mifosplatform.infrastructure.dataqueries.data.DatatableData;
import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData; import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData;
import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData; import org.mifosplatform.infrastructure.documentmanagement.data.DocumentData;
@@ -28,6 +29,7 @@ import org.mifosplatform.portfolio.loanaccount.gaurantor.data.GuarantorData;
import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData;
import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.loanproduct.data.LoanProductData;
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData; import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData; import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData;
import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData; import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData;
@@ -153,4 +155,6 @@ public interface PortfolioApiJsonSerializerService {
String serializeGuarantorDataToJson(boolean prettyPrint, Set<String> responseParameters, GuarantorData guarantorData); String serializeGuarantorDataToJson(boolean prettyPrint, Set<String> responseParameters, GuarantorData guarantorData);
String serializeSavingScheduleDataToJson(boolean prettyPrint, Set<String> responseParameters, SavingScheduleData savingScheduleData);
} }
@@ -18,13 +18,17 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo; 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.ApiParameterHelper;
import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService; import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService;
import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService; import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.savingsaccount.command.CalculateSavingScheduleCommand;
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand; import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData; import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData;
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
import org.mifosplatform.portfolio.savingsaccount.service.CalculateSavingSchedule;
import org.mifosplatform.portfolio.savingsaccount.service.SavingAccountReadPlatformService; import org.mifosplatform.portfolio.savingsaccount.service.SavingAccountReadPlatformService;
import org.mifosplatform.portfolio.savingsaccount.service.SavingAccountWritePlatformService; import org.mifosplatform.portfolio.savingsaccount.service.SavingAccountWritePlatformService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -35,114 +39,136 @@ import org.springframework.stereotype.Component;
@Component @Component
@Scope("singleton") @Scope("singleton")
public class SavingsAccountApiResource { public class SavingsAccountApiResource {
@Autowired
private SavingAccountWritePlatformService savingAccountWritePlatformService;
@Autowired
private SavingAccountReadPlatformService savingAccountReadPlatformService;
@Autowired
private PortfolioApiDataConversionService apiDataConversionService;
@Autowired
private PortfolioApiJsonSerializerService apiJsonSerializerService;
@Autowired private final String entityType = "SAVINGSACCOUNT";
private SavingAccountWritePlatformService savingAccountWritePlatformService;
@Autowired
@Autowired private PlatformSecurityContext context;
private SavingAccountReadPlatformService savingAccountReadPlatformService;
@Autowired
@Autowired private CalculateSavingSchedule calculateSavingSchedule;
private PortfolioApiDataConversionService apiDataConversionService;
private static final Set<String> typicalResponseParameters = new HashSet<String>(
@Autowired Arrays.asList("id", "status", "externalId", "clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod", "savingsFrequencyType",
private PortfolioApiJsonSerializerService apiJsonSerializerService; "totalDepositAmount", "reccuringInterestRate", "savingInterestRate", "interestType", "interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate",
"actualCommencementDate", "maturesOnDate", "projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount", "preClosureAllowed",
private final String entityType = "SAVINGSACCOUNT"; "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed", "lockinPeriod", "lockinPeriodType"));
@Autowired
private PlatformSecurityContext context; @POST
@Consumes({MediaType.APPLICATION_JSON})
private static final Set<String> typicalResponseParameters = new HashSet<String>(Arrays.asList("id", "status", "externalId", @Produces({MediaType.APPLICATION_JSON})
"clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod", public String createSavingAccount(@QueryParam("command") final String commandParam,
"savingsFrequencyType", "totalDepositAmount", "reccuringInterestRate", "savingInterestRate", "interestType", @Context final UriInfo uriInfo,final String jsonRequestBody){
"interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate", "actualCommencementDate", "maturesOnDate",
"projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount", final SavingAccountCommand command = this.apiDataConversionService.convertJsonToSavingAccountCommand(null, jsonRequestBody);
"preClosureAllowed", "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed",
"lockinPeriod", "lockinPeriodType")); if (is(commandParam, "calculateSavingSchedule")) {
CalculateSavingScheduleCommand calculateSavingScheduleCommand = command.toCalculateSavingScheduleCommand();
@POST return calculateSavingSchedule(uriInfo,calculateSavingScheduleCommand);
@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());
EntityIdentifier entityIdentifier = this.savingAccountWritePlatformService.createSavingAccount(command);
return this.apiJsonSerializerService.serializeEntityIdentifier(entityIdentifier);
}
private String calculateSavingSchedule(final UriInfo uriInfo, final CalculateSavingScheduleCommand command) {
SavingScheduleData savingScheduleData = this.calculateSavingSchedule.calculateSavingSchedule(command);
final Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serializeSavingScheduleDataToJson(prettyPrint, responseParameters, savingScheduleData);
}
Collection<SavingAccountData> accounts = this.savingAccountReadPlatformService.retrieveAllSavingsAccounts(); @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) {
return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, accounts); context.authenticatedUser().validateHasReadPermission(entityType);
}
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
}
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
@GET Collection<SavingAccountData> accounts = this.savingAccountReadPlatformService.retrieveAllSavingsAccounts();
@Path("{accountId}")
@Consumes({ MediaType.APPLICATION_JSON }) return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, accounts);
@Produces({ MediaType.APPLICATION_JSON }) }
public String retrieveDepositAccount(@PathParam("accountId") final Long accountId, @Context final UriInfo uriInfo) {
@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); 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);
}
Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); @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) {
if (responseParameters.isEmpty()) { context.authenticatedUser().validateHasReadPermission(entityType);
responseParameters.addAll(typicalResponseParameters);
} Set<String> responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters());
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); if (responseParameters.isEmpty()) {
responseParameters.addAll(typicalResponseParameters);
SavingAccountData account = this.savingAccountReadPlatformService.retrieveSavingsAccount(accountId); }
boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters());
return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, account);
} SavingAccountData account = null;
// this.savingAccountReadPlatformService.retrieveNewSavingsAccountDetails(clientId, productId);
@SuppressWarnings("unused")
@GET return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, account);
@Path("template") }
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON }) private boolean is(final String commandParam, final String commandValue) {
public String retrieveNewDepositAccountDetails(@QueryParam("clientId") final Long clientId, return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
@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,63 @@
package org.mifosplatform.portfolio.savingsaccount.command;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
public class CalculateSavingScheduleCommand {
private final Long productId;
private final BigDecimal deposit;
private final Integer payEvery;
private final Integer paymentFrequencyType;
private final BigDecimal interestRate;
private final LocalDate paymentsStartingFromDate;
private final Integer tenure;
public CalculateSavingScheduleCommand(final Long productId,
final BigDecimal deposit,
final Integer payEvery,
final Integer paymentFrequencyType,
final BigDecimal interestRate,
final LocalDate paymentsStartingFromDate,
final Integer tenure) {
this.productId = productId;
this.deposit = deposit;
this.payEvery = payEvery;
this.paymentFrequencyType=paymentFrequencyType;
this.interestRate= interestRate;
this.paymentsStartingFromDate=paymentsStartingFromDate;
this.tenure = tenure;
}
public Long getProductId() {
return this.productId;
}
public BigDecimal getDeposit() {
return this.deposit;
}
public Integer getPayEvery() {
return this.payEvery;
}
public Integer getPaymentFrequencyType() {
return this.paymentFrequencyType;
}
public BigDecimal getInterestRate() {
return this.interestRate;
}
public LocalDate getPaymentsStartingFromDate() {
return this.paymentsStartingFromDate;
}
public Integer getTenure() {
return this.tenure;
}
}
@@ -6,224 +6,245 @@ import java.util.Set;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
public class SavingAccountCommand { public class SavingAccountCommand {
private final Long id;
private final Long clientId;
private final Long productId;
private final String externalId;
private final Long id; private final String currencyCode;
private final Long clientId; private final Integer digitsAfterDecimal;
private final Long productId; private final BigDecimal savingsDepositAmount;
private final String externalId; 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 Integer payEvery;
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,
final Integer payEvery) {
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;
this.payEvery = payEvery;
}
private final String currencyCode; public Long getId() {
private final Integer digitsAfterDecimal; return id;
private final BigDecimal savingsDepositAmount; }
private final BigDecimal recurringInterestRate;
private final BigDecimal savingInterestRate;
private final Integer tenure;
private final boolean isLockinPeriodAllowed; public Long getClientId() {
private final Integer lockinPeriod; return clientId;
private final Integer lockinPeriodType; }
private final LocalDate commencementDate; public Long getProductId() {
private final Integer savingProductType; return productId;
private final Integer tenureType; }
private final Integer frequency;
private final Integer interestType;
private final Integer interestCalculationMethod; public String getExternalId() {
private final BigDecimal minimumBalanceForWithdrawal; return externalId;
private final boolean isPartialDepositAllowed; }
private final Set<String> modifiedParameters; public String getCurrencyCode() {
return currencyCode;
}
public SavingAccountCommand(final Set<String> modifiedParameters, final Long id, final Long clientId, final Long productId, public Integer getDigitsAfterDecimal() {
final String externalId, final String currencyCode, final Integer digitsAfterDecimal, final BigDecimal savingsDepositAmount, return digitsAfterDecimal;
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; public BigDecimal getSavingsDepositAmount() {
this.digitsAfterDecimal = digitsAfterDecimal; return savingsDepositAmount;
this.savingsDepositAmount = savingsDepositAmount; }
this.recurringInterestRate = recurringInterestRate;
this.savingInterestRate = savingInterestRate;
this.tenure = tenure;
this.modifiedParameters = modifiedParameters; public BigDecimal getRecurringInterestRate() {
this.commencementDate = commencementDate; return recurringInterestRate;
}
this.savingProductType = savingProductType; public BigDecimal getSavingInterestRate() {
this.tenureType = tenureType; return savingInterestRate;
this.frequency = frequency; }
this.interestType = interestType;
this.isPartialDepositAllowed = isPartialDepositAllowed;
this.isLockinPeriodAllowed = isLockinPeriodAllowed; public Integer getTenure() {
this.lockinPeriod = lockInPeriod; return tenure;
this.lockinPeriodType = lockinPeriodType; }
this.minimumBalanceForWithdrawal = minimumBalanceForWithdrawal;
this.interestCalculationMethod = interestCalculationMethod;
}
public Long getId() { public boolean isLockinPeriodAllowed() {
return id; return isLockinPeriodAllowed;
} }
public Long getClientId() { public Integer getLockinPeriod() {
return clientId; return lockinPeriod;
} }
public Long getProductId() { public Integer getLockinPeriodType() {
return productId; return lockinPeriodType;
} }
public String getExternalId() { public LocalDate getCommencementDate() {
return externalId; return commencementDate;
} }
public String getCurrencyCode() { public Integer getSavingProductType() {
return currencyCode; return savingProductType;
} }
public Integer getDigitsAfterDecimal() { public Integer getTenureType() {
return digitsAfterDecimal; return tenureType;
} }
public BigDecimal getSavingsDepositAmount() { public Integer getFrequency() {
return savingsDepositAmount; return frequency;
} }
public BigDecimal getRecurringInterestRate() { public Integer getInterestType() {
return recurringInterestRate; return interestType;
} }
public BigDecimal getSavingInterestRate() { public Integer getInterestCalculationMethod() {
return savingInterestRate; return interestCalculationMethod;
} }
public Integer getTenure() { public BigDecimal getMinimumBalanceForWithdrawal() {
return tenure; return minimumBalanceForWithdrawal;
} }
public boolean isLockinPeriodAllowed() { public boolean isPartialDepositAllowed() {
return isLockinPeriodAllowed; return isPartialDepositAllowed;
} }
public Integer getLockinPeriod() { public Integer getPayEvery() {
return lockinPeriod; return this.payEvery;
} }
public Integer getLockinPeriodType() { public boolean isNoFieldChanged() {
return lockinPeriodType; 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 LocalDate getCommencementDate() { public boolean isTenureInMonthsChanged() {
return commencementDate; 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 Integer getSavingProductType() { public boolean isTenureTypeEnumChanged() {
return savingProductType; return this.modifiedParameters.contains("tenureType");
} }
public Integer getTenureType() { public boolean isSavingProductTypeChanged() {
return tenureType; return this.modifiedParameters.contains("savingProductType");
} }
public Integer getFrequency() { public boolean isSavingFrequencyTypeChanged() {
return frequency; return this.modifiedParameters.contains("frequency");
} }
public Integer getInterestType() { public boolean isSavingInterestCalculationMethodChanged() {
return interestType; return this.modifiedParameters.contains("interestCalculationMethod");
} }
public Integer getInterestCalculationMethod() { public boolean isReccuringInterestRateChanged() {
return interestCalculationMethod; return this.modifiedParameters.contains("recurringInterestRate");
} }
public BigDecimal getMinimumBalanceForWithdrawal() { public boolean isSavingInterestRateChanged() {
return minimumBalanceForWithdrawal; return this.modifiedParameters.contains("savingInterestRate");
} }
public boolean isPartialDepositAllowed() { public boolean isLockinPeriodAllowedChanged() {
return isPartialDepositAllowed; return this.modifiedParameters.contains("isLockinPeriodAllowed");
} }
public boolean isNoFieldChanged() { public boolean isLockinPeriodTypeChanged() {
return this.modifiedParameters.isEmpty(); return this.modifiedParameters.contains("lockinPeriodType");
} }
public boolean isProductIdChanged() { public boolean isPartialDepositAllowedChanged() {
return this.modifiedParameters.contains("productId"); return this.modifiedParameters.contains("isPartialDepositAllowed");
} }
public boolean isPayEveryChanged(){
return this.modifiedParameters.contains("payEvery");
}
public boolean isExternalIdChanged() { public CalculateSavingScheduleCommand toCalculateSavingScheduleCommand() {
return this.modifiedParameters.contains("externalId"); return new CalculateSavingScheduleCommand(productId, savingsDepositAmount, payEvery, frequency, recurringInterestRate, commencementDate,tenure);
} }
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,34 @@
package org.mifosplatform.portfolio.savingsaccount.data;
import java.math.BigDecimal;
import java.util.Collection;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
public class SavingScheduleData {
private final CurrencyData currency;
private final BigDecimal cumulativeDepositDue;
private final Collection<SavingSchedulePeriodData> periods;
public SavingScheduleData(final CurrencyData currency, final BigDecimal cumulativeDepositDue,
final Collection<SavingSchedulePeriodData> periods) {
this.currency = currency;
this.cumulativeDepositDue= cumulativeDepositDue;
this.periods= periods;
}
public CurrencyData getCurrency() {
return this.currency;
}
public BigDecimal getCumulativeDepositDue() {
return this.cumulativeDepositDue;
}
public Collection<SavingSchedulePeriodData> getPeriods() {
return this.periods;
}
}
@@ -0,0 +1,41 @@
package org.mifosplatform.portfolio.savingsaccount.data;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
public class SavingSchedulePeriodData {
private final Integer period;
private final LocalDate dueDate;
private final BigDecimal depositDue;
private final BigDecimal depositPaid;
public SavingSchedulePeriodData(final Integer period, final LocalDate dueDate, final BigDecimal depositDue, final BigDecimal depositPaid) {
this.period = period;
this.dueDate = dueDate;
this.depositDue= depositDue;
this.depositPaid= depositPaid;
}
public static SavingSchedulePeriodData addScheduleInformation(int periodNumber, LocalDate scheduleDate, BigDecimal depositAmountPerPeriod){
return new SavingSchedulePeriodData(periodNumber, scheduleDate, depositAmountPerPeriod, BigDecimal.ZERO);
}
public Integer getPeriod() {
return this.period;
}
public LocalDate getDueDate() {
return this.dueDate;
}
public BigDecimal getDepositDue() {
return this.depositDue;
}
public BigDecimal getDepositPaid() {
return this.depositPaid;
}
}
@@ -0,0 +1,12 @@
package org.mifosplatform.portfolio.savingsaccount.domain;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
public interface DepositScheduleDateGenerator {
List<LocalDate> generate(LocalDate startDate, Integer paymentPeriods, Integer depositFrequency, PeriodFrequencyType depositFrequencyType);
}
@@ -1,18 +1,24 @@
package org.mifosplatform.portfolio.savingsaccount.domain; package org.mifosplatform.portfolio.savingsaccount.domain;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Embedded; import javax.persistence.Embedded;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.JoinColumn; import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Temporal; import javax.persistence.Temporal;
import javax.persistence.TemporalType; import javax.persistence.TemporalType;
import javax.persistence.UniqueConstraint; import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom; import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
@@ -31,307 +37,345 @@ import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum;
import org.mifosplatform.useradministration.domain.AppUser; import org.mifosplatform.useradministration.domain.AppUser;
@Entity @Entity
@Table(name = "m_saving_account", uniqueConstraints = @UniqueConstraint(name = "saving_acc_external_id", columnNames = { "external_id" })) @Table(name = "m_saving_account", uniqueConstraints = @UniqueConstraint(name="saving_acc_external_id", columnNames = { "external_id" }))
public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> { public class SavingAccount extends AbstractAuditableCustom<AppUser, Long> {
@ManyToOne
@JoinColumn(name = "client_id", nullable = false)
private Client client;
@ManyToOne @ManyToOne
@JoinColumn(name = "client_id", nullable = false) @JoinColumn(name = "product_id")
private Client client; 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;
@ManyToOne @Column(name = "is_lock_in_period_allowed", nullable=false)
@JoinColumn(name = "product_id") private boolean isLockinPeriodAllowed = false;
private SavingProduct product;
@Column(name = "lock_in_period", nullable=false)
private Integer lockinPeriod;
@Column(name = "lock_in_period_type", nullable=false)
private PeriodFrequencyType lockinPeriodType;
// see
// http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags
@LazyCollection(LazyCollectionOption.FALSE)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "savingAccount", orphanRemoval = true)
private final List<SavingScheduleInstallments> savingScheduleInstallments = new ArrayList<SavingScheduleInstallments>();
// 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") public static SavingAccount openNew(
private String externalId; 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);
}
@SuppressWarnings("unused") public SavingAccount(Client client, String externalId,
@Embedded SavingProduct product, Money savingsDeposit,
private MonetaryCurrency currency; 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);
}
@Column(name = "deposit_amount_per_period", scale = 6, precision = 19, nullable = false) DepositAccountStatus statusEnum = lifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_CREATED, from);
private BigDecimal savingsDepositAmountPerPeriod; 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;
}
@SuppressWarnings("unused") public boolean isPendingApproval() {
@Column(name = "total_deposit_amount", scale = 6, precision = 19, nullable = false) return this.accountStatus.equals(100);
private BigDecimal totalSavingsAmount; }
@Column(name = "reccuring_nominal_interest_rate", scale = 6, precision = 19, nullable = false) public Client getClient() {
private BigDecimal reccuringInterestRate; return client;
}
@Column(name = "regular_saving_nominal_interest_rate", scale = 6, precision = 19, nullable = false) public SavingProduct getProduct() {
private BigDecimal savingInterestRate; return product;
}
@Column(name = "tenure", nullable = false) public SavingProductType getSavingProductType() {
private Integer tenure; return savingProductType;
}
@Column(name = "tenure_type", nullable = false) public String getExternalId() {
private TenureTypeEnum tenureType; return externalId;
}
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use public BigDecimal getSavingsDepositAmountPerPeriod() {
// Integer e.g. private Integer savingProductType; return savingsDepositAmountPerPeriod;
@Column(name = "frequency", nullable = false) }
private SavingFrequencyType frequency;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use public BigDecimal getReccuringInterestRate() {
// Integer e.g. private Integer savingProductType; return reccuringInterestRate;
@Column(name = "interest_type", nullable = false) }
private SavingsInterestType interestType;
// FIXME - MADHUKAR - Do not use the actual enum type here but instead use public BigDecimal getSavingInterestRate() {
// Integer e.g. private Integer savingProductType; return savingInterestRate;
@Column(name = "interest_calculation_method") }
private SavingInterestCalculationMethod interestCalculationMethod;
@Temporal(TemporalType.DATE) public Integer getTenure() {
@Column(name = "projected_commencement_date") return tenure;
private Date projectedCommencementDate; }
@SuppressWarnings("unused") public TenureTypeEnum getTenureType() {
@Temporal(TemporalType.DATE) return tenureType;
@Column(name = "actual_commencement_date") }
private Date actualCommencementDate;
@SuppressWarnings("unused") public SavingFrequencyType getFrequency() {
@Temporal(TemporalType.DATE) return frequency;
@Column(name = "matures_on_date") }
private Date maturesOnDate;
@SuppressWarnings("unused") public SavingsInterestType getInterestType() {
@Column(name = "projected_interest_accrued_on_maturity", scale = 6, precision = 19, nullable = false) return interestType;
private BigDecimal projectedInterestAccruedOnMaturity; }
@SuppressWarnings("unused") public SavingInterestCalculationMethod getInterestCalculationMethod() {
@Column(name = "actual_interest_accrued", scale = 6, precision = 19, nullable = false) return interestCalculationMethod;
private BigDecimal interestAccrued; }
@SuppressWarnings("unused") public Date getProjectedCommencementDate() {
@Column(name = "projected_total_maturity_amount", scale = 6, precision = 19, nullable = false) return projectedCommencementDate;
private BigDecimal projectedTotalOnMaturity; }
@SuppressWarnings("unused") public BigDecimal getPreClosureInterestRate() {
@Column(name = "actual_total_amount", scale = 6, precision = 19, nullable = false) return preClosureInterestRate;
private BigDecimal total; }
@Column(name = "pre_closure_interest_rate", scale = 6, precision = 19, nullable = false) public boolean isPreClosureAllowed() {
private BigDecimal preClosureInterestRate; return preClosureAllowed;
}
@Column(name = "is_preclosure_allowed", nullable = false) public Date getWithdrawnOnDate() {
private boolean preClosureAllowed = false; return withdrawnOnDate;
}
@Column(name = "is_deleted", nullable = false) public boolean isLockinPeriodAllowed() {
private boolean deleted = false; return isLockinPeriodAllowed;
}
@Column(name = "status_enum", nullable = false) public Integer getLockinPeriod() {
private Integer accountStatus; return lockinPeriod;
}
@SuppressWarnings("unused") public PeriodFrequencyType getLockinPeriodType() {
@Temporal(TemporalType.DATE) return lockinPeriodType;
@Column(name = "closedon_date") }
private Date closedOnDate;
public void addSavingScheduleInstallment(final SavingScheduleInstallments installment) {
@SuppressWarnings("unused") installment.updateAccount(this);
@Temporal(TemporalType.DATE) this.savingScheduleInstallments.add(installment);
@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;
}
} }
@@ -0,0 +1,60 @@
package org.mifosplatform.portfolio.savingsaccount.domain;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.Column;
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 org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.useradministration.domain.AppUser;
@Entity
@Table(name="m_saving_schedule")
public class SavingScheduleInstallments extends AbstractAuditableCustom<AppUser, Long> {
@ManyToOne(optional = false)
@JoinColumn(name = "saving_account_id", nullable=false)
private SavingAccount savingAccount;
@Temporal(TemporalType.DATE)
@Column(name = "duedate", nullable=false)
private final Date dueDate;
@Column(name = "installment", nullable=false)
private final Integer installmentNumber;
@Column(name = "deposit", scale=6, precision=19, nullable=false)
private BigDecimal deposit;
@Temporal(TemporalType.DATE)
@Column(name = "payment_date", nullable=true)
private final Date paymentDate;
@Column(name = "deposit_paid", scale=6, precision=19, nullable=true)
private BigDecimal depositPaid;
@Column(name="completed_derived", nullable=false)
private boolean completed;
public SavingScheduleInstallments(SavingAccount account, Date dueDate,
Integer installmentNumber, BigDecimal deposit) {
this.savingAccount = account;
this.dueDate = dueDate;
this.installmentNumber = installmentNumber;
this.deposit = deposit;
this.paymentDate = null;
this.depositPaid = BigDecimal.ZERO;
this.completed = false;
}
public void updateAccount(SavingAccount account){
this.savingAccount = account;
}
}
@@ -0,0 +1,10 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import org.mifosplatform.portfolio.savingsaccount.command.CalculateSavingScheduleCommand;
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
public interface CalculateSavingSchedule {
SavingScheduleData calculateSavingSchedule(CalculateSavingScheduleCommand command);
}
@@ -0,0 +1,62 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepository;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccount.command.CalculateSavingScheduleCommand;
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductRepository;
import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingProductNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class CalculateSavingScheduleImpl implements CalculateSavingSchedule {
private final PlatformSecurityContext context;
private final SavingProductRepository savingProductRepository;
private final SavingScheduleGenerator savingScheduleGenerator;
private final ApplicationCurrencyRepository applicationCurrencyRepository;
@Autowired
public CalculateSavingScheduleImpl(
final PlatformSecurityContext context,
final SavingProductRepository savingProductRepository,
final ApplicationCurrencyRepository applicationCurrencyRepository) {
this.context = context;
this.savingProductRepository = savingProductRepository;
this.savingScheduleGenerator = new SavingScheduleGenerator();
this.applicationCurrencyRepository = applicationCurrencyRepository;
}
@Override
public SavingScheduleData calculateSavingSchedule(CalculateSavingScheduleCommand command) {
context.authenticatedUser();
// FIXME Validations should write here
final SavingProduct savingProduct = this.savingProductRepository.findOne(command.getProductId());
if (savingProduct == null)
throw new SavingProductNotFoundException(command.getProductId());
final Integer depositFrequency = command.getPayEvery();
final PeriodFrequencyType depositFrequencyType = PeriodFrequencyType.fromInt(command.getPaymentFrequencyType());
final LocalDate scheduleStartDate = command.getPaymentsStartingFromDate();
@SuppressWarnings("unused")
final BigDecimal interestRate = command.getInterestRate();
final BigDecimal depositAmountPerPeriod = command.getDeposit();
final Integer tenure = command.getTenure();
final ApplicationCurrency applicationCurrency = this.applicationCurrencyRepository.findOneByCode(savingProduct.getCurrency().getCode());
SavingScheduleData savingScheduleData = savingScheduleGenerator.generate(scheduleStartDate,depositAmountPerPeriod,
depositFrequency,depositFrequencyType,savingProduct,tenure,applicationCurrency);
return savingScheduleData;
}
}
@@ -0,0 +1,47 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import java.util.ArrayList;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccount.domain.DepositScheduleDateGenerator;
public class DefaultDepositScheduleDateGenerator implements DepositScheduleDateGenerator {
@Override
public List<LocalDate> generate(LocalDate scheuleStartDate, Integer paymentPeriods, Integer depositFrequency, PeriodFrequencyType depositFrequencyType) {
List<LocalDate> duePaymentPeriodDates = new ArrayList<LocalDate>(depositFrequency);
LocalDate startDate = scheuleStartDate;
for (int period=1; period <= paymentPeriods; period++){
LocalDate duePaymentPeriodDate = startDate;
if (period == 1) {
duePaymentPeriodDate = startDate;
} else {
switch (depositFrequencyType) {
case DAYS:
duePaymentPeriodDate = startDate.plusDays(depositFrequency);
break;
case WEEKS:
duePaymentPeriodDate = startDate.plusWeeks(depositFrequency);
break;
case MONTHS:
duePaymentPeriodDate = startDate.plusMonths(depositFrequency);
break;
case YEARS:
duePaymentPeriodDate = startDate.plusYears(depositFrequency);
break;
case INVALID:
break;
}
}
duePaymentPeriodDates.add(duePaymentPeriodDate);
startDate = duePaymentPeriodDate;
}
return duePaymentPeriodDates;
}
}
@@ -12,15 +12,18 @@ import org.mifosplatform.portfolio.client.domain.ClientRepository;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException; import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType; import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand; import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand;
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
import org.mifosplatform.portfolio.savingsaccount.data.SavingSchedulePeriodData;
import org.mifosplatform.portfolio.savingsaccount.domain.ReccuringDepositInterestCalculator; import org.mifosplatform.portfolio.savingsaccount.domain.ReccuringDepositInterestCalculator;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccount; import org.mifosplatform.portfolio.savingsaccount.domain.SavingAccount;
import org.mifosplatform.portfolio.savingsaccount.domain.SavingScheduleInstallments;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingFrequencyType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingInterestCalculationMethod;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductRepository; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductRepository;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsInterestType; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsInterestType;
import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingsProductNotFoundException; import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingProductNotFoundException;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachine; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachine;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachineImpl; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachineImpl;
@@ -30,174 +33,191 @@ import org.springframework.stereotype.Service;
@Service @Service
public class SavingAccountAssembler { public class SavingAccountAssembler {
private final ClientRepository clientRepository;
private final SavingProductRepository savingProductRepository;
private final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator;
private final CalculateSavingSchedule calculateSavingSchedule;
@Autowired
public SavingAccountAssembler(final ClientRepository clientRepository,final SavingProductRepository savingProductRepository,
final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator,final CalculateSavingSchedule calculateSavingSchedule) {
this.clientRepository=clientRepository;
this.savingProductRepository=savingProductRepository;
this.reccuringDepositInterestCalculator=reccuringDepositInterestCalculator;
this.calculateSavingSchedule = calculateSavingSchedule;
}
//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 SavingProductNotFoundException(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());
SavingScheduleData savingScheduleData = this.calculateSavingSchedule.calculateSavingSchedule(command.toCalculateSavingScheduleCommand());
for(SavingSchedulePeriodData savingSchedulePeriodData : savingScheduleData.getPeriods()){
final SavingScheduleInstallments installment = new SavingScheduleInstallments(
account,
savingSchedulePeriodData.getDueDate().toDate(),
savingSchedulePeriodData.getPeriod(),
savingSchedulePeriodData.getDepositDue());
account.addSavingScheduleInstallment(installment);
}
return account;
}
private final ClientRepository clientRepository; public void assembleFrom(SavingAccountCommand command, SavingAccount account) {
private final SavingProductRepository savingProductRepository;
private final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator; SavingProduct product=account.getProduct();
if(command.isProductIdChanged()){
@Autowired if(product.getId() != command.getProductId()){
public SavingAccountAssembler(final ClientRepository clientRepository, final SavingProductRepository savingProductRepository, product = this.savingProductRepository.findOne(command.getProductId());
final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) { if(product == null || product.isDeleted())
this.clientRepository = clientRepository; throw new SavingProductNotFoundException(command.getProductId());
this.savingProductRepository = savingProductRepository; }
this.reccuringDepositInterestCalculator = reccuringDepositInterestCalculator; }
}
String externalId = account.getExternalId();
// minimumBalanceForWithdrawal,isPartialDepositAllowed if(command.isExternalIdChanged()){
public SavingAccount assembleFrom(SavingAccountCommand command) { externalId = command.getExternalId();
}
Client client = this.clientRepository.findOne(command.getClientId());
if (client == null || client.isDeleted()) { throw new ClientNotFoundException(command.getClientId()); } Money savingsDeposit = Money.of(product.getCurrency(), account.getSavingsDepositAmountPerPeriod());
if(command.isDepositAmountChanged()){
SavingProduct product = this.savingProductRepository.findOne(command.getProductId()); savingsDeposit = Money.of(product.getCurrency(), command.getSavingsDepositAmount());
if (product == null || product.isDeleted()) { throw new SavingsProductNotFoundException(command.getProductId()); } }
Integer tenure = account.getTenure();
MonetaryCurrency currency = product.getCurrency(); if(command.isTenureInMonthsChanged()){
if (command.getCurrencyCode() != null && command.getDigitsAfterDecimal() != null) { tenure = command.getTenure();
currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal()); }
}
LocalDate commencementDate = new LocalDate(account.getProjectedCommencementDate());
Money savingsDeposit = Money.of(currency, command.getSavingsDepositAmount()); if (command.isCommencementDateChanged()) {
commencementDate = command.getCommencementDate();
Integer tenure = product.getSavingProductRelatedDetail().getTenure(); }
if (command.getTenure() != null) {
tenure = command.getTenure(); TenureTypeEnum tenureTypeEnum=account.getTenureType();
} if(command.isTenureTypeEnumChanged()){
tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType());
TenureTypeEnum tenureTypeEnum = product.getSavingProductRelatedDetail().getTenureType(); }
if (command.getTenureType() != null) {
tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType()); SavingProductType savingProductType= account.getSavingProductType();
} if (command.isSavingProductTypeChanged()) {
savingProductType = SavingProductType.fromInt(command.getSavingProductType());
SavingProductType savingProductType = product.getSavingProductRelatedDetail().getSavingProductType(); }
if (command.getSavingProductType() != null) {
savingProductType = SavingProductType.fromInt(command.getSavingProductType()); SavingFrequencyType savingFrequencyType = account.getFrequency();
} if (command.isSavingFrequencyTypeChanged()) {
savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency());
SavingFrequencyType savingFrequencyType = product.getSavingProductRelatedDetail().getFrequency(); }
if (command.getFrequency() != null) {
savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency()); SavingInterestCalculationMethod savingInterestCalculationMethod =account.getInterestCalculationMethod();
} if (command.isSavingInterestCalculationMethodChanged()) {
savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod());
SavingInterestCalculationMethod savingInterestCalculationMethod = product.getSavingProductRelatedDetail() }
.getInterestCalculationMethod();
if (command.getInterestCalculationMethod() != null) { BigDecimal reccuringInterestRate = account.getReccuringInterestRate();
savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod()); if (command.isReccuringInterestRateChanged()) {
} reccuringInterestRate = command.getRecurringInterestRate();
}
SavingsInterestType interestType = product.getSavingProductRelatedDetail().getInterestType();
if (command.getInterestType() != null) { BigDecimal savingInterestRate = account.getSavingInterestRate();
interestType = SavingsInterestType.fromInt(command.getInterestType()); if (command.isSavingInterestRateChanged()) {
} savingInterestRate = command.getSavingInterestRate();
}
BigDecimal reccuringInterestRate = command.getRecurringInterestRate();
BigDecimal savingInterestRate = product.getInterestRate(); boolean isLockinPeriodAllowed = account.isLockinPeriodAllowed();
if (command.getSavingInterestRate() != null) savingInterestRate = command.getSavingInterestRate(); if (command.isLockinPeriodAllowedChanged()) {
isLockinPeriodAllowed = command.isLockinPeriodAllowed();
boolean isLockinPeriodAllowed = product.getSavingProductRelatedDetail().isLockinPeriodAllowed(); }
if (command.isLockinPeriodChanged()) {
isLockinPeriodAllowed = command.isLockinPeriodAllowed(); Integer lockinPeriod =account.getLockinPeriod();
} if (command.isLockinPeriodChanged()) {
lockinPeriod = command.getLockinPeriod();
Integer lockinPeriod = product.getSavingProductRelatedDetail().getLockinPeriod(); }
if (command.getLockinPeriod() != null) {
lockinPeriod = command.getLockinPeriod(); PeriodFrequencyType lockinPeriodType = account.getLockinPeriodType();
} if (command.isLockinPeriodTypeChanged()) {
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
PeriodFrequencyType lockinPeriodType = product.getSavingProductRelatedDetail().getLockinPeriodType(); }
if (command.getLockinPeriodType() != null) { account.modifyAccount(product, externalId, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure,
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType()); commencementDate, tenureTypeEnum, savingProductType, savingFrequencyType, savingInterestCalculationMethod,
} isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, this.reccuringDepositInterestCalculator);
SavingAccount account = SavingAccount.openNew(client, product, command.getExternalId(), savingsDeposit, reccuringInterestRate, }
savingInterestRate, tenure, command.getCommencementDate(), tenureTypeEnum, savingProductType, savingFrequencyType,
interestType, savingInterestCalculationMethod, isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, private DepositLifecycleStateMachine defaultDepositLifecycleStateMachine() {
this.reccuringDepositInterestCalculator, defaultDepositLifecycleStateMachine()); List<DepositAccountStatus> allowedDepositStatuses = Arrays.asList(DepositAccountStatus.values());
return new DepositLifecycleStateMachineImpl(allowedDepositStatuses);
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,44 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import java.math.BigDecimal;
import org.joda.time.LocalDate;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.portfolio.savingsaccount.command.CalculateSavingScheduleCommand;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductRelatedDetail;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductRepository;
import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingProductNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SavingProductRelatedDetailAssembler {
private final SavingProductRepository savingProductRepository;
@Autowired
public SavingProductRelatedDetailAssembler(final SavingProductRepository savingProductRepository) {
this.savingProductRepository = savingProductRepository;
}
public SavingProductRelatedDetail assembleFrom(CalculateSavingScheduleCommand command) {
final BigDecimal depositAmountForPeriod = command.getDeposit();
final BigDecimal depositInterestRate = command.getInterestRate();
final LocalDate installmentDate = command.getPaymentsStartingFromDate();
final Integer payEvery = command.getPayEvery();
final Integer paymentFrequencyType = command.getPaymentFrequencyType();
final SavingProduct savingProduct = this.savingProductRepository.findOne(command.getProductId());
if (savingProduct == null) {
throw new SavingProductNotFoundException(command.getProductId());
}
final MonetaryCurrency currency = savingProduct.getCurrency();
return null;
}
}
@@ -0,0 +1,58 @@
package org.mifosplatform.portfolio.savingsaccount.service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.joda.time.LocalDate;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType;
import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData;
import org.mifosplatform.portfolio.savingsaccount.data.SavingSchedulePeriodData;
import org.mifosplatform.portfolio.savingsaccount.domain.DepositScheduleDateGenerator;
import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct;
public class SavingScheduleGenerator {
private final DepositScheduleDateGenerator scheduledDateGenerator = new DefaultDepositScheduleDateGenerator();
public SavingScheduleData generate(
final LocalDate scheduleStartDate,
final BigDecimal depositAmountPerPeriod,
final Integer depositFrequency,
final PeriodFrequencyType depositFrequencyType,
final SavingProduct savingProduct,
final Integer tenure,
final ApplicationCurrency applicationCurrency) {
LocalDate startDate = scheduleStartDate;
int periodNumber = 1;
Integer paymentPeriods = tenure/depositFrequency;
final Collection<SavingSchedulePeriodData> periods = new ArrayList<SavingSchedulePeriodData>();
final List<LocalDate> scheduledDates = this.scheduledDateGenerator.generate(startDate,paymentPeriods,depositFrequency,depositFrequencyType);
final MonetaryCurrency currency = savingProduct.getCurrency();
final Money depositAmount = Money.of(currency, depositAmountPerPeriod);
Money totalDeposit = Money.zero(currency);
for(LocalDate scheduleDate : scheduledDates){
totalDeposit = totalDeposit.plus(depositAmount);
SavingSchedulePeriodData installment = SavingSchedulePeriodData.addScheduleInformation(periodNumber, scheduleDate, depositAmount.getAmount());
periods.add(installment);
periodNumber++;
}
CurrencyData currencyData = new CurrencyData(
applicationCurrency.getCode(),
applicationCurrency.getName(),
currency.getDigitsAfterDecimal(),
applicationCurrency.getDisplaySymbol(),
applicationCurrency.getNameCode());
return new SavingScheduleData(currencyData, totalDeposit.getAmount(), periods);
}
}
@@ -37,6 +37,7 @@ import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountW
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommand; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountsForLookup;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositPermissionData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositPermissionData;
import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountReadPlatformService; import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountReadPlatformService;
import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountWritePlatformService; import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountWritePlatformService;
@@ -257,5 +258,16 @@ public class DepositAccountsApiResource {
private boolean is(final String commandParam, final String commandValue) { private boolean is(final String commandParam, final String commandValue) {
return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue); return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue);
}
@POST
@Path("postinterest")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response postInterest(){
Collection<DepositAccountsForLookup> accounts = this.depositAccountReadPlatformService.retrieveDepositAccountForLookup();
@SuppressWarnings("unused")
EntityIdentifier entityIdentifier = this.depositAccountWritePlatformService.postInterestToDepositAccount(accounts);
return Response.ok().entity(entityIdentifier).build();
} }
} }
@@ -65,6 +65,11 @@ public class DepositAccountData {
private final boolean isLockinPeriodAllowed; private final boolean isLockinPeriodAllowed;
private final Integer lockinPeriod; private final Integer lockinPeriod;
private final EnumOptionData lockinPeriodType; private final EnumOptionData lockinPeriodType;
private final BigDecimal availableInterest;
private final BigDecimal interestPostedAmount;
private final LocalDate lastInterestPostedDate;
private final LocalDate nextInterestPostedDate;
/* /*
* used when returning account template data but only a clientId is passed, * used when returning account template data but only a clientId is passed,
@@ -119,6 +124,11 @@ public class DepositAccountData {
this.isLockinPeriodAllowed = true; this.isLockinPeriodAllowed = true;
this.lockinPeriod = null; this.lockinPeriod = null;
this.lockinPeriodType = null; this.lockinPeriodType = null;
this.availableInterest = BigDecimal.ZERO;
this.interestPostedAmount = BigDecimal.ZERO;
this.lastInterestPostedDate = null;
this.nextInterestPostedDate = null;
} }
public DepositAccountData(final DepositAccountData account, final List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions, public DepositAccountData(final DepositAccountData account, final List<EnumOptionData> interestCompoundedEveryPeriodTypeOptions,
@@ -166,6 +176,11 @@ public class DepositAccountData {
this.lockinPeriod = account.getLockinPeriod(); this.lockinPeriod = account.getLockinPeriod();
this.lockinPeriodType = account.getLockinPeriodType(); this.lockinPeriodType = account.getLockinPeriodType();
this.isLockinPeriodAllowed = account.isLockinPeriodAllowed(); this.isLockinPeriodAllowed = account.isLockinPeriodAllowed();
this.availableInterest = account.getAvailableInterest();
this.interestPostedAmount = account.getInterestPostedAmount();
this.lastInterestPostedDate = account.getLastInterestPostedDate();
this.nextInterestPostedDate = account.getNextInterestPostedDate();
} }
public DepositAccountData(final DepositAccountData account, final DepositPermissionData permissions, public DepositAccountData(final DepositAccountData account, final DepositPermissionData permissions,
@@ -213,6 +228,11 @@ public class DepositAccountData {
this.lockinPeriod = account.getLockinPeriod(); this.lockinPeriod = account.getLockinPeriod();
this.lockinPeriodType = account.getLockinPeriodType(); this.lockinPeriodType = account.getLockinPeriodType();
this.isLockinPeriodAllowed = account.isLockinPeriodAllowed(); this.isLockinPeriodAllowed = account.isLockinPeriodAllowed();
this.availableInterest = account.getAvailableInterest();
this.interestPostedAmount = account.getInterestPostedAmount();
this.lastInterestPostedDate = account.getLastInterestPostedDate();
this.nextInterestPostedDate = account.getNextInterestPostedDate();
} }
public DepositAccountData(final Long id, final String externalId, final EnumOptionData status, final Long clientId, public DepositAccountData(final Long id, final String externalId, final EnumOptionData status, final Long clientId,
@@ -224,7 +244,8 @@ public class DepositAccountData {
final boolean preClosureAllowed, final BigDecimal preClosureInterestRate, final LocalDate withdrawnonDate, final boolean preClosureAllowed, final BigDecimal preClosureInterestRate, final LocalDate withdrawnonDate,
final LocalDate rejectedonDate, final LocalDate closedonDate, final boolean isInterestWithdrawable, final LocalDate rejectedonDate, final LocalDate closedonDate, final boolean isInterestWithdrawable,
final BigDecimal interestPaid, final boolean interestCompoundingAllowed, final boolean isLockinPeriodAllowed, final BigDecimal interestPaid, final boolean interestCompoundingAllowed, final boolean isLockinPeriodAllowed,
final Integer lockinPeriod, final EnumOptionData lockinPeriodType) { final Integer lockinPeriod, final EnumOptionData lockinPeriodType,final BigDecimal availableInterest,
final BigDecimal interestPostedAmount, final LocalDate lastInterestPostedDate, final LocalDate nextInterestPostedDate) {
this.id = id; this.id = id;
this.externalId = externalId; this.externalId = externalId;
this.status = status; this.status = status;
@@ -269,6 +290,11 @@ public class DepositAccountData {
this.isLockinPeriodAllowed = isLockinPeriodAllowed; this.isLockinPeriodAllowed = isLockinPeriodAllowed;
this.lockinPeriod = lockinPeriod; this.lockinPeriod = lockinPeriod;
this.lockinPeriodType = lockinPeriodType; this.lockinPeriodType = lockinPeriodType;
this.availableInterest = availableInterest;
this.interestPostedAmount = interestPostedAmount;
this.lastInterestPostedDate = lastInterestPostedDate;
this.nextInterestPostedDate = nextInterestPostedDate;
} }
public DepositAccountData(final Long clientId, final String clientName, final Long productId, final String productName, public DepositAccountData(final Long clientId, final String clientName, final Long productId, final String productName,
@@ -319,6 +345,11 @@ public class DepositAccountData {
this.lockinPeriod = Integer.valueOf(0); this.lockinPeriod = Integer.valueOf(0);
this.isLockinPeriodAllowed = true; this.isLockinPeriodAllowed = true;
this.lockinPeriodType = interestCompoundedEveryPeriodType; this.lockinPeriodType = interestCompoundedEveryPeriodType;
this.availableInterest = BigDecimal.ZERO;
this.interestPostedAmount = BigDecimal.ZERO;
this.lastInterestPostedDate = null;
this.nextInterestPostedDate = null;
} }
public Long getId() { public Long getId() {
@@ -477,68 +508,67 @@ public class DepositAccountData {
return lockinPeriodType; return lockinPeriodType;
} }
private BigDecimal determineAvailableInterestForWithdrawal(final DepositAccountData account) { public BigDecimal getAvailableInterest() {
BigDecimal availableInterestForWithdrawal = BigDecimal.ZERO; return this.availableInterest;
}
if (this.status != null) { public BigDecimal getInterestPostedAmount() {
if (account.getStatus().getId() == 300) { return this.interestPostedAmount;
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)) public LocalDate getLastInterestPostedDate() {
.doubleValue() - account.getInterestPaid().doubleValue()); return this.lastInterestPostedDate;
} else { }
return BigDecimal.ZERO;
}
} else
return BigDecimal.ZERO;
return availableInterestForWithdrawal; public LocalDate getNextInterestPostedDate() {
} return this.nextInterestPostedDate;
}
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();
private BigDecimal determineAvalableWithdrawalAmount(final DepositAccountData account) { availableInterestForWithdrawal = BigDecimal.valueOf(interestGettingForPeriod.multiply(new BigDecimal(noOfPeriods)).doubleValue()- account.getInterestPaid().doubleValue());
}else {
BigDecimal avalablePreclosureWithdrawalAmount = BigDecimal.ZERO; return BigDecimal.ZERO;
if (this.status != null) { }
if (account.getStatus().getId() == 300) { }else return BigDecimal.ZERO;
if (new LocalDate().isBefore(account.getMaturedOn()) || new LocalDate().isEqual(account.getMaturedOn())) {
MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN); return availableInterestForWithdrawal;
Integer monthsInYear = 12; }
BigDecimal interestRateAsFraction = account.getPreClosureInterestRate().divide(BigDecimal.valueOf(100), mc);
BigDecimal interestRateForOneMonth = interestRateAsFraction.divide(BigDecimal.valueOf(monthsInYear.doubleValue()), mc); private BigDecimal determineAvalableWithdrawalAmount(final DepositAccountData account) {
Integer noOfMonthsforInterestCal = Months.monthsBetween(account.getActualCommencementDate(), new LocalDate())
.getMonths(); BigDecimal avalablePreclosureWithdrawalAmount = BigDecimal.ZERO;
Integer days = Days.daysBetween(account.getActualCommencementDate().plusMonths(noOfMonthsforInterestCal), if(this.status != null){
new LocalDate()).getDays(); if (account.getStatus().getId() == 300) {
BigDecimal interest = BigDecimal.valueOf(account.getDeposit().doubleValue() * new Double(noOfMonthsforInterestCal) // if(new LocalDate().isBefore(account.getMaturedOn()) || new LocalDate().isEqual(account.getMaturedOn())){
* interestRateForOneMonth.doubleValue()); Integer days = Days.daysBetween(account.getLastInterestPostedDate(), new LocalDate()).getDays();
avalablePreclosureWithdrawalAmount = interest.add(account.getDeposit()).subtract(account.getInterestPaid()) avalablePreclosureWithdrawalAmount=account.getAvailableInterest().add(account.getDeposit()).add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days));
.add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days));
} else if (new LocalDate().isAfter(account.getMaturedOn())) { // }else if(new LocalDate().isAfter(account.getMaturedOn())){
Integer days = Days.daysBetween(account.getMaturedOn(), new LocalDate()).getDays(); // Integer days = Days.daysBetween(account.getLastInterestPostedDate(), new LocalDate()).getDays();
avalablePreclosureWithdrawalAmount = determineAvailableInterestForWithdrawal(account).add(account.getDeposit()).add( // avalablePreclosureWithdrawalAmount=account.getAvailableInterest().add(account.getDeposit()).add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days));
determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days)); // }
} }else{
} else { avalablePreclosureWithdrawalAmount=account.getDeposit();
avalablePreclosureWithdrawalAmount = account.getDeposit(); }
} }
} return avalablePreclosureWithdrawalAmount;
return avalablePreclosureWithdrawalAmount; }
}
private BigDecimal determineRemainInerestAmount(final BigDecimal depsoitAmount, final BigDecimal interstRateApplicable, final Integer days){
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());
}
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());
}
} }
@@ -0,0 +1,15 @@
package org.mifosplatform.portfolio.savingsdepositaccount.data;
public class DepositAccountsForLookup {
private final Long id;
public DepositAccountsForLookup(final Long id) {
this.id = id;
}
public Long getId() {
return id;
}
}
@@ -152,6 +152,21 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
@Column(name = "lock_in_period_type", nullable=false) @Column(name = "lock_in_period_type", nullable=false)
private PeriodFrequencyType lockinPeriodType; private PeriodFrequencyType lockinPeriodType;
//for interest posting
@Column(name = "available_interest", scale = 6, precision = 19)
private BigDecimal availableInterest;
@Column(name = "interest_posted_amount", scale = 6, precision = 19)
private BigDecimal interestPostedAmount;
@Temporal(TemporalType.DATE)
@Column(name = "last_interest_posted_date")
private Date lastInterestPostedDate;
@Temporal(TemporalType.DATE)
@Column(name = "next_interest_posting_date")
private Date nextInterestPostingDate;
public DepositAccount openNew( public DepositAccount openNew(
final Client client, final DepositProduct product, final Client client, final DepositProduct product,
@@ -325,6 +340,12 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
depositaccountTransaction.updateAccount(this); depositaccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositaccountTransaction); this.depositaccountTransactions.add(depositaccountTransaction);
//for interest posting initializing
this.lastInterestPostedDate = this.actualCommencementDate;
this.nextInterestPostingDate = new LocalDate(this.lastInterestPostedDate).plusMonths(this.interestCompoundedEvery).toDate();
this.availableInterest = BigDecimal.ZERO;
this.interestPostedAmount = BigDecimal.ZERO;
LocalDate submittalDate = new LocalDate(this.projectedCommencementDate); LocalDate submittalDate = new LocalDate(this.projectedCommencementDate);
if (actualCommencementDate.isBefore(submittalDate)) { if (actualCommencementDate.isBefore(submittalDate)) {
final String errorMessage = "The date on which a deposit is approved cannot be before its submittal date: " + submittalDate.toString(); final String errorMessage = "The date on which a deposit is approved cannot be before its submittal date: " + submittalDate.toString();
@@ -545,46 +566,44 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
public void withdrawDepositAccountMoney(DepositLifecycleStateMachine depositLifecycleStateMachine, FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,LocalDate eventDate) { public void withdrawDepositAccountMoney(DepositLifecycleStateMachine depositLifecycleStateMachine, FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,LocalDate eventDate) {
if (eventDate.isBefore(getLastInterestPostedDate())) {
final String errorMessage = "Deposit Account Preclosed date \"" +eventDate+ "\"cannot before last interest posted date \"" + getLastInterestPostedDate()+"\"";
throw new InvalidDepositStateTransitionException("withdraw", "event.date.cannot.before.last.interest.posted.date",errorMessage, getLastInterestPostedDate(), eventDate);
}
if (eventDate.isAfter(maturesOnDate()) || eventDate.equals(maturesOnDate())) { if (eventDate.isAfter(maturesOnDate()) || eventDate.equals(maturesOnDate())) {
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_CLOSED, DepositAccountStatus.fromInt(this.depositStatus)); DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_CLOSED, DepositAccountStatus.fromInt(this.depositStatus));
this.depositStatus = statusEnum.getValue(); this.depositStatus = statusEnum.getValue();
} else if(eventDate.isBefore(maturesOnDate())){
Integer days = Days.daysBetween(maturesOnDate(), eventDate).getDays();
Money accuredInterestAfterMaturityToTillDate = fixedTermDepositInterestCalculator.calculateRemainInterest(getDeposit(), days, preClosureInterestRate);
this.interestAccrued = this.interestAccrued.add(accuredInterestAfterMaturityToTillDate.getAmount());
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), eventDate,getAccuredInterest());
depositaccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositaccountTransaction);
this.closedOnDate = eventDate.toDate();
this.withdrawnOnDate = null;
this.rejectedOnDate = null;
}else if(new LocalDate().isBefore(maturesOnDate())){
DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_PRECLOSED, DepositAccountStatus.fromInt(this.depositStatus)); DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_PRECLOSED, DepositAccountStatus.fromInt(this.depositStatus));
this.depositStatus = statusEnum.getValue(); this.depositStatus = statusEnum.getValue();
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), eventDate, getAccuredInterest());
depositaccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositaccountTransaction);
this.closedOnDate = eventDate.toDate();
this.withdrawnOnDate = null;
this.rejectedOnDate = null;
} }
Integer days = Days.daysBetween(getLastInterestPostedDate(), eventDate).getDays();
Money accuredInterestAfterMaturityToTillDate = fixedTermDepositInterestCalculator.calculateRemainInterest(getDeposit(), days, preClosureInterestRate);
this.interestAccrued = this.interestAccrued.add(accuredInterestAfterMaturityToTillDate.getAmount());
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(getDeposit(), eventDate,getAccuredInterest());
depositaccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositaccountTransaction);
this.closedOnDate = eventDate.toDate();
this.withdrawnOnDate = null;
this.rejectedOnDate = null;
} }
public void adjustTotalAmountForPreclosureInterest(DepositAccount account, FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,LocalDate eventDate) { /*public void adjustTotalAmountForPreclosureInterest(DepositAccount account, FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,LocalDate eventDate) {
LocalDate commnencementDate = getActualCommencementDate(); LocalDate commnencementDate = getActualCommencementDate();
LocalDate lastInterestPosedDate = getLastInterestPostedDate();
LocalDate preClosedDate = eventDate; LocalDate preClosedDate = eventDate;
Integer tenure = Months.monthsBetween(commnencementDate, preClosedDate).getMonths(); if (preClosedDate.isBefore(lastInterestPosedDate)) {
LocalDate actualPrecloseCalculationDate = commnencementDate.plusMonths(tenure); throw new DepositAccountTransactionsException("deposit.account.preclosed.date.should.be.after.last.interest.posted.date", null);
}
Integer tenure = Months.monthsBetween(lastInterestPosedDate, preClosedDate).getMonths();
LocalDate actualPrecloseCalculationDate = lastInterestPosedDate.plusMonths(tenure);
Integer missedDays = Days.daysBetween(actualPrecloseCalculationDate, preClosedDate).getDays(); Integer missedDays = Days.daysBetween(actualPrecloseCalculationDate, preClosedDate).getDays();
Money deposit = Money.of(account.getDeposit().getCurrency(), account.getDeposit().getAmount()); Money deposit = Money.of(account.getDeposit().getCurrency(), account.getDeposit().getAmount());
@@ -607,15 +626,17 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
this.total = account.isInterestCompoundingAllowed()?accuredtotalAmount.getAmount():BigDecimal.valueOf(accuredtotalAmount.getAmount().doubleValue()-this.interstPaid.doubleValue()); this.total = account.isInterestCompoundingAllowed()?accuredtotalAmount.getAmount():BigDecimal.valueOf(accuredtotalAmount.getAmount().doubleValue()-this.interstPaid.doubleValue());
this.interestAccrued = accuredtotalAmount.minus(deposit).getAmount(); this.interestAccrued = accuredtotalAmount.minus(deposit).getAmount();
} }*/
public void withdrawInterest(Money interest) { public void withdrawInterest(Money interest) {
@SuppressWarnings("unused")
if(this.depositStatus == 300 ){ boolean statustest = isActive();
if(isActive()){
DepositAccountTransaction depositAccountTransaction = DepositAccountTransaction.withdraw(null, new LocalDate(), interest); DepositAccountTransaction depositAccountTransaction = DepositAccountTransaction.withdraw(null, new LocalDate(), interest);
depositAccountTransaction.updateAccount(this); depositAccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositAccountTransaction); this.depositaccountTransactions.add(depositAccountTransaction);
this.interstPaid = this.interstPaid.add(interest.getAmount()); this.interstPaid = this.interstPaid.add(interest.getAmount());
this.availableInterest = this.availableInterest.subtract(interest.getAmount());
this.total = this.total.subtract(interest.getAmount()); this.total = this.total.subtract(interest.getAmount());
} }
@@ -639,7 +660,6 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
final boolean renewalAllowed, final boolean preClosureAllowed, final boolean renewalAllowed, final boolean preClosureAllowed,
final boolean isInterestWithdrawable, final boolean isInterestCompoundingAllowed, final boolean isInterestWithdrawable, final boolean isInterestCompoundingAllowed,
final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator, final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator,
@SuppressWarnings("unused") final DepositLifecycleStateMachine depositLifecycleStateMachine,
final boolean isLockinPeriodAllowed, final boolean isLockinPeriodAllowed,
final Integer lockinPeriod, final Integer lockinPeriod,
final PeriodFrequencyType lockinPeriodType) { final PeriodFrequencyType lockinPeriodType) {
@@ -695,4 +715,120 @@ public class DepositAccount extends AbstractAuditableCustom<AppUser, Long> {
public boolean isActive() { public boolean isActive() {
return DepositAccountStatus.fromInt(this.depositStatus).isActive(); return DepositAccountStatus.fromInt(this.depositStatus).isActive();
} }
public void postInterestForDepositAccount(DepositAccount account, FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator) {
LocalDate lastInterestPostedDate = getLastInterestPostedDate();
LocalDate nextInterestPostingDate = getNextInterestPostedDate();
Integer monthsForInterestCalculation = Months.monthsBetween(lastInterestPostedDate, new LocalDate()).getMonths();
Integer postInterestItereations = monthsForInterestCalculation/this.interestCompoundedEvery;
Money deposit = Money.of(this.currency, this.depositAmount);
while (postInterestItereations > 0) {
lastInterestPostedDate = getLastInterestPostedDate();
nextInterestPostingDate = getNextInterestPostedDate();
if (lastInterestPostedDate.isBefore(getMaturityDate())){
if (nextInterestPostingDate.isAfter(getMaturityDate())){
Integer noofRemainMonthsAfterMaturity = Months.monthsBetween(getMaturityDate(), nextInterestPostingDate).getMonths();
Integer noOfMonthsBeforeMaturity = Months.monthsBetween(lastInterestPostedDate, getMaturityDate()).getMonths();
Money futureValueOnMaturity =null;
if (noOfMonthsBeforeMaturity >0) {
if (this.interestCompoundingAllowed) {
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, noOfMonthsBeforeMaturity,this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
} else {
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit, noOfMonthsBeforeMaturity, this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
}
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
this.availableInterest = this.availableInterest.add(futureValueOnMaturity.minus(deposit).getAmount());
this.lastInterestPostedDate = nextInterestPostingDate.toDate();
this.nextInterestPostingDate = nextInterestPostingDate.plusMonths(this.interestCompoundedEvery).toDate();
}
if (noofRemainMonthsAfterMaturity >0){
if (this.interestCompoundingAllowed) {
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
} else {
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit, noofRemainMonthsAfterMaturity, this.preClosureInterestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
}
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
this.availableInterest = this.availableInterest.add(futureValueOnMaturity.minus(deposit).getAmount());
this.lastInterestPostedDate = nextInterestPostingDate.toDate();
this.nextInterestPostingDate = nextInterestPostingDate.plusMonths(this.interestCompoundedEvery).toDate();
}
// add transaction entry for each interest posting
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate,futureValueOnMaturity.minus(deposit));
depositaccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositaccountTransaction);
} else {
Money futureValueOnMaturity =null;
if (this.interestCompoundingAllowed) {
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
} else {
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit, this.interestCompoundedEvery, this.interestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
}
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
this.availableInterest = this.availableInterest.add(futureValueOnMaturity.minus(deposit).getAmount());
this.lastInterestPostedDate = nextInterestPostingDate.toDate();
this.nextInterestPostingDate = nextInterestPostingDate.plusMonths(this.interestCompoundedEvery).toDate();
// add transaction entry for each interest posting
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate,futureValueOnMaturity.minus(deposit));
depositaccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositaccountTransaction);
}
} else{
Money futureValueOnMaturity =null;
if (this.interestCompoundingAllowed) {
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
} else {
futureValueOnMaturity = fixedTermDepositInterestCalculator.calculateInterestOnMaturityForSimpleInterest(deposit, this.interestCompoundedEvery, this.preClosureInterestRate, this.interestCompoundedEvery, getInterestCompoundedFrequencyType());
}
this.interestPostedAmount = this.interestPostedAmount.add(futureValueOnMaturity.minus(deposit).getAmount());
this.availableInterest = this.availableInterest.add(futureValueOnMaturity.minus(deposit).getAmount());
this.lastInterestPostedDate = nextInterestPostingDate.toDate();
this.nextInterestPostingDate = nextInterestPostingDate.plusMonths(this.interestCompoundedEvery).toDate();
// add transaction entry for each interest posting
DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.postInterest(null, nextInterestPostingDate,futureValueOnMaturity.minus(deposit));
depositaccountTransaction.updateAccount(this);
this.depositaccountTransactions.add(depositaccountTransaction);
}
postInterestItereations--;
}
}
private final LocalDate getLastInterestPostedDate() {
LocalDate lastInterestPostedDate;
if (this.lastInterestPostedDate == null){
lastInterestPostedDate = new LocalDate(this.actualCommencementDate);
} else {
lastInterestPostedDate = new LocalDate(this.lastInterestPostedDate);
}
return lastInterestPostedDate;
}
private final LocalDate getNextInterestPostedDate() {
LocalDate nextInterestPostingDate;
if (this.nextInterestPostingDate == null){
nextInterestPostingDate = new LocalDate(this.nextInterestPostingDate).plusMonths(this.interestCompoundedEvery);
} else {
nextInterestPostingDate = new LocalDate(this.nextInterestPostingDate);
}
return nextInterestPostingDate;
}
public BigDecimal getAvailableInterest() {
return availableInterest;
}
public BigDecimal getInterestPostedAmount() {
return interestPostedAmount;
}
} }
@@ -102,6 +102,10 @@ public class DepositAccountTransaction extends AbstractPersistable<Long> {
return new DepositAccountTransaction(DepositAccountTransactionType.WITHDRAW, amount == null ? new BigDecimal(0) : amount.getAmount(), paymentDate, interest==null ? new BigDecimal(0) : interest.getAmount()); return new DepositAccountTransaction(DepositAccountTransactionType.WITHDRAW, amount == null ? new BigDecimal(0) : amount.getAmount(), paymentDate, interest==null ? new BigDecimal(0) : interest.getAmount());
} }
public static DepositAccountTransaction postInterest(Money depositAmount, LocalDate paymentDate, Money interest) {
return new DepositAccountTransaction(DepositAccountTransactionType.INTEREST_POSTING, depositAmount == null ? new BigDecimal(0) : depositAmount.getAmount(), paymentDate, interest==null ? new BigDecimal(0) : interest.getAmount());
}
public void updateAccount(DepositAccount depositAccount) { public void updateAccount(DepositAccount depositAccount) {
this.depositAccount=depositAccount; this.depositAccount=depositAccount;
} }
@@ -5,7 +5,8 @@ public enum DepositAccountTransactionType {
INVALID(0, "depositTransactionType.invalid"), // INVALID(0, "depositTransactionType.invalid"), //
DEPOSIT(1, "depositTransactionType.deposit"), // DEPOSIT(1, "depositTransactionType.deposit"), //
WITHDRAW(2, "depositTransactionType.withdraw"), // WITHDRAW(2, "depositTransactionType.withdraw"), //
REVERSAL(3, "depositTransactionType.reversal"); REVERSAL(3, "depositTransactionType.reversal"),
INTEREST_POSTING(4,"depositTransactionType.interestPosting");
private final Integer value; private final Integer value;
private final String code; private final String code;
@@ -43,6 +44,10 @@ public enum DepositAccountTransactionType {
depositTransactionType=DepositAccountTransactionType.REVERSAL; depositTransactionType=DepositAccountTransactionType.REVERSAL;
break; break;
case 4:
depositTransactionType=DepositAccountTransactionType.INTEREST_POSTING;
break;
default : default :
depositTransactionType=DepositAccountTransactionType.INVALID; depositTransactionType=DepositAccountTransactionType.INVALID;
break; break;
@@ -230,9 +230,9 @@ public class DepositAccountAssembler {
return newAccount; return newAccount;
} }
public void adjustTotalAmountForPreclosureInterest(DepositAccount account,LocalDate eventDate) { /*public void adjustTotalAmountForPreclosureInterest(DepositAccount account,LocalDate eventDate) {
account.adjustTotalAmountForPreclosureInterest(account,this.fixedTermDepositInterestCalculator,eventDate); account.adjustTotalAmountForPreclosureInterest(account,this.fixedTermDepositInterestCalculator,eventDate);
} }*/
public void assembleUpdatedDepositAccount(DepositAccount account,DepositAccountCommand command) { public void assembleUpdatedDepositAccount(DepositAccount account,DepositAccountCommand command) {
@@ -323,7 +323,7 @@ public class DepositAccountAssembler {
lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType()); lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType());
} }
account.update(product,externalId,commencementDate,deposit,tenureInMonths,maturityInterestRate,preClosureInterestRate,compoundingInterestEvery,compoundingInterestFrequency,renewalAllowed, account.update(product,externalId,commencementDate,deposit,tenureInMonths,maturityInterestRate,preClosureInterestRate,compoundingInterestEvery,compoundingInterestFrequency,renewalAllowed,
preClosureAllowed,isInterestWithdrawable,isInterestCompoundingAllowed,this.fixedTermDepositInterestCalculator,defaultDepositLifecycleStateMachine(),isLockinPeriodAllowed,lockinPeriod,lockinPeriodType); preClosureAllowed,isInterestWithdrawable,isInterestCompoundingAllowed,this.fixedTermDepositInterestCalculator,isLockinPeriodAllowed,lockinPeriod,lockinPeriodType);
} }
public void updateApprovedDepositAccount(DepositAccount account, DepositAccountCommand command) { public void updateApprovedDepositAccount(DepositAccount account, DepositAccountCommand command) {
@@ -340,4 +340,8 @@ public class DepositAccountAssembler {
account.update(renewalAllowed,isInterestWithdrawable); account.update(renewalAllowed,isInterestWithdrawable);
} }
public void postInterest(DepositAccount account) {
account.postInterestForDepositAccount(account,this.fixedTermDepositInterestCalculator);
}
} }
@@ -4,6 +4,7 @@ import java.math.BigDecimal;
import java.util.Collection; import java.util.Collection;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountsForLookup;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositPermissionData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositPermissionData;
public interface DepositAccountReadPlatformService { public interface DepositAccountReadPlatformService {
@@ -17,4 +18,6 @@ public interface DepositAccountReadPlatformService {
DepositPermissionData retrieveDepositAccountsPermissions(DepositAccountData depositAccountData); DepositPermissionData retrieveDepositAccountsPermissions(DepositAccountData depositAccountData);
BigDecimal retrieveAvailableInterestForWithdrawal(DepositAccountData account); BigDecimal retrieveAvailableInterestForWithdrawal(DepositAccountData account);
Collection<DepositAccountsForLookup> retrieveDepositAccountForLookup();
} }
@@ -18,6 +18,7 @@ import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundExce
import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingsDepositEnumerations; import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingsDepositEnumerations;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountTransactionData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountTransactionData;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountsForLookup;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositPermissionData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositPermissionData;
import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData; import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData;
import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductLookup; import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductLookup;
@@ -143,6 +144,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
+ " da.withdrawnon_date as withdrawnonDate, da.rejectedon_date as rejectedonDate, da.closedon_date as closedonDate, " + " 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.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, " + " da.is_lock_in_period_allowed as isLockinPeriodAllowed, da.lock_in_period as lockinPeriod, da.lock_in_period_type lockinPeriodType, "
+ " da.available_interest as availableInterest, da.interest_posted_amount as interestPostedAmount, da.last_interest_posted_date as lastInterestPostedDate, da.next_interest_posting_date as nextInterestPostedDate,"
+ " c.firstname as firstname, c.lastname as lastname, pd.name as productName," + " 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 " + " 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 " + " from m_deposit_account da " + " join m_currency curr on curr.code = da.currency_code "
@@ -206,13 +208,18 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
Integer lockinPeriod = JdbcSupport.getInteger(rs, "lockinPeriod"); Integer lockinPeriod = JdbcSupport.getInteger(rs, "lockinPeriod");
Integer lockinPeriodTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodType"); Integer lockinPeriodTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodType");
EnumOptionData lockinPeriodType = SavingsDepositEnumerations.interestCompoundingPeriodType(lockinPeriodTypeValue); EnumOptionData lockinPeriodType = SavingsDepositEnumerations.interestCompoundingPeriodType(lockinPeriodTypeValue);
BigDecimal availableInterest = rs.getBigDecimal("availableInterest");
BigDecimal interestPostedAmount = rs.getBigDecimal("interestPostedAmount");
LocalDate lastInterestPostedDate = JdbcSupport.getLocalDate(rs, "lastInterestPostedDate");
LocalDate nextInterestPostedDate = JdbcSupport.getLocalDate(rs, "nextInterestPostedDate");
return new DepositAccountData(id, externalId, status, clientId, clientName, productId, productName, currencyData, return new DepositAccountData(id, externalId, status, clientId, clientName, productId, productName, currencyData,
depositAmount, interestRate, termInMonths, projectedCommencementDate, actualCommencementDate, maturedOn, depositAmount, interestRate, termInMonths, projectedCommencementDate, actualCommencementDate, maturedOn,
projectedInterestAccrued, actualInterestAccrued, projectedMaturityAmount, actualMaturityAmount, projectedInterestAccrued, actualInterestAccrued, projectedMaturityAmount, actualMaturityAmount,
interestCompoundedEvery, interestCompoundedEveryPeriodType, renewalAllowed, preClosureAllowed, preClosureInterestRate, interestCompoundedEvery, interestCompoundedEveryPeriodType, renewalAllowed, preClosureAllowed, preClosureInterestRate,
withdrawnonDate, rejectedonDate, closedonDate, isInterestWithdrawable, interestPaid, interestCompoundingAllowed, withdrawnonDate, rejectedonDate, closedonDate, isInterestWithdrawable, interestPaid, interestCompoundingAllowed,
isLockinPeriodAllowed, lockinPeriod, lockinPeriodType); isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, availableInterest, interestPostedAmount, lastInterestPostedDate, nextInterestPostedDate);
} }
} }
@@ -247,18 +254,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
boolean undoApprovalAllowed = (depositAccountData.getStatus().getId().equals(300L)); boolean undoApprovalAllowed = (depositAccountData.getStatus().getId().equals(300L));
boolean renewelAllowed = false; boolean renewelAllowed = false;
if (depositAccountData.getMaturedOn() != null) { if (depositAccountData.getMaturedOn() != null) {
if (new LocalDate().isAfter(depositAccountData.getMaturedOn())/* if (new LocalDate().isAfter(depositAccountData.getMaturedOn())/* || depositAccountData.getMaturedOn().isEqual(new LocalDate()) */) {
* ||
* depositAccountData
* .
* getMaturedOn
* ().
* isEqual
* (
* new
* LocalDate
* ())
*/) {
renewelAllowed = depositAccountData.isRenewalAllowed(); renewelAllowed = depositAccountData.isRenewalAllowed();
} }
} }
@@ -280,4 +276,28 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
return BigDecimal.valueOf(interstGettingForPeriod.multiply(new BigDecimal(noOfPeriods)).doubleValue() return BigDecimal.valueOf(interstGettingForPeriod.multiply(new BigDecimal(noOfPeriods)).doubleValue()
- account.getInterestPaid().doubleValue()); - account.getInterestPaid().doubleValue());
} }
@Override
public Collection<DepositAccountsForLookup> retrieveDepositAccountForLookup() {
this.context.authenticatedUser();
DepositAccountLookupMapper mapper = new DepositAccountLookupMapper();
String sql = "select "+mapper.depositAccountLookupSchema();
return this.jdbcTemplate.query(sql, mapper, new Object[]{});
}
private static final class DepositAccountLookupMapper implements RowMapper<DepositAccountsForLookup> {
public String depositAccountLookupSchema(){
return " da.id as id from m_deposit_account da where da.status_enum=300 and da.is_deleted=0";
}
@Override
public DepositAccountsForLookup mapRow(ResultSet rs, int rowNum) throws SQLException {
Long id = rs.getLong("id");
return new DepositAccountsForLookup(id);
}
}
} }
@@ -1,5 +1,7 @@
package org.mifosplatform.portfolio.savingsdepositaccount.service; package org.mifosplatform.portfolio.savingsdepositaccount.service;
import java.util.Collection;
import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.infrastructure.core.data.EntityIdentifier;
import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand; import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountCommand; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountCommand;
@@ -7,6 +9,7 @@ import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountW
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawalCommand; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountWithdrawalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommand; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountsForLookup;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
public interface DepositAccountWritePlatformService { public interface DepositAccountWritePlatformService {
@@ -49,4 +52,7 @@ public interface DepositAccountWritePlatformService {
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'RENEW_DEPOSITACCOUNT')") @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'RENEW_DEPOSITACCOUNT')")
EntityIdentifier renewDepositAccount(DepositAccountCommand command); EntityIdentifier renewDepositAccount(DepositAccountCommand command);
@PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')")
EntityIdentifier postInterestToDepositAccount(Collection<DepositAccountsForLookup> accounts);
} }
@@ -2,6 +2,7 @@ package org.mifosplatform.portfolio.savingsdepositaccount.service;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.List; import java.util.List;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
@@ -24,6 +25,7 @@ import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTra
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommandValidator; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommandValidator;
import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand;
import org.mifosplatform.portfolio.savingsdepositaccount.command.WithDrawDepositAccountInterestCommandValidator; import org.mifosplatform.portfolio.savingsdepositaccount.command.WithDrawDepositAccountInterestCommandValidator;
import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountsForLookup;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccount; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccount;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountRepository; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountRepository;
import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus;
@@ -303,9 +305,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
"deposit.transaction.canot.withdraw.before.lockinperiod.reached", "deposit.transaction.canot.withdraw.before.lockinperiod.reached",
"You can not withdraw your application before maturity date reached"); } "You can not withdraw your application before maturity date reached"); }
} }
if (eventDate.isBefore(account.maturesOnDate())) { // if (eventDate.isBefore(account.maturesOnDate())) {
this.depositAccountAssembler.adjustTotalAmountForPreclosureInterest(account, eventDate); // this.depositAccountAssembler.adjustTotalAmountForPreclosureInterest(account, eventDate);
} // }
account.withdrawDepositAccountMoney(defaultDepositLifecycleStateMachine(), fixedTermDepositInterestCalculator, eventDate); account.withdrawDepositAccountMoney(defaultDepositLifecycleStateMachine(), fixedTermDepositInterestCalculator, eventDate);
this.depositAccountRepository.save(account); this.depositAccountRepository.save(account);
String noteText = command.getNote(); String noteText = command.getNote();
@@ -419,4 +421,26 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
return new EntityIdentifier(Long.valueOf(-1)); return new EntityIdentifier(Long.valueOf(-1));
} }
} }
@Transactional
@Override
public EntityIdentifier postInterestToDepositAccount(Collection<DepositAccountsForLookup> accounts) {
try {
for (DepositAccountsForLookup accountData : accounts)
{
DepositAccount account = this.depositAccountRepository.findOne(accountData.getId());
if (account == null || account.isDeleted()) {
throw new DepositAccountNotFoundException(accountData.getId());
}
this.depositAccountAssembler.postInterest(account);
this.depositAccountRepository.save(account);
}
return new EntityIdentifier(new Long(accounts.size()));
} catch (Exception e) {
return new EntityIdentifier(Long.valueOf(-1));
}
}
} }