From 3b4c1171e892f497a4899b841d5804a54000539c Mon Sep 17 00:00:00 2001 From: Madhukar Date: Wed, 10 Oct 2012 16:07:23 +0530 Subject: [PATCH] Display deposit transactions in UI Adding saving product SavingProduct Definition basic saving account creation patch-2 reccuring deposit account Saving account creation final patch --- .../patches/patch-saving_account_creation.sql | 47 +++ .../patches/patch-saving_product_creation.sql | 33 ++ .../api/SavingProductsApiResource.java | 65 +++- .../api/SavingsAccountApiResource.java | 139 +++++++ .../api/commands/SavingAccountCommand.java | 235 ++++++++++++ .../api/commands/SavingProductCommand.java | 159 +++++++- .../platform/api/data/DepositAccountData.java | 6 +- .../data/DepositAccountTransactionData.java | 14 +- .../platform/api/data/SavingAccountData.java | 231 ++++++++++++ .../platform/api/data/SavingProductData.java | 252 ++++++++++--- .../ApiDataConversionService.java | 3 + .../ApiDataConversionServiceImpl.java | 76 +++- .../ApiJsonSerializerService.java | 5 + .../GoogleGsonApiJsonSerializerService.java | 38 +- .../SavingAccountNotFoundException.java | 9 + .../saving/domain/DepositAccount.java | 5 +- .../ReccuringDepositInterestCalculator.java | 76 ++++ .../platform/saving/domain/SavingAccount.java | 344 ++++++++++++++++++ .../domain/SavingAccountRepository.java | 10 + ...DepositAccountReadPlatformServiceImpl.java | 8 +- .../service/SavingAccountAssembler.java | 209 +++++++++++ .../SavingAccountCommandValidator.java | 94 +++++ .../SavingAccountReadPlatformService.java | 15 + .../SavingAccountReadPlatformServiceImpl.java | 160 ++++++++ .../SavingAccountWritePlatformService.java | 18 + ...WritePlatformServiceJpaRepositoryImpl.java | 99 +++++ .../savingproduct/domain/DepositProduct.java | 1 - .../domain/SavingFrequencyType.java | 54 +++ .../SavingInterestCalculationMethod.java | 44 +++ .../savingproduct/domain/SavingProduct.java | 24 +- .../domain/SavingProductRelatedDetail.java | 184 ++++++++-- .../domain/SavingProductType.java | 50 +++ .../domain/SavingsInterestType.java | 42 +++ .../domain/SavingsLockinPeriodEnum.java | 52 +++ .../savingproduct/domain/TenureTypeEnum.java | 42 +++ .../SavingProductCommandValidator.java | 50 ++- .../service/SavingProductEnumerations.java | 163 +++++++++ .../SavingProductReadPlatformServiceImpl.java | 41 ++- ...WritePlatformServiceJpaRepositoryImpl.java | 18 +- 39 files changed, 2961 insertions(+), 154 deletions(-) create mode 100644 mifosng-db/patches/patch-saving_account_creation.sql create mode 100644 mifosng-db/patches/patch-saving_product_creation.sql create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/api/SavingsAccountApiResource.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SavingAccountCommand.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/api/data/SavingAccountData.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/exceptions/SavingAccountNotFoundException.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/ReccuringDepositInterestCalculator.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/SavingAccount.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/SavingAccountRepository.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountAssembler.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountCommandValidator.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountReadPlatformService.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountReadPlatformServiceImpl.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountWritePlatformService.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountWritePlatformServiceJpaRepositoryImpl.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingFrequencyType.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingInterestCalculationMethod.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProductType.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingsInterestType.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingsLockinPeriodEnum.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/TenureTypeEnum.java create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductEnumerations.java diff --git a/mifosng-db/patches/patch-saving_account_creation.sql b/mifosng-db/patches/patch-saving_account_creation.sql new file mode 100644 index 000000000..bcdf9e24e --- /dev/null +++ b/mifosng-db/patches/patch-saving_account_creation.sql @@ -0,0 +1,47 @@ +DROP TABLE if exists `m_saving_account`; +CREATE TABLE `m_saving_account` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `is_deleted` tinyint(1) NOT NULL DEFAULT '0', + `status_enum` smallint(5) NOT NULL DEFAULT '0', + `external_id` varchar(100) DEFAULT NULL, + `client_id` bigint(20) NOT NULL, + `product_id` bigint(20) NOT NULL, + `deposit_amount_per_period` decimal(19,6) NOT NULL, + `savings_product_type` smallint(5) DEFAULT NULL, + `currency_code` varchar(3) NOT NULL, + `currency_digits` smallint(5) NOT NULL, + `total_deposit_amount` decimal(19,6) NOT NULL, + `reccuring_nominal_interest_rate` decimal(19,6) NOT NULL, + `regular_saving_nominal_interest_rate` decimal(19,6) NOT NULL, + `tenure` int(11) NOT NULL, + `tenure_type` smallint(5) DEFAULT NULL, + `frequency` int(11) DEFAULT NULL, + `interest_type` smallint(5) DEFAULT NULL, + `interest_calculation_method` smallint(5) DEFAULT NULL, + `projected_commencement_date` date NOT NULL, + `actual_commencement_date` date DEFAULT NULL, + `matures_on_date` datetime DEFAULT NULL, + `projected_interest_accrued_on_maturity` decimal(19,6) NOT NULL, + `actual_interest_accrued` decimal(19,6) DEFAULT NULL, + `projected_total_maturity_amount` decimal(19,6) NOT NULL, + `actual_total_amount` decimal(19,6) DEFAULT NULL, + `is_preclosure_allowed` tinyint(1) NOT NULL DEFAULT '0', + `pre_closure_interest_rate` decimal(19,6) NOT NULL, + `is_lock_in_period_allowed` tinyint(1) NOT NULL DEFAULT '0', + `lock_in_period` bigint(20) DEFAULT NULL, + `lock_in_period_type` smallint(5) NOT NULL DEFAULT '1', + `withdrawnon_date` datetime DEFAULT NULL, + `rejectedon_date` datetime DEFAULT NULL, + `closedon_date` datetime DEFAULT 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`), + UNIQUE KEY `deposit_acc_external_id` (`external_id`), + KEY `FKSA0000000000001` (`client_id`), + KEY `FKSA0000000000002` (`product_id`), + CONSTRAINT `FKSA0000000000001` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`), + CONSTRAINT `FKSA0000000000002` FOREIGN KEY (`product_id`) REFERENCES `m_product_savings` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; + diff --git a/mifosng-db/patches/patch-saving_product_creation.sql b/mifosng-db/patches/patch-saving_product_creation.sql new file mode 100644 index 000000000..7f4996e44 --- /dev/null +++ b/mifosng-db/patches/patch-saving_product_creation.sql @@ -0,0 +1,33 @@ +DROP TABLE IF EXISTS `m_product_savings`; +CREATE TABLE `m_product_savings` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `description` varchar(500) DEFAULT NULL, + `currency_code` varchar(3) DEFAULT NULL, + `currency_digits` smallint(5) DEFAULT NULL, + `interest_rate` decimal(19,6) DEFAULT NULL, + `min_interest_rate` decimal(19,6) DEFAULT NULL, + `max_interest_rate` decimal(19,6) DEFAULT NULL, + `savings_deposit_amount` decimal(19,6) NOT NULL, + `savings_product_type` smallint(5) DEFAULT NULL, + `tenure_type` smallint(5) DEFAULT NULL, + `tenure` int(11) DEFAULT NULL, + `frequency` int(11) DEFAULT NULL, + `interest_type` smallint(5) DEFAULT NULL, + `interest_calculation_method` smallint(5) DEFAULT NULL, + `min_bal_for_withdrawal` decimal(19,6) NOT NULL, + `is_partial_deposit_allowed` tinyint(1) NOT NULL DEFAULT '0', + `is_lock_in_period_allowed` tinyint(1) NOT NULL DEFAULT '0', + `lock_in_period` bigint(20) DEFAULT NULL, + `lock_in_period_type` smallint(5) NOT NULL DEFAULT '1', + `is_deleted` tinyint(1) NOT NULL DEFAULT '0', + `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 `FKJPW0000000000003` (`createdby_id`), + KEY `FKJPW0000000000004` (`lastmodifiedby_id`), + CONSTRAINT `FKJPW0000000000003` FOREIGN KEY (`createdby_id`) REFERENCES `m_appuser` (`id`), + CONSTRAINT `FKJPW0000000000004` FOREIGN KEY (`lastmodifiedby_id`) REFERENCES `m_appuser` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/SavingProductsApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/SavingProductsApiResource.java index a3dd2d34c..3c1c57232 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/SavingProductsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/SavingProductsApiResource.java @@ -3,6 +3,7 @@ package org.mifosng.platform.api; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; import javax.ws.rs.Consumes; @@ -19,11 +20,21 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.mifosng.platform.api.commands.SavingProductCommand; +import org.mifosng.platform.api.data.CurrencyData; import org.mifosng.platform.api.data.EntityIdentifier; +import org.mifosng.platform.api.data.EnumOptionData; import org.mifosng.platform.api.data.SavingProductData; import org.mifosng.platform.api.infrastructure.ApiDataConversionService; import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService; import org.mifosng.platform.api.infrastructure.ApiParameterHelper; +import org.mifosng.platform.currency.service.CurrencyReadPlatformService; +import org.mifosng.platform.savingproduct.domain.SavingFrequencyType; +import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod; +import org.mifosng.platform.savingproduct.domain.SavingProductType; +import org.mifosng.platform.savingproduct.domain.SavingsInterestType; +import org.mifosng.platform.savingproduct.domain.SavingsLockinPeriodEnum; +import org.mifosng.platform.savingproduct.domain.TenureTypeEnum; +import org.mifosng.platform.savingproduct.service.SavingProductEnumerations; import org.mifosng.platform.savingproduct.service.SavingProductReadPlatformService; import org.mifosng.platform.savingproduct.service.SavingProductWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; @@ -46,6 +57,9 @@ public class SavingProductsApiResource { @Autowired private ApiJsonSerializerService apiJsonSerializerService; + + @Autowired + private CurrencyReadPlatformService currencyReadPlatformService; @POST @Consumes({MediaType.APPLICATION_JSON}) @@ -75,8 +89,10 @@ public class SavingProductsApiResource { @Produces({MediaType.APPLICATION_JSON}) public String retrieveAllSavingProducts(@Context final UriInfo uriInfo) { - Set typicalResponseParameters = new HashSet(Arrays.asList("id", "name", "description", "createdOn", "lastModifedOn", - "interestRate","currencyCode","digitsAfterDecimal","minimumBalance","maximumBalance")); + Set typicalResponseParameters = new HashSet(Arrays.asList("id", "createdOn", "lastModifedOn", + "locale", "name", "description","currencyCode", "digitsAfterDecimal","interstRate", "minInterestRate","maxInterestRate", + "savingsDepositAmount","savingProductType","tenureType","tenure", "frequency","interestType","interestCalculationMethod", + "minimumBalanceForWithdrawal","isPartialDepositAllowed","isLockinPeriodAllowed","lockinPeriod","lockinPeriodType")); Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); if (responseParameters.isEmpty()) { @@ -95,8 +111,10 @@ public class SavingProductsApiResource { @Produces({MediaType.APPLICATION_JSON}) public String retrieveSavingProductDetails(@PathParam("productId") final Long productId, @Context final UriInfo uriInfo) { - Set typicalResponseParameters = new HashSet(Arrays.asList("id", "name", "description", "createdOn", "lastModifedOn", - "interestRate","currencyCode","digitsAfterDecimal","minimumBalance","maximumBalance")); + Set typicalResponseParameters = new HashSet(Arrays.asList("id", "createdOn", "lastModifedOn", + "locale", "name", "description","currencyCode", "digitsAfterDecimal","interstRate", "minInterestRate","maxInterestRate", + "savingsDepositAmount","savingProductType","tenureType","tenure", "frequency","interestType","interestCalculationMethod", + "minimumBalanceForWithdrawal","isPartialDepositAllowed","isLockinPeriodAllowed","lockinPeriod","lockinPeriodType")); Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); if (responseParameters.isEmpty()) { @@ -120,7 +138,10 @@ public class SavingProductsApiResource { public String retrieveNewSavingProductDetails(@Context final UriInfo uriInfo) { Set typicalResponseParameters = new HashSet( - Arrays.asList("id", "name", "description", "createdOn", "lastModifedOn","interestRate","currencyCode","digitsAfterDecimal", "currencyOptions","minimumBalance","maximumBalance")); + Arrays.asList("id", "createdOn", "lastModifedOn", + "locale", "name", "description","currencyCode", "digitsAfterDecimal","interstRate", + "savingsDepositAmount","savingProductType","tenureType","tenure", "frequency","interestType","interestCalculationMethod", + "minimumBalanceForWithdrawal","isPartialDepositAllowed","isLockinPeriodAllowed","lockinPeriod","lockinPeriodType","currencyOptions")); Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); if (responseParameters.isEmpty()) { @@ -129,10 +150,42 @@ public class SavingProductsApiResource { boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); SavingProductData savingProduct = this.savingProductReadPlatformService.retrieveNewSavingProductDetails(); - + savingProduct = handleTemplateRelatedData(responseParameters,savingProduct); return this.apiJsonSerializerService.serializeSavingProductDataToJson(prettyPrint, responseParameters, savingProduct); } + private SavingProductData handleTemplateRelatedData(Set responseParameters, SavingProductData savingProduct) { + + responseParameters.addAll(Arrays.asList("currencyOptions", "savingsProductTypeOptions", "tenureTypeOptions", "savingFrequencyOptions", "savingsInterestTypeOptions", + "lockinPeriodTypeOptions", "interestCalculationOptions")); + List currencyOptions = this.currencyReadPlatformService.retrieveAllowedCurrencies(); + + EnumOptionData reccuring = SavingProductEnumerations.savingProductType(SavingProductType.RECCURING); + EnumOptionData regular = SavingProductEnumerations.savingProductType(SavingProductType.REGULAR); + List savingsProductTypeOptions = Arrays.asList(reccuring,regular); + + EnumOptionData fixed = SavingProductEnumerations.tenureTypeEnum(TenureTypeEnum.FIXED_PERIOD); + EnumOptionData perpetual = SavingProductEnumerations.tenureTypeEnum(TenureTypeEnum.PERPETUAL); + List tenureTypeOptions = Arrays.asList(fixed,perpetual); + + EnumOptionData monthly = SavingProductEnumerations.interestFrequencyType(SavingFrequencyType.MONTHLY); + List savingFrequencyOptions = Arrays.asList(monthly); + + EnumOptionData simple = SavingProductEnumerations.savingInterestType(SavingsInterestType.SIMPLE); + EnumOptionData compounding = SavingProductEnumerations.savingInterestType(SavingsInterestType.COMPOUNDING); + List savingsInterestTypeOptions = Arrays.asList(simple,compounding); + + EnumOptionData months = SavingProductEnumerations.savingsLockinPeriod(SavingsLockinPeriodEnum.MONTHS); + List lockinPeriodTypeOptions = Arrays.asList(months); + + EnumOptionData averagebal = SavingProductEnumerations.savingInterestCalculationMethod(SavingInterestCalculationMethod.AVERAGEBAL); + EnumOptionData minbal = SavingProductEnumerations.savingInterestCalculationMethod(SavingInterestCalculationMethod.MINBAL); + EnumOptionData monthlyCollection = SavingProductEnumerations.savingInterestCalculationMethod(SavingInterestCalculationMethod.MONTHLYCOLLECTION); + List interestCalculationOptions= Arrays.asList(averagebal,minbal,monthlyCollection); + + return new SavingProductData(savingProduct,currencyOptions,savingsProductTypeOptions,tenureTypeOptions,savingFrequencyOptions,savingsInterestTypeOptions,lockinPeriodTypeOptions,interestCalculationOptions); + } + @DELETE @Path("{productId}") @Consumes({MediaType.APPLICATION_JSON}) diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/SavingsAccountApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/SavingsAccountApiResource.java new file mode 100644 index 000000000..b5630117b --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/SavingsAccountApiResource.java @@ -0,0 +1,139 @@ +package org.mifosng.platform.api; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.mifosng.platform.api.commands.SavingAccountCommand; +import org.mifosng.platform.api.data.EntityIdentifier; +import org.mifosng.platform.api.data.SavingAccountData; +import org.mifosng.platform.api.infrastructure.ApiDataConversionService; +import org.mifosng.platform.api.infrastructure.ApiJsonSerializerService; +import org.mifosng.platform.api.infrastructure.ApiParameterHelper; +import org.mifosng.platform.saving.service.SavingAccountReadPlatformService; +import org.mifosng.platform.saving.service.SavingAccountWritePlatformService; +import org.mifosng.platform.savingproduct.service.SavingProductReadPlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +@Path("/savingaccounts") +@Component +@Scope("singleton") +public class SavingsAccountApiResource { + + @Autowired + private SavingAccountWritePlatformService savingAccountWritePlatformService; + + @Autowired + private SavingAccountReadPlatformService savingAccountReadPlatformService; + + @Autowired + private SavingProductReadPlatformService savingProductReadPlatformService; + + @Autowired + private ApiDataConversionService apiDataConversionService; + + @Autowired + private ApiJsonSerializerService apiJsonSerializerService; + + 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) { + + Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); + if (responseParameters.isEmpty()) { + responseParameters.addAll(typicalResponseParameters); + } + boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + + 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) { + + 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); + } + + @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) { + + Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); + if (responseParameters.isEmpty()) { + responseParameters.addAll(typicalResponseParameters); + } + boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + + SavingAccountData account = this.savingAccountReadPlatformService.retrieveNewSavingsAccountDetails(clientId, productId); + + return this.apiJsonSerializerService.serializeSavingAccountsDataToJson(prettyPrint, responseParameters, account); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SavingAccountCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SavingAccountCommand.java new file mode 100644 index 000000000..e72b3943e --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SavingAccountCommand.java @@ -0,0 +1,235 @@ +package org.mifosng.platform.api.commands; + +import java.math.BigDecimal; +import java.util.Set; + +import org.joda.time.LocalDate; + +public class SavingAccountCommand { + + + private final Long id; + private final Long clientId; + private final Long productId; + private final String externalId; + + private final String currencyCode; + private final Integer digitsAfterDecimal; + private final BigDecimal savingsDepositAmount; + private final BigDecimal recurringInterestRate; + private final BigDecimal savingInterestRate; + private final Integer tenure; + + private final boolean isLockinPeriodAllowed; + private final Integer lockinPeriod; + private final Integer lockinPeriodType; + + private final LocalDate commencementDate; + private final Integer savingProductType; + private final Integer tenureType; + private final Integer frequency; + private final Integer interestType; + + private final Integer interestCalculationMethod; + private final BigDecimal minimumBalanceForWithdrawal; + private final boolean isPartialDepositAllowed; + + private final Set 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) { + this.id = id; + this.clientId = clientId; + this.productId = productId; + this.externalId = externalId; + + this.currencyCode = currencyCode; + this.digitsAfterDecimal = digitsAfterDecimal; + this.savingsDepositAmount = savingsDepositAmount; + this.recurringInterestRate = recurringInterestRate; + this.savingInterestRate = savingInterestRate; + this.tenure = tenure; + + this.modifiedParameters = modifiedParameters; + this.commencementDate = commencementDate; + + this.savingProductType=savingProductType; + this.tenureType=tenureType; + this.frequency=frequency; + this.interestType=interestType; + this.isPartialDepositAllowed=isPartialDepositAllowed; + + + this.isLockinPeriodAllowed = isLockinPeriodAllowed; + this.lockinPeriod = lockInPeriod; + this.lockinPeriodType = lockinPeriodType; + this.minimumBalanceForWithdrawal=minimumBalanceForWithdrawal; + this.interestCalculationMethod=interestCalculationMethod; + } + + public Long getId() { + return id; + } + + public Long getClientId() { + return clientId; + } + + public Long getProductId() { + return productId; + } + + public String getExternalId() { + return externalId; + } + + public String getCurrencyCode() { + return currencyCode; + } + + public Integer getDigitsAfterDecimal() { + return digitsAfterDecimal; + } + + public BigDecimal getSavingsDepositAmount() { + return savingsDepositAmount; + } + + public BigDecimal getRecurringInterestRate() { + return recurringInterestRate; + } + + public BigDecimal getSavingInterestRate() { + return savingInterestRate; + } + + public Integer getTenure() { + return tenure; + } + + public boolean isLockinPeriodAllowed() { + return isLockinPeriodAllowed; + } + + public Integer getLockinPeriod() { + return lockinPeriod; + } + + public Integer getLockinPeriodType() { + return lockinPeriodType; + } + + public LocalDate getCommencementDate() { + return commencementDate; + } + + public Integer getSavingProductType() { + return savingProductType; + } + + public Integer getTenureType() { + return tenureType; + } + + public Integer getFrequency() { + return frequency; + } + + public Integer getInterestType() { + return interestType; + } + + public Integer getInterestCalculationMethod() { + return interestCalculationMethod; + } + + public BigDecimal getMinimumBalanceForWithdrawal() { + return minimumBalanceForWithdrawal; + } + + public boolean isPartialDepositAllowed() { + return isPartialDepositAllowed; + } + + public boolean isNoFieldChanged() { + return this.modifiedParameters.isEmpty(); + } + + public boolean isProductIdChanged(){ + return this.modifiedParameters.contains("productId"); + } + + public boolean isExternalIdChanged(){ + return this.modifiedParameters.contains("externalId"); + } + + public boolean isDepositAmountChanged(){ + return this.modifiedParameters.contains("deposit"); + } + + public boolean isTenureInMonthsChanged() { + return this.modifiedParameters.contains("tenureInMonths"); + } + + public boolean isLockinPeriodChanged() { + return this.modifiedParameters.contains("lockinPeriod"); + } + + public boolean isPreClosureInterestRateChanged(){ + return this.modifiedParameters.contains("preClosureInterestRate"); + } + + public boolean isPreClosureAllowedChanged() { + return this.modifiedParameters.contains("preClosureAllowed"); + } + + public boolean isCommencementDateChanged() { + return this.modifiedParameters.contains("commencementDate"); + } + + public boolean isTenureTypeEnumChanged() { + return this.modifiedParameters.contains("tenureType"); + } + + public boolean isSavingProductTypeChanged() { + return this.modifiedParameters.contains("savingProductType"); + } + + public boolean isSavingFrequencyTypeChanged() { + return this.modifiedParameters.contains("frequency"); + } + + public boolean isSavingInterestCalculationMethodChanged() { + return this.modifiedParameters.contains("interestCalculationMethod"); + } + + public boolean isReccuringInterestRateChanged() { + return this.modifiedParameters.contains("recurringInterestRate"); + } + + public boolean isSavingInterestRateChanged() { + return this.modifiedParameters.contains("savingInterestRate"); + } + + public boolean isLockinPeriodAllowedChanged() { + return this.modifiedParameters.contains("isLockinPeriodAllowed"); + } + + public boolean isLockinPeriodTypeChanged() { + return this.modifiedParameters.contains("lockinPeriodType"); + } + + public boolean isPartialDepositAllowedChanged() { + return this.modifiedParameters.contains("isPartialDepositAllowed"); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SavingProductCommand.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SavingProductCommand.java index 16d1c9eef..6ea17c8fd 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SavingProductCommand.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/commands/SavingProductCommand.java @@ -11,16 +11,37 @@ public class SavingProductCommand { private final String currencyCode; private final Integer digitsAfterDecimal; private final BigDecimal interestRate; + private final BigDecimal minInterestRate; + private final BigDecimal maxInterestRate; + + private final BigDecimal savingsDepositAmount; + private final Integer savingProductType; + private final Integer tenureType; + private final Integer tenure; + private final Integer frequency; + private final Integer interestType; + private final Integer interestCalculationMethod; + private final BigDecimal minimumBalanceForWithdrawal; + private final boolean isPartialDepositAllowed; + private final boolean isLockinPeriodAllowed; + private final Integer lockinPeriod; + private final Integer lockinPeriodType; - private final BigDecimal minimumBalance; - private final BigDecimal maximumBalance; private final Set modifiedParameters; - - public SavingProductCommand(final Set modifiedParameters, - final Long id, final String name, final String description, - final String currencyCode, final Integer digitsAfterDecimal, - final BigDecimal interestRate, final BigDecimal minimumBalance, final BigDecimal maximumBalance) { + + public SavingProductCommand(Set modifiedParameters, + Long id, String name, String description, + String currencyCode, Integer digitsAfterDecimal, + BigDecimal interestRate, BigDecimal minInterestRate, + BigDecimal maxInterestRate, BigDecimal savingsDepositAmount, + Integer savingProductType, Integer tenureType, Integer tenure, + Integer frequency, Integer interestType, + Integer interestCalculationMethod, + BigDecimal minimumBalanceForWithdrawal, + boolean isPartialDepositAllowed, boolean isLockinPeriodAllowed, + Integer lockinPeriod, Integer lockinPeriodType) { + this.id = id; this.name = name; this.description = description; @@ -28,9 +49,21 @@ public class SavingProductCommand { this.currencyCode = currencyCode; this.digitsAfterDecimal = digitsAfterDecimal; this.interestRate = interestRate; + this.minInterestRate = minInterestRate; + this.maxInterestRate = maxInterestRate; - this.minimumBalance=minimumBalance; - this.maximumBalance=maximumBalance; + this.savingsDepositAmount=savingsDepositAmount; + this.savingProductType=savingProductType; + this.tenureType=tenureType; + this.tenure=tenure; + this.frequency=frequency; + this.interestType=interestType; + this.interestCalculationMethod=interestCalculationMethod; + this.minimumBalanceForWithdrawal=minimumBalanceForWithdrawal; + this.isPartialDepositAllowed=isPartialDepositAllowed; + this.isLockinPeriodAllowed=isLockinPeriodAllowed; + this.lockinPeriod=lockinPeriod; + this.lockinPeriodType=lockinPeriodType; this.modifiedParameters = modifiedParameters; } @@ -58,14 +91,61 @@ public class SavingProductCommand { public BigDecimal getInterestRate() { return interestRate; } - - - public BigDecimal getMinimumBalance() { - return minimumBalance; + + public BigDecimal getMinInterestRate() { + return minInterestRate; } - public BigDecimal getMaximumBalance() { - return maximumBalance; + public BigDecimal getMaxInterestRate() { + return maxInterestRate; + } + + public BigDecimal getSavingsDepositAmount() { + return savingsDepositAmount; + } + + public Integer getSavingProductType() { + return savingProductType; + } + + public Integer getTenureType() { + return tenureType; + } + + public Integer getTenure() { + return tenure; + } + + public Integer getFrequency() { + return frequency; + } + + public Integer getInterestType() { + return interestType; + } + + public Integer getInterestCalculationMethod() { + return interestCalculationMethod; + } + + public BigDecimal getMinimumBalanceForWithdrawal() { + return minimumBalanceForWithdrawal; + } + + public boolean isPartialDepositAllowed() { + return isPartialDepositAllowed; + } + + public boolean isLockinPeriodAllowed() { + return isLockinPeriodAllowed; + } + + public Integer getLockinPeriod() { + return lockinPeriod; + } + + public Integer getLockinPeriodType() { + return lockinPeriodType; } public boolean isNameChanged() { @@ -88,11 +168,52 @@ public class SavingProductCommand { return this.modifiedParameters.contains("interestRate"); } - public boolean isMinimumBalanceChanged(){ - return this.modifiedParameters.contains("minimumBalance"); + public boolean isSavingsDepositAmountChanged(){ + return this.modifiedParameters.contains("savingsDepositAmount"); } - public boolean isMaximumBalanceChanged(){ - return this.modifiedParameters.contains("maximumBalance"); + public boolean isSavingProductTypeChanged() { + return this.modifiedParameters.contains("savingProductType"); } + + public boolean isTenureTypeChanged() { + return this.modifiedParameters.contains("tenureType"); + } + + public boolean isTenureChanged() { + return this.modifiedParameters.contains("tenure"); + } + + public boolean isFrequencyChanged() { + return this.modifiedParameters.contains("frequency"); + } + + public boolean isInterestTypeChanged() { + return this.modifiedParameters.contains("interestType"); + } + + public boolean isInterestCalculationMethodChanged() { + return this.modifiedParameters.contains("interestCalculationMethod"); + } + + public boolean isMinimumBalanceForWithdrawalChanged() { + return this.modifiedParameters.contains("minimumBalanceForWithdrawal"); + } + + public boolean isPartialDepositAllowedChanged() { + return this.modifiedParameters.contains("isPartialDepositAllowed"); + } + + public boolean isLockinPeriodAllowedChanged() { + return this.modifiedParameters.contains("isLockinPeriodAllowed"); + } + + public boolean isLockinPeriodChanged() { + return this.modifiedParameters.contains("lockinPeriod"); + } + + public boolean isLockinPeriodTypeChanged() { + return this.modifiedParameters.contains("lockinPeriodType"); + } + } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DepositAccountData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DepositAccountData.java index a833d3971..f1ac3ffa8 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DepositAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DepositAccountData.java @@ -514,7 +514,7 @@ public class DepositAccountData { if(this.status!=null){ if (account.getStatus().getId() == 300) { BigDecimal interestGettingForPeriod = BigDecimal.valueOf(account.getActualInterestAccrued().doubleValue()/ new Double(account.getTenureInMonths())); - LocalDate interestWithdrawingDate= new LocalDate().isAfter(getMaturedOn())?getMaturedOn().plusDays(1):new LocalDate(); + LocalDate interestWithdrawingDate= new LocalDate().isBefore(getMaturedOn())?new LocalDate():getMaturedOn().plusDays(1); Integer noOfMonthsforInterestCal = Months.monthsBetween(account.getActualCommencementDate(), interestWithdrawingDate).getMonths(); Integer noOfPeriods = noOfMonthsforInterestCal/ account.getInterestCompoundedEvery(); @@ -532,7 +532,7 @@ public class DepositAccountData { BigDecimal avalablePreclosureWithdrawalAmount = BigDecimal.ZERO; if(this.status != null){ if (account.getStatus().getId() == 300) { - if(new LocalDate().isBefore(account.getMaturedOn())){ + 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); @@ -541,7 +541,7 @@ public class DepositAccountData { 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()) || new LocalDate().isEqual(account.getMaturedOn())){ + }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)); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DepositAccountTransactionData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DepositAccountTransactionData.java index 6dcfb4722..d845a55ba 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DepositAccountTransactionData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/DepositAccountTransactionData.java @@ -14,15 +14,19 @@ public class DepositAccountTransactionData { private final LocalDate transactionDate; private final BigDecimal transactionAmount; private final Long accountId; + private final BigDecimal interestAmount; + private final BigDecimal total; public DepositAccountTransactionData( final Long transactionId, final Long accountId, final EnumOptionData transactionType, - final LocalDate transactionDate, final BigDecimal transactionAmount ) { + final LocalDate transactionDate, final BigDecimal transactionAmount, final BigDecimal interstAmount, final BigDecimal total ) { this.transactionId = transactionId; this.accountId = accountId; this.transactionType = transactionType; this.transactionDate = transactionDate; this.transactionAmount = transactionAmount; + this.interestAmount = interstAmount; + this.total = total; } public Long getAccountId() { @@ -44,4 +48,12 @@ public class DepositAccountTransactionData { public BigDecimal getTransactionAmount() { return transactionAmount; } + + public BigDecimal getInterestAmount() { + return interestAmount; + } + + public BigDecimal getTotal() { + return total; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/SavingAccountData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/SavingAccountData.java new file mode 100644 index 000000000..979a821f9 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/SavingAccountData.java @@ -0,0 +1,231 @@ +package org.mifosng.platform.api.data; + +import java.math.BigDecimal; + +import org.joda.time.LocalDate; + +public class SavingAccountData { + + private final Long id; + private final EnumOptionData status; + private final String externalId; + private final Long clientId; + private final String clientName; + private final Long productId; + private final String productName; + private final EnumOptionData productType; + private final CurrencyData currencyData; + private final BigDecimal savingsDepostiAmountPerPeriod; + private final EnumOptionData savingsFrequencyType; + private final BigDecimal totalDepositAmount; + private final BigDecimal reccuringInterestRate; + private final BigDecimal savingInterestRate; + private final EnumOptionData interestType; + private final EnumOptionData interestCalculationMethod; + private final Integer tenure; + private final EnumOptionData tenureType; + private final LocalDate projectedCommencementDate; + private final LocalDate actualCommencementDate; + private final LocalDate maturesOnDate; + private final BigDecimal projectedInterestAccuredOnMaturity; + private final BigDecimal actualInterestAccured; + private final BigDecimal projectedMaturityAmount; + private final BigDecimal actualMaturityAmount; + private final boolean preClosureAllowed; + private final BigDecimal preClosureInterestRate; + private final LocalDate withdrawnonDate; + private final LocalDate rejectedonDate; + private final LocalDate closedonDate; + private final boolean isLockinPeriodAllowed; + private final Integer lockinPeriod; + private final EnumOptionData lockinPeriodType; + + public SavingAccountData(Long id, EnumOptionData status, String externalId, + Long clientId, String clientName, Long productId, + String productName, EnumOptionData productType, + CurrencyData currencyData, + BigDecimal savingsDepostiAmountPerPeriod, + EnumOptionData savingsFrequencyType, BigDecimal totalDepositAmount, + BigDecimal reccuringInterestRate, BigDecimal savingInterestRate, + EnumOptionData interestType, + EnumOptionData interestCalculationMethod, Integer tenure, + EnumOptionData tenureType, LocalDate projectedCommencementDate, + LocalDate actualCommencementDate, LocalDate maturesOnDate, + BigDecimal projectedInterestAccuredOnMaturity, + BigDecimal actualInterestAccured, + BigDecimal projectedMaturityAmount, + BigDecimal actualMaturityAmount, boolean preClosureAllowed, + BigDecimal preClosureInterestRate, LocalDate withdrawnonDate, + LocalDate rejectedonDate, LocalDate closedonDate, + boolean isLockinPeriodAllowed, Integer lockinPeriod, + EnumOptionData lockinPeriodType) { + + this.id = id; + this.status = status; + this.externalId = externalId; + this.clientId = clientId; + this.clientName = clientName; + this.productId = productId; + this.productName = productName; + this.productType = productType; + this.currencyData = currencyData; + this.savingsDepostiAmountPerPeriod = savingsDepostiAmountPerPeriod; + this.savingsFrequencyType = savingsFrequencyType; + this.totalDepositAmount = totalDepositAmount; + this.reccuringInterestRate = reccuringInterestRate; + this.savingInterestRate = savingInterestRate; + this.interestType =interestType; + this.interestCalculationMethod = interestCalculationMethod; + this.tenure = tenure; + this.tenureType = tenureType; + this.projectedCommencementDate = projectedCommencementDate; + this.actualCommencementDate = actualCommencementDate; + this.maturesOnDate = maturesOnDate; + this.projectedInterestAccuredOnMaturity = projectedInterestAccuredOnMaturity; + this.actualInterestAccured = actualInterestAccured; + this.projectedMaturityAmount = projectedMaturityAmount; + this.actualMaturityAmount =actualMaturityAmount; + this.preClosureAllowed = preClosureAllowed; + this.preClosureInterestRate = preClosureInterestRate; + this.withdrawnonDate = withdrawnonDate; + this.rejectedonDate = rejectedonDate; + this.closedonDate = closedonDate; + this.isLockinPeriodAllowed = isLockinPeriodAllowed; + this.lockinPeriod = lockinPeriod; + this.lockinPeriodType = lockinPeriodType; + + } + + public Long getId() { + return id; + } + + public EnumOptionData getStatus() { + return status; + } + + public String getExternalId() { + return externalId; + } + + public Long getClientId() { + return clientId; + } + + public String getClientName() { + return clientName; + } + + public Long getProductId() { + return productId; + } + + public String getProductName() { + return productName; + } + + public EnumOptionData getProductType() { + return productType; + } + + public CurrencyData getCurrencyData() { + return currencyData; + } + + public BigDecimal getSavingsDepostiAmountPerPeriod() { + return savingsDepostiAmountPerPeriod; + } + + public EnumOptionData getSavingsFrequencyType() { + return savingsFrequencyType; + } + + public BigDecimal getTotalDepositAmount() { + return totalDepositAmount; + } + + public BigDecimal getReccuringInterestRate() { + return reccuringInterestRate; + } + + public BigDecimal getSavingInterestRate() { + return savingInterestRate; + } + + public EnumOptionData getInterestType() { + return interestType; + } + + public EnumOptionData getInterestCalculationMethod() { + return interestCalculationMethod; + } + + public Integer getTenure() { + return tenure; + } + + public EnumOptionData getTenureType() { + return tenureType; + } + + public LocalDate getProjectedCommencementDate() { + return projectedCommencementDate; + } + + public LocalDate getActualCommencementDate() { + return actualCommencementDate; + } + + public LocalDate getMaturesOnDate() { + return maturesOnDate; + } + + public BigDecimal getProjectedInterestAccuredOnMaturity() { + return projectedInterestAccuredOnMaturity; + } + + public BigDecimal getActualInterestAccured() { + return actualInterestAccured; + } + + public BigDecimal getProjectedMaturityAmount() { + return projectedMaturityAmount; + } + + public BigDecimal getActualMaturityAmount() { + return actualMaturityAmount; + } + + public boolean isPreClosureAllowed() { + return preClosureAllowed; + } + + public BigDecimal getPreClosureInterestRate() { + return preClosureInterestRate; + } + + public LocalDate getWithdrawnonDate() { + return withdrawnonDate; + } + + public LocalDate getRejectedonDate() { + return rejectedonDate; + } + + public LocalDate getClosedonDate() { + return closedonDate; + } + + public boolean isLockinPeriodAllowed() { + return isLockinPeriodAllowed; + } + + public Integer getLockinPeriod() { + return lockinPeriod; + } + + public EnumOptionData getLockinPeriodType() { + return lockinPeriodType; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/SavingProductData.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/SavingProductData.java index 2c423f5bd..d34c2ac5a 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/data/SavingProductData.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/data/SavingProductData.java @@ -9,102 +9,226 @@ import org.joda.time.DateTime; public class SavingProductData implements Serializable { - private Long id; - private String name; - private String description; - private String currencyCode; - private Integer digitsAfterDecimal; + private final Long id; + private final String name; + private final String description; + private final CurrencyData currency; + private final Integer digitsAfterDecimal; - private BigDecimal interestRate = BigDecimal.ZERO; - private BigDecimal minimumBalance = BigDecimal.ZERO; - private BigDecimal maximumBalance = BigDecimal.ZERO; + private final BigDecimal interestRate; + private final BigDecimal minInterestRate; + private final BigDecimal maxInterestRate; + private final BigDecimal savingsDepositAmount; + private final EnumOptionData savingProductType; + private final EnumOptionData tenureType; + private final Integer tenure; + private final EnumOptionData savingFrequencyType; + private final EnumOptionData interestType; + private final EnumOptionData interestCalculationMethod; + private final BigDecimal minimumBalanceForWithdrawal; + private final boolean isPartialDepositAllowed; + private final boolean isLockinPeriodAllowed; + private final Integer lockinPeriod; + private final EnumOptionData lockinPeriodType; private DateTime createdOn; private DateTime lastModifedOn; private List currencyOptions = new ArrayList(); + List savingsProductTypeOptions = new ArrayList(); + List tenureTypeOptions = new ArrayList(); + List savingFrequencyOptions = new ArrayList(); + List savingsInterestTypeOptions = new ArrayList(); + List lockinPeriodTypeOptions = new ArrayList(); + List interestCalculationOptions = new ArrayList(); public SavingProductData(){ - // + this.createdOn=new DateTime(); + this.lastModifedOn=new DateTime(); + this.id=null; + this.name=null; + this.description=null; + this.interestRate=BigDecimal.ZERO; + this.minInterestRate=BigDecimal.ZERO; + this.maxInterestRate=BigDecimal.ZERO; + this.currency=null; + this.digitsAfterDecimal=null; + this.savingsDepositAmount=null; + this.savingProductType=null; + this.tenureType = null; + this.tenure = null; + this.savingFrequencyType=null; + this.interestType=null; + this.interestCalculationMethod=null; + this.minimumBalanceForWithdrawal=null; + this.isPartialDepositAllowed=true; + this.isLockinPeriodAllowed=true; + this.lockinPeriod=null; + this.lockinPeriodType=null; } - public SavingProductData(DateTime createdOn, DateTime lastModifedOn, Long id,String name, String description,BigDecimal interestRate,String currencyCode, Integer digitsAfterDecimal,BigDecimal minimumBalance,BigDecimal maximumBalance) { + public SavingProductData(DateTime createdOn, DateTime lastModifedOn, + Long id, String name, String description, + BigDecimal interestRate, BigDecimal minInterestRate, BigDecimal maxInterestRate, CurrencyData currency, + Integer digitsAfterDecimal, BigDecimal savingsDepositAmount, + EnumOptionData savingProductType, + EnumOptionData tenureType, Integer tenure, + EnumOptionData savingFrequencyType, + EnumOptionData savingInterestType, + EnumOptionData interestCalculationMethod, + BigDecimal minimumBalanceForWithdrawal, + boolean isPartialDepositAllowed, boolean isLockinPeriodAllowed, + Integer lockinPeriod, EnumOptionData lockinPeriodType) { this.createdOn=createdOn; this.lastModifedOn=lastModifedOn; this.id=id; this.name=name; this.description=description; this.interestRate=interestRate; - this.currencyCode=currencyCode; + this.minInterestRate=minInterestRate; + this.maxInterestRate=maxInterestRate; + this.currency=currency; this.digitsAfterDecimal=digitsAfterDecimal; - this.minimumBalance=minimumBalance; - this.maximumBalance=maximumBalance; + this.savingsDepositAmount=savingsDepositAmount; + this.savingProductType=savingProductType; + this.tenureType = tenureType; + this.tenure = tenure; + this.savingFrequencyType=savingFrequencyType; + this.interestType=savingInterestType; + this.interestCalculationMethod=interestCalculationMethod; + this.minimumBalanceForWithdrawal=minimumBalanceForWithdrawal; + this.isPartialDepositAllowed=isPartialDepositAllowed; + this.isLockinPeriodAllowed=isLockinPeriodAllowed; + this.lockinPeriod=lockinPeriod; + this.lockinPeriodType=lockinPeriodType; + } + + public SavingProductData(SavingProductData product, + List currencyOptions, + List savingsProductTypeOptions, + List tenureTypeOptions, + List savingFrequencyOptions, + List savingsInterestTypeOptions, + List lockinPeriodTypeOptions, + List interestCalculationOptions) { + + this.createdOn=product.getCreatedOn(); + this.lastModifedOn=product.getLastModifedOn(); + this.id=product.getId(); + this.name=product.getName(); + this.description=product.getDescription(); + this.interestRate=product.getInterestRate(); + this.minInterestRate=product.getMinInterestRate(); + this.maxInterestRate=product.getMaxInterestRate(); + this.currency=product.getCurrency(); + this.digitsAfterDecimal=product.getDigitsAfterDecimal(); + this.savingsDepositAmount=product.getSavingsDepositAmount(); + this.savingProductType=product.getSavingProductType(); + this.tenureType = product.getTenureType(); + this.tenure = product.getTenure(); + this.savingFrequencyType=product.getSavingFrequencyType(); + this.interestType=product.getInterestType(); + this.interestCalculationMethod=product.getInterestCalculationMethod(); + this.minimumBalanceForWithdrawal=product.getMinimumBalanceForWithdrawal(); + this.isPartialDepositAllowed=product.isPartialDepositAllowed(); + this.isLockinPeriodAllowed=product.isLockinPeriodAllowed(); + this.lockinPeriod=product.getLockinPeriod(); + this.lockinPeriodType=product.getLockinPeriodType(); + + this.currencyOptions=currencyOptions; + this.savingsProductTypeOptions=savingsProductTypeOptions; + this.tenureTypeOptions=tenureTypeOptions; + this.savingFrequencyOptions=savingFrequencyOptions; + this.savingsInterestTypeOptions=savingsInterestTypeOptions; + this.lockinPeriodTypeOptions=lockinPeriodTypeOptions; + this.interestCalculationOptions=interestCalculationOptions; + } public Long getId() { return id; } - public void setId(Long id) { - this.id = id; - } - public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - public String getDescription() { return description; } - public void setDescription(String description) { - this.description = description; + public CurrencyData getCurrency() { + return currency; } - - public DateTime getCreatedOn() { - return createdOn; + + public Integer getDigitsAfterDecimal() { + return digitsAfterDecimal; } public BigDecimal getInterestRate() { return interestRate; } - public void setInterestRate(BigDecimal interestRate) { - this.interestRate = interestRate; + public BigDecimal getMinInterestRate() { + return minInterestRate; } - public void setCreatedOn(DateTime createdOn) { - this.createdOn = createdOn; + public BigDecimal getMaxInterestRate() { + return maxInterestRate; + } + + public BigDecimal getSavingsDepositAmount() { + return savingsDepositAmount; + } + + public EnumOptionData getSavingProductType() { + return savingProductType; + } + + public EnumOptionData getTenureType() { + return tenureType; + } + + public Integer getTenure() { + return tenure; + } + + public EnumOptionData getInterestType() { + return interestType; + } + + public EnumOptionData getInterestCalculationMethod() { + return interestCalculationMethod; + } + + public BigDecimal getMinimumBalanceForWithdrawal() { + return minimumBalanceForWithdrawal; + } + + public boolean isPartialDepositAllowed() { + return isPartialDepositAllowed; + } + + public boolean isLockinPeriodAllowed() { + return isLockinPeriodAllowed; + } + + public Integer getLockinPeriod() { + return lockinPeriod; + } + + public EnumOptionData getLockinPeriodType() { + return lockinPeriodType; + } + + public DateTime getCreatedOn() { + return createdOn; } public DateTime getLastModifedOn() { return lastModifedOn; } - public void setLastModifedOn(DateTime lastModifedOn) { - this.lastModifedOn = lastModifedOn; - } - - public String getCurrencyCode() { - return currencyCode; - } - - public void setCurrencyCode(String currencyCode) { - this.currencyCode = currencyCode; - } - - public Integer getDigitsAfterDecimal() { - return digitsAfterDecimal; - } - - public void setDigitsAfterDecimal(Integer digitsAfterDecimal) { - this.digitsAfterDecimal = digitsAfterDecimal; - } - public List getCurrencyOptions() { return currencyOptions; } @@ -113,20 +237,32 @@ public class SavingProductData implements Serializable { this.currencyOptions = currencyOptions; } - public BigDecimal getMinimumBalance() { - return minimumBalance; + public EnumOptionData getSavingFrequencyType() { + return savingFrequencyType; } - public void setMinimumBalance(BigDecimal minimumBalance) { - this.minimumBalance = minimumBalance; + public List getSavingsProductTypeOptions() { + return savingsProductTypeOptions; } - public BigDecimal getMaximumBalance() { - return maximumBalance; + public List getTenureTypeOptions() { + return tenureTypeOptions; } - public void setMaximumBalance(BigDecimal maximumBalance) { - this.maximumBalance = maximumBalance; + public List getSavingFrequencyOptions() { + return savingFrequencyOptions; + } + + public List getSavingsInterestTypeOptions() { + return savingsInterestTypeOptions; + } + + public List getLockinPeriodTypeOptions() { + return lockinPeriodTypeOptions; + } + + public List getInterestCalculationOptions() { + return interestCalculationOptions; } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java index 0fe3c7c64..41fa3729a 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionService.java @@ -24,6 +24,7 @@ import org.mifosng.platform.api.commands.NoteCommand; import org.mifosng.platform.api.commands.OfficeCommand; import org.mifosng.platform.api.commands.OrganisationCurrencyCommand; import org.mifosng.platform.api.commands.RoleCommand; +import org.mifosng.platform.api.commands.SavingAccountCommand; import org.mifosng.platform.api.commands.SavingProductCommand; import org.mifosng.platform.api.commands.StaffCommand; import org.mifosng.platform.api.commands.UserCommand; @@ -85,4 +86,6 @@ public interface ApiDataConversionService { CodeCommand convertJsonToCodeCommand(Long resourceIdentifier, String json); + SavingAccountCommand convertJsonToSavingAccountCommand(Long resourceIdentifier,String jsonRequestBody); + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java index 456ccc217..0a07ae810 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java @@ -41,6 +41,7 @@ import org.mifosng.platform.api.commands.NoteCommand; import org.mifosng.platform.api.commands.OfficeCommand; import org.mifosng.platform.api.commands.OrganisationCurrencyCommand; import org.mifosng.platform.api.commands.RoleCommand; +import org.mifosng.platform.api.commands.SavingAccountCommand; import org.mifosng.platform.api.commands.SavingProductCommand; import org.mifosng.platform.api.commands.StaffCommand; import org.mifosng.platform.api.commands.UserCommand; @@ -1289,7 +1290,10 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Type typeOfMap = new TypeToken>() {}.getType(); Map requestMap = gsonConverter.fromJson(json, typeOfMap); - Set supportedParams = new HashSet(Arrays.asList("name","description","currencyCode", "digitsAfterDecimal","interestRate","locale","minimumBalance","maximumBalance")); + Set supportedParams = new HashSet(Arrays.asList("locale", "name", "description","currencyCode", "digitsAfterDecimal","interestRate", "minInterestRate", + "maxInterestRate","savingsDepositAmount","savingProductType","tenureType","tenure", "frequency","interestType","interestCalculationMethod", + "minimumBalanceForWithdrawal","isPartialDepositAllowed","isLockinPeriodAllowed","lockinPeriod","lockinPeriodType")); + checkForUnsupportedParameters(requestMap, supportedParams); Set modifiedParameters = new HashSet(); String name = extractStringParameter("name", requestMap,modifiedParameters); @@ -1297,11 +1301,25 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { String currencyCode=extractStringParameter("currencyCode", requestMap,modifiedParameters); Integer digitsAfterDecimalValue = extractIntegerParameter("digitsAfterDecimal", requestMap, modifiedParameters); BigDecimal interestRate = extractBigDecimalParameter("interestRate", requestMap, modifiedParameters); - BigDecimal minimumBalance=extractBigDecimalParameter("minimumBalance", requestMap, modifiedParameters); - BigDecimal maximumBalance=extractBigDecimalParameter("maximumBalance", requestMap, modifiedParameters); + BigDecimal minInterestRate = extractBigDecimalParameter("minInterestRate", requestMap, modifiedParameters); + BigDecimal maxInterestRate = extractBigDecimalParameter("maxInterestRate", requestMap, modifiedParameters); + BigDecimal savingsDepositAmount=extractBigDecimalParameter("savingsDepositAmount", requestMap, modifiedParameters); + Integer savingProductType = extractIntegerParameter("savingProductType", requestMap, modifiedParameters); + Integer tenureType = extractIntegerParameter("tenureType", requestMap, modifiedParameters); + Integer tenure = extractIntegerParameter("tenure", requestMap, modifiedParameters); + Integer frequency = extractIntegerParameter("frequency", requestMap, modifiedParameters); + Integer interestType = extractIntegerParameter("interestType", requestMap, modifiedParameters); + Integer interestCalculationMethod=extractIntegerParameter("interestCalculationMethod", requestMap, modifiedParameters); + BigDecimal minimumBalanceForWithdrawal=extractBigDecimalParameter("minimumBalanceForWithdrawal", requestMap, modifiedParameters); + boolean isPartialDepositAllowed = extractBooleanParameter("isPartialDepositAllowed", requestMap, modifiedParameters); + boolean isLockinPeriodAllowed = extractBooleanParameter("isLockinPeriodAllowed", requestMap, modifiedParameters); + Integer lockinPeriod = extractIntegerParameter("lockinPeriod", requestMap, modifiedParameters); + Integer lockinPeriodType = extractIntegerParameter("lockinPeriodType", requestMap, modifiedParameters); - return new SavingProductCommand(modifiedParameters, resourceIdentifier,name, description,currencyCode,digitsAfterDecimalValue,interestRate,minimumBalance,maximumBalance); + return new SavingProductCommand(modifiedParameters, resourceIdentifier,name, description,currencyCode,digitsAfterDecimalValue,interestRate, minInterestRate, + maxInterestRate, savingsDepositAmount,savingProductType, tenureType,tenure,frequency,interestType,interestCalculationMethod,minimumBalanceForWithdrawal, + isPartialDepositAllowed, isLockinPeriodAllowed,lockinPeriod,lockinPeriodType); } @Override @@ -1553,4 +1571,54 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { + @Override + public SavingAccountCommand convertJsonToSavingAccountCommand(Long resourceIdentifier, String json) { + + + if (StringUtils.isBlank(json)) { + throw new InvalidJsonException(); + } + + Type typeOfMap = new TypeToken>() {}.getType(); + Map requestMap = gsonConverter.fromJson(json, typeOfMap); + + // currencyCode, currencyDigits + Set supportedParams = new HashSet( + Arrays.asList("clientId", "productId", "externalId", "currencyCode", "digitsAfterDecimal", "savingsDepositAmountPerPeriod", "recurringInterestRate", "savingInterestRate", + "tenure", "commencementDate", "locale", "dateFormat","isLockinPeriodAllowed","lockinPeriod","lockinPeriodType", + "savingProductType","tenureType", "frequency","interestType","interestCalculationMethod", + "minimumBalanceForWithdrawal","isPartialDepositAllowed" ) + ); + checkForUnsupportedParameters(requestMap, supportedParams); + Set modifiedParameters = new HashSet(); + + Long clientId = extractLongParameter("clientId", requestMap, modifiedParameters); + Long productId = extractLongParameter("productId", requestMap, modifiedParameters); + String externalId = extractStringParameter("externalId", requestMap,modifiedParameters); + String currencyCode=extractStringParameter("currencyCode", requestMap,modifiedParameters); + Integer digitsAfterDecimalValue = extractIntegerParameter("digitsAfterDecimal", requestMap, modifiedParameters); + BigDecimal savingsDepositAmount=extractBigDecimalParameter("savingsDepositAmountPerPeriod", requestMap, modifiedParameters); + BigDecimal recurringInterestRate = extractBigDecimalParameter("recurringInterestRate", requestMap, modifiedParameters); + BigDecimal savingInterestRate = extractBigDecimalParameter("savingInterestRate", requestMap, modifiedParameters); + Integer tenure = extractIntegerParameter("tenure", requestMap, modifiedParameters); + + boolean isLockinPeriodAllowed = extractBooleanParameter("isLockinPeriodAllowed", requestMap, modifiedParameters); + Integer lockinPeriod = extractIntegerParameter("lockinPeriod", requestMap, modifiedParameters); + Integer lockinPeriodType = extractIntegerParameter("lockinPeriodType", requestMap, modifiedParameters); + + LocalDate commencementDate = extractLocalDateParameter("commencementDate", requestMap, modifiedParameters); + Integer savingProductType = extractIntegerParameter("savingProductType", requestMap, modifiedParameters); + Integer tenureType = extractIntegerParameter("tenureType", requestMap, modifiedParameters); + Integer frequency = extractIntegerParameter("frequency", requestMap, modifiedParameters); + Integer interestType = extractIntegerParameter("interestType", requestMap, modifiedParameters); + Integer interestCalculationMethod=extractIntegerParameter("interestCalculationMethod", requestMap, modifiedParameters); + BigDecimal minimumBalanceForWithdrawal=extractBigDecimalParameter("minimumBalanceForWithdrawal", requestMap, modifiedParameters); + boolean isPartialDepositAllowed = extractBooleanParameter("isPartialDepositAllowed", 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); + + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiJsonSerializerService.java index de47ed30c..a51cf73df 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiJsonSerializerService.java @@ -32,6 +32,7 @@ import org.mifosng.platform.api.data.OfficeData; import org.mifosng.platform.api.data.OfficeTransactionData; import org.mifosng.platform.api.data.PermissionData; import org.mifosng.platform.api.data.RoleData; +import org.mifosng.platform.api.data.SavingAccountData; import org.mifosng.platform.api.data.SavingProductData; import org.mifosng.platform.api.data.StaffData; @@ -133,4 +134,8 @@ public interface ApiJsonSerializerService { String serializeCodeDataToJson(boolean prettyPrint,Set responseParameters, CodeData code); + String serializeSavingAccountsDataToJson(boolean prettyPrint, Set responseParameters, SavingAccountData account); + + String serializeSavingAccountsDataToJson(boolean prettyPrint, Set responseParameters, Collection accounts); + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java index 01b051b3c..d51fdd917 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/GoogleGsonApiJsonSerializerService.java @@ -34,6 +34,7 @@ import org.mifosng.platform.api.data.OfficeData; import org.mifosng.platform.api.data.OfficeTransactionData; import org.mifosng.platform.api.data.PermissionData; import org.mifosng.platform.api.data.RoleData; +import org.mifosng.platform.api.data.SavingAccountData; import org.mifosng.platform.api.data.SavingProductData; import org.mifosng.platform.api.data.StaffData; import org.springframework.beans.factory.annotation.Autowired; @@ -91,10 +92,12 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ "transactionProcessingStrategyOptions", "chargeOptions")); private static final Set SAVINGS_PRODUCT_DATA_PARAMETERS = new HashSet( - Arrays.asList("id", "name", "description", "createdOn", - "lastModifedOn", "interestRate", "currencyCode", - "digitsAfterDecimal", "currencyOptions", "minimumBalance", - "maximumBalance")); + Arrays.asList("currencyOptions", "id", "createdOn", "lastModifedOn", + "locale", "name", "description","currencyCode", "digitsAfterDecimal","interstRate", "minInterestRate","maxInterestRate", + "savingsDepositAmount","savingProductType","tenureType","tenure", "frequency","interestType","interestCalculationMethod", + "minimumBalanceForWithdrawal","isPartialDepositAllowed","isLockinPeriodAllowed","lockinPeriod","lockinPeriodType", + "currencyOptions", "savingsProductTypeOptions", "tenureTypeOptions", "savingFrequencyOptions", "savingsInterestTypeOptions", + "lockinPeriodTypeOptions", "interestCalculationOptions")); private static final Set SAVINGS_DEPOSIT_PRODUCT_DATA_PARAMETERS = new HashSet( Arrays.asList("currencyOptions", @@ -203,6 +206,12 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ private static final Set CODE_DATA_PARAMETERS = new HashSet( Arrays.asList("id", "codename")); + + private static final Set SAVINGS_ACCOUNTS_DATA_PARAMETERS = 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")); private final GoogleGsonSerializerHelper helper; @@ -702,4 +711,25 @@ public class GoogleGsonApiJsonSerializerService implements ApiJsonSerializerServ return helper.serializedJsonFrom(gsonDeserializer, code); } + @Override + public String serializeSavingAccountsDataToJson(boolean prettyPrint, + Set responseParameters, SavingAccountData account) { + final Gson gsonDeserializer = helper + .createGsonBuilderWithParameterExclusionSerializationStrategy( + SAVINGS_ACCOUNTS_DATA_PARAMETERS, prettyPrint, responseParameters); + return helper.serializedJsonFrom(gsonDeserializer, account); + } + + @Override + public String serializeSavingAccountsDataToJson(boolean prettyPrint, + Set responseParameters, + Collection accounts) { + final Gson gsonDeserializer = helper + .createGsonBuilderWithParameterExclusionSerializationStrategy( + SAVINGS_ACCOUNTS_DATA_PARAMETERS, prettyPrint, responseParameters); + return helper.serializedJsonFrom(gsonDeserializer, + accounts.toArray(new SavingAccountData[accounts.size()])); + + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/SavingAccountNotFoundException.java b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/SavingAccountNotFoundException.java new file mode 100644 index 000000000..5e77dc8d0 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/SavingAccountNotFoundException.java @@ -0,0 +1,9 @@ +package org.mifosng.platform.exceptions; + +public class SavingAccountNotFoundException extends AbstractPlatformResourceNotFoundException { + + public SavingAccountNotFoundException(final Long id) { + super("error.msg.saving.account.id.invalid", "Saving account with identifier " + id + " does not exist", id); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccount.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccount.java index 63dbc9b24..e95eb5af3 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccount.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccount.java @@ -245,7 +245,9 @@ public class DepositAccount extends AbstractAuditableCustom { this.projectedInterestAccruedOnMaturity = futureValueOnMaturity.minus(deposit).getAmount(); this.projectedTotalOnMaturity = futureValueOnMaturity.getAmount(); this.depositStatus=depositStatus; - this.interstPaid = BigDecimal.ZERO; + this.interestAccrued=BigDecimal.ZERO; + this.interstPaid=BigDecimal.ZERO; + this.total=BigDecimal.ZERO; } private void setExternalId(final String externalId) { @@ -677,6 +679,7 @@ public class DepositAccount extends AbstractAuditableCustom { this.isLockinPeriodAllowed = isLockinPeriodAllowed; this.lockinPeriod = lockinPeriod; this.lockinPeriodType = lockinPeriodType; + this.interestAccrued=BigDecimal.ZERO; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/ReccuringDepositInterestCalculator.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/ReccuringDepositInterestCalculator.java new file mode 100644 index 000000000..097e5187b --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/ReccuringDepositInterestCalculator.java @@ -0,0 +1,76 @@ +package org.mifosng.platform.saving.domain; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +import org.joda.time.LocalDate; +import org.mifosng.platform.currency.domain.Money; +import org.mifosng.platform.savingproduct.domain.SavingFrequencyType; +import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod; +import org.mifosng.platform.savingproduct.domain.TenureTypeEnum; +import org.springframework.stereotype.Service; + +@Service +public class ReccuringDepositInterestCalculator { + + public Money calculateInterestOnMaturityFor(Money savingsDepositPerPeriod, + Integer tenure, BigDecimal reccuringInterestRate, + LocalDate commencementDate, TenureTypeEnum tenureTypeEnum, + SavingFrequencyType savingFrequencyType, + SavingInterestCalculationMethod savingInterestCalculationMethod) { + + /* + // Assuming tenure in months + // see http://www.onemint.com/2012/04/03/how-to-calculate-interest-on-recurring-deposits/ + + A=P(1+r/n)^nt + + A = final amount + P = principal amount (initial investment) + r = annual nominal interest rate (as a decimal, not in percentage) + n = number of times the interest is compounded per year + t = number of years + + */ + MathContext mc = new MathContext(8, RoundingMode.HALF_EVEN); + Integer monthsInYear = 12; + + BigDecimal interestRateAsFraction = reccuringInterestRate.divide(BigDecimal.valueOf(100), mc); + Integer noofTimesInterestCompoundPerYear = Integer.valueOf(0); + switch (savingFrequencyType) { + case MONTHLY: + noofTimesInterestCompoundPerYear = monthsInYear; + break; + case QUATERLY: + noofTimesInterestCompoundPerYear = monthsInYear/3; + break; + case HALFYEARLY: + noofTimesInterestCompoundPerYear = monthsInYear/6; + break; + case YEARLY: + noofTimesInterestCompoundPerYear = monthsInYear/12; + break; + default: + throw new RuntimeException("The specified frequency not supported"); + + } + + BigDecimal interestRatePerPeriod = BigDecimal.valueOf(interestRateAsFraction.doubleValue()/noofTimesInterestCompoundPerYear.doubleValue()); + BigDecimal onePlusInterestRatePerPeriod = BigDecimal.ONE.add(interestRatePerPeriod); + BigDecimal monthsExpressedInYears; + BigDecimal timeforOneCalculationPeriod; + BigDecimal amountPerPeriod; + BigDecimal finalAmount = BigDecimal.ZERO; + while (tenure > 0) { + monthsExpressedInYears = BigDecimal.valueOf(tenure.doubleValue()/monthsInYear.doubleValue()); + timeforOneCalculationPeriod = BigDecimal.valueOf(noofTimesInterestCompoundPerYear*monthsExpressedInYears.doubleValue()); + amountPerPeriod = savingsDepositPerPeriod.getAmount().multiply(BigDecimal.valueOf(Math.pow(onePlusInterestRatePerPeriod.doubleValue(), timeforOneCalculationPeriod.doubleValue()))); + finalAmount=finalAmount.add(amountPerPeriod); + tenure--; + } + + return Money.of(savingsDepositPerPeriod.getCurrency(), finalAmount); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/SavingAccount.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/SavingAccount.java new file mode 100644 index 000000000..7b61b33fd --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/SavingAccount.java @@ -0,0 +1,344 @@ +package org.mifosng.platform.saving.domain; + +import java.math.BigDecimal; +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.UniqueConstraint; + +import org.joda.time.LocalDate; +import org.mifosng.platform.client.domain.Client; +import org.mifosng.platform.currency.domain.MonetaryCurrency; +import org.mifosng.platform.currency.domain.Money; +import org.mifosng.platform.infrastructure.AbstractAuditableCustom; +import org.mifosng.platform.loan.domain.PeriodFrequencyType; +import org.mifosng.platform.savingproduct.domain.SavingFrequencyType; +import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod; +import org.mifosng.platform.savingproduct.domain.SavingProduct; +import org.mifosng.platform.savingproduct.domain.SavingProductType; +import org.mifosng.platform.savingproduct.domain.SavingsInterestType; +import org.mifosng.platform.savingproduct.domain.TenureTypeEnum; +import org.mifosng.platform.user.domain.AppUser; + +@Entity +@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 = "product_id") + private SavingProduct product; + + @Column(name = "savings_product_type", nullable=false) + private SavingProductType savingProductType; + + @Column(name = "external_id") + private String externalId; + + @Embedded + private MonetaryCurrency currency; + + @Column(name = "deposit_amount_per_period", scale = 6, precision = 19, nullable = false) + private BigDecimal savingsDepositAmountPerPeriod; + + @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; + + @Column(name = "frequency", nullable=false) + private SavingFrequencyType frequency; + + @Column(name = "interest_type", nullable=false) + private SavingsInterestType interestType; + + @Column(name = "interest_calculation_method") + private SavingInterestCalculationMethod interestCalculationMethod; + + @Temporal(TemporalType.DATE) + @Column(name = "projected_commencement_date") + private Date projectedCommencementDate; + + @Temporal(TemporalType.DATE) + @Column(name = "actual_commencement_date") + private Date actualCommencementDate; + + @Temporal(TemporalType.DATE) + @Column(name = "matures_on_date") + private Date maturesOnDate; + + @Column(name = "projected_interest_accrued_on_maturity", scale = 6, precision = 19, nullable = false) + private BigDecimal projectedInterestAccruedOnMaturity; + + @Column(name = "actual_interest_accrued", scale = 6, precision = 19, nullable = false) + private BigDecimal interestAccrued; + + @Column(name = "projected_total_maturity_amount", scale = 6, precision = 19, nullable = false) + private BigDecimal projectedTotalOnMaturity; + + @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; + + @Temporal(TemporalType.DATE) + @Column(name = "closedon_date") + private Date closedOnDate; + + @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; + 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; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/SavingAccountRepository.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/SavingAccountRepository.java new file mode 100644 index 000000000..16a7944cc --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/SavingAccountRepository.java @@ -0,0 +1,10 @@ +package org.mifosng.platform.saving.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +public interface SavingAccountRepository extends +JpaRepository, +JpaSpecificationExecutor{ + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountReadPlatformServiceImpl.java index d305392fe..470d72a68 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountReadPlatformServiceImpl.java @@ -217,7 +217,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead private static final class DepositAccountTransactionMapper implements RowMapper{ public String schema() { - return " txn.id as transactionId, txn.deposit_account_id as accountId, txn.transaction_type_enum as transactionType, txn.transaction_date as transactionDate, txn.amount as transactionAmount " + return " txn.id as transactionId, txn.deposit_account_id as accountId, txn.transaction_type_enum as transactionType, txn.transaction_date as transactionDate, txn.amount as transactionAmount, txn.interest as interestAmount " + " from m_deposit_account_transaction txn"; } @@ -231,8 +231,10 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead EnumOptionData transactionType=DepositAccountTransactionEnumerations.depositType(transactionTypeValue); LocalDate transactionDate = JdbcSupport.getLocalDate(rs, "transactionDate"); BigDecimal transactionAmount = rs.getBigDecimal("transactionAmount"); + BigDecimal interestAmount = rs.getBigDecimal("interestAmount"); + BigDecimal total = transactionAmount.add(interestAmount); - return new DepositAccountTransactionData(transactionId, accountId, transactionType, transactionDate, transactionAmount); + return new DepositAccountTransactionData(transactionId, accountId, transactionType, transactionDate, transactionAmount, interestAmount, total); } } @@ -243,7 +245,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(); } } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountAssembler.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountAssembler.java new file mode 100644 index 000000000..51da595d1 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountAssembler.java @@ -0,0 +1,209 @@ +package org.mifosng.platform.saving.service; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; + +import org.joda.time.LocalDate; +import org.mifosng.platform.api.commands.SavingAccountCommand; +import org.mifosng.platform.client.domain.Client; +import org.mifosng.platform.client.domain.ClientRepository; +import org.mifosng.platform.currency.domain.MonetaryCurrency; +import org.mifosng.platform.currency.domain.Money; +import org.mifosng.platform.exceptions.ClientNotFoundException; +import org.mifosng.platform.exceptions.ProductNotFoundException; +import org.mifosng.platform.loan.domain.PeriodFrequencyType; +import org.mifosng.platform.saving.domain.DepositAccountStatus; +import org.mifosng.platform.saving.domain.DepositLifecycleStateMachine; +import org.mifosng.platform.saving.domain.DepositLifecycleStateMachineImpl; +import org.mifosng.platform.saving.domain.ReccuringDepositInterestCalculator; +import org.mifosng.platform.saving.domain.SavingAccount; +import org.mifosng.platform.savingproduct.domain.SavingFrequencyType; +import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod; +import org.mifosng.platform.savingproduct.domain.SavingProduct; +import org.mifosng.platform.savingproduct.domain.SavingProductRepository; +import org.mifosng.platform.savingproduct.domain.SavingProductType; +import org.mifosng.platform.savingproduct.domain.SavingsInterestType; +import org.mifosng.platform.savingproduct.domain.TenureTypeEnum; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class SavingAccountAssembler { + + private final ClientRepository clientRepository; + private final SavingProductRepository savingProductRepository; + private final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator; + + @Autowired + public SavingAccountAssembler(final ClientRepository clientRepository,final SavingProductRepository savingProductRepository, + final ReccuringDepositInterestCalculator reccuringDepositInterestCalculator) { + this.clientRepository=clientRepository; + this.savingProductRepository=savingProductRepository; + this.reccuringDepositInterestCalculator=reccuringDepositInterestCalculator; + } + //minimumBalanceForWithdrawal,isPartialDepositAllowed + public SavingAccount assembleFrom(SavingAccountCommand command){ + + Client client = this.clientRepository.findOne(command.getClientId()); + if (client == null || client.isDeleted()) { + throw new ClientNotFoundException(command.getClientId()); + } + + SavingProduct product=this.savingProductRepository.findOne(command.getProductId()); + if(product == null || product.isDeleted()){ + throw new ProductNotFoundException(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 ProductNotFoundException(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); + } + + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountCommandValidator.java new file mode 100644 index 000000000..0bb33875d --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountCommandValidator.java @@ -0,0 +1,94 @@ +package org.mifosng.platform.saving.service; + +import java.util.ArrayList; +import java.util.List; + +import org.mifosng.platform.DataValidatorBuilder; +import org.mifosng.platform.api.commands.SavingAccountCommand; +import org.mifosng.platform.api.data.ApiParameterError; +import org.mifosng.platform.exceptions.PlatformApiDataValidationException; + +public class SavingAccountCommandValidator { + + private final SavingAccountCommand command; + + public SavingAccountCommandValidator(final SavingAccountCommand command) { + this.command = command; + } + + public void validateForCreate() { + + List dataValidationErrors = new ArrayList(); + DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("saving.account"); + + baseDataValidator.reset().parameter("clientId").value(command.getClientId()).notNull(); + baseDataValidator.reset().parameter("productId").value(command.getProductId()).notNull(); + baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); + baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank(); + baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).notNull().inMinMaxRange(0, 6); + baseDataValidator.reset().parameter("savingsDepositAmountPerPeriod").value(command.getSavingsDepositAmount()).notNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("recurringInterestRate").value(command.getRecurringInterestRate()).notNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("savingInterestRate").value(command.getSavingInterestRate()).notNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("savingInterestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getSavingInterestRate(), command.getRecurringInterestRate()); + baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).notNull(); + baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).notNull(); + baseDataValidator.reset().parameter("tenure").value(command.getTenure()).notNull(); + baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).notNull(); + baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).notNull(); + baseDataValidator.reset().parameter("interestCalculationMethod").value(command.getInterestCalculationMethod()).notNull(); + baseDataValidator.reset().parameter("minimumBalanceForWithdrawal").value(command.getMinimumBalanceForWithdrawal()).notNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("isPartialDepositAllowed").value(command.isPartialDepositAllowed()).trueOrFalseRequired(command.isPartialDepositAllowedChanged()).notNull(); + baseDataValidator.reset().parameter("isLockinPeriodAllowed").value(command.isLockinPeriodAllowed()).trueOrFalseRequired(command.isLockinPeriodAllowedChanged()).notNull(); + baseDataValidator.reset().parameter("lockinPeriod").value(command.getLockinPeriod()).notNull(); + baseDataValidator.reset().parameter("lockinPeriodType").value(command.getLockinPeriodType()).notNull(); + baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).notNull(); + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); + } + + } + + public void validateForUpdate() { + + List dataValidationErrors = new ArrayList(); + DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("saving.account"); + + baseDataValidator.reset().parameter("id").value(command.getId()).notNull(); + baseDataValidator.reset().parameter("clientId").value(command.getClientId()).ignoreIfNull().notNull(); + baseDataValidator.reset().parameter("productId").value(command.getProductId()).ignoreIfNull().notNull(); + baseDataValidator.reset().parameter("externalId").value(command.getExternalId()).ignoreIfNull().notExceedingLengthOf(100); + baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank(); + baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).ignoreIfNull().inMinMaxRange(0, 6); + baseDataValidator.reset().parameter("savingsDepositAmountPerPeriod").value(command.getSavingsDepositAmount()).ignoreIfNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("recurringInterestRate").value(command.getRecurringInterestRate()).ignoreIfNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("savingInterestRate").value(command.getSavingInterestRate()).ignoreIfNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("savingInterestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getSavingInterestRate(), command.getRecurringInterestRate()); + baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).ignoreIfNull(); + baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).ignoreIfNull(); + baseDataValidator.reset().parameter("tenure").value(command.getTenure()).ignoreIfNull(); + baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).ignoreIfNull(); + baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).ignoreIfNull(); + baseDataValidator.reset().parameter("interestCalculationMethod").value(command.getInterestCalculationMethod()).ignoreIfNull(); + baseDataValidator.reset().parameter("minimumBalanceForWithdrawal").value(command.getMinimumBalanceForWithdrawal()).ignoreIfNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("isPartialDepositAllowed").value(command.isPartialDepositAllowed()).trueOrFalseRequired(command.isPartialDepositAllowedChanged()).ignoreIfNull(); + baseDataValidator.reset().parameter("isLockinPeriodAllowed").value(command.isLockinPeriodAllowed()).trueOrFalseRequired(command.isLockinPeriodAllowedChanged()).ignoreIfNull(); + baseDataValidator.reset().parameter("lockinPeriod").value(command.getLockinPeriod()).ignoreIfNull(); + baseDataValidator.reset().parameter("lockinPeriodType").value(command.getLockinPeriodType()).ignoreIfNull(); + baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).ignoreIfNull(); + baseDataValidator.reset().parameter("commencementDate").value(command.getCommencementDate()).ignoreIfNull(); + + if (command.isNoFieldChanged()) { + StringBuilder validationErrorCode = new StringBuilder("validation.msg.").append("deposit.account").append(".no.parameters.for.update"); + StringBuilder defaultEnglishMessage = new StringBuilder("No parameters passed for update."); + ApiParameterError error = ApiParameterError.parameterError(validationErrorCode.toString(), defaultEnglishMessage.toString(), "id"); + dataValidationErrors.add(error); + } + + if (!dataValidationErrors.isEmpty()) { + throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); + } + + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountReadPlatformService.java new file mode 100644 index 000000000..03dd4fb25 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountReadPlatformService.java @@ -0,0 +1,15 @@ +package org.mifosng.platform.saving.service; + +import java.util.Collection; + +import org.mifosng.platform.api.data.SavingAccountData; + +public interface SavingAccountReadPlatformService { + + Collection retrieveAllSavingsAccounts(); + + SavingAccountData retrieveSavingsAccount(Long accountId); + + SavingAccountData retrieveNewSavingsAccountDetails(Long clientId, Long productId); + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountReadPlatformServiceImpl.java new file mode 100644 index 000000000..799c2498c --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountReadPlatformServiceImpl.java @@ -0,0 +1,160 @@ +package org.mifosng.platform.saving.service; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Collection; + +import org.joda.time.LocalDate; +import org.mifosng.platform.api.data.CurrencyData; +import org.mifosng.platform.api.data.EnumOptionData; +import org.mifosng.platform.api.data.SavingAccountData; +import org.mifosng.platform.client.service.ClientReadPlatformService; +import org.mifosng.platform.infrastructure.JdbcSupport; +import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource; +import org.mifosng.platform.savingproduct.service.SavingProductEnumerations; +import org.mifosng.platform.savingproduct.service.SavingProductReadPlatformService; +import org.mifosng.platform.security.PlatformSecurityContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Service; + +@Service +public class SavingAccountReadPlatformServiceImpl implements + SavingAccountReadPlatformService { + + private final PlatformSecurityContext context; + private final JdbcTemplate jdbcTemplate; + private final SavingProductReadPlatformService savingProductReadPlatformService; + private final ClientReadPlatformService clientReadPlatformService; + + @Autowired + public SavingAccountReadPlatformServiceImpl( + final PlatformSecurityContext context, + final TenantAwareRoutingDataSource dataSource, + SavingProductReadPlatformService savingProductReadPlatformService, + final ClientReadPlatformService clientReadPlatformService ) { + this.context = context; + this.jdbcTemplate = new JdbcTemplate(dataSource); + this.savingProductReadPlatformService = savingProductReadPlatformService; + this.clientReadPlatformService = clientReadPlatformService; + } + + @Override + public Collection retrieveAllSavingsAccounts() { + + this.context.authenticatedUser(); + SavingAccountMapper mapper = new SavingAccountMapper(); + String sql = "select " + mapper.schema() + " where sa.is_deleted=0"; + return this.jdbcTemplate.query(sql,mapper, new Object[]{}); + + } + + @Override + public SavingAccountData retrieveSavingsAccount(Long accountId) { + + this.context.authenticatedUser(); + SavingAccountMapper mapper = new SavingAccountMapper(); + String sql = "select " + mapper.schema() + " where sa.id = ? and sa.is_deleted=0"; + SavingAccountData savingAccountData = this.jdbcTemplate.queryForObject(sql,mapper, new Object[]{accountId}); + return savingAccountData; + } + + @Override + public SavingAccountData retrieveNewSavingsAccountDetails(Long clientId, + Long productId) { + // TODO Auto-generated method stub + return null; + } + + private static final class SavingAccountMapper implements RowMapper { + + public String schema() { + return "sa.id AS id, sa.status_enum AS status, sa.external_id AS externalId," + + " sa.client_id AS clientId, sa.product_id AS productId, sa.deposit_amount_per_period AS savingsDepostiAmountPerPeriod," + + " sa.savings_product_type AS savingsProductType, sa.currency_code AS currencyCode, sa.currency_digits AS currencyDigits," + + " sa.total_deposit_amount AS totalDepositAmount, sa.reccuring_nominal_interest_rate AS reccuringInterestRate," + + " sa.regular_saving_nominal_interest_rate AS savingInterestRate, sa.tenure AS tenure, sa.tenure_type AS tenureType," + + " sa.frequency AS savingsFrequencyType, sa.interest_type AS interestType, sa.interest_calculation_method AS interestCalculationMethod," + + " sa.projected_commencement_date AS projectedCommencementDate, sa.actual_commencement_date AS actualCommencementDate," + + " sa.matures_on_date AS maturesOnDate, sa.projected_interest_accrued_on_maturity AS projectedInterestAccuredOnMaturity," + + " sa.actual_interest_accrued AS actualInterestAccured, sa.projected_total_maturity_amount AS projectedTotalMaturityAmount," + + " sa.actual_total_amount AS actualTotalAmount, sa.is_preclosure_allowed AS isPreclosureAllowed," + + " sa.pre_closure_interest_rate AS preClosureInterestRate, sa.is_lock_in_period_allowed AS isLockinPeriodAllowed," + + " sa.lock_in_period AS lockinPeriod, sa.lock_in_period_type AS lockinPeriodType, sa.withdrawnon_date AS withdrawnonDate," + + " sa.rejectedon_date AS rejectedonDate, sa.closedon_date AS closedonDate, ps.name AS productName," + + " c.firstname AS firstname, c.lastname AS lastname, curr.name AS currencyName, " + + " curr.internationalized_name_code AS currencyNameCode, curr.display_symbol AS currencyDisplaySymbol " + + " FROM m_saving_account sa " + + " JOIN m_client c ON c.id = sa.client_id" + + " JOIN m_currency curr ON curr.code = sa.currency_code " + + " JOIN m_product_savings ps ON sa.product_id = ps.id "; + } + + @Override + public SavingAccountData mapRow(ResultSet rs, int rowNum) throws SQLException { + + Long id = rs.getLong("id"); + String externalId = rs.getString("externalId"); + Long clientId = rs.getLong("clientId"); + String clientName = rs.getString("firstname") + " " + rs.getString("lastname"); + + Long productId = rs.getLong("productId"); + String productName = rs.getString("productName"); + EnumOptionData productType = SavingProductEnumerations.savingProductType(JdbcSupport.getInteger(rs, "savingsProductType")); + + Integer statusId = JdbcSupport.getInteger(rs, "status"); + EnumOptionData status = DepositAccountEnumerations.status(statusId); + + String currencyCode = rs.getString("currencyCode"); + String currencyName = rs.getString("currencyName"); + String currencyNameCode = rs.getString("currencyNameCode"); + String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol"); + Integer currencyDigits = JdbcSupport.getInteger(rs,"currencyDigits"); + CurrencyData currencyData = new CurrencyData(currencyCode,currencyName, currencyDigits, currencyDisplaySymbol,currencyNameCode); + + BigDecimal savingsDepostiAmountPerPeriod = rs.getBigDecimal("savingsDepostiAmountPerPeriod"); + EnumOptionData savingsFrequencyType = SavingProductEnumerations.interestFrequencyType(JdbcSupport.getInteger(rs, "savingsFrequencyType")); + BigDecimal totalDepositAmount = rs.getBigDecimal("totalDepositAmount"); + + BigDecimal reccuringInterestRate = rs.getBigDecimal("reccuringInterestRate"); + BigDecimal savingInterestRate = rs.getBigDecimal("savingInterestRate"); + EnumOptionData interestType = SavingProductEnumerations.savingInterestType(JdbcSupport.getInteger(rs, "interestType")); + EnumOptionData interestCalculationMethod = SavingProductEnumerations.savingInterestCalculationMethod(JdbcSupport.getInteger(rs, "interestCalculationMethod")); + + Integer tenure = JdbcSupport.getInteger(rs,"tenure"); + EnumOptionData tenureType = SavingProductEnumerations.tenureTypeEnum(JdbcSupport.getInteger(rs, "tenureType")); + + LocalDate projectedCommencementDate = JdbcSupport.getLocalDate(rs, "projectedCommencementDate"); + LocalDate actualCommencementDate = JdbcSupport.getLocalDate(rs, "actualCommencementDate"); + LocalDate maturesOnDate = JdbcSupport.getLocalDate(rs, "maturesOnDate"); + BigDecimal projectedInterestAccuredOnMaturity = rs.getBigDecimal("projectedInterestAccuredOnMaturity"); + BigDecimal actualInterestAccured = rs.getBigDecimal("actualInterestAccured"); + + BigDecimal projectedMaturityAmount = rs.getBigDecimal("projectedTotalMaturityAmount"); + BigDecimal actualMaturityAmount = rs.getBigDecimal("actualTotalAmount"); + + boolean preClosureAllowed = rs.getBoolean("isPreclosureAllowed"); + BigDecimal preClosureInterestRate = rs.getBigDecimal("preClosureInterestRate"); + + LocalDate withdrawnonDate = JdbcSupport.getLocalDate(rs, "withdrawnonDate"); + LocalDate rejectedonDate = JdbcSupport.getLocalDate(rs, "rejectedonDate"); + LocalDate closedonDate = JdbcSupport.getLocalDate(rs, "closedonDate"); + + boolean isLockinPeriodAllowed = rs.getBoolean("isLockinPeriodAllowed"); + Integer lockinPeriod = JdbcSupport.getInteger(rs, "lockinPeriod"); + Integer lockinPeriodTypeValue = JdbcSupport.getInteger(rs, "lockinPeriodType"); + EnumOptionData lockinPeriodType = SavingProductEnumerations.savingsLockinPeriod(lockinPeriodTypeValue); + + return new SavingAccountData(id, status, externalId, clientId, clientName, productId, productName, productType, currencyData, + savingsDepostiAmountPerPeriod, savingsFrequencyType, totalDepositAmount, reccuringInterestRate, savingInterestRate, + interestType, interestCalculationMethod, tenure, tenureType, projectedCommencementDate, actualCommencementDate, + maturesOnDate,projectedInterestAccuredOnMaturity, actualInterestAccured, + projectedMaturityAmount, actualMaturityAmount, preClosureAllowed, preClosureInterestRate, withdrawnonDate, + rejectedonDate, closedonDate, isLockinPeriodAllowed, lockinPeriod, lockinPeriodType); + } + + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountWritePlatformService.java new file mode 100644 index 000000000..57d3eb223 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountWritePlatformService.java @@ -0,0 +1,18 @@ +package org.mifosng.platform.saving.service; + +import org.mifosng.platform.api.commands.SavingAccountCommand; +import org.mifosng.platform.api.data.EntityIdentifier; +import org.springframework.security.access.prepost.PreAuthorize; + +public interface SavingAccountWritePlatformService { + + @PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')") + EntityIdentifier createSavingAccount(SavingAccountCommand command); + + @PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')") + EntityIdentifier deleteSavingAccount(SavingAccountCommand command); + + @PreAuthorize(value = "hasRole('ORGANISATION_ADMINISTRATION_SUPER_USER_ROLE')") + EntityIdentifier updateSavingAccount(SavingAccountCommand command); + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountWritePlatformServiceJpaRepositoryImpl.java new file mode 100644 index 000000000..3b23cd41f --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/SavingAccountWritePlatformServiceJpaRepositoryImpl.java @@ -0,0 +1,99 @@ +package org.mifosng.platform.saving.service; + +import org.mifosng.platform.api.commands.SavingAccountCommand; +import org.mifosng.platform.api.data.EntityIdentifier; +import org.mifosng.platform.client.domain.NoteRepository; +import org.mifosng.platform.exceptions.PlatformDataIntegrityException; +import org.mifosng.platform.exceptions.SavingAccountNotFoundException; +import org.mifosng.platform.saving.domain.SavingAccount; +import org.mifosng.platform.saving.domain.SavingAccountRepository; +import org.mifosng.platform.security.PlatformSecurityContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class SavingAccountWritePlatformServiceJpaRepositoryImpl implements SavingAccountWritePlatformService { + + private final static Logger logger = LoggerFactory.getLogger(SavingAccountWritePlatformServiceJpaRepositoryImpl.class); + + private final PlatformSecurityContext context; + private final SavingAccountRepository savingAccountRepository; + private final SavingAccountAssembler savingAccountAssembler; + @SuppressWarnings("unused") + private final NoteRepository noteRepository; + + @Autowired + public SavingAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,final SavingAccountRepository savingAccountRepository, + SavingAccountAssembler savingAccountAssembler,NoteRepository noteRepository) { + this.context=context; + this.savingAccountRepository=savingAccountRepository; + this.savingAccountAssembler=savingAccountAssembler; + this.noteRepository=noteRepository; + } + + + @Transactional + @Override + public EntityIdentifier createSavingAccount(SavingAccountCommand command) { + try { + this.context.authenticatedUser(); + SavingAccountCommandValidator validator=new SavingAccountCommandValidator(command); + validator.validateForCreate(); + + SavingAccount account=this.savingAccountAssembler.assembleFrom(command); + this.savingAccountRepository.save(account); + + return new EntityIdentifier(account.getId()); + } catch (DataIntegrityViolationException dve) { + handleDataIntegrityIssues(command, dve); + return new EntityIdentifier(Long.valueOf(-1)); + } + + } + + @Override + public EntityIdentifier deleteSavingAccount(SavingAccountCommand command) { + + return null; + } + + @Override + public EntityIdentifier updateSavingAccount(SavingAccountCommand command) { + try { + this.context.authenticatedUser(); + SavingAccountCommandValidator validator=new SavingAccountCommandValidator(command); + validator.validateForUpdate(); + + SavingAccount account=this.savingAccountRepository.findOne(command.getId()); + if (account == null || account.isDeleted()) { + throw new SavingAccountNotFoundException(command.getId()); + } + if(account.isPendingApproval()){ + this.savingAccountAssembler.assembleFrom(command,account); + this.savingAccountRepository.save(account); + } + return new EntityIdentifier(account.getId()); + } catch (DataIntegrityViolationException dve) { + handleDataIntegrityIssues(command, dve); + return new EntityIdentifier(Long.valueOf(-1)); + } + } + + /* + * Guaranteed to throw an exception no matter what the data integrity issue is. + */ + private void handleDataIntegrityIssues(final SavingAccountCommand command, DataIntegrityViolationException dve) { + + Throwable realCause = dve.getMostSpecificCause(); + if (realCause.getMessage().contains("saving_acc_external_id")) { + throw new PlatformDataIntegrityException("error.msg.saving.account.duplicate.externalId", "Saving account with externalId " + command.getExternalId() + " already exists", "externalId", command.getExternalId()); + } + + logger.error(dve.getMessage(), dve); + throw new PlatformDataIntegrityException("error.msg.saving.account.unknown.data.integrity.issue", "Unknown data integrity issue with resource."); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/DepositProduct.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/DepositProduct.java index ec8150361..e429e682e 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/DepositProduct.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/DepositProduct.java @@ -29,7 +29,6 @@ public class DepositProduct extends AbstractAuditableCustom { @Column(name = "external_id", length=100) private String externalId; - @SuppressWarnings("unused") @Column(name = "description") private String description; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingFrequencyType.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingFrequencyType.java new file mode 100644 index 000000000..1076515db --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingFrequencyType.java @@ -0,0 +1,54 @@ +package org.mifosng.platform.savingproduct.domain; + + +public enum SavingFrequencyType { + + INVALID(0,"savingFrequencyType.invalid"), + DAILY(1,"savingFrequencyType.daily"), + MONTHLY(2,"savingFrequencyType.monthly"), + QUATERLY(3,"savingFrequencyType.quaterly"), + HALFYEARLY(4,"savingFrequencyType.halfyearly"), + YEARLY(5,"savingFrequencyType.yearly"); + + private final Integer value; + private final String code; + + private SavingFrequencyType(final Integer value,final String code) { + this.value=value; + this.code=code; + } + + public Integer getValue() { + return value; + } + public String getCode() { + return code; + } + + public static SavingFrequencyType fromInt(final Integer frequency) { + + SavingFrequencyType savingFrequencyType = SavingFrequencyType.INVALID; + switch (frequency) { + case 1: + savingFrequencyType = SavingFrequencyType.DAILY; + break; + case 2: + savingFrequencyType = SavingFrequencyType.MONTHLY; + break; + case 3: + savingFrequencyType = SavingFrequencyType.QUATERLY; + break; + case 4: + savingFrequencyType = SavingFrequencyType.HALFYEARLY; + break; + case 5: + savingFrequencyType = SavingFrequencyType.YEARLY; + break; + default: + savingFrequencyType = SavingFrequencyType.INVALID; + break; + } + return savingFrequencyType; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingInterestCalculationMethod.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingInterestCalculationMethod.java new file mode 100644 index 000000000..6fbb5f966 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingInterestCalculationMethod.java @@ -0,0 +1,44 @@ +package org.mifosng.platform.savingproduct.domain; + +public enum SavingInterestCalculationMethod { + + AVERAGEBAL(1,"savinginterest.calculation.method.averagebal"), + MINBAL(2,"savinginterest.calculation.method.minbal"), + MONTHLYCOLLECTION(3,"savinginterest.calculation.method.monthlycllection"), + INVALID(0,"savinginterest.calculation.method.invalid"); + + private final Integer value; + private final String code; + + private SavingInterestCalculationMethod(final Integer value,final String code) { + this.value=value; + this.code=code; + } + + public Integer getValue() { + return value; + } + + public String getCode() { + return code; + } + public static SavingInterestCalculationMethod fromInt(final Integer frequency) { + + SavingInterestCalculationMethod savingInterestCalculationMethod = SavingInterestCalculationMethod.INVALID; + switch (frequency) { + case 1: + savingInterestCalculationMethod = SavingInterestCalculationMethod.AVERAGEBAL; + break; + case 2: + savingInterestCalculationMethod = SavingInterestCalculationMethod.MINBAL; + break; + case 3: + savingInterestCalculationMethod = SavingInterestCalculationMethod.MONTHLYCOLLECTION; + break; + default: + savingInterestCalculationMethod = SavingInterestCalculationMethod.INVALID; + break; + } + return savingInterestCalculationMethod; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProduct.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProduct.java index 05945c7e5..1b8e6e8fc 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProduct.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProduct.java @@ -11,6 +11,7 @@ import org.apache.commons.lang.StringUtils; import org.mifosng.platform.api.commands.SavingProductCommand; import org.mifosng.platform.currency.domain.MonetaryCurrency; import org.mifosng.platform.infrastructure.AbstractAuditableCustom; +import org.mifosng.platform.loan.domain.PeriodFrequencyType; import org.mifosng.platform.user.domain.AppUser; @Entity @@ -34,18 +35,23 @@ public class SavingProduct extends AbstractAuditableCustom { this.description = null; this.savingProductRelatedDetail = null; } - - public SavingProduct(final String name, final String description, final MonetaryCurrency currency,final BigDecimal interestRate, final BigDecimal minimumBalance,final BigDecimal maximumBalance) { + + public SavingProduct(final String name, final String description, final MonetaryCurrency currency,final BigDecimal interestRate, final BigDecimal minInterestRate, final BigDecimal maxInterestRate, final BigDecimal savingsDepositAmount, + final SavingProductType savingProductType, final TenureTypeEnum tenureType, final Integer tenure, final SavingFrequencyType savingFrequencyType, + final SavingsInterestType savingsInterestType, SavingInterestCalculationMethod savingInterestCalculationMethod, final BigDecimal minimumBalanceForWithdrawal, + final boolean isPartialDepositAllowed, final boolean isLockinPeriodAllowed, final Integer lockinPeriod, final PeriodFrequencyType lockinPeriodType){ + this.name = name.trim(); if (StringUtils.isNotBlank(description)) { this.description = description.trim(); } else { this.description = null; } - this.savingProductRelatedDetail=new SavingProductRelatedDetail(currency, interestRate,minimumBalance,maximumBalance); + this.savingProductRelatedDetail = new SavingProductRelatedDetail(currency, interestRate, minInterestRate, maxInterestRate, savingsDepositAmount, savingProductType, tenureType, tenure, + savingFrequencyType, savingsInterestType, savingInterestCalculationMethod, minimumBalanceForWithdrawal, isPartialDepositAllowed, isLockinPeriodAllowed, lockinPeriod, lockinPeriodType); } - - public String getName() { + + public String getName() { return this.name; } @@ -65,10 +71,6 @@ public class SavingProduct extends AbstractAuditableCustom { return this.savingProductRelatedDetail.getMinimumBalance(); } - public BigDecimal getMaximumBalance(){ - return this.savingProductRelatedDetail.getMaximumBalance(); - } - public boolean isDeleted() { return deleted; } @@ -77,6 +79,10 @@ public class SavingProduct extends AbstractAuditableCustom { this.deleted = true; } + public SavingProductRelatedDetail getSavingProductRelatedDetail() { + return savingProductRelatedDetail; + } + public void update(final SavingProductCommand command) { if (command.isNameChanged()) { diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProductRelatedDetail.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProductRelatedDetail.java index d4c67be57..2a3a4a641 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProductRelatedDetail.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProductRelatedDetail.java @@ -8,6 +8,7 @@ import javax.persistence.Embedded; import org.mifosng.platform.api.commands.SavingProductCommand; import org.mifosng.platform.currency.domain.MonetaryCurrency; +import org.mifosng.platform.loan.domain.PeriodFrequencyType; @Embeddable public class SavingProductRelatedDetail { @@ -18,25 +19,79 @@ public class SavingProductRelatedDetail { @Column(name = "interest_rate", scale = 6, precision = 19, nullable = false) private BigDecimal interestRate; - @Column(name = "minimum_balance", scale = 6, precision = 19, nullable = false) - private BigDecimal minimumBalance; + @Column(name = "min_interest_rate", scale = 6, precision = 19, nullable = false) + private BigDecimal minInterestRate; - @Column(name = "maximum_balance", scale = 6, precision = 19, nullable = false) - private BigDecimal maximumBalance; + @Column(name = "max_interest_rate", scale = 6, precision = 19, nullable = false) + private BigDecimal maxInterestRate; + + @Column(name = "savings_deposit_amount", scale = 6, precision = 19, nullable = false) + private BigDecimal savingsDepositAmount; + + @Column(name = "savings_product_type", nullable=false) + private SavingProductType savingProductType; + + @Column(name = "tenure_type", nullable=false) + private TenureTypeEnum tenureType; + + @Column(name = "tenure", nullable=false) + private Integer tenure; + + @Column(name = "frequency", nullable=false) + private SavingFrequencyType frequency; + + @Column(name = "interest_type", nullable=false) + private SavingsInterestType interestType; + + @Column(name = "interest_calculation_method") + private SavingInterestCalculationMethod interestCalculationMethod; + + @Column(name = "min_bal_for_withdrawal", scale = 6, precision = 19, nullable = false) + private BigDecimal minimumBalanceForWithdrawal; + + @Column(name = "is_partial_deposit_allowed", nullable=false) + private boolean isPartialDepositAllowed; + + @Column(name = "is_lock_in_period_allowed", nullable=false) + private boolean isLockinPeriodAllowed; + + @Column(name = "lock_in_period", nullable=false) + private Integer lockinPeriod; + + @Column(name = "lock_in_period_type", nullable=false) + private PeriodFrequencyType lockinPeriodType; public SavingProductRelatedDetail() { this.interestRate=null; - this.maximumBalance=null; - this.minimumBalance=null; + this.savingsDepositAmount=null; } - public SavingProductRelatedDetail(final MonetaryCurrency currency,final BigDecimal interestRate, final BigDecimal minimumBalance,final BigDecimal maximumBalance) { + public SavingProductRelatedDetail(final MonetaryCurrency currency,final BigDecimal interestRate, final BigDecimal minInterestRate, final BigDecimal maxInterestRate, + final BigDecimal savingsDepositAmount, final SavingProductType savingProductType, + final TenureTypeEnum tenureType, final Integer tenure, + final SavingFrequencyType frequency, final SavingsInterestType interestType, + final SavingInterestCalculationMethod interestCalculationMethod, + final BigDecimal minimumBalanceForWithdrawal, + final boolean isPartialDepositAllowed, final boolean isLockinPeriodAllowed, + final Integer lockinPeriod, final PeriodFrequencyType lockinPeriodType) { this.currency=currency; this.interestRate=interestRate; - this.minimumBalance=minimumBalance; - this.maximumBalance=maximumBalance; + this.minInterestRate = minInterestRate; + this.maxInterestRate = maxInterestRate; + this.savingsDepositAmount=savingsDepositAmount; + this.savingProductType=savingProductType; + this.tenureType=tenureType; + this.tenure=tenure; + this.frequency=frequency; + this.interestType=interestType; + this.interestCalculationMethod=interestCalculationMethod; + this.minimumBalanceForWithdrawal=minimumBalanceForWithdrawal; + this.isPartialDepositAllowed=isPartialDepositAllowed; + this.isLockinPeriodAllowed=isLockinPeriodAllowed; + this.lockinPeriod=lockinPeriod; + this.lockinPeriodType=lockinPeriodType; } - + public MonetaryCurrency getCurrency() { return this.currency.copy(); } @@ -46,17 +101,13 @@ public class SavingProductRelatedDetail { } public BigDecimal getMinimumBalance(){ - return BigDecimal.valueOf(Double.valueOf(this.minimumBalance.stripTrailingZeros().toString())); - } - - public BigDecimal getMaximumBalance(){ - return BigDecimal.valueOf(Double.valueOf(this.maximumBalance.stripTrailingZeros().toString())); + return BigDecimal.valueOf(Double.valueOf(this.savingsDepositAmount.stripTrailingZeros().toString())); } public void update(SavingProductCommand command){ - Integer digitsAfterDecimalChanged = this.currency.getDigitsAfterDecimal(); + Integer digitsAfterDecimal = this.currency.getDigitsAfterDecimal(); if (command.isDigitsAfterDecimalChanged()) { - digitsAfterDecimalChanged = command.getDigitsAfterDecimal(); + digitsAfterDecimal = command.getDigitsAfterDecimal(); } String currencyCodeChanged = this.currency.getCode(); @@ -65,19 +116,108 @@ public class SavingProductRelatedDetail { } if (command.isDigitsAfterDecimalChanged() || command.isCurrencyCodeChanged()) { - this.currency = new MonetaryCurrency(currencyCodeChanged, digitsAfterDecimalChanged); + this.currency = new MonetaryCurrency(currencyCodeChanged, digitsAfterDecimal); } if (command.isInterestRateChanged()) { this.interestRate = command.getInterestRate(); } - if(command.isMaximumBalanceChanged()){ - this.minimumBalance=command.getMinimumBalance(); + if(command.isSavingsDepositAmountChanged()){ + this.savingsDepositAmount=command.getSavingsDepositAmount(); } - if(command.isMaximumBalanceChanged()){ - this.maximumBalance=command.getMaximumBalance(); + if (command.isSavingProductTypeChanged()) { + this.savingProductType=SavingProductType.fromInt(command.getSavingProductType()); + } + + if(command.isTenureTypeChanged()){ + this.tenureType=TenureTypeEnum.fromInt(command.getTenureType()); + } + + if (command.isTenureChanged()) { + this.tenure = command.getTenure(); + } + + if (command.isFrequencyChanged()){ + this.frequency = SavingFrequencyType.fromInt(command.getFrequency()); + } + + if (command.isInterestTypeChanged()) { + this.interestType = SavingsInterestType.fromInt(command.getInterestType()); + } + + if (command.isInterestCalculationMethodChanged()){ + this.interestCalculationMethod = SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod()); + } + + if (command.isMinimumBalanceForWithdrawalChanged()) { + this.minimumBalanceForWithdrawal = command.getMinimumBalanceForWithdrawal(); + } + + if (command.isPartialDepositAllowedChanged()) { + this.isPartialDepositAllowed = command.isPartialDepositAllowed(); + } + + if (command.isLockinPeriodAllowedChanged()){ + this.isLockinPeriodAllowed = command.isLockinPeriodAllowed(); + } + + if (command.isLockinPeriodChanged()){ + this.lockinPeriod = command.getLockinPeriod(); + } + + if (command.isLockinPeriodTypeChanged()){ + this.lockinPeriodType=PeriodFrequencyType.fromInt(command.getLockinPeriodType()); } } + + public BigDecimal getSavingsDepositAmount() { + return savingsDepositAmount; + } + + public SavingProductType getSavingProductType() { + return savingProductType; + } + + public TenureTypeEnum getTenureType() { + return tenureType; + } + + public Integer getTenure() { + return tenure; + } + + public SavingFrequencyType getFrequency() { + return frequency; + } + + public SavingsInterestType getInterestType() { + return interestType; + } + + public SavingInterestCalculationMethod getInterestCalculationMethod() { + return interestCalculationMethod; + } + + public BigDecimal getMinimumBalanceForWithdrawal() { + return minimumBalanceForWithdrawal; + } + + public boolean isPartialDepositAllowed() { + return isPartialDepositAllowed; + } + + public boolean isLockinPeriodAllowed() { + return isLockinPeriodAllowed; + } + + public Integer getLockinPeriod() { + return lockinPeriod; + } + + public PeriodFrequencyType getLockinPeriodType() { + return lockinPeriodType; + } + } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProductType.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProductType.java new file mode 100644 index 000000000..aea6a5731 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingProductType.java @@ -0,0 +1,50 @@ +package org.mifosng.platform.savingproduct.domain; + + +public enum SavingProductType { + + INVALID(0,"savingProductType.invalid"), + RECCURING(1,"savingProductType.reccuring"), + REGULAR(2,"savingProductType.regular"); + + private final Integer value; + private final String code; + + private SavingProductType(final Integer value,final String code) { + this.value=value; + this.code=code; + } + + public Integer getValue() { + return value; + } + public String getCode() { + return code; + } + + public static SavingProductType fromInt(final Integer frequency) { + + SavingProductType savingProductType = SavingProductType.INVALID; + switch (frequency) { + case 1: + savingProductType = SavingProductType.RECCURING; + break; + case 2: + savingProductType = SavingProductType.REGULAR; + break; + default: + savingProductType = SavingProductType.INVALID; + break; + } + return savingProductType; + } + + public boolean isReccuring(){ + return this.value.equals(SavingProductType.RECCURING.getValue()); + } + + public boolean isRegular(){ + return this.value.equals(SavingProductType.REGULAR.getValue()); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingsInterestType.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingsInterestType.java new file mode 100644 index 000000000..61c6714f0 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingsInterestType.java @@ -0,0 +1,42 @@ +package org.mifosng.platform.savingproduct.domain; + + +public enum SavingsInterestType { + + INVALID(0,"savingsInterestType.invalid"), + SIMPLE(1,"savingsInterestType.simple"), + COMPOUNDING(2,"savingsInterestType.compounding"); + + private final Integer value; + private final String code; + + private SavingsInterestType(final Integer value,final String code) { + this.value=value; + this.code=code; + } + + public Integer getValue() { + return value; + } + public String getCode() { + return code; + } + + public static SavingsInterestType fromInt(final Integer frequency) { + + SavingsInterestType savingsInterestType = SavingsInterestType.INVALID; + switch (frequency) { + case 1: + savingsInterestType = SavingsInterestType.SIMPLE; + break; + case 2: + savingsInterestType = SavingsInterestType.COMPOUNDING; + break; + default: + savingsInterestType = SavingsInterestType.INVALID; + break; + } + return savingsInterestType; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingsLockinPeriodEnum.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingsLockinPeriodEnum.java new file mode 100644 index 000000000..05ef48cb2 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/SavingsLockinPeriodEnum.java @@ -0,0 +1,52 @@ +package org.mifosng.platform.savingproduct.domain; + + +public enum SavingsLockinPeriodEnum { + + DAYS(0, "lockin.period.type.days"), // + WEEKS(1, "lockin.period.type.weeks"), // + MONTHS(2, "lockin.period.type.months"), // + YEARS(3, "lockin.period.type.years"), // + INVALID(4, "lockin.period.type.invalid"); + + private final Integer value; + private final String code; + + private SavingsLockinPeriodEnum(final Integer value, final String code) { + this.value = value; + this.code = code; + } + + public Integer getValue() { + return this.value; + } + + public String getCode() { + return code; + } + + public static SavingsLockinPeriodEnum fromInt(final Integer frequency) { + + SavingsLockinPeriodEnum lockinPeriodType = SavingsLockinPeriodEnum.INVALID; + switch (frequency) { + case 0: + lockinPeriodType = SavingsLockinPeriodEnum.DAYS; + break; + case 1: + lockinPeriodType = SavingsLockinPeriodEnum.WEEKS; + break; + case 2: + lockinPeriodType = SavingsLockinPeriodEnum.MONTHS; + break; + case 3: + lockinPeriodType = SavingsLockinPeriodEnum.YEARS; + break; + default: + lockinPeriodType = SavingsLockinPeriodEnum.INVALID; + break; + } + return lockinPeriodType; + } + + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/TenureTypeEnum.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/TenureTypeEnum.java new file mode 100644 index 000000000..16fc6dbef --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/domain/TenureTypeEnum.java @@ -0,0 +1,42 @@ +package org.mifosng.platform.savingproduct.domain; + + +public enum TenureTypeEnum { + + INVALID(0,"tenureTypeEnum.invalid"), + FIXED_PERIOD(1,"tenureTypeEnum.fixedPeriod"), + PERPETUAL(2,"tenureTypeEnum.perpetual"); + + private final Integer value; + private final String code; + + private TenureTypeEnum(final Integer value,final String code) { + this.value=value; + this.code=code; + } + + public Integer getValue() { + return value; + } + public String getCode() { + return code; + } + + public static TenureTypeEnum fromInt(final Integer frequency) { + + TenureTypeEnum tenureTypeEnum = TenureTypeEnum.INVALID; + switch (frequency) { + case 1: + tenureTypeEnum = TenureTypeEnum.FIXED_PERIOD; + break; + case 2: + tenureTypeEnum = TenureTypeEnum.PERPETUAL; + break; + default: + tenureTypeEnum = TenureTypeEnum.INVALID; + break; + } + return tenureTypeEnum; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductCommandValidator.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductCommandValidator.java index 093eb5778..49060c1b9 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductCommandValidator.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductCommandValidator.java @@ -25,14 +25,25 @@ public class SavingProductCommandValidator { baseDataValidator.reset().parameter("name").value(command.getName()).ignoreIfNull().notBlank(); baseDataValidator.reset().parameter("description").value(command.getDescription()).ignoreIfNull().notExceedingLengthOf(500); baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).ignoreIfNull().notBlank(); - baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).ignoreIfNull().notNull().inMinMaxRange(0, 6); + baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).ignoreIfNull().inMinMaxRange(0, 6); baseDataValidator.reset().parameter("interestRate").value(command.getInterestRate()).ignoreIfNull().notBlank(); - baseDataValidator.reset().parameter("maximumBalance").value(command.getMaximumBalance()).notNull(); - baseDataValidator.reset().parameter("minimumBalance").value(command.getMinimumBalance()).notNull(); - baseDataValidator.reset().parameter("maximumBalance").value(command.getMaximumBalance()).zeroOrPositiveAmount(); - baseDataValidator.reset().parameter("minimumBalance").value(command.getMinimumBalance()).zeroOrPositiveAmount(); - baseDataValidator.reset().comapareMinimumAndMaximumAmounts(command.getMinimumBalance(), command.getMaximumBalance()); - baseDataValidator.reset().anyOfNotNull(command.getName(), command.getDescription(),command.getCurrencyCode(),command.getDigitsAfterDecimal(),command.getInterestRate(),command.getMinimumBalance(),command.getMaximumBalance()); + baseDataValidator.reset().parameter("minInterestRate").value(command.getMinInterestRate()).ignoreIfNull().notBlank(); + baseDataValidator.reset().parameter("maxInterestRate").value(command.getMaxInterestRate()).ignoreIfNull().notBlank(); + baseDataValidator.reset().parameter("minInterestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getMinInterestRate(), command.getMaxInterestRate()); + baseDataValidator.reset().parameter("interestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getInterestRate(), command.getMaxInterestRate()); + baseDataValidator.reset().parameter("minInterestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getMinInterestRate(), command.getInterestRate()); + baseDataValidator.reset().parameter("savingsDepositAmount").value(command.getSavingsDepositAmount()).ignoreIfNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).ignoreIfNull(); + baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).ignoreIfNull(); + baseDataValidator.reset().parameter("tenure").value(command.getTenure()).ignoreIfNull(); + baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).ignoreIfNull(); + baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).ignoreIfNull(); + baseDataValidator.reset().parameter("interestCalculationMethod").value(command.getInterestCalculationMethod()).ignoreIfNull(); + baseDataValidator.reset().parameter("minimumBalanceForWithdrawal").value(command.getMinimumBalanceForWithdrawal()).ignoreIfNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("isPartialDepositAllowed").value(command.isPartialDepositAllowed()).trueOrFalseRequired(command.isPartialDepositAllowedChanged()).ignoreIfNull(); + baseDataValidator.reset().parameter("isLockinPeriodAllowed").value(command.isLockinPeriodAllowed()).trueOrFalseRequired(command.isLockinPeriodAllowedChanged()).ignoreIfNull(); + baseDataValidator.reset().parameter("lockinPeriod").value(command.getLockinPeriod()).ignoreIfNull(); + baseDataValidator.reset().parameter("lockinPeriodType").value(command.getLockinPeriodType()).ignoreIfNull(); if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); @@ -48,12 +59,25 @@ public class SavingProductCommandValidator { baseDataValidator.reset().parameter("description").value(command.getDescription()).notExceedingLengthOf(500); baseDataValidator.reset().parameter("currencyCode").value(command.getCurrencyCode()).notBlank(); baseDataValidator.reset().parameter("digitsAfterDecimal").value(command.getDigitsAfterDecimal()).notNull().inMinMaxRange(0, 6); - baseDataValidator.reset().parameter("interestRate").value(command.getInterestRate()).notNull(); - baseDataValidator.reset().parameter("maximumBalance").value(command.getMaximumBalance()).notNull(); - baseDataValidator.reset().parameter("minimumBalance").value(command.getMinimumBalance()).notNull(); - baseDataValidator.reset().parameter("maximumBalance").value(command.getMaximumBalance()).zeroOrPositiveAmount(); - baseDataValidator.reset().parameter("minimumBalance").value(command.getMinimumBalance()).zeroOrPositiveAmount(); - baseDataValidator.reset().comapareMinimumAndMaximumAmounts(command.getMinimumBalance(), command.getMaximumBalance()); + baseDataValidator.reset().parameter("interestRate").value(command.getInterestRate()).notNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("minInterestRate").value(command.getMinInterestRate()).notNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("maxInterestRate").value(command.getMaxInterestRate()).notNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("minInterestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getMinInterestRate(), command.getMaxInterestRate()); + baseDataValidator.reset().parameter("interestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getInterestRate(), command.getMaxInterestRate()); + baseDataValidator.reset().parameter("minInterestRate").comapareMinAndMaxOfTwoBigDecmimalNos(command.getMinInterestRate(), command.getInterestRate()); + baseDataValidator.reset().parameter("savingsDepositAmount").value(command.getSavingsDepositAmount()).notNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("savingProductType").value(command.getSavingProductType()).notNull(); + baseDataValidator.reset().parameter("tenureType").value(command.getTenureType()).notNull(); + baseDataValidator.reset().parameter("tenure").value(command.getTenure()).notNull(); + baseDataValidator.reset().parameter("frequency").value(command.getFrequency()).notNull(); + baseDataValidator.reset().parameter("interestType").value(command.getInterestType()).notNull(); + baseDataValidator.reset().parameter("interestCalculationMethod").value(command.getInterestCalculationMethod()).notNull(); + baseDataValidator.reset().parameter("minimumBalanceForWithdrawal").value(command.getMinimumBalanceForWithdrawal()).notNull().zeroOrPositiveAmount(); + baseDataValidator.reset().parameter("isPartialDepositAllowed").value(command.isPartialDepositAllowed()).trueOrFalseRequired(command.isPartialDepositAllowedChanged()).notNull(); + baseDataValidator.reset().parameter("isLockinPeriodAllowed").value(command.isLockinPeriodAllowed()).trueOrFalseRequired(command.isLockinPeriodAllowedChanged()).notNull(); + baseDataValidator.reset().parameter("lockinPeriod").value(command.getLockinPeriod()).notNull(); + baseDataValidator.reset().parameter("lockinPeriodType").value(command.getLockinPeriodType()).notNull(); + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductEnumerations.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductEnumerations.java new file mode 100644 index 000000000..e132e2b50 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductEnumerations.java @@ -0,0 +1,163 @@ +package org.mifosng.platform.savingproduct.service; + +import org.mifosng.platform.api.data.EnumOptionData; +import org.mifosng.platform.savingproduct.domain.SavingFrequencyType; +import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod; +import org.mifosng.platform.savingproduct.domain.SavingProductType; +import org.mifosng.platform.savingproduct.domain.SavingsInterestType; +import org.mifosng.platform.savingproduct.domain.SavingsLockinPeriodEnum; +import org.mifosng.platform.savingproduct.domain.TenureTypeEnum; + +public class SavingProductEnumerations { + + public static EnumOptionData savingProductType(final int id) { + return savingProductType(SavingProductType.fromInt(id)); + } + + public static EnumOptionData tenureTypeEnum(final int id) { + return tenureTypeEnum(TenureTypeEnum.fromInt(id)); + } + + public static EnumOptionData interestFrequencyType(final int id) { + return interestFrequencyType(SavingFrequencyType.fromInt(id)); + } + + public static EnumOptionData savingInterestType(final int id) { + return savingInterestType(SavingsInterestType.fromInt(id)); + } + + public static EnumOptionData savingInterestCalculationMethod(final int id) { + return savingInterestCalculationMethod(SavingInterestCalculationMethod.fromInt(id)); + } + + public static EnumOptionData savingsLockinPeriod(final int id){ + return savingsLockinPeriod(SavingsLockinPeriodEnum.fromInt(id)); + } + + public static EnumOptionData savingsLockinPeriod(SavingsLockinPeriodEnum type) { + final String codePrefix = "savings.product."; + EnumOptionData optionData = null; + switch (type) { + case DAYS: + optionData = new EnumOptionData(SavingsLockinPeriodEnum.DAYS.getValue().longValue(), codePrefix+SavingsLockinPeriodEnum.DAYS.getCode(), "Days"); + break; + case MONTHS: + optionData = new EnumOptionData(SavingsLockinPeriodEnum.MONTHS.getValue().longValue(), codePrefix+SavingsLockinPeriodEnum.MONTHS.getCode(), "Months"); + break; + case WEEKS: + optionData = new EnumOptionData(SavingsLockinPeriodEnum.WEEKS.getValue().longValue(), codePrefix+SavingsLockinPeriodEnum.WEEKS.getCode(), "Weeks"); + break; + case YEARS: + optionData = new EnumOptionData(SavingsLockinPeriodEnum.YEARS.getValue().longValue(), codePrefix+SavingsLockinPeriodEnum.YEARS.getCode(), "Years"); + break; + default: + optionData = new EnumOptionData(SavingsLockinPeriodEnum.INVALID.getValue().longValue(), codePrefix+SavingsLockinPeriodEnum.INVALID.getCode(), "Invalid"); + break; + } + return optionData; + } + + public static EnumOptionData savingInterestCalculationMethod(SavingInterestCalculationMethod type) { + final String codePrefix = "savings.interestCalculation.method."; + EnumOptionData optionData = null; + switch (type) { + case MINBAL: + optionData = new EnumOptionData(SavingInterestCalculationMethod.MINBAL.getValue().longValue(), codePrefix+SavingInterestCalculationMethod.MINBAL.getCode(), "Minimumbalance"); + break; + case AVERAGEBAL: + optionData = new EnumOptionData(SavingInterestCalculationMethod.AVERAGEBAL.getValue().longValue(), codePrefix+SavingInterestCalculationMethod.AVERAGEBAL.getCode(), "AverageBalance"); + break; + case INVALID: + optionData = new EnumOptionData(SavingInterestCalculationMethod.INVALID.getValue().longValue(), codePrefix+SavingInterestCalculationMethod.INVALID.getCode(), "Invalid"); + break; + case MONTHLYCOLLECTION: + optionData = new EnumOptionData(SavingInterestCalculationMethod.MONTHLYCOLLECTION.getValue().longValue(), codePrefix+SavingInterestCalculationMethod.MONTHLYCOLLECTION.getCode(), "MonthlyCollection"); + break; + default: + optionData = new EnumOptionData(SavingInterestCalculationMethod.INVALID.getValue().longValue(), codePrefix+SavingInterestCalculationMethod.INVALID.getCode(), "Invalid"); + break; + } + return optionData; + } + + public static EnumOptionData savingInterestType(SavingsInterestType type) { + final String codePrefix = "savings.interest.type."; + EnumOptionData optionData = null; + switch (type) { + case COMPOUNDING: + optionData = new EnumOptionData(SavingsInterestType.COMPOUNDING.getValue().longValue(), codePrefix+SavingsInterestType.COMPOUNDING.getCode(), "Compounding"); + break; + case SIMPLE: + optionData = new EnumOptionData(SavingsInterestType.SIMPLE.getValue().longValue(), codePrefix+SavingsInterestType.SIMPLE.getCode(), "Simple"); + break; + default: + optionData = new EnumOptionData(SavingsInterestType.INVALID.getValue().longValue(), codePrefix+SavingsInterestType.INVALID.getCode(), "Invalid"); + break; + } + return optionData; + } + + public static EnumOptionData interestFrequencyType(SavingFrequencyType type) { + final String codePrefix = "saving.product.frequency.period."; + EnumOptionData optionData = null; + switch (type) { + case DAILY: + optionData = new EnumOptionData(SavingFrequencyType.DAILY.getValue().longValue(), codePrefix + SavingFrequencyType.DAILY.getCode(), "Days"); + break; + case MONTHLY: + optionData = new EnumOptionData(SavingFrequencyType.MONTHLY.getValue().longValue(), codePrefix + SavingFrequencyType.MONTHLY.getCode(), "Weeks"); + break; + case QUATERLY: + optionData = new EnumOptionData(SavingFrequencyType.QUATERLY.getValue().longValue(), codePrefix + SavingFrequencyType.QUATERLY.getCode(), "Months"); + break; + case HALFYEARLY: + optionData = new EnumOptionData(SavingFrequencyType.HALFYEARLY.getValue().longValue(), codePrefix + SavingFrequencyType.HALFYEARLY.getCode(), "Months"); + break; + case YEARLY: + optionData = new EnumOptionData(SavingFrequencyType.YEARLY.getValue().longValue(), codePrefix + SavingFrequencyType.YEARLY.getCode(), "Yearly"); + break; + default: + optionData = new EnumOptionData(SavingFrequencyType.INVALID.getValue().longValue(), SavingFrequencyType.INVALID.getCode(), "Invalid"); + break; + } + return optionData; + } + + public static EnumOptionData tenureTypeEnum(final TenureTypeEnum type) { + final String codePrefix = "savings.tenure."; + EnumOptionData optionData = null; + switch (type) { + case FIXED_PERIOD: + optionData = new EnumOptionData(TenureTypeEnum.FIXED_PERIOD.getValue().longValue(), codePrefix+TenureTypeEnum.FIXED_PERIOD.getCode(), "FixedPeriod"); + break; + case PERPETUAL: + optionData = new EnumOptionData(TenureTypeEnum.PERPETUAL.getValue().longValue(), codePrefix+TenureTypeEnum.PERPETUAL.getCode(), "Perpetual"); + break; + default: + optionData = new EnumOptionData(TenureTypeEnum.INVALID.getValue().longValue(), codePrefix+TenureTypeEnum.INVALID.getCode(), "Invalid"); + break; + } + return optionData; + } + + public static EnumOptionData savingProductType(final SavingProductType type) { + final String codePrefix = "savings.product."; + EnumOptionData optionData = null; + switch (type) { + case RECCURING: + optionData = new EnumOptionData(SavingProductType.RECCURING.getValue().longValue(), codePrefix + SavingProductType.RECCURING.getCode(), "Reccuring"); + break; + case REGULAR: + optionData = new EnumOptionData(SavingProductType.REGULAR.getValue().longValue(), codePrefix + SavingProductType.REGULAR.getCode(), "Regular"); + break; + case INVALID: + optionData = new EnumOptionData(SavingProductType.INVALID.getValue().longValue(), codePrefix + SavingProductType.INVALID.getCode(), "Invalid"); + break; + default: + optionData = new EnumOptionData(SavingProductType.INVALID.getValue().longValue(), SavingProductType.INVALID.getCode(), "Invalid"); + break; + } + return optionData; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductReadPlatformServiceImpl.java index ba6444fd1..af629a0fe 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductReadPlatformServiceImpl.java @@ -8,12 +8,15 @@ import java.util.List; import org.joda.time.DateTime; import org.mifosng.platform.api.data.CurrencyData; +import org.mifosng.platform.api.data.EnumOptionData; import org.mifosng.platform.api.data.SavingProductData; import org.mifosng.platform.api.data.SavingProductLookup; import org.mifosng.platform.currency.service.CurrencyReadPlatformService; import org.mifosng.platform.exceptions.LoanProductNotFoundException; import org.mifosng.platform.infrastructure.JdbcSupport; import org.mifosng.platform.infrastructure.TenantAwareRoutingDataSource; +import org.mifosng.platform.loan.domain.PeriodFrequencyType; +import org.mifosng.platform.savingproduct.domain.SavingProductType; import org.mifosng.platform.security.PlatformSecurityContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.EmptyResultDataAccessException; @@ -65,6 +68,7 @@ public class SavingProductReadPlatformServiceImpl implements @Override public SavingProductData retrieveSavingProduct(Long savingProductId) { try{ + this.context.authenticatedUser(); SavingProductMapper savingProductMapper=new SavingProductMapper(); String sql = "select " + savingProductMapper.savingProductSchema() + " where sp.id = ? and sp.is_deleted=0"; @@ -92,7 +96,12 @@ public class SavingProductReadPlatformServiceImpl implements private static final class SavingProductMapper implements RowMapper { public String savingProductSchema(){ - return "sp.id as id,sp.name as name, sp.description as description,sp.currency_code as currencyCode, sp.currency_digits as currencyDigits,sp.interest_rate as interestRate,sp.minimum_balance as minimumBalance,sp.maximum_balance as maximumBalance,sp.created_date as createdon, sp.lastmodified_date as modifiedon, " + return "sp.id as id,sp.name as name, sp.description as description,sp.currency_code as currencyCode, sp.currency_digits as currencyDigits,sp.interest_rate as interestRate, " + + "sp.min_interest_rate as minInterestRate, sp.max_interest_rate as maxInterstRate, " + + " sp.savings_deposit_amount as savingsDepositAmount, sp.savings_product_type as savingProductType, sp.tenure_type as tenureType, sp.tenure as tenure, sp.frequency as frequency, " + + " sp.interest_type as interestType, sp.interest_calculation_method as interestCalculationMethod, sp.min_bal_for_withdrawal as minimumBalanceForWithdrawal, " + + " sp.is_partial_deposit_allowed as isPartialDepositAllowed, sp.is_lock_in_period_allowed as isLockinPeriodAllowed, sp.lock_in_period as lockinPeriod, sp.lock_in_period_type as lockinPeriodType, " + + " sp.created_date as createdon, sp.lastmodified_date as modifiedon, " + "curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, curr.display_symbol as currencyDisplaySymbol" + " from m_product_savings sp join m_currency curr on curr.code = sp.currency_code"; } @@ -106,21 +115,35 @@ public class SavingProductReadPlatformServiceImpl implements String description = rs.getString("description"); String currencyCode = rs.getString("currencyCode"); - //String currencyName = rs.getString("currencyName"); - //String currencyNameCode = rs.getString("currencyNameCode"); - //String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol"); + String currencyName = rs.getString("currencyName"); + String currencyNameCode = rs.getString("currencyNameCode"); + String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol"); Integer currencyDigits = JdbcSupport.getInteger(rs,"currencyDigits"); - //CurrencyData currencyData = new CurrencyData(currencyCode,currencyName, currencyDigits, currencyDisplaySymbol,currencyNameCode);*/ + CurrencyData currencyData = new CurrencyData(currencyCode,currencyName, currencyDigits, currencyDisplaySymbol,currencyNameCode); BigDecimal interestRate = rs.getBigDecimal("interestRate"); + BigDecimal minInterestRate = rs.getBigDecimal("minInterestRate"); + BigDecimal maxInterestRate = rs.getBigDecimal("maxInterstRate"); DateTime createdOn = JdbcSupport.getDateTime(rs, "createdon"); DateTime lastModifedOn = JdbcSupport.getDateTime(rs, "modifiedon"); - BigDecimal minimumBalance=rs.getBigDecimal("minimumBalance"); - BigDecimal maximumBalance=rs.getBigDecimal("maximumBalance"); + BigDecimal savingsDepositAmount=rs.getBigDecimal("savingsDepositAmount"); + EnumOptionData savingProductTypeEnum=SavingProductEnumerations.savingProductType(SavingProductType.fromInt(JdbcSupport.getInteger(rs, "savingProductType"))); + EnumOptionData tenureTypeEnum = SavingProductEnumerations.tenureTypeEnum(JdbcSupport.getInteger(rs, "tenureType")); + Integer tenure = JdbcSupport.getInteger(rs, "tenure"); + EnumOptionData savingFrequencyType = SavingProductEnumerations.interestFrequencyType(JdbcSupport.getInteger(rs, "frequency")); + EnumOptionData savingInterestType = SavingProductEnumerations.savingInterestType(JdbcSupport.getInteger(rs, "interestType")); + EnumOptionData interestCalculationMethodEnum=SavingProductEnumerations.savingInterestCalculationMethod(JdbcSupport.getInteger(rs, "interestCalculationMethod")); + BigDecimal minimumBalanceForWithdrawal=rs.getBigDecimal("minimumBalanceForWithdrawal"); + boolean isPartialDepositAllowed = rs.getBoolean("isPartialDepositAllowed"); + boolean isLockinPeriodAllowed =rs.getBoolean("isLockinPeriodAllowed"); + Integer lockinPeriod=JdbcSupport.getInteger(rs, "lockinPeriod"); + EnumOptionData lockinPeriodType= SavingsDepositEnumerations.interestCompoundingPeriodType(PeriodFrequencyType.fromInt(JdbcSupport.getInteger(rs, "lockinPeriodType"))); - return new SavingProductData(createdOn, lastModifedOn, id, name,description,interestRate,currencyCode,currencyDigits,minimumBalance,maximumBalance); + return new SavingProductData(createdOn, lastModifedOn, id, name, description, interestRate, minInterestRate, maxInterestRate, currencyData, currencyDigits, savingsDepositAmount, + savingProductTypeEnum, tenureTypeEnum, tenure, savingFrequencyType, savingInterestType, interestCalculationMethodEnum, + minimumBalanceForWithdrawal, isPartialDepositAllowed, isLockinPeriodAllowed, lockinPeriod, lockinPeriodType); } } @@ -132,7 +155,7 @@ public class SavingProductReadPlatformServiceImpl implements } @Override - public SavingProductLookup mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) + public SavingProductLookup mapRow(final ResultSet rs, final int rowNum) throws SQLException { Long id = rs.getLong("id"); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductWritePlatformServiceJpaRepositoryImpl.java index b48a05751..ba5752d0b 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/savingproduct/service/SavingProductWritePlatformServiceJpaRepositoryImpl.java @@ -5,8 +5,14 @@ import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.currency.domain.MonetaryCurrency; import org.mifosng.platform.exceptions.ProductNotFoundException; import org.mifosng.platform.exceptions.SavingProductNotFoundException; +import org.mifosng.platform.loan.domain.PeriodFrequencyType; +import org.mifosng.platform.savingproduct.domain.SavingFrequencyType; +import org.mifosng.platform.savingproduct.domain.SavingInterestCalculationMethod; import org.mifosng.platform.savingproduct.domain.SavingProduct; import org.mifosng.platform.savingproduct.domain.SavingProductRepository; +import org.mifosng.platform.savingproduct.domain.SavingProductType; +import org.mifosng.platform.savingproduct.domain.SavingsInterestType; +import org.mifosng.platform.savingproduct.domain.TenureTypeEnum; import org.mifosng.platform.security.PlatformSecurityContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -32,9 +38,19 @@ public class SavingProductWritePlatformServiceJpaRepositoryImpl implements Savin SavingProductCommandValidator validator=new SavingProductCommandValidator(command); validator.validateForCreate(); + SavingProductType savingProductType = SavingProductType.fromInt(command.getSavingProductType()); + TenureTypeEnum tenureType = TenureTypeEnum.fromInt(command.getTenureType()); + SavingFrequencyType savingFrequencyType=SavingFrequencyType.fromInt(command.getFrequency()); + SavingsInterestType interestType = SavingsInterestType.fromInt(command.getInterestType()); + PeriodFrequencyType lockinPeriodType = PeriodFrequencyType.fromInt(command.getLockinPeriodType()); + SavingInterestCalculationMethod savingInterestCalculationMethod=SavingInterestCalculationMethod.fromInt(command.getInterestCalculationMethod()); MonetaryCurrency currency = new MonetaryCurrency(command.getCurrencyCode(), command.getDigitsAfterDecimal()); - SavingProduct product = new SavingProduct(command.getName(),command.getDescription(),currency,command.getInterestRate(),command.getMinimumBalance(),command.getMaximumBalance()); + SavingProduct product = new SavingProduct(command.getName(), command.getDescription(), currency, command.getInterestRate(), command.getMinInterestRate(), command.getMaxInterestRate(), + command.getSavingsDepositAmount(), savingProductType, tenureType, command.getTenure(), savingFrequencyType, interestType, + savingInterestCalculationMethod, command.getMinimumBalanceForWithdrawal(), command.isPartialDepositAllowed(), + command.isLockinPeriodAllowed(), command.getLockinPeriod(), lockinPeriodType); + this.savingProductRepository.save(product); return new EntityIdentifier(product.getId()); }