From d1a1ed60abba749541a89ecf469c337711fbbb48 Mon Sep 17 00:00:00 2001 From: Madhukar Date: Tue, 4 Dec 2012 15:10:06 +0000 Subject: [PATCH] Madhukars interest posting for fixed deposit and recurrint deposit work. --- api-docs/apiLive.htm | 3 + .../patch-05-saving-schedule-creation.sql | 18 + ...GsonPortfolioApiJsonSerializerService.java | 11 + ...PortfolioApiDataConversionServiceImpl.java | 5 +- .../PortfolioApiJsonSerializerService.java | 4 + .../api/SavingsAccountApiResource.java | 228 ++++--- .../CalculateSavingScheduleCommand.java | 63 ++ .../command/SavingAccountCommand.java | 389 ++++++------ .../data/SavingScheduleData.java | 34 + .../data/SavingSchedulePeriodData.java | 41 ++ .../domain/DepositScheduleDateGenerator.java | 12 + .../savingsaccount/domain/SavingAccount.java | 596 ++++++++++-------- .../domain/SavingScheduleInstallments.java | 60 ++ .../service/CalculateSavingSchedule.java | 10 + .../service/CalculateSavingScheduleImpl.java | 62 ++ .../DefaultDepositScheduleDateGenerator.java | 47 ++ .../service/SavingAccountAssembler.java | 360 ++++++----- .../SavingProductRelatedDetailAssembler.java | 44 ++ .../service/SavingScheduleGenerator.java | 58 ++ .../api/DepositAccountsApiResource.java | 12 + .../data/DepositAccountData.java | 150 +++-- .../data/DepositAccountsForLookup.java | 15 + .../domain/DepositAccount.java | 200 +++++- .../domain/DepositAccountTransaction.java | 4 + .../domain/DepositAccountTransactionType.java | 7 +- .../service/DepositAccountAssembler.java | 10 +- .../DepositAccountReadPlatformService.java | 3 + ...DepositAccountReadPlatformServiceImpl.java | 46 +- .../DepositAccountWritePlatformService.java | 6 + ...WritePlatformServiceJpaRepositoryImpl.java | 30 +- 30 files changed, 1683 insertions(+), 845 deletions(-) create mode 100644 mifosng-db/patches/patch-05-saving-schedule-creation.sql create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/command/CalculateSavingScheduleCommand.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/data/SavingScheduleData.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/data/SavingSchedulePeriodData.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/DepositScheduleDateGenerator.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/SavingScheduleInstallments.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/CalculateSavingSchedule.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/CalculateSavingScheduleImpl.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/DefaultDepositScheduleDateGenerator.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingProductRelatedDetailAssembler.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingScheduleGenerator.java create mode 100644 mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/data/DepositAccountsForLookup.java diff --git a/api-docs/apiLive.htm b/api-docs/apiLive.htm index 7e7fbc5b6..a5d317283 100644 --- a/api-docs/apiLive.htm +++ b/api-docs/apiLive.htm @@ -123,6 +123,9 @@ function getBaseURL(docURL) offices/{officeId}Retrieve an OfficeUpdate an Office LOAN PRODUCTloanproductsCreate a Loan ProductList Loan Products loanproducts/{productId}Retrieve a Loan ProductUpdate a Loan Product + + FIXED DEPOSITSdepositaccountsCreate a New Deposit ApplicationList Deposit Applications + depositaccounts/{accountId}Approve, Undo Approve, Interest withdraw, Reject a Deposit Application or Withdraw a Deposit ApplicationRetrieve a Deposit Application Update a Deposit ApplicationDelete a Deposit Application diff --git a/mifosng-db/patches/patch-05-saving-schedule-creation.sql b/mifosng-db/patches/patch-05-saving-schedule-creation.sql new file mode 100644 index 000000000..f6fb8f414 --- /dev/null +++ b/mifosng-db/patches/patch-05-saving-schedule-creation.sql @@ -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; \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/GoogleGsonPortfolioApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/GoogleGsonPortfolioApiJsonSerializerService.java index 224cc4e8c..a0bf39812 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/GoogleGsonPortfolioApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/GoogleGsonPortfolioApiJsonSerializerService.java @@ -31,6 +31,7 @@ import org.mifosplatform.portfolio.loanaccount.gaurantor.data.GuarantorData; import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleData; import org.mifosplatform.portfolio.loanproduct.data.LoanProductData; import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData; +import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData; import org.mifosplatform.portfolio.savingsaccountproduct.data.SavingProductData; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData; import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData; @@ -166,6 +167,9 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi private static final Set GUARANTOR_DATA_PARAMETERS = new HashSet(Arrays.asList("externalGuarantor", "existingClientId", "firstname", "lastname", "addressLine1", "addressLine2", "city", "state", "zip", "country", "mobileNumber", "housePhoneNumber", "comment", "dob")); + + private static final Set SAVING_SCHEDULE_DATA_PARAMETERS = new HashSet(Arrays.asList("periods", + "cumulativeDepositDue")); private final GoogleGsonSerializerHelper helper; @@ -555,4 +559,11 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi prettyPrint, responseParameters); return helper.serializedJsonFrom(gsonDeserializer, guarantorData); } + + @Override + public String serializeSavingScheduleDataToJson(boolean prettyPrint, Set responseParameters, SavingScheduleData savingScheduleData) { + final Gson gsonDeserializer = helper.createGsonBuilderWithParameterExclusionSerializationStrategy(SAVING_SCHEDULE_DATA_PARAMETERS, + prettyPrint, responseParameters); + return helper.serializedJsonFrom(gsonDeserializer, savingScheduleData); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionServiceImpl.java index da02272a8..91dd7d2ae 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionServiceImpl.java @@ -1528,7 +1528,7 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo "digitsAfterDecimal", "savingsDepositAmountPerPeriod", "recurringInterestRate", "savingInterestRate", "tenure", "commencementDate", "locale", "dateFormat", "isLockinPeriodAllowed", "lockinPeriod", "lockinPeriodType", "savingProductType", "tenureType", "frequency", "interestType", "interestCalculationMethod", "minimumBalanceForWithdrawal", - "isPartialDepositAllowed")); + "isPartialDepositAllowed","payEvery")); checkForUnsupportedParameters(requestMap, supportedParams); Set modifiedParameters = new HashSet(); @@ -1554,11 +1554,12 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo Integer interestCalculationMethod = extractIntegerParameter("interestCalculationMethod", requestMap, modifiedParameters); BigDecimal minimumBalanceForWithdrawal = extractBigDecimalParameter("minimumBalanceForWithdrawal", requestMap, modifiedParameters); boolean isPartialDepositAllowed = extractBooleanParameter("isPartialDepositAllowed", requestMap, modifiedParameters); + Integer payEvery = extractIntegerParameter("payEvery", requestMap, modifiedParameters); return new SavingAccountCommand(modifiedParameters, resourceIdentifier, clientId, productId, externalId, currencyCode, digitsAfterDecimalValue, savingsDepositAmount, recurringInterestRate, savingInterestRate, tenure, commencementDate, savingProductType, tenureType, frequency, interestType, minimumBalanceForWithdrawal, interestCalculationMethod, - isLockinPeriodAllowed, isPartialDepositAllowed, lockinPeriod, lockinPeriodType); + isLockinPeriodAllowed, isPartialDepositAllowed, lockinPeriod, lockinPeriodType,payEvery); } @Override diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiJsonSerializerService.java index f76b0cd7c..8601242c6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiJsonSerializerService.java @@ -5,6 +5,7 @@ import java.util.Set; import org.mifosplatform.commands.data.CommandSourceData; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; + import org.mifosplatform.infrastructure.dataqueries.data.DatatableData; import org.mifosplatform.infrastructure.dataqueries.data.GenericResultsetData; 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.loanproduct.data.LoanProductData; 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.savingsdepositaccount.data.DepositAccountData; import org.mifosplatform.portfolio.savingsdepositproduct.data.DepositProductData; @@ -153,4 +155,6 @@ public interface PortfolioApiJsonSerializerService { String serializeGuarantorDataToJson(boolean prettyPrint, Set responseParameters, GuarantorData guarantorData); + String serializeSavingScheduleDataToJson(boolean prettyPrint, Set responseParameters, SavingScheduleData savingScheduleData); + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/api/SavingsAccountApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/api/SavingsAccountApiResource.java index 9f200c6e5..93c84a2a4 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/api/SavingsAccountApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/api/SavingsAccountApiResource.java @@ -18,13 +18,17 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import org.apache.commons.lang.StringUtils; import org.mifosplatform.infrastructure.core.api.ApiParameterHelper; import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService; import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.mifosplatform.portfolio.savingsaccount.command.CalculateSavingScheduleCommand; import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand; 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.SavingAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; @@ -35,114 +39,136 @@ import org.springframework.stereotype.Component; @Component @Scope("singleton") public class SavingsAccountApiResource { + + @Autowired + private SavingAccountWritePlatformService savingAccountWritePlatformService; + + @Autowired + private SavingAccountReadPlatformService savingAccountReadPlatformService; + + @Autowired + private PortfolioApiDataConversionService apiDataConversionService; + + @Autowired + private PortfolioApiJsonSerializerService apiJsonSerializerService; - @Autowired - private SavingAccountWritePlatformService savingAccountWritePlatformService; - - @Autowired - private SavingAccountReadPlatformService savingAccountReadPlatformService; - - @Autowired - private PortfolioApiDataConversionService apiDataConversionService; - - @Autowired - private PortfolioApiJsonSerializerService apiJsonSerializerService; - - private final String entityType = "SAVINGSACCOUNT"; - @Autowired - private PlatformSecurityContext context; - - private static final Set typicalResponseParameters = new HashSet(Arrays.asList("id", "status", "externalId", - "clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod", - "savingsFrequencyType", "totalDepositAmount", "reccuringInterestRate", "savingInterestRate", "interestType", - "interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate", "actualCommencementDate", "maturesOnDate", - "projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount", - "preClosureAllowed", "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed", - "lockinPeriod", "lockinPeriodType")); - - @POST - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response createSavingAccount(final String jsonRequestBody) { - - final SavingAccountCommand command = this.apiDataConversionService.convertJsonToSavingAccountCommand(null, jsonRequestBody); - - EntityIdentifier entityIdentifier = this.savingAccountWritePlatformService.createSavingAccount(command); - - return Response.ok().entity(entityIdentifier).build(); - } - - @PUT - @Path("{accountId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response updateSavingAccount(@PathParam("accountId") final Long accountId, final String jsonRequestBody) { - - final SavingAccountCommand command = this.apiDataConversionService.convertJsonToSavingAccountCommand(accountId, jsonRequestBody); - - EntityIdentifier entityIdentifier = this.savingAccountWritePlatformService.updateSavingAccount(command); - - return Response.ok().entity(entityIdentifier).build(); - } - - @GET - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveAllDepositAccounts(@Context final UriInfo uriInfo) { - - context.authenticatedUser().validateHasReadPermission(entityType); - - Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); - if (responseParameters.isEmpty()) { - responseParameters.addAll(typicalResponseParameters); + private final String entityType = "SAVINGSACCOUNT"; + + @Autowired + private PlatformSecurityContext context; + + @Autowired + private CalculateSavingSchedule calculateSavingSchedule; + + private static final Set typicalResponseParameters = new HashSet( + Arrays.asList("id", "status", "externalId", "clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod", "savingsFrequencyType", + "totalDepositAmount", "reccuringInterestRate", "savingInterestRate", "interestType", "interestCalculationMethod", "tenure", "tenureType", "projectedCommencementDate", + "actualCommencementDate", "maturesOnDate", "projectedInterestAccuredOnMaturity", "actualInterestAccured", "projectedMaturityAmount", "actualMaturityAmount", "preClosureAllowed", + "preClosureInterestRate", "withdrawnonDate", "rejectedonDate", "closedonDate", "isLockinPeriodAllowed", "lockinPeriod", "lockinPeriodType")); + + @POST + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public String createSavingAccount(@QueryParam("command") final String commandParam, + @Context final UriInfo uriInfo,final String jsonRequestBody){ + + final SavingAccountCommand command = this.apiDataConversionService.convertJsonToSavingAccountCommand(null, jsonRequestBody); + + if (is(commandParam, "calculateSavingSchedule")) { + CalculateSavingScheduleCommand calculateSavingScheduleCommand = command.toCalculateSavingScheduleCommand(); + return calculateSavingSchedule(uriInfo,calculateSavingScheduleCommand); } - 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 responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); + boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + + return this.apiJsonSerializerService.serializeSavingScheduleDataToJson(prettyPrint, responseParameters, savingScheduleData); + } - Collection 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 responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); + if (responseParameters.isEmpty()) { + responseParameters.addAll(typicalResponseParameters); + } + boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); - @GET - @Path("{accountId}") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveDepositAccount(@PathParam("accountId") final Long accountId, @Context final UriInfo uriInfo) { + Collection accounts = this.savingAccountReadPlatformService.retrieveAllSavingsAccounts(); + + return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, accounts); + } + + @GET + @Path("{accountId}") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public String retrieveDepositAccount(@PathParam("accountId") final Long accountId, @Context final UriInfo uriInfo) { - context.authenticatedUser().validateHasReadPermission(entityType); + context.authenticatedUser().validateHasReadPermission(entityType); + + Set 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 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()) { - responseParameters.addAll(typicalResponseParameters); - } - boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); - - SavingAccountData account = this.savingAccountReadPlatformService.retrieveSavingsAccount(accountId); - - return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, account); - } - - @SuppressWarnings("unused") - @GET - @Path("template") - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveNewDepositAccountDetails(@QueryParam("clientId") final Long clientId, - @QueryParam("productId") final Long productId, @Context final UriInfo uriInfo) { - - context.authenticatedUser().validateHasReadPermission(entityType); - - Set 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); + context.authenticatedUser().validateHasReadPermission(entityType); + + Set 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); + } + + private boolean is(final String commandParam, final String commandValue) { + return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/command/CalculateSavingScheduleCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/command/CalculateSavingScheduleCommand.java new file mode 100644 index 000000000..ea5408b77 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/command/CalculateSavingScheduleCommand.java @@ -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; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/command/SavingAccountCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/command/SavingAccountCommand.java index e4d83362f..866e548bb 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/command/SavingAccountCommand.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/command/SavingAccountCommand.java @@ -6,224 +6,245 @@ import java.util.Set; import org.joda.time.LocalDate; public class SavingAccountCommand { + + + private final Long id; + private final Long clientId; + private final Long productId; + private final String externalId; - private final Long id; - private final Long clientId; - private final Long productId; - private final String externalId; + private final String currencyCode; + private final Integer digitsAfterDecimal; + private final BigDecimal savingsDepositAmount; + private final BigDecimal recurringInterestRate; + private final BigDecimal savingInterestRate; + private final Integer tenure; + + private final boolean isLockinPeriodAllowed; + private final Integer lockinPeriod; + private final Integer lockinPeriodType; + + private final LocalDate commencementDate; + private final Integer savingProductType; + private final Integer tenureType; + private final Integer frequency; + private final Integer interestType; + + private final Integer interestCalculationMethod; + private final BigDecimal minimumBalanceForWithdrawal; + private final boolean isPartialDepositAllowed; + private final Integer payEvery; + + private final Set modifiedParameters; + + public SavingAccountCommand(final Set 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; - private final Integer digitsAfterDecimal; - private final BigDecimal savingsDepositAmount; - private final BigDecimal recurringInterestRate; - private final BigDecimal savingInterestRate; - private final Integer tenure; + public Long getId() { + return id; + } - private final boolean isLockinPeriodAllowed; - private final Integer lockinPeriod; - private final Integer lockinPeriodType; + public Long getClientId() { + return clientId; + } - private final LocalDate commencementDate; - private final Integer savingProductType; - private final Integer tenureType; - private final Integer frequency; - private final Integer interestType; + public Long getProductId() { + return productId; + } - private final Integer interestCalculationMethod; - private final BigDecimal minimumBalanceForWithdrawal; - private final boolean isPartialDepositAllowed; + public String getExternalId() { + return externalId; + } - private final Set modifiedParameters; + public String getCurrencyCode() { + return currencyCode; + } - public SavingAccountCommand(final Set modifiedParameters, final Long id, final Long clientId, final Long productId, - final String externalId, final String currencyCode, final Integer digitsAfterDecimal, final BigDecimal savingsDepositAmount, - final BigDecimal recurringInterestRate, final BigDecimal savingInterestRate, final Integer tenure, - final LocalDate commencementDate, final Integer savingProductType, final Integer tenureType, final Integer frequency, - final Integer interestType, final BigDecimal minimumBalanceForWithdrawal, final Integer interestCalculationMethod, - final boolean isLockinPeriodAllowed, final boolean isPartialDepositAllowed, final Integer lockInPeriod, - final Integer lockinPeriodType) { - this.id = id; - this.clientId = clientId; - this.productId = productId; - this.externalId = externalId; + public Integer getDigitsAfterDecimal() { + return digitsAfterDecimal; + } - this.currencyCode = currencyCode; - this.digitsAfterDecimal = digitsAfterDecimal; - this.savingsDepositAmount = savingsDepositAmount; - this.recurringInterestRate = recurringInterestRate; - this.savingInterestRate = savingInterestRate; - this.tenure = tenure; + public BigDecimal getSavingsDepositAmount() { + return savingsDepositAmount; + } - this.modifiedParameters = modifiedParameters; - this.commencementDate = commencementDate; + public BigDecimal getRecurringInterestRate() { + return recurringInterestRate; + } - this.savingProductType = savingProductType; - this.tenureType = tenureType; - this.frequency = frequency; - this.interestType = interestType; - this.isPartialDepositAllowed = isPartialDepositAllowed; + public BigDecimal getSavingInterestRate() { + return savingInterestRate; + } - this.isLockinPeriodAllowed = isLockinPeriodAllowed; - this.lockinPeriod = lockInPeriod; - this.lockinPeriodType = lockinPeriodType; - this.minimumBalanceForWithdrawal = minimumBalanceForWithdrawal; - this.interestCalculationMethod = interestCalculationMethod; - } + public Integer getTenure() { + return tenure; + } - public Long getId() { - return id; - } + public boolean isLockinPeriodAllowed() { + return isLockinPeriodAllowed; + } - public Long getClientId() { - return clientId; - } + public Integer getLockinPeriod() { + return lockinPeriod; + } - public Long getProductId() { - return productId; - } + public Integer getLockinPeriodType() { + return lockinPeriodType; + } - public String getExternalId() { - return externalId; - } + public LocalDate getCommencementDate() { + return commencementDate; + } - public String getCurrencyCode() { - return currencyCode; - } + public Integer getSavingProductType() { + return savingProductType; + } - public Integer getDigitsAfterDecimal() { - return digitsAfterDecimal; - } + public Integer getTenureType() { + return tenureType; + } - public BigDecimal getSavingsDepositAmount() { - return savingsDepositAmount; - } + public Integer getFrequency() { + return frequency; + } - public BigDecimal getRecurringInterestRate() { - return recurringInterestRate; - } + public Integer getInterestType() { + return interestType; + } - public BigDecimal getSavingInterestRate() { - return savingInterestRate; - } + public Integer getInterestCalculationMethod() { + return interestCalculationMethod; + } - public Integer getTenure() { - return tenure; - } + public BigDecimal getMinimumBalanceForWithdrawal() { + return minimumBalanceForWithdrawal; + } - public boolean isLockinPeriodAllowed() { - return isLockinPeriodAllowed; - } + public boolean isPartialDepositAllowed() { + return isPartialDepositAllowed; + } - public Integer getLockinPeriod() { - return lockinPeriod; - } + public Integer getPayEvery() { + return this.payEvery; + } - public Integer getLockinPeriodType() { - return lockinPeriodType; - } + public boolean isNoFieldChanged() { + return this.modifiedParameters.isEmpty(); + } + + public boolean isProductIdChanged(){ + return this.modifiedParameters.contains("productId"); + } + + public boolean isExternalIdChanged(){ + return this.modifiedParameters.contains("externalId"); + } + + public boolean isDepositAmountChanged(){ + return this.modifiedParameters.contains("deposit"); + } - public LocalDate getCommencementDate() { - return commencementDate; - } + 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 Integer getSavingProductType() { - return savingProductType; - } + public boolean isTenureTypeEnumChanged() { + return this.modifiedParameters.contains("tenureType"); + } - public Integer getTenureType() { - return tenureType; - } + public boolean isSavingProductTypeChanged() { + return this.modifiedParameters.contains("savingProductType"); + } - public Integer getFrequency() { - return frequency; - } + public boolean isSavingFrequencyTypeChanged() { + return this.modifiedParameters.contains("frequency"); + } - public Integer getInterestType() { - return interestType; - } + public boolean isSavingInterestCalculationMethodChanged() { + return this.modifiedParameters.contains("interestCalculationMethod"); + } - public Integer getInterestCalculationMethod() { - return interestCalculationMethod; - } + public boolean isReccuringInterestRateChanged() { + return this.modifiedParameters.contains("recurringInterestRate"); + } - public BigDecimal getMinimumBalanceForWithdrawal() { - return minimumBalanceForWithdrawal; - } + public boolean isSavingInterestRateChanged() { + return this.modifiedParameters.contains("savingInterestRate"); + } - public boolean isPartialDepositAllowed() { - return isPartialDepositAllowed; - } + public boolean isLockinPeriodAllowedChanged() { + return this.modifiedParameters.contains("isLockinPeriodAllowed"); + } - public boolean isNoFieldChanged() { - return this.modifiedParameters.isEmpty(); - } + public boolean isLockinPeriodTypeChanged() { + return this.modifiedParameters.contains("lockinPeriodType"); + } - public boolean isProductIdChanged() { - return this.modifiedParameters.contains("productId"); - } + public boolean isPartialDepositAllowedChanged() { + return this.modifiedParameters.contains("isPartialDepositAllowed"); + } + + public boolean isPayEveryChanged(){ + return this.modifiedParameters.contains("payEvery"); + } - public boolean isExternalIdChanged() { - return this.modifiedParameters.contains("externalId"); - } - - public boolean isDepositAmountChanged() { - return this.modifiedParameters.contains("deposit"); - } - - public boolean isTenureInMonthsChanged() { - return this.modifiedParameters.contains("tenureInMonths"); - } - - public boolean isLockinPeriodChanged() { - return this.modifiedParameters.contains("lockinPeriod"); - } - - public boolean isPreClosureInterestRateChanged() { - return this.modifiedParameters.contains("preClosureInterestRate"); - } - - public boolean isPreClosureAllowedChanged() { - return this.modifiedParameters.contains("preClosureAllowed"); - } - - public boolean isCommencementDateChanged() { - return this.modifiedParameters.contains("commencementDate"); - } - - public boolean isTenureTypeEnumChanged() { - return this.modifiedParameters.contains("tenureType"); - } - - public boolean isSavingProductTypeChanged() { - return this.modifiedParameters.contains("savingProductType"); - } - - public boolean isSavingFrequencyTypeChanged() { - return this.modifiedParameters.contains("frequency"); - } - - public boolean isSavingInterestCalculationMethodChanged() { - return this.modifiedParameters.contains("interestCalculationMethod"); - } - - public boolean isReccuringInterestRateChanged() { - return this.modifiedParameters.contains("recurringInterestRate"); - } - - public boolean isSavingInterestRateChanged() { - return this.modifiedParameters.contains("savingInterestRate"); - } - - public boolean isLockinPeriodAllowedChanged() { - return this.modifiedParameters.contains("isLockinPeriodAllowed"); - } - - public boolean isLockinPeriodTypeChanged() { - return this.modifiedParameters.contains("lockinPeriodType"); - } - - public boolean isPartialDepositAllowedChanged() { - return this.modifiedParameters.contains("isPartialDepositAllowed"); - } + public CalculateSavingScheduleCommand toCalculateSavingScheduleCommand() { + return new CalculateSavingScheduleCommand(productId, savingsDepositAmount, payEvery, frequency, recurringInterestRate, commencementDate,tenure); + } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/data/SavingScheduleData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/data/SavingScheduleData.java new file mode 100644 index 000000000..8ce7184f7 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/data/SavingScheduleData.java @@ -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 periods; + + public SavingScheduleData(final CurrencyData currency, final BigDecimal cumulativeDepositDue, + final Collection periods) { + this.currency = currency; + this.cumulativeDepositDue= cumulativeDepositDue; + this.periods= periods; + + } + + public CurrencyData getCurrency() { + return this.currency; + } + + public BigDecimal getCumulativeDepositDue() { + return this.cumulativeDepositDue; + } + + public Collection getPeriods() { + return this.periods; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/data/SavingSchedulePeriodData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/data/SavingSchedulePeriodData.java new file mode 100644 index 000000000..4708c05db --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/data/SavingSchedulePeriodData.java @@ -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; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/DepositScheduleDateGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/DepositScheduleDateGenerator.java new file mode 100644 index 000000000..de9c3ad00 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/DepositScheduleDateGenerator.java @@ -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 generate(LocalDate startDate, Integer paymentPeriods, Integer depositFrequency, PeriodFrequencyType depositFrequencyType); + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/SavingAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/SavingAccount.java index 3e2ebba86..a99657aba 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/SavingAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/SavingAccount.java @@ -1,18 +1,24 @@ package org.mifosplatform.portfolio.savingsaccount.domain; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Date; +import java.util.List; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import javax.persistence.UniqueConstraint; +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom; import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; @@ -31,307 +37,345 @@ import org.mifosplatform.portfolio.savingsdepositproduct.domain.TenureTypeEnum; import org.mifosplatform.useradministration.domain.AppUser; @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 { + + @ManyToOne + @JoinColumn(name = "client_id", nullable = false) + private Client client; - @ManyToOne - @JoinColumn(name = "client_id", nullable = false) - private Client client; + @ManyToOne + @JoinColumn(name = "product_id") + private SavingProduct product; + + // FIXME - MADHUKAR - Do not use the actual enum type here but instead use Integer e.g. private Integer savingProductType; + @Column(name = "savings_product_type", nullable=false) + private SavingProductType savingProductType; + + @Column(name = "external_id") + private String externalId; + + @SuppressWarnings("unused") + @Embedded + private MonetaryCurrency currency; + + @Column(name = "deposit_amount_per_period", scale = 6, precision = 19, nullable = false) + private BigDecimal savingsDepositAmountPerPeriod; + + @SuppressWarnings("unused") + @Column(name = "total_deposit_amount", scale = 6, precision = 19, nullable = false) + private BigDecimal totalSavingsAmount; + + @Column(name = "reccuring_nominal_interest_rate", scale = 6, precision = 19, nullable = false) + private BigDecimal reccuringInterestRate; + + @Column(name = "regular_saving_nominal_interest_rate", scale = 6, precision = 19, nullable = false) + private BigDecimal savingInterestRate; + + @Column(name = "tenure", nullable=false) + private Integer tenure; + + @Column(name = "tenure_type", nullable=false) + private TenureTypeEnum tenureType; + + // FIXME - MADHUKAR - Do not use the actual enum type here but instead use Integer e.g. private Integer savingProductType; + @Column(name = "frequency", nullable=false) + private SavingFrequencyType frequency; + + // FIXME - MADHUKAR - Do not use the actual enum type here but instead use Integer e.g. private Integer savingProductType; + @Column(name = "interest_type", nullable=false) + private SavingsInterestType interestType; + + // FIXME - MADHUKAR - Do not use the actual enum type here but instead use Integer e.g. private Integer savingProductType; + @Column(name = "interest_calculation_method") + private SavingInterestCalculationMethod interestCalculationMethod; + + @Temporal(TemporalType.DATE) + @Column(name = "projected_commencement_date") + private Date projectedCommencementDate; + + @SuppressWarnings("unused") + @Temporal(TemporalType.DATE) + @Column(name = "actual_commencement_date") + private Date actualCommencementDate; + + @SuppressWarnings("unused") + @Temporal(TemporalType.DATE) + @Column(name = "matures_on_date") + private Date maturesOnDate; + + @SuppressWarnings("unused") + @Column(name = "projected_interest_accrued_on_maturity", scale = 6, precision = 19, nullable = false) + private BigDecimal projectedInterestAccruedOnMaturity; + + @SuppressWarnings("unused") + @Column(name = "actual_interest_accrued", scale = 6, precision = 19, nullable = false) + private BigDecimal interestAccrued; + + @SuppressWarnings("unused") + @Column(name = "projected_total_maturity_amount", scale = 6, precision = 19, nullable = false) + private BigDecimal projectedTotalOnMaturity; + + @SuppressWarnings("unused") + @Column(name = "actual_total_amount", scale = 6, precision = 19, nullable = false) + private BigDecimal total; + + @Column(name = "pre_closure_interest_rate", scale = 6, precision = 19, nullable = false) + private BigDecimal preClosureInterestRate; + + @Column(name = "is_preclosure_allowed", nullable = false) + private boolean preClosureAllowed = false; + + @Column(name = "is_deleted", nullable=false) + private boolean deleted = false; + + @Column(name = "status_enum", nullable = false) + private Integer accountStatus; + + @SuppressWarnings("unused") + @Temporal(TemporalType.DATE) + @Column(name = "closedon_date") + private Date closedOnDate; + + @SuppressWarnings("unused") + @Temporal(TemporalType.DATE) + @Column(name = "rejectedon_date") + private Date rejectedOnDate; + + @Temporal(TemporalType.DATE) + @Column(name = "withdrawnon_date") + private Date withdrawnOnDate; - @ManyToOne - @JoinColumn(name = "product_id") - private SavingProduct product; + @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; + + // 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 = new ArrayList(); - // 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; + 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); + } - @SuppressWarnings("unused") - @Embedded - private MonetaryCurrency currency; + 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); + } - @Column(name = "deposit_amount_per_period", scale = 6, precision = 19, nullable = false) - private BigDecimal savingsDepositAmountPerPeriod; + 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; + } - @SuppressWarnings("unused") - @Column(name = "total_deposit_amount", scale = 6, precision = 19, nullable = false) - private BigDecimal totalSavingsAmount; + public boolean isPendingApproval() { + return this.accountStatus.equals(100); + } - @Column(name = "reccuring_nominal_interest_rate", scale = 6, precision = 19, nullable = false) - private BigDecimal reccuringInterestRate; + public Client getClient() { + return client; + } - @Column(name = "regular_saving_nominal_interest_rate", scale = 6, precision = 19, nullable = false) - private BigDecimal savingInterestRate; + public SavingProduct getProduct() { + return product; + } - @Column(name = "tenure", nullable = false) - private Integer tenure; + public SavingProductType getSavingProductType() { + return savingProductType; + } - @Column(name = "tenure_type", nullable = false) - private TenureTypeEnum tenureType; + public String getExternalId() { + return externalId; + } - // 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; + public BigDecimal getSavingsDepositAmountPerPeriod() { + return savingsDepositAmountPerPeriod; + } - // 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; + public BigDecimal getReccuringInterestRate() { + return reccuringInterestRate; + } - // 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; + public BigDecimal getSavingInterestRate() { + return savingInterestRate; + } - @Temporal(TemporalType.DATE) - @Column(name = "projected_commencement_date") - private Date projectedCommencementDate; + public Integer getTenure() { + return tenure; + } - @SuppressWarnings("unused") - @Temporal(TemporalType.DATE) - @Column(name = "actual_commencement_date") - private Date actualCommencementDate; + public TenureTypeEnum getTenureType() { + return tenureType; + } - @SuppressWarnings("unused") - @Temporal(TemporalType.DATE) - @Column(name = "matures_on_date") - private Date maturesOnDate; + public SavingFrequencyType getFrequency() { + return frequency; + } - @SuppressWarnings("unused") - @Column(name = "projected_interest_accrued_on_maturity", scale = 6, precision = 19, nullable = false) - private BigDecimal projectedInterestAccruedOnMaturity; + public SavingsInterestType getInterestType() { + return interestType; + } - @SuppressWarnings("unused") - @Column(name = "actual_interest_accrued", scale = 6, precision = 19, nullable = false) - private BigDecimal interestAccrued; + public SavingInterestCalculationMethod getInterestCalculationMethod() { + return interestCalculationMethod; + } - @SuppressWarnings("unused") - @Column(name = "projected_total_maturity_amount", scale = 6, precision = 19, nullable = false) - private BigDecimal projectedTotalOnMaturity; + public Date getProjectedCommencementDate() { + return projectedCommencementDate; + } - @SuppressWarnings("unused") - @Column(name = "actual_total_amount", scale = 6, precision = 19, nullable = false) - private BigDecimal total; + public BigDecimal getPreClosureInterestRate() { + return preClosureInterestRate; + } - @Column(name = "pre_closure_interest_rate", scale = 6, precision = 19, nullable = false) - private BigDecimal preClosureInterestRate; + public boolean isPreClosureAllowed() { + return preClosureAllowed; + } - @Column(name = "is_preclosure_allowed", nullable = false) - private boolean preClosureAllowed = false; + public Date getWithdrawnOnDate() { + return withdrawnOnDate; + } - @Column(name = "is_deleted", nullable = false) - private boolean deleted = false; + public boolean isLockinPeriodAllowed() { + return isLockinPeriodAllowed; + } - @Column(name = "status_enum", nullable = false) - private Integer accountStatus; + public Integer getLockinPeriod() { + return lockinPeriod; + } - @SuppressWarnings("unused") - @Temporal(TemporalType.DATE) - @Column(name = "closedon_date") - private Date closedOnDate; - - @SuppressWarnings("unused") - @Temporal(TemporalType.DATE) - @Column(name = "rejectedon_date") - private Date rejectedOnDate; - - @Temporal(TemporalType.DATE) - @Column(name = "withdrawnon_date") - private Date withdrawnOnDate; - - @Column(name = "is_lock_in_period_allowed", nullable = false) - private boolean isLockinPeriodAllowed = false; - - @Column(name = "lock_in_period", nullable = false) - private Integer lockinPeriod; - - @Column(name = "lock_in_period_type", nullable = false) - private PeriodFrequencyType lockinPeriodType; - - public static SavingAccount openNew(Client client, SavingProduct product, String externalId, Money savingsDeposit, - BigDecimal reccuringInterestRate, BigDecimal savingInterestRate, Integer tenure, LocalDate commencementDate, - TenureTypeEnum tenureTypeEnum, SavingProductType savingProductType, SavingFrequencyType savingFrequencyType, - SavingsInterestType interestType, SavingInterestCalculationMethod savingInterestCalculationMethod, - boolean isLockinPeriodAllowed, Integer lockinPeriod, PeriodFrequencyType lockinPeriodType, - ReccuringDepositInterestCalculator reccuringDepositInterestCalculator, final DepositLifecycleStateMachine lifecycleStateMachine) { - - Money futureValueOnMaturity = null; - if (savingProductType.isReccuring()) { - futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure, - reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod); - } else if (savingProductType.isRegular()) { - futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure, - savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod); - } - - return new SavingAccount(client, externalId, product, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure, - commencementDate, tenureTypeEnum, savingProductType, savingFrequencyType, interestType, savingInterestCalculationMethod, - isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, futureValueOnMaturity, lifecycleStateMachine); - } - - public SavingAccount(Client client, String externalId, SavingProduct product, Money savingsDeposit, BigDecimal reccuringInterestRate, - BigDecimal savingInterestRate, Integer tenure, LocalDate commencementDate, TenureTypeEnum tenureTypeEnum, - SavingProductType savingProductType, SavingFrequencyType savingFrequencyType, SavingsInterestType interestType, - SavingInterestCalculationMethod savingInterestCalculationMethod, boolean isLockinPeriodAllowed, Integer lockinPeriod, - PeriodFrequencyType lockinPeriodType, Money futureValueOnMaturity, final DepositLifecycleStateMachine lifecycleStateMachine) { - - DepositAccountStatus from = null; - if (accountStatus != null) { - from = DepositAccountStatus.fromInt(accountStatus); - } - - DepositAccountStatus statusEnum = lifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_CREATED, from); - accountStatus = statusEnum.getValue(); - - this.total = BigDecimal.ZERO; - this.preClosureInterestRate = BigDecimal.ZERO; - this.totalSavingsAmount = BigDecimal.ZERO; - this.interestAccrued = BigDecimal.ZERO; - - this.client = client; - this.externalId = externalId; - this.product = product; - this.savingsDepositAmountPerPeriod = savingsDeposit.getAmount(); - this.currency = savingsDeposit.getCurrency(); - this.reccuringInterestRate = reccuringInterestRate; - this.savingInterestRate = savingInterestRate; - this.tenure = tenure; - this.projectedCommencementDate = commencementDate.toDate(); - this.tenureType = tenureTypeEnum; - this.savingProductType = savingProductType; - this.frequency = savingFrequencyType; - this.interestType = interestType; - this.interestCalculationMethod = savingInterestCalculationMethod; - this.isLockinPeriodAllowed = isLockinPeriodAllowed; - this.lockinPeriod = lockinPeriod; - this.lockinPeriodType = lockinPeriodType; - this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount(); - this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.getAmount().subtract( - BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue())); - } - - public void modifyAccount(SavingProduct product, String externalId, Money savingsDeposit, BigDecimal reccuringInterestRate, - BigDecimal savingInterestRate, Integer tenure, LocalDate commencementDate, TenureTypeEnum tenureTypeEnum, - SavingProductType savingProductType, SavingFrequencyType savingFrequencyType, - SavingInterestCalculationMethod savingInterestCalculationMethod, boolean isLockinPeriodAllowed, Integer lockinPeriod, - PeriodFrequencyType lockinPeriodType, ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) { - - Money futureValueOnMaturity = null; - if (savingProductType.isReccuring()) { - futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure, - reccuringInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod); - } else if (savingProductType.isRegular()) { - futureValueOnMaturity = reccuringDepositInterestCalculator.calculateInterestOnMaturityFor(savingsDeposit, tenure, - savingInterestRate, commencementDate, tenureTypeEnum, savingFrequencyType, savingInterestCalculationMethod); - } - - this.product = product; - this.externalId = externalId; - this.savingsDepositAmountPerPeriod = savingsDeposit.getAmount(); - this.reccuringInterestRate = reccuringInterestRate; - this.savingInterestRate = savingInterestRate; - this.tenure = tenure; - this.projectedCommencementDate = commencementDate.toDate(); - this.tenureType = tenureTypeEnum; - this.savingProductType = savingProductType; - this.frequency = savingFrequencyType; - this.interestCalculationMethod = savingInterestCalculationMethod; - this.isLockinPeriodAllowed = isLockinPeriodAllowed; - this.lockinPeriod = lockinPeriod; - this.lockinPeriodType = lockinPeriodType; - - // FIXME - MADHUKAR - futureValueOnMaturity is possibly null - this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount(); - this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.getAmount().subtract( - BigDecimal.valueOf(savingsDeposit.getAmount().doubleValue() * tenure.doubleValue())); - } - - public boolean isDeleted() { - return this.deleted; - } - - public boolean isPendingApproval() { - return this.accountStatus.equals(100); - } - - public Client getClient() { - return client; - } - - public SavingProduct getProduct() { - return product; - } - - public SavingProductType getSavingProductType() { - return savingProductType; - } - - public String getExternalId() { - return externalId; - } - - public BigDecimal getSavingsDepositAmountPerPeriod() { - return savingsDepositAmountPerPeriod; - } - - public BigDecimal getReccuringInterestRate() { - return reccuringInterestRate; - } - - public BigDecimal getSavingInterestRate() { - return savingInterestRate; - } - - public Integer getTenure() { - return tenure; - } - - public TenureTypeEnum getTenureType() { - return tenureType; - } - - public SavingFrequencyType getFrequency() { - return frequency; - } - - public SavingsInterestType getInterestType() { - return interestType; - } - - public SavingInterestCalculationMethod getInterestCalculationMethod() { - return interestCalculationMethod; - } - - public Date getProjectedCommencementDate() { - return projectedCommencementDate; - } - - public BigDecimal getPreClosureInterestRate() { - return preClosureInterestRate; - } - - public boolean isPreClosureAllowed() { - return preClosureAllowed; - } - - public Date getWithdrawnOnDate() { - return withdrawnOnDate; - } - - public boolean isLockinPeriodAllowed() { - return isLockinPeriodAllowed; - } - - public Integer getLockinPeriod() { - return lockinPeriod; - } - - public PeriodFrequencyType getLockinPeriodType() { - return lockinPeriodType; - } + public PeriodFrequencyType getLockinPeriodType() { + return lockinPeriodType; + } + + public void addSavingScheduleInstallment(final SavingScheduleInstallments installment) { + installment.updateAccount(this); + this.savingScheduleInstallments.add(installment); + } + } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/SavingScheduleInstallments.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/SavingScheduleInstallments.java new file mode 100644 index 000000000..5f8390510 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/domain/SavingScheduleInstallments.java @@ -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 { + + @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; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/CalculateSavingSchedule.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/CalculateSavingSchedule.java new file mode 100644 index 000000000..9a75093f5 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/CalculateSavingSchedule.java @@ -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); + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/CalculateSavingScheduleImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/CalculateSavingScheduleImpl.java new file mode 100644 index 000000000..3d5baaa3c --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/CalculateSavingScheduleImpl.java @@ -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; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/DefaultDepositScheduleDateGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/DefaultDepositScheduleDateGenerator.java new file mode 100644 index 000000000..f236fa984 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/DefaultDepositScheduleDateGenerator.java @@ -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 generate(LocalDate scheuleStartDate, Integer paymentPeriods, Integer depositFrequency, PeriodFrequencyType depositFrequencyType) { + + List duePaymentPeriodDates = new ArrayList(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; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingAccountAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingAccountAssembler.java index 2691f1a32..4f46a6d59 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingAccountAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingAccountAssembler.java @@ -12,15 +12,18 @@ import org.mifosplatform.portfolio.client.domain.ClientRepository; import org.mifosplatform.portfolio.client.exception.ClientNotFoundException; import org.mifosplatform.portfolio.loanproduct.domain.PeriodFrequencyType; import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand; +import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData; +import org.mifosplatform.portfolio.savingsaccount.data.SavingSchedulePeriodData; import org.mifosplatform.portfolio.savingsaccount.domain.ReccuringDepositInterestCalculator; 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.SavingInterestCalculationMethod; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProduct; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductRepository; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingProductType; import org.mifosplatform.portfolio.savingsaccountproduct.domain.SavingsInterestType; -import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingsProductNotFoundException; +import org.mifosplatform.portfolio.savingsaccountproduct.exception.SavingProductNotFoundException; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachine; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositLifecycleStateMachineImpl; @@ -30,174 +33,191 @@ import org.springframework.stereotype.Service; @Service 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; - private final SavingProductRepository savingProductRepository; - private final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator; - - @Autowired - public SavingAccountAssembler(final ClientRepository clientRepository, final SavingProductRepository savingProductRepository, - final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) { - this.clientRepository = clientRepository; - this.savingProductRepository = savingProductRepository; - this.reccuringDepositInterestCalculator = reccuringDepositInterestCalculator; - } - - // minimumBalanceForWithdrawal,isPartialDepositAllowed - public SavingAccount assembleFrom(SavingAccountCommand command) { - - Client client = this.clientRepository.findOne(command.getClientId()); - if (client == null || client.isDeleted()) { throw new ClientNotFoundException(command.getClientId()); } - - SavingProduct product = this.savingProductRepository.findOne(command.getProductId()); - if (product == null || product.isDeleted()) { throw new SavingsProductNotFoundException(command.getProductId()); } - - MonetaryCurrency currency = product.getCurrency(); - if (command.getCurrencyCode() != null && command.getDigitsAfterDecimal() != null) { - currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal()); - } - - Money savingsDeposit = Money.of(currency, command.getSavingsDepositAmount()); - - Integer tenure = product.getSavingProductRelatedDetail().getTenure(); - if (command.getTenure() != null) { - tenure = command.getTenure(); - } - - TenureTypeEnum tenureTypeEnum = product.getSavingProductRelatedDetail().getTenureType(); - if (command.getTenureType() != null) { - tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType()); - } - - SavingProductType savingProductType = product.getSavingProductRelatedDetail().getSavingProductType(); - if (command.getSavingProductType() != null) { - savingProductType = SavingProductType.fromInt(command.getSavingProductType()); - } - - SavingFrequencyType savingFrequencyType = product.getSavingProductRelatedDetail().getFrequency(); - if (command.getFrequency() != null) { - savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency()); - } - - SavingInterestCalculationMethod savingInterestCalculationMethod = product.getSavingProductRelatedDetail() - .getInterestCalculationMethod(); - if (command.getInterestCalculationMethod() != null) { - savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod()); - } - - SavingsInterestType interestType = product.getSavingProductRelatedDetail().getInterestType(); - if (command.getInterestType() != null) { - interestType = SavingsInterestType.fromInt(command.getInterestType()); - } - - BigDecimal reccuringInterestRate = command.getRecurringInterestRate(); - BigDecimal savingInterestRate = product.getInterestRate(); - if (command.getSavingInterestRate() != null) savingInterestRate = command.getSavingInterestRate(); - - boolean isLockinPeriodAllowed = product.getSavingProductRelatedDetail().isLockinPeriodAllowed(); - if (command.isLockinPeriodChanged()) { - isLockinPeriodAllowed = command.isLockinPeriodAllowed(); - } - - Integer lockinPeriod = product.getSavingProductRelatedDetail().getLockinPeriod(); - if (command.getLockinPeriod() != null) { - lockinPeriod = command.getLockinPeriod(); - } - - PeriodFrequencyType lockinPeriodType = product.getSavingProductRelatedDetail().getLockinPeriodType(); - if (command.getLockinPeriodType() != null) { - lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType()); - } - - SavingAccount account = SavingAccount.openNew(client, product, command.getExternalId(), savingsDeposit, reccuringInterestRate, - savingInterestRate, tenure, command.getCommencementDate(), tenureTypeEnum, savingProductType, savingFrequencyType, - interestType, savingInterestCalculationMethod, isLockinPeriodAllowed, lockinPeriod, lockinPeriodType, - this.reccuringDepositInterestCalculator, defaultDepositLifecycleStateMachine()); - - return account; - } - - public void assembleFrom(SavingAccountCommand command, SavingAccount account) { - - SavingProduct product = account.getProduct(); - if (command.isProductIdChanged()) { - if (product.getId() != command.getProductId()) { - product = this.savingProductRepository.findOne(command.getProductId()); - if (product == null || product.isDeleted()) throw new SavingsProductNotFoundException(command.getProductId()); - } - } - - String externalId = account.getExternalId(); - if (command.isExternalIdChanged()) { - externalId = command.getExternalId(); - } - - Money savingsDeposit = Money.of(product.getCurrency(), account.getSavingsDepositAmountPerPeriod()); - if (command.isDepositAmountChanged()) { - savingsDeposit = Money.of(product.getCurrency(), command.getSavingsDepositAmount()); - } - Integer tenure = account.getTenure(); - if (command.isTenureInMonthsChanged()) { - tenure = command.getTenure(); - } - - LocalDate commencementDate = new LocalDate(account.getProjectedCommencementDate()); - if (command.isCommencementDateChanged()) { - commencementDate = command.getCommencementDate(); - } - - TenureTypeEnum tenureTypeEnum = account.getTenureType(); - if (command.isTenureTypeEnumChanged()) { - tenureTypeEnum = TenureTypeEnum.fromInt(command.getTenureType()); - } - - SavingProductType savingProductType = account.getSavingProductType(); - if (command.isSavingProductTypeChanged()) { - savingProductType = SavingProductType.fromInt(command.getSavingProductType()); - } - - SavingFrequencyType savingFrequencyType = account.getFrequency(); - if (command.isSavingFrequencyTypeChanged()) { - savingFrequencyType = SavingFrequencyType.fromInt(command.getFrequency()); - } - - SavingInterestCalculationMethod savingInterestCalculationMethod = account.getInterestCalculationMethod(); - if (command.isSavingInterestCalculationMethodChanged()) { - savingInterestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod()); - } - - BigDecimal reccuringInterestRate = account.getReccuringInterestRate(); - if (command.isReccuringInterestRateChanged()) { - reccuringInterestRate = command.getRecurringInterestRate(); - } - - BigDecimal savingInterestRate = account.getSavingInterestRate(); - if (command.isSavingInterestRateChanged()) { - savingInterestRate = command.getSavingInterestRate(); - } - - boolean isLockinPeriodAllowed = account.isLockinPeriodAllowed(); - if (command.isLockinPeriodAllowedChanged()) { - isLockinPeriodAllowed = command.isLockinPeriodAllowed(); - } - - Integer lockinPeriod = account.getLockinPeriod(); - if (command.isLockinPeriodChanged()) { - lockinPeriod = command.getLockinPeriod(); - } - - PeriodFrequencyType lockinPeriodType = account.getLockinPeriodType(); - if (command.isLockinPeriodTypeChanged()) { - lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType()); - } - account.modifyAccount(product, externalId, savingsDeposit, reccuringInterestRate, savingInterestRate, tenure, commencementDate, - tenureTypeEnum, savingProductType, savingFrequencyType, savingInterestCalculationMethod, isLockinPeriodAllowed, - lockinPeriod, lockinPeriodType, this.reccuringDepositInterestCalculator); - - } - - private DepositLifecycleStateMachine defaultDepositLifecycleStateMachine() { - List allowedDepositStatuses = Arrays.asList(DepositAccountStatus.values()); - return new DepositLifecycleStateMachineImpl(allowedDepositStatuses); - } + 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 SavingProductNotFoundException(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 allowedDepositStatuses = Arrays.asList(DepositAccountStatus.values()); + return new DepositLifecycleStateMachineImpl(allowedDepositStatuses); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingProductRelatedDetailAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingProductRelatedDetailAssembler.java new file mode 100644 index 000000000..9733fc603 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingProductRelatedDetailAssembler.java @@ -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; + } + + + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingScheduleGenerator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingScheduleGenerator.java new file mode 100644 index 000000000..b96b33942 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsaccount/service/SavingScheduleGenerator.java @@ -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 periods = new ArrayList(); + final List 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); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/api/DepositAccountsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/api/DepositAccountsApiResource.java index 408c9096d..a5c15de05 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/api/DepositAccountsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/api/DepositAccountsApiResource.java @@ -37,6 +37,7 @@ import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositAccountW import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionApprovalCommand; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData; +import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountsForLookup; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositPermissionData; import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountReadPlatformService; import org.mifosplatform.portfolio.savingsdepositaccount.service.DepositAccountWritePlatformService; @@ -257,5 +258,16 @@ public class DepositAccountsApiResource { private boolean is(final String commandParam, final String commandValue) { return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue); + } + @POST + @Path("postinterest") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public Response postInterest(){ + Collection accounts = this.depositAccountReadPlatformService.retrieveDepositAccountForLookup(); + @SuppressWarnings("unused") + EntityIdentifier entityIdentifier = this.depositAccountWritePlatformService.postInterestToDepositAccount(accounts); + return Response.ok().entity(entityIdentifier).build(); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/data/DepositAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/data/DepositAccountData.java index 93351dfe4..f196c87ee 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/data/DepositAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/data/DepositAccountData.java @@ -65,6 +65,11 @@ public class DepositAccountData { private final boolean isLockinPeriodAllowed; private final Integer lockinPeriod; 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, @@ -119,6 +124,11 @@ public class DepositAccountData { this.isLockinPeriodAllowed = true; this.lockinPeriod = 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 interestCompoundedEveryPeriodTypeOptions, @@ -166,6 +176,11 @@ public class DepositAccountData { this.lockinPeriod = account.getLockinPeriod(); this.lockinPeriodType = account.getLockinPeriodType(); 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, @@ -213,6 +228,11 @@ public class DepositAccountData { this.lockinPeriod = account.getLockinPeriod(); this.lockinPeriodType = account.getLockinPeriodType(); 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, @@ -224,7 +244,8 @@ public class DepositAccountData { final boolean preClosureAllowed, final BigDecimal preClosureInterestRate, final LocalDate withdrawnonDate, final LocalDate rejectedonDate, final LocalDate closedonDate, final boolean isInterestWithdrawable, final BigDecimal interestPaid, final boolean interestCompoundingAllowed, final boolean isLockinPeriodAllowed, - final Integer lockinPeriod, final EnumOptionData lockinPeriodType) { + final Integer lockinPeriod, final EnumOptionData lockinPeriodType,final BigDecimal availableInterest, + final BigDecimal interestPostedAmount, final LocalDate lastInterestPostedDate, final LocalDate nextInterestPostedDate) { this.id = id; this.externalId = externalId; this.status = status; @@ -269,6 +290,11 @@ public class DepositAccountData { this.isLockinPeriodAllowed = isLockinPeriodAllowed; this.lockinPeriod = lockinPeriod; 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, @@ -319,6 +345,11 @@ public class DepositAccountData { this.lockinPeriod = Integer.valueOf(0); this.isLockinPeriodAllowed = true; this.lockinPeriodType = interestCompoundedEveryPeriodType; + + this.availableInterest = BigDecimal.ZERO; + this.interestPostedAmount = BigDecimal.ZERO; + this.lastInterestPostedDate = null; + this.nextInterestPostedDate = null; } public Long getId() { @@ -477,68 +508,67 @@ public class DepositAccountData { return lockinPeriodType; } - private BigDecimal determineAvailableInterestForWithdrawal(final DepositAccountData account) { - BigDecimal availableInterestForWithdrawal = BigDecimal.ZERO; + public BigDecimal getAvailableInterest() { + return this.availableInterest; + } - 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(); + public BigDecimal getInterestPostedAmount() { + return this.interestPostedAmount; + } - availableInterestForWithdrawal = BigDecimal.valueOf(interestGettingForPeriod.multiply(new BigDecimal(noOfPeriods)) - .doubleValue() - account.getInterestPaid().doubleValue()); - } else { - return BigDecimal.ZERO; - } - } else - return BigDecimal.ZERO; + public LocalDate getLastInterestPostedDate() { + return this.lastInterestPostedDate; + } - 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) { - - BigDecimal avalablePreclosureWithdrawalAmount = BigDecimal.ZERO; - if (this.status != null) { - if (account.getStatus().getId() == 300) { - if (new LocalDate().isBefore(account.getMaturedOn()) || new LocalDate().isEqual(account.getMaturedOn())) { - MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN); - Integer monthsInYear = 12; - BigDecimal interestRateAsFraction = account.getPreClosureInterestRate().divide(BigDecimal.valueOf(100), mc); - BigDecimal interestRateForOneMonth = interestRateAsFraction.divide(BigDecimal.valueOf(monthsInYear.doubleValue()), mc); - Integer noOfMonthsforInterestCal = Months.monthsBetween(account.getActualCommencementDate(), new LocalDate()) - .getMonths(); - Integer days = Days.daysBetween(account.getActualCommencementDate().plusMonths(noOfMonthsforInterestCal), - new LocalDate()).getDays(); - BigDecimal interest = BigDecimal.valueOf(account.getDeposit().doubleValue() * new Double(noOfMonthsforInterestCal) - * interestRateForOneMonth.doubleValue()); - avalablePreclosureWithdrawalAmount = interest.add(account.getDeposit()).subtract(account.getInterestPaid()) - .add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days)); - } else if (new LocalDate().isAfter(account.getMaturedOn())) { - Integer days = Days.daysBetween(account.getMaturedOn(), new LocalDate()).getDays(); - avalablePreclosureWithdrawalAmount = determineAvailableInterestForWithdrawal(account).add(account.getDeposit()).add( - determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days)); - } - } else { - avalablePreclosureWithdrawalAmount = account.getDeposit(); - } - } - return avalablePreclosureWithdrawalAmount; - } - - private BigDecimal determineRemainInerestAmount(final BigDecimal depsoitAmount, final BigDecimal interstRateApplicable, - final Integer days) { - - MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN); - Integer daysInYear = 365; - BigDecimal interestRateAsFraction = interstRateApplicable.divide(BigDecimal.valueOf(100), mc); - BigDecimal interestRateForOneDay = interestRateAsFraction.divide(BigDecimal.valueOf(daysInYear.doubleValue()), mc); - return BigDecimal.valueOf(depsoitAmount.doubleValue() * days.doubleValue() * interestRateForOneDay.doubleValue()); - - } + availableInterestForWithdrawal = BigDecimal.valueOf(interestGettingForPeriod.multiply(new BigDecimal(noOfPeriods)).doubleValue()- account.getInterestPaid().doubleValue()); + }else { + return BigDecimal.ZERO; + } + }else return BigDecimal.ZERO; + + return availableInterestForWithdrawal; + } + + private BigDecimal determineAvalableWithdrawalAmount(final DepositAccountData account) { + + BigDecimal avalablePreclosureWithdrawalAmount = BigDecimal.ZERO; + if(this.status != null){ + if (account.getStatus().getId() == 300) { + // if(new LocalDate().isBefore(account.getMaturedOn()) || new LocalDate().isEqual(account.getMaturedOn())){ + Integer days = Days.daysBetween(account.getLastInterestPostedDate(), new LocalDate()).getDays(); + avalablePreclosureWithdrawalAmount=account.getAvailableInterest().add(account.getDeposit()).add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days)); + + // }else if(new LocalDate().isAfter(account.getMaturedOn())){ + // Integer days = Days.daysBetween(account.getLastInterestPostedDate(), new LocalDate()).getDays(); + // avalablePreclosureWithdrawalAmount=account.getAvailableInterest().add(account.getDeposit()).add(determineRemainInerestAmount(account.getDeposit(), account.getPreClosureInterestRate(), days)); + // } + }else{ + avalablePreclosureWithdrawalAmount=account.getDeposit(); + } + } + return avalablePreclosureWithdrawalAmount; + } + + private BigDecimal determineRemainInerestAmount(final BigDecimal depsoitAmount, final BigDecimal interstRateApplicable, final Integer days){ + MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN); + Integer daysInYear = 365; + BigDecimal interestRateAsFraction = interstRateApplicable.divide(BigDecimal.valueOf(100), mc); + BigDecimal interestRateForOneDay = interestRateAsFraction.divide(BigDecimal.valueOf(daysInYear.doubleValue()), mc); + return BigDecimal.valueOf(depsoitAmount.doubleValue()*days.doubleValue()*interestRateForOneDay.doubleValue()); + + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/data/DepositAccountsForLookup.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/data/DepositAccountsForLookup.java new file mode 100644 index 000000000..0d45086b0 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/data/DepositAccountsForLookup.java @@ -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; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccount.java index 5ef6e4c28..22da4e5da 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccount.java @@ -152,6 +152,21 @@ public class DepositAccount extends AbstractAuditableCustom { @Column(name = "lock_in_period_type", nullable=false) 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( final Client client, final DepositProduct product, @@ -325,6 +340,12 @@ public class DepositAccount extends AbstractAuditableCustom { depositaccountTransaction.updateAccount(this); 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); if (actualCommencementDate.isBefore(submittalDate)) { 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 { 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())) { - DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_CLOSED, DepositAccountStatus.fromInt(this.depositStatus)); this.depositStatus = statusEnum.getValue(); - - 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())){ - + } else if(eventDate.isBefore(maturesOnDate())){ DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_PRECLOSED, DepositAccountStatus.fromInt(this.depositStatus)); 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 lastInterestPosedDate = getLastInterestPostedDate(); LocalDate preClosedDate = eventDate; - Integer tenure = Months.monthsBetween(commnencementDate, preClosedDate).getMonths(); - LocalDate actualPrecloseCalculationDate = commnencementDate.plusMonths(tenure); + if (preClosedDate.isBefore(lastInterestPosedDate)) { + 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(); Money deposit = Money.of(account.getDeposit().getCurrency(), account.getDeposit().getAmount()); @@ -607,15 +626,17 @@ public class DepositAccount extends AbstractAuditableCustom { this.total = account.isInterestCompoundingAllowed()?accuredtotalAmount.getAmount():BigDecimal.valueOf(accuredtotalAmount.getAmount().doubleValue()-this.interstPaid.doubleValue()); this.interestAccrued = accuredtotalAmount.minus(deposit).getAmount(); - } + }*/ public void withdrawInterest(Money interest) { - - if(this.depositStatus == 300 ){ + @SuppressWarnings("unused") + boolean statustest = isActive(); + if(isActive()){ DepositAccountTransaction depositAccountTransaction = DepositAccountTransaction.withdraw(null, new LocalDate(), interest); depositAccountTransaction.updateAccount(this); this.depositaccountTransactions.add(depositAccountTransaction); this.interstPaid = this.interstPaid.add(interest.getAmount()); + this.availableInterest = this.availableInterest.subtract(interest.getAmount()); this.total = this.total.subtract(interest.getAmount()); } @@ -639,7 +660,6 @@ public class DepositAccount extends AbstractAuditableCustom { final boolean renewalAllowed, final boolean preClosureAllowed, final boolean isInterestWithdrawable, final boolean isInterestCompoundingAllowed, final FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator, - @SuppressWarnings("unused") final DepositLifecycleStateMachine depositLifecycleStateMachine, final boolean isLockinPeriodAllowed, final Integer lockinPeriod, final PeriodFrequencyType lockinPeriodType) { @@ -695,4 +715,120 @@ public class DepositAccount extends AbstractAuditableCustom { public boolean 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; + } + + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccountTransaction.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccountTransaction.java index 1cdd703f9..7962daed8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccountTransaction.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccountTransaction.java @@ -102,6 +102,10 @@ public class DepositAccountTransaction extends AbstractPersistable { 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) { this.depositAccount=depositAccount; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccountTransactionType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccountTransactionType.java index 598c41d73..e6ba7c5a2 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccountTransactionType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/domain/DepositAccountTransactionType.java @@ -5,7 +5,8 @@ public enum DepositAccountTransactionType { INVALID(0, "depositTransactionType.invalid"), // DEPOSIT(1, "depositTransactionType.deposit"), // WITHDRAW(2, "depositTransactionType.withdraw"), // - REVERSAL(3, "depositTransactionType.reversal"); + REVERSAL(3, "depositTransactionType.reversal"), + INTEREST_POSTING(4,"depositTransactionType.interestPosting"); private final Integer value; private final String code; @@ -43,6 +44,10 @@ public enum DepositAccountTransactionType { depositTransactionType=DepositAccountTransactionType.REVERSAL; break; + case 4: + depositTransactionType=DepositAccountTransactionType.INTEREST_POSTING; + break; + default : depositTransactionType=DepositAccountTransactionType.INVALID; break; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountAssembler.java index f425bb7c2..70e740d81 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountAssembler.java @@ -230,9 +230,9 @@ public class DepositAccountAssembler { return newAccount; } - public void adjustTotalAmountForPreclosureInterest(DepositAccount account,LocalDate eventDate) { + /*public void adjustTotalAmountForPreclosureInterest(DepositAccount account,LocalDate eventDate) { account.adjustTotalAmountForPreclosureInterest(account,this.fixedTermDepositInterestCalculator,eventDate); - } + }*/ public void assembleUpdatedDepositAccount(DepositAccount account,DepositAccountCommand command) { @@ -323,7 +323,7 @@ public class DepositAccountAssembler { lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType()); } 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) { @@ -340,4 +340,8 @@ public class DepositAccountAssembler { account.update(renewalAllowed,isInterestWithdrawable); } + + public void postInterest(DepositAccount account) { + account.postInterestForDepositAccount(account,this.fixedTermDepositInterestCalculator); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountReadPlatformService.java index da9cb900b..d862c8bc0 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountReadPlatformService.java @@ -4,6 +4,7 @@ import java.math.BigDecimal; import java.util.Collection; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData; +import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountsForLookup; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositPermissionData; public interface DepositAccountReadPlatformService { @@ -17,4 +18,6 @@ public interface DepositAccountReadPlatformService { DepositPermissionData retrieveDepositAccountsPermissions(DepositAccountData depositAccountData); BigDecimal retrieveAvailableInterestForWithdrawal(DepositAccountData account); + + Collection retrieveDepositAccountForLookup(); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountReadPlatformServiceImpl.java index 4bd0d7df1..bb0e00108 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountReadPlatformServiceImpl.java @@ -18,6 +18,7 @@ import org.mifosplatform.portfolio.loanproduct.exception.LoanProductNotFoundExce import org.mifosplatform.portfolio.savingsaccountproduct.service.SavingsDepositEnumerations; import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountData; 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.savingsdepositproduct.data.DepositProductData; 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.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.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," + " 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 " @@ -206,13 +208,18 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead Integer lockinPeriod = JdbcSupport.getInteger(rs, "lockinPeriod"); Integer lockinPeriodTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodType"); 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, depositAmount, interestRate, termInMonths, projectedCommencementDate, actualCommencementDate, maturedOn, projectedInterestAccrued, actualInterestAccrued, projectedMaturityAmount, actualMaturityAmount, interestCompoundedEvery, interestCompoundedEveryPeriodType, renewalAllowed, preClosureAllowed, preClosureInterestRate, 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 renewelAllowed = false; if (depositAccountData.getMaturedOn() != null) { - if (new LocalDate().isAfter(depositAccountData.getMaturedOn())/* - * || - * depositAccountData - * . - * getMaturedOn - * (). - * isEqual - * ( - * new - * LocalDate - * ()) - */) { + if (new LocalDate().isAfter(depositAccountData.getMaturedOn())/* || depositAccountData.getMaturedOn().isEqual(new LocalDate()) */) { renewelAllowed = depositAccountData.isRenewalAllowed(); } } @@ -280,4 +276,28 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead return BigDecimal.valueOf(interstGettingForPeriod.multiply(new BigDecimal(noOfPeriods)).doubleValue() - account.getInterestPaid().doubleValue()); } + + @Override + public Collection 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 { + + 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); + } + + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountWritePlatformService.java index ceebae674..d2f77e405 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountWritePlatformService.java @@ -1,5 +1,7 @@ package org.mifosplatform.portfolio.savingsdepositaccount.service; +import java.util.Collection; + import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.portfolio.loanaccount.command.UndoStateTransitionCommand; 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.DepositStateTransitionApprovalCommand; import org.mifosplatform.portfolio.savingsdepositaccount.command.DepositStateTransitionCommand; +import org.mifosplatform.portfolio.savingsdepositaccount.data.DepositAccountsForLookup; import org.springframework.security.access.prepost.PreAuthorize; public interface DepositAccountWritePlatformService { @@ -49,4 +52,7 @@ public interface DepositAccountWritePlatformService { @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'ORGANISATION_ADMINISTRATION_SUPER_USER', 'RENEW_DEPOSITACCOUNT')") EntityIdentifier renewDepositAccount(DepositAccountCommand command); + + @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER')") + EntityIdentifier postInterestToDepositAccount(Collection accounts); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java index 804a3daef..f95b3d8ee 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savingsdepositaccount/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java @@ -2,6 +2,7 @@ package org.mifosplatform.portfolio.savingsdepositaccount.service; import java.math.BigDecimal; import java.util.Arrays; +import java.util.Collection; import java.util.List; 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.DepositStateTransitionCommand; 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.DepositAccountRepository; import org.mifosplatform.portfolio.savingsdepositaccount.domain.DepositAccountStatus; @@ -303,9 +305,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo "deposit.transaction.canot.withdraw.before.lockinperiod.reached", "You can not withdraw your application before maturity date reached"); } } - if (eventDate.isBefore(account.maturesOnDate())) { - this.depositAccountAssembler.adjustTotalAmountForPreclosureInterest(account, eventDate); - } + // if (eventDate.isBefore(account.maturesOnDate())) { + // this.depositAccountAssembler.adjustTotalAmountForPreclosureInterest(account, eventDate); + // } account.withdrawDepositAccountMoney(defaultDepositLifecycleStateMachine(), fixedTermDepositInterestCalculator, eventDate); this.depositAccountRepository.save(account); String noteText = command.getNote(); @@ -419,4 +421,26 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo return new EntityIdentifier(Long.valueOf(-1)); } } + + @Transactional + @Override + public EntityIdentifier postInterestToDepositAccount(Collection 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)); + } + + } } \ No newline at end of file