diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java index 727ca3fa6..a198932e6 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/CommandWrapperBuilder.java @@ -2571,4 +2571,36 @@ public class CommandWrapperBuilder { this.href = "/loans/" + loanId + "/schedule"; return this; } + + public CommandWrapperBuilder createProduct(String productType) { + this.entityName = productType.toUpperCase()+"PRODUCT" ; //To Support different type of products + this.actionName = "CREATE"; + this.entityId = null; + this.href = "/products/"+productType; + return this; + } + + public CommandWrapperBuilder updateProduct(String productType, final Long productId) { + this.entityName = productType.toUpperCase()+"PRODUCT" ; + this.actionName = "UPDATE"; + this.entityId = productId; + this.href = "/products/" + productType+"/"+productId; + return this; + } + + public CommandWrapperBuilder createAccount(String accountType) { + this.entityName = accountType.toUpperCase()+"ACCOUNT" ; //To Support different type of Accounts + this.actionName = "CREATE"; + this.entityId = null; + this.href = "/accounts/"+accountType; + return this; + } + + public CommandWrapperBuilder updateAccount(String accountType, final Long accountId) { + this.entityName = accountType.toUpperCase()+"ACCOUNT" ; + this.actionName = "UPDATE"; + this.entityId = accountId; + this.href = "/accounts/" + accountType+"/"+accountId; + return this; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/api/AccountsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/api/AccountsApiResource.java new file mode 100644 index 000000000..7c984f658 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/api/AccountsApiResource.java @@ -0,0 +1,127 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.api; + +import java.util.Collection; +import java.util.HashSet; + +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.UriInfo; + +import org.mifosplatform.commands.domain.CommandWrapper; +import org.mifosplatform.commands.service.CommandWrapperBuilder; +import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; +import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; +import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.mifosplatform.portfolio.accounts.constants.AccountsApiConstants; +import org.mifosplatform.portfolio.accounts.data.AccountData; +import org.mifosplatform.portfolio.accounts.service.AccountReadPlatformService; +import org.mifosplatform.portfolio.accounts.service.AccountsCommandsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + + +@Path("/accounts/{type}") +@Component +@Scope("singleton") +public class AccountsApiResource { + + private final ApplicationContext applicationContext ; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final DefaultToApiJsonSerializer toApiJsonSerializer; + private final PlatformSecurityContext platformSecurityContext; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + private final DefaultToApiJsonSerializer toApiObjectJsonSerializer ; + + @Autowired + public AccountsApiResource(final ApplicationContext applicationContext, + final ApiRequestParameterHelper apiRequestParameterHelper, + final DefaultToApiJsonSerializer toApiJsonSerializer, + final PlatformSecurityContext platformSecurityContext, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, + final DefaultToApiJsonSerializer toApiObjectJsonSerializer) { + this.applicationContext = applicationContext ; + this.apiRequestParameterHelper = apiRequestParameterHelper ; + this.toApiJsonSerializer = toApiJsonSerializer ; + this.platformSecurityContext = platformSecurityContext ; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService ; + this.toApiObjectJsonSerializer = toApiObjectJsonSerializer ; + } + + @GET + @Path("{accountId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveAccount(@PathParam("accountId") final Long accountId, @PathParam("type") final String accountType, + @Context final UriInfo uriInfo) { + String serviceName = accountType+AccountsApiConstants.READPLATFORM_NAME ; + AccountReadPlatformService service = (AccountReadPlatformService) this.applicationContext.getBean(serviceName) ; + AccountData data = service.retrieveOne(accountId) ; + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams()); + } + + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveAllAccounts(@PathParam("type") final String accountType, @Context final UriInfo uriInfo) { + String serviceName = accountType+AccountsApiConstants.READPLATFORM_NAME ; + AccountReadPlatformService service = (AccountReadPlatformService) this.applicationContext.getBean(serviceName) ; + Collection data = service.retrieveAll() ; + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams()); + } + + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String createAccount(@PathParam("type") final String accountType, final String apiRequestBodyAsJson) { + CommandWrapper commandWrapper = null; + this.platformSecurityContext.authenticatedUser(); + commandWrapper = new CommandWrapperBuilder().createAccount(accountType).withJson(apiRequestBodyAsJson).build(); + final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper); + return this.toApiJsonSerializer.serialize(commandProcessingResult); + } + + @POST + @Path("{accountId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String handleCommands(@PathParam("type") final String accountType, @PathParam("accountId") final Long accountId, @QueryParam("command") final String commandParam, + @Context final UriInfo uriInfo, final String apiRequestBodyAsJson) { + String serviceName = accountType.toUpperCase()+AccountsApiConstants.ACCOUNT_COMMANDSERVICE ; + AccountsCommandsService service = (AccountsCommandsService) this.applicationContext.getBean(serviceName) ; + final Object obj = service.handleCommand(accountId, commandParam, apiRequestBodyAsJson) ; + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiObjectJsonSerializer.serialize(settings, obj, new HashSet()); + } + + @PUT + @Path("{accountId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String updateAccount(@PathParam("type") final String accountType, @PathParam("accountId") final Long accountId, final String apiRequestBodyAsJson) { + this.platformSecurityContext.authenticatedUser(); + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateAccount(accountType, accountId) + .withJson(apiRequestBodyAsJson).build(); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/constants/AccountsApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/constants/AccountsApiConstants.java new file mode 100644 index 000000000..48bb29b44 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/constants/AccountsApiConstants.java @@ -0,0 +1,14 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.constants; + + +public interface AccountsApiConstants { + + public final String READPLATFORM_NAME = "AccountReadPlatformService" ; + + public final String ACCOUNT_COMMANDSERVICE = "ACCOUNT_COMMANDSERVICE" ; +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/constants/ShareAccountApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/constants/ShareAccountApiConstants.java new file mode 100644 index 000000000..1eca329d5 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/constants/ShareAccountApiConstants.java @@ -0,0 +1,64 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.constants; + + + +public interface ShareAccountApiConstants { + + //Command Strings + String APPROVE_COMMAND = "approve" ; + String REJECT_COMMAND = "reject" ; + String APPLY_ADDITIONALSHARES_COMMAND = "applyadditionalshares" ; + String APPROVE_ADDITIONSHARES_COMMAND = "approveadditionalshares" ; + String REJECT_ADDITIONSHARES_COMMAND = "rejectadditionalshares" ; + + // + String id_paramname = "id" ; + + String clientid_paramname = "clientId" ; + + String productid_paramname = "productId" ; + + String submitteddate_paramname = "submittedDate" ; + + String approveddate_paramname = "approvedDate" ; + + String fieldofferid_paramname = "fieldOfficerId" ; + + String externalid_paramname = "externalId" ; + + String currency_paramname = "currencyCode" ; + + String digitsafterdecimal_paramname = "digitsAfterDecimal" ; + + String inmultiplesof_paramname = "inMultiplesOf" ; + + String purchasedshares_paramname = "purchasedShares" ; + + String additionalshares_paramname = "additionalShares" ; + + String suspenseaccount_paramname = "suspenseAccount" ; + + String equityaccount_paramname = "equityAccount" ; + + String savingsaccountid_paramname = "savingsAccountId" ; + + String lockperiod_paramname = "lockPeriod" ; + + String minimumactiveperiodfordividends_paramname = "minimumActivePeriodForDividends" ; + + String allowdividendcalculationforinactiveclients_paramname = "allowDividendCalculationForInactiveClients" ; + + String charges_paramname = "charges" ; + + String purchaseddate_paramname = "purchasedDate" ; + + String numberofshares_paramname = "numberOfShares" ; + + String purchasedprice_paramname = "purchasedPrice" ; + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/AccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/AccountData.java new file mode 100644 index 000000000..444a5dd7e --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/AccountData.java @@ -0,0 +1,11 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.data; + + +public interface AccountData { + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/PurchasedSharesData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/PurchasedSharesData.java new file mode 100644 index 000000000..e302c08cc --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/PurchasedSharesData.java @@ -0,0 +1,47 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.data; + +import java.math.BigDecimal; +import java.util.Date; + + +public class PurchasedSharesData { + + private final Date purchasedDate ; + + private final Long numberOfShares ; + + private final BigDecimal purchasedPrice ; + + private final String status ; + + public PurchasedSharesData(final Date purchasedDate, final Long numberOfShares, final BigDecimal purchasedPrice, final String status) { + this.purchasedDate = purchasedDate ; + this.numberOfShares = numberOfShares ; + this.purchasedPrice = purchasedPrice ; + this.status = status ; + } + + + public Date getPurchasedDate() { + return this.purchasedDate; + } + + + public Long getNumberOfShares() { + return this.numberOfShares; + } + + + public BigDecimal getPurchasedPrice() { + return this.purchasedPrice; + } + + public String getStatus() { + return this.status ; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/ShareAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/ShareAccountData.java new file mode 100644 index 000000000..5490baf5b --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/ShareAccountData.java @@ -0,0 +1,86 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.data; + +import java.util.Collection; +import java.util.Date; + +import org.mifosplatform.accounting.glaccount.data.GLAccountData; +import org.mifosplatform.infrastructure.core.data.EnumOptionData; +import org.mifosplatform.organisation.monetary.data.CurrencyData; + +public class ShareAccountData implements AccountData{ + + private Long id; + + private String accountNo; + + private String externalId; + + private Long productId; + + private String productName; + + private String loanProductDescription; + + private Long fieldOfficerId; + + private String fieldOfficerName; + + private Long clientId; + + private String clientName; + + private Long clientOfficeId; + + private CurrencyData currency; + + private Date submittedDate; + + private Date approvedDate; + + private Collection purchasedShares; + + private GLAccountData suspenseAccount; + + private GLAccountData equityAccount; + + private Long savingsAccountId; + + private EnumOptionData lockPeriod; + + private EnumOptionData minimumActivePeriodForDividends; + + private Boolean allowDividendCalculationForInactiveClients; + + private Collection charges ; + + private String status ; + + public ShareAccountData(final Long id, final String accountNo, final Long clientId, final String clientName, final Long productId, final String productName, + final Long fieldOfficerId, final String externalId, final Date submittedDate, final Collection purchasedShares, final GLAccountData suspenseAccount, + final GLAccountData equityAccount, final EnumOptionData lockPeriod, final EnumOptionData minimumActivePeriodForDividends, + final Boolean allowDividendCalculationForInactiveClients, final Collection charges, final String status) { + this.id = id ; + this.accountNo = accountNo ; + this.clientId = clientId ; + this.clientName = clientName ; + this.productId = productId ; + this.productName = productName ; + this.fieldOfficerId = fieldOfficerId ; + this.externalId = externalId ; + this.submittedDate = submittedDate ; + this.purchasedShares = purchasedShares ; + this.suspenseAccount = suspenseAccount ; + this.equityAccount = equityAccount ; + this.lockPeriod = lockPeriod ; + this.minimumActivePeriodForDividends = minimumActivePeriodForDividends ; + this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients ; + this.charges = charges ; + this.status = status ; + + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/ShareChargeData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/ShareChargeData.java new file mode 100644 index 000000000..1a9bdc0d8 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/data/ShareChargeData.java @@ -0,0 +1,19 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.data; + + +public class ShareChargeData { + + private Long accountId ; + + private Long chargeId ; + + public ShareChargeData(final Long accountId, final Long chargeId) { + this.accountId = accountId ; + this.chargeId = chargeId ; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/PurchasedShares.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/PurchasedShares.java new file mode 100644 index 000000000..152871bf2 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/PurchasedShares.java @@ -0,0 +1,80 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.domain; + +import java.math.BigDecimal; +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.mifosplatform.portfolio.accounts.data.PurchasedSharesData; +import org.springframework.data.jpa.domain.AbstractPersistable; + +@Entity +@Table(name = "m_purchasedshares") +public class PurchasedShares extends AbstractPersistable { + + @ManyToOne(optional = false) + @JoinColumn(name = "account_id", referencedColumnName = "id", nullable = false) + private ShareAccount shareAccount ; + + @Column(name = "purchased_date") + @Temporal(TemporalType.DATE) + private Date purchasedDate ; + + @Column(name = "share_count") + private Long totalShares ; + + @Column(name = "share_price") + private BigDecimal shareValue ; + + @Column(name ="status") + private String status = "Submitted"; + + protected PurchasedShares() { + + } + + public void setShareAccount(final ShareAccount shareAccount) { + this.shareAccount = shareAccount ; + } + + public PurchasedShares(final Date purchasedDate, final Long totalShares, final BigDecimal shareValue) { + this.purchasedDate = purchasedDate ; + this.totalShares = totalShares ; + this.shareValue = shareValue ; + } + + public PurchasedSharesData toData() { + return new PurchasedSharesData(this.purchasedDate, this.totalShares, this.shareValue, this.status) ; + } + + public Date getPurchasedDate() { + return this.purchasedDate ; + } + + public Long getTotalShares() { + return this.totalShares ; + } + + public BigDecimal getPurchasePrice() { + return this.shareValue ; + } + + public String getStatus() { + return this.status ; + } + + public void setStatus(String status) { + this.status = status ; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccount.java new file mode 100644 index 000000000..df6853170 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccount.java @@ -0,0 +1,320 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.domain; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; +import org.joda.time.DateTime; +import org.mifosplatform.accounting.glaccount.data.GLAccountData; +import org.mifosplatform.accounting.glaccount.domain.GLAccount; +import org.mifosplatform.infrastructure.core.data.EnumOptionData; +import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom; +import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; +import org.mifosplatform.portfolio.accounts.data.PurchasedSharesData; +import org.mifosplatform.portfolio.accounts.data.ShareAccountData; +import org.mifosplatform.portfolio.accounts.data.ShareChargeData; +import org.mifosplatform.portfolio.client.domain.Client; +import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType; +import org.mifosplatform.portfolio.savings.domain.SavingsAccount; +import org.mifosplatform.portfolio.shares.domain.ShareProduct; +import org.mifosplatform.useradministration.domain.AppUser; + +@Entity +@Table(name = "m_shareaccounts") +public class ShareAccount extends AbstractAuditableCustom { + + @ManyToOne + @JoinColumn(name = "client_id", nullable = true) + private Client client ; + + @ManyToOne + @JoinColumn(name = "product_id", nullable = true) + private ShareProduct shareProduct ; + + @Column(name = "submitted_date") + @Temporal(TemporalType.TIMESTAMP) + private Date submittedDate ; + + @Column(name = "approved_date") + @Temporal(TemporalType.TIMESTAMP) + private Date approvedDate ; + + @Column(name = "field_officer") + private Long fieldOfficerId ; + + @Column(name = "external_id") + private String externalId ; + + @Embedded + private MonetaryCurrency currency; + + @ManyToOne + @JoinColumn(name = "suspense_account", nullable = true) + private GLAccount suspenseAccount ; + + @ManyToOne + @JoinColumn(name = "equity_account", nullable = true) + private GLAccount equityAccount ; + + @ManyToOne + @JoinColumn(name = "savings_id", nullable = true) + private SavingsAccount savingsAccount ; + + @LazyCollection(LazyCollectionOption.FALSE) + @OneToMany(cascade = CascadeType.ALL, mappedBy = "shareAccount", orphanRemoval = true) + private Set purchasedShares ; + + @Column(name = "allow_dividends_inactive_clients") + private Boolean allowDividendCalculationForInactiveClients; + + @Enumerated(EnumType.ORDINAL) + @Column(name = "lock_period", nullable = true) + private PeriodFrequencyType lockPeriod; + + @Enumerated(EnumType.ORDINAL) + @Column(name = "dividend_active_period", nullable = true) + private PeriodFrequencyType minimumActivePeriodForDividends; + + @Column(name = "status") + private String status = "Submitted"; //change it to enum + + @LazyCollection(LazyCollectionOption.FALSE) + @OneToMany(cascade = CascadeType.ALL, mappedBy = "shareAccount", orphanRemoval = true) + private Set charges ; + + protected ShareAccount() { + + } + + public ShareAccount(final Client client, final ShareProduct shareProduct, final Date submittedDate, final Date approvedDate, + final Long fieldOfficerId , final String externalId, final MonetaryCurrency currency, GLAccount suspenseAccount, + final GLAccount equityAccount, final SavingsAccount savingsAccount, final Set purchasedShares, + final Boolean allowDividendCalculationForInactiveClients, final PeriodFrequencyType lockPeriod, + final PeriodFrequencyType minimumActivePeriodForDividends, Set charges, + AppUser createdBy, DateTime createdDate, AppUser lastModifiedBy, DateTime lastModifiedDate) { + this.client = client ; + this.shareProduct = shareProduct ; + this.submittedDate = submittedDate ; + this.approvedDate = approvedDate ; + this.fieldOfficerId = fieldOfficerId ; + this.externalId = externalId ; + this.currency = currency ; + this.suspenseAccount = suspenseAccount ; + this.equityAccount = equityAccount ; + this.savingsAccount = savingsAccount ; + this.purchasedShares = purchasedShares ; + this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients ; + this.lockPeriod = lockPeriod ; + this.minimumActivePeriodForDividends = minimumActivePeriodForDividends ; + this.charges = charges ; + setCreatedBy(createdBy) ; + setCreatedDate(createdDate) ; + setLastModifiedBy(lastModifiedBy) ; + setLastModifiedDate(lastModifiedDate) ; + } + + public boolean setShareProduct(final ShareProduct shareProduct) { + boolean toReturn = false ; + if(!this.shareProduct.getId().equals(shareProduct.getId())) { + this.shareProduct = shareProduct ; + toReturn = true ; + } + return toReturn ; + } + + public ShareProduct getShareProduct() { + return this.shareProduct ; + } + + public boolean setSubmittedDate(final Date submittedDate) { + boolean toReturn = false ; + if(!this.submittedDate.equals(submittedDate)) { + this.submittedDate = submittedDate ; + toReturn = true ; + } + return toReturn ; + } + + public boolean setApprovedDate(final Date approvedDate) { + boolean toReturn = false ; + if(!this.approvedDate.equals(approvedDate)) { + this.approvedDate = approvedDate ; + toReturn = true ; + } + return toReturn ; + } + + public boolean setFieldOfficer(final Long fieldOfficerId) { + boolean toReturn = false ; + if(!this.fieldOfficerId.equals(fieldOfficerId)) { + this.fieldOfficerId = fieldOfficerId ; + toReturn = true ; + } + return toReturn ; + } + + public boolean setExternalId(final String externalId) { + boolean toReturn = false ; + if(!this.externalId.equals(externalId)) { + this.externalId = externalId ; + toReturn = true ; + } + return toReturn ; + } + + public boolean setSuspenseAccount(GLAccount suspenseAccount) { + boolean returnValue = false; + if (!this.suspenseAccount.getId().equals(suspenseAccount.getId())) { + this.suspenseAccount = suspenseAccount; + returnValue = true; + } + return returnValue; + } + + public boolean setEquityAccount(GLAccount equityAccount) { + boolean returnValue = false; + if (!this.equityAccount.getId().equals(equityAccount.getId())) { + this.equityAccount = equityAccount; + returnValue = true; + } + return returnValue; + } + + public boolean setSavingsAccount(final SavingsAccount savingsAccount) { + boolean returnValue = false; + if (!this.savingsAccount.getId().equals(savingsAccount.getId())) { + this.savingsAccount = savingsAccount; + returnValue = true; + } + return returnValue; + } + + public boolean setPurchasedShares(Set purchasedShares) { + this.purchasedShares = purchasedShares ; + return true ; + } + + public boolean setAllowDividendCalculationForInactiveClients(Boolean allowDividendCalculationForInactiveClients) { + boolean returnValue = false; + if (!this.allowDividendCalculationForInactiveClients.equals(allowDividendCalculationForInactiveClients)) { + this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients; + returnValue = true; + } + return returnValue; + } + + public boolean setLockPeriod(final PeriodFrequencyType lockPeriod) { + boolean returnValue = false; + if (!this.lockPeriod.equals(lockPeriod)) { + this.lockPeriod = lockPeriod; + returnValue = true; + } + return returnValue; + } + + public boolean setminimumActivePeriodForDividends(final PeriodFrequencyType minimumActivePeriodForDividends) { + boolean returnValue = false; + if (!this.minimumActivePeriodForDividends.equals(minimumActivePeriodForDividends)) { + this.minimumActivePeriodForDividends = minimumActivePeriodForDividends; + returnValue = true; + } + return returnValue; + } + + public boolean setCharges(final Set charges) { + this.charges = charges ; + return true ; + } + //FIXME: Remove this + public void setTempId(Long id) { + setId(id) ; + } + + public ShareAccountData toData() { + String accountNo = "000025900"+getId() ; + Collection purchasedSharesdata = new ArrayList<>(); + for(PurchasedShares val: purchasedShares) { + purchasedSharesdata.add(new PurchasedSharesData(val.getPurchasedDate(), val.getTotalShares(), val.getPurchasePrice(), val.getStatus())) ; + } + Collection chargesdata = new ArrayList<>(); + for(ShareAccountCharge charge: charges) { + chargesdata.add(new ShareChargeData(charge.getAccountId(), charge.getChargeId())) ; + } + + GLAccountData suspenseAccount1 = new GLAccountData(suspenseAccount.getId(), suspenseAccount.getName(), suspenseAccount.getGlCode()); + GLAccountData equityAccount1 = new GLAccountData(equityAccount.getId(), equityAccount.getName(), equityAccount.getGlCode()); + EnumOptionData lock = new EnumOptionData(this.lockPeriod.getValue().longValue(), this.lockPeriod.getCode(), + this.lockPeriod.toString()); + EnumOptionData mini = new EnumOptionData(this.minimumActivePeriodForDividends.getValue().longValue(), this.minimumActivePeriodForDividends.getCode(), + this.minimumActivePeriodForDividends.toString());; + + ShareAccountData data = new ShareAccountData(getId(), accountNo, this.client.getId(), this.client.getDisplayName(), this.shareProduct.getId(), + this.shareProduct.getProductName(), fieldOfficerId, externalId, + submittedDate, purchasedSharesdata, suspenseAccount1, equityAccount1, lock, mini, + allowDividendCalculationForInactiveClients, chargesdata, status) ; + return data ; + } + + public Long getClientId() { + return this.client.getId() ; + } + + public String getClientName() { + return this.client.getDisplayName() ; + } + + public Long getTotalShares() { + long value = 0 ; + for(PurchasedShares val: purchasedShares) { + if(val.getStatus().equals("Approved")) { + value += val.getTotalShares().longValue() ; + } + } + return new Long(value) ; + } + + public String getShareAccountNo() { + return "000025900"+getId() ; + } + + public String getSavingsAccountNo() { + return this.savingsAccount.getAccountNumber() ; + } + + public void setStatus(String status) { + this.status = status ; + } + + public String getStatus() { + return this.status ; + } + + public void addAddtionalShares(Set additionalShares) { + this.purchasedShares.addAll(additionalShares) ; + } + + public Set getPurchasedShares() { + return this.purchasedShares ; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccountCharge.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccountCharge.java new file mode 100644 index 000000000..69e84c61d --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccountCharge.java @@ -0,0 +1,52 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.domain; + +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +import org.mifosplatform.portfolio.charge.domain.Charge; +import org.springframework.data.jpa.domain.AbstractPersistable; + +@Entity +@Table(name = "m_shareaccounts_charges") +public class ShareAccountCharge extends AbstractPersistable { + + @ManyToOne(optional = false) + @JoinColumn(name = "account_id", referencedColumnName = "id", nullable = false) + private ShareAccount shareAccount; + + @ManyToOne(optional = false) + @JoinColumn(name = "charge_id", referencedColumnName = "id", nullable = false) + private Charge charge; + + protected ShareAccountCharge() { + + } + + public ShareAccountCharge(final ShareAccount shareAccount, final Charge charge) { + this.shareAccount = shareAccount; + this.charge = charge; + } + + public ShareAccountCharge(final Charge charge) { + this.charge = charge; + } + + public void setShareAccount(ShareAccount shareAccount) { + this.shareAccount = shareAccount; + } + + public Long getAccountId() { + return this.shareAccount.getId() ; + } + + public Long getChargeId() { + return this.charge.getId() ; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccountRepository.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccountRepository.java new file mode 100644 index 000000000..9c2c7ac02 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccountRepository.java @@ -0,0 +1,14 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + + +public interface ShareAccountRepository extends JpaRepository, JpaSpecificationExecutor { + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccountTempRepository.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccountTempRepository.java new file mode 100644 index 000000000..26320683a --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/domain/ShareAccountTempRepository.java @@ -0,0 +1,43 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.domain; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.mifosplatform.portfolio.shares.domain.ShareProductTempRepository; + + +public class ShareAccountTempRepository { + + private final static ShareAccountTempRepository instance = new ShareAccountTempRepository() ; + + private Map cache = new HashMap<>() ; + + private ShareAccountTempRepository() { + + } + + public static ShareAccountTempRepository getInstance() { + return instance ; + } + + public void save(ShareAccount account) { + Long id = new Long(cache.size()+1) ; + account.setTempId(id) ; + cache.put(id, account) ; + ShareProductTempRepository.getInstance().addAccount(account.getShareProduct().getId(), account) ; + } + + public ShareAccount findOne(Long id) { + return cache.get(id) ; + } + + public Collection findAll() { + return cache.values() ; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/exceptions/ShareAccountNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/exceptions/ShareAccountNotFoundException.java new file mode 100644 index 000000000..ca30f3470 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/exceptions/ShareAccountNotFoundException.java @@ -0,0 +1,16 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.exceptions; + +import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + + +public class ShareAccountNotFoundException extends AbstractPlatformResourceNotFoundException{ + + public ShareAccountNotFoundException(final Long id) { + super("error.msg.shareaccount.id.invalid", " Account with identifier " + id + " does not exist" , id); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/handler/CreateShareAccountCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/handler/CreateShareAccountCommandHandler.java new file mode 100644 index 000000000..599d88f05 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/handler/CreateShareAccountCommandHandler.java @@ -0,0 +1,34 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.handler; + +import org.mifosplatform.commands.annotation.CommandType; +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.portfolio.accounts.service.ShareAccountWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "SHAREACCOUNT", action = "CREATE") +public class CreateShareAccountCommandHandler implements NewCommandSourceHandler{ + + + private final ShareAccountWritePlatformService shareAccountWritePlatformService ; + + @Autowired + public CreateShareAccountCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) { + this.shareAccountWritePlatformService = shareAccountWritePlatformService ; + } + @Transactional + @Override + public CommandProcessingResult processCommand(JsonCommand jsonCommand) { + return this.shareAccountWritePlatformService.createShareAccount(jsonCommand); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/handler/UpdateShareAccountCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/handler/UpdateShareAccountCommandHandler.java new file mode 100644 index 000000000..91cda6791 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/handler/UpdateShareAccountCommandHandler.java @@ -0,0 +1,34 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.handler; + +import org.mifosplatform.commands.annotation.CommandType; +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.portfolio.accounts.service.ShareAccountWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "SHAREACCOUNT", action = "UPDATE") +public class UpdateShareAccountCommandHandler implements NewCommandSourceHandler { + + private final ShareAccountWritePlatformService shareAccountWritePlatformService ; + + @Autowired + public UpdateShareAccountCommandHandler(final ShareAccountWritePlatformService shareAccountWritePlatformService) { + this.shareAccountWritePlatformService = shareAccountWritePlatformService ; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(JsonCommand jsonCommand) { + return this.shareAccountWritePlatformService.updateShareAccount(jsonCommand.entityId(), jsonCommand); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/serialization/ShareAccountDataSerializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/serialization/ShareAccountDataSerializer.java new file mode 100644 index 000000000..4e03220c7 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/serialization/ShareAccountDataSerializer.java @@ -0,0 +1,320 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.serialization; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.mifosplatform.accounting.glaccount.domain.GLAccount; +import org.mifosplatform.accounting.glaccount.domain.GLAccountRepositoryWrapper; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; +import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.mifosplatform.infrastructure.core.service.DateUtils; +import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; +import org.mifosplatform.portfolio.accounts.constants.ShareAccountApiConstants; +import org.mifosplatform.portfolio.accounts.domain.PurchasedShares; +import org.mifosplatform.portfolio.accounts.domain.ShareAccount; +import org.mifosplatform.portfolio.accounts.domain.ShareAccountCharge; +import org.mifosplatform.portfolio.charge.domain.Charge; +import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper; +import org.mifosplatform.portfolio.client.domain.Client; +import org.mifosplatform.portfolio.client.domain.ClientRepositoryWrapper; +import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType; +import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException; +import org.mifosplatform.portfolio.products.exception.ProductNotFoundException; +import org.mifosplatform.portfolio.savings.domain.SavingsAccount; +import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepositoryWrapper; +import org.mifosplatform.portfolio.shares.domain.ShareProduct; +import org.mifosplatform.portfolio.shares.domain.ShareProductTempRepository; +import org.mifosplatform.useradministration.domain.AppUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; + +@Service +public class ShareAccountDataSerializer { + + private final Set supportedParameters = new HashSet<>(Arrays.asList("")); + + private final PlatformSecurityContext platformSecurityContext; + + private final FromJsonHelper fromApiJsonHelper; + + private final ChargeRepositoryWrapper chargeRepository; + + private final GLAccountRepositoryWrapper glAccountRepository; + + private final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper; + + private final ClientRepositoryWrapper clientRepositoryWrapper; + + @Autowired + public ShareAccountDataSerializer(final PlatformSecurityContext platformSecurityContext, final FromJsonHelper fromApiJsonHelper, + final ChargeRepositoryWrapper chargeRepository, GLAccountRepositoryWrapper glAccountRepository, + final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper, final ClientRepositoryWrapper clientRepositoryWrapper) { + this.platformSecurityContext = platformSecurityContext; + this.fromApiJsonHelper = fromApiJsonHelper; + this.chargeRepository = chargeRepository; + this.glAccountRepository = glAccountRepository; + this.savingsAccountRepositoryWrapper = savingsAccountRepositoryWrapper; + this.clientRepositoryWrapper = clientRepositoryWrapper; + } + + public ShareAccount validateAndCreate(JsonCommand jsonCommand) { + + if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); } + final Type typeOfMap = new TypeToken>() {}.getType(); + //this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), supportedParameters); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount"); + JsonElement element = jsonCommand.parsedJson(); + + final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject()); + final Long clientId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.clientid_paramname, element); + final Long productId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.productid_paramname, element); + final Date submittedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.submitteddate_paramname, element) + .toDate(); + // On creation submitted date will not be there. + final Long fieldOfficerId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.fieldofferid_paramname, element); + final String externalId = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.externalid_paramname, element); + + Long suspenseAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.suspenseaccount_paramname, element); + Long equityAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.equityaccount_paramname, element); + Long savingsAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.savingsaccountid_paramname, element); + Set sharesPurchased = asemblePurchasedShares(element); + + Boolean allowdividendsForInactiveClients = this.fromApiJsonHelper.extractBooleanNamed( + ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element); + PeriodFrequencyType lockPeriod = extractPeriodType(ShareAccountApiConstants.lockperiod_paramname, element); + PeriodFrequencyType minimumActivePeriod = extractPeriodType(ShareAccountApiConstants.minimumactiveperiodfordividends_paramname, + element); + + Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId); + GLAccount suspenseAccount = glAccountRepository.findOneWithNotFoundDetection(suspenseAccountId); + GLAccount equityAccount = glAccountRepository.findOneWithNotFoundDetection(equityAccountId); + SavingsAccount savingsAccount = this.savingsAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsAccountId); + ShareProduct shareProduct = ShareProductTempRepository.getInstance().fineOne(productId); + if(shareProduct == null) { + throw new ProductNotFoundException(productId, "Share") ; + } + final MonetaryCurrency currency = shareProduct.getCurrency() ; + Set charges = assembleListOfAccountCharges(element, currency.getCode()); + AppUser modifiedBy = null; + DateTime modifiedOn = null; + Date approvedDate = null; + AppUser createdBy = platformSecurityContext.authenticatedUser(); + DateTime createdDate = DateUtils.getLocalDateTimeOfTenant().toDateTime(); + ShareAccount account = new ShareAccount(client, shareProduct, submittedDate, approvedDate, fieldOfficerId, externalId, currency, + suspenseAccount, equityAccount, savingsAccount, sharesPurchased, allowdividendsForInactiveClients, lockPeriod, + minimumActivePeriod, charges, createdBy, createdDate, modifiedBy, modifiedOn); + + for(PurchasedShares pur: sharesPurchased) { + pur.setShareAccount(account) ; + } + + for(ShareAccountCharge charge: charges) { + charge.setShareAccount(account) ; + } + return account; + } + + public Map validateAndUpdate(JsonCommand jsonCommand, ShareAccount account) { + Map actualChanges = new HashMap<>(); + if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); } + final Type typeOfMap = new TypeToken>() {}.getType(); + //this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), supportedParameters); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount"); + JsonElement element = jsonCommand.parsedJson(); + + final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject()); + + if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.productid_paramname, element)) { + final Long productId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.productid_paramname, element); + ShareProduct shareProduct = ShareProductTempRepository.getInstance().fineOne(productId); + if(account.setShareProduct(shareProduct)) { + actualChanges.put(ShareAccountApiConstants.productid_paramname, shareProduct) ; + } + + } + + if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.submitteddate_paramname, element)) { + final Date submittedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.submitteddate_paramname, element) + .toDate(); + if(account.setSubmittedDate(submittedDate)) { + actualChanges.put(ShareAccountApiConstants.submitteddate_paramname, submittedDate) ; + } + } + + if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.fieldofferid_paramname, element)) { + final Long fieldOfficerId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.fieldofferid_paramname, element); + if(account.setFieldOfficer(fieldOfficerId)){ + actualChanges.put(ShareAccountApiConstants.fieldofferid_paramname, fieldOfficerId) ; + } + } + + if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.externalid_paramname, element)) { + final String externalId = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.externalid_paramname, element); + if(account.setExternalId(externalId)) { + actualChanges.put(ShareAccountApiConstants.externalid_paramname, externalId) ; + } + } + + if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.suspenseaccount_paramname, element)) { + Long suspenseAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.suspenseaccount_paramname, element); + GLAccount suspenseAccount = glAccountRepository.findOneWithNotFoundDetection(suspenseAccountId); + if(account.setSuspenseAccount(suspenseAccount)) { + actualChanges.put(ShareAccountApiConstants.suspenseaccount_paramname, suspenseAccount) ; + } + } + + if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.equityaccount_paramname, element)) { + Long equityAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.equityaccount_paramname, element); + GLAccount equityAccount = glAccountRepository.findOneWithNotFoundDetection(equityAccountId); + if(account.setEquityAccount(equityAccount)) { + actualChanges.put(ShareAccountApiConstants.equityaccount_paramname, equityAccount) ; + } + } + + if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.savingsaccountid_paramname, element)) { + Long savingsAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.savingsaccountid_paramname, element); + SavingsAccount savingsAccount = this.savingsAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsAccountId); + if(account.setSavingsAccount(savingsAccount)) { + actualChanges.put(ShareAccountApiConstants.savingsaccountid_paramname, savingsAccount) ; + } + } + + if(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.purchasedshares_paramname, element)) { + Set sharesPurchased = asemblePurchasedShares(element); + account.setPurchasedShares(sharesPurchased) ; + actualChanges.put(ShareAccountApiConstants.purchasedshares_paramname, sharesPurchased) ; + } + + if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element)) { + Boolean allowdividendsForInactiveClients = this.fromApiJsonHelper.extractBooleanNamed( + ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element); + if (account.setAllowDividendCalculationForInactiveClients(allowdividendsForInactiveClients)) { + actualChanges.put(ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, + allowdividendsForInactiveClients); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.lockperiod_paramname, element)) { + PeriodFrequencyType lockPeriod = extractPeriodType(ShareAccountApiConstants.lockperiod_paramname, element); + if (account.setLockPeriod(lockPeriod)) { + actualChanges.put(ShareAccountApiConstants.lockperiod_paramname, lockPeriod); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.minimumactiveperiodfordividends_paramname, element)) { + PeriodFrequencyType minimumActivePeriod = extractPeriodType(ShareAccountApiConstants.minimumactiveperiodfordividends_paramname, + element); + if (account.setminimumActivePeriodForDividends(minimumActivePeriod)) { + actualChanges.put(ShareAccountApiConstants.minimumactiveperiodfordividends_paramname, minimumActivePeriod); + } + } + if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.charges_paramname, element)) { + ShareProduct shareProduct = account.getShareProduct() ; + Set charges = assembleListOfAccountCharges(element, shareProduct.getCurrency().getCode()); + if(account.setCharges(charges)) { + actualChanges.put(ShareAccountApiConstants.charges_paramname, charges); + } + } + AppUser modifiedBy = platformSecurityContext.authenticatedUser(); + DateTime modifiedOn = DateUtils.getLocalDateTimeOfTenant().toDateTime(); + + return actualChanges; + } + + private Set assembleListOfAccountCharges(final JsonElement element, final String currencyCode) { + final Set charges = new HashSet<>(); + if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.charges_paramname, element)) { + JsonArray chargesArray = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.charges_paramname, element); + if (chargesArray != null) { + for (int i = 0; i < chargesArray.size(); i++) { + final JsonObject jsonObject = chargesArray.get(i).getAsJsonObject(); + if (jsonObject.has("id")) { + final Long id = jsonObject.get("id").getAsLong(); + final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(id); + if (!currencyCode.equals(charge.getCurrencyCode())) { + final String errorMessage = "Charge and Share Account must have the same currency."; + throw new InvalidCurrencyException("charge", "attach.to.share.account", errorMessage); + } + ShareAccountCharge accountCharge = new ShareAccountCharge(charge); + charges.add(accountCharge); + } + } + } + } + return charges; + } + + private PeriodFrequencyType extractPeriodType(String paramName, final JsonElement element) { + PeriodFrequencyType frequencyType = PeriodFrequencyType.INVALID; + frequencyType = PeriodFrequencyType.fromInt(this.fromApiJsonHelper.extractIntegerWithLocaleNamed(paramName, element)); + return frequencyType; + } + + private Set asemblePurchasedShares(final JsonElement element) { + Set set = null; + if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.purchasedshares_paramname, element)) { + set = new HashSet<>(); + JsonArray array = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.purchasedshares_paramname, element); + for (JsonElement arrayElement : array) { + LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.purchaseddate_paramname, + arrayElement); + final Long shares = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.numberofshares_paramname, arrayElement); + final BigDecimal shareValue = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed( + ShareAccountApiConstants.purchasedprice_paramname, arrayElement); + + PurchasedShares obj = new PurchasedShares(localDate.toDate(), shares, shareValue); + set.add(obj); + } + } + return set; + } + + public Set asembleAdditionalShares(final JsonElement element) { + Set set = null; + if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.additionalshares_paramname, element)) { + set = new HashSet<>(); + JsonArray array = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.additionalshares_paramname, element); + for (JsonElement arrayElement : array) { + LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.purchaseddate_paramname, + arrayElement); + final Long shares = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.numberofshares_paramname, arrayElement); + final BigDecimal shareValue = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed( + ShareAccountApiConstants.purchasedprice_paramname, arrayElement); + + PurchasedShares obj = new PurchasedShares(localDate.toDate(), shares, shareValue); + set.add(obj); + } + } + return set; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/AccountReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/AccountReadPlatformService.java new file mode 100644 index 000000000..76cf4f809 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/AccountReadPlatformService.java @@ -0,0 +1,21 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.service; + +import java.util.Collection; +import java.util.Set; + +import org.mifosplatform.portfolio.accounts.data.AccountData; + + +public interface AccountReadPlatformService { + + public AccountData retrieveOne(Long id) ; + + public Collection retrieveAll() ; + + public Set getResponseDataParams(); +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/AccountsCommandsService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/AccountsCommandsService.java new file mode 100644 index 000000000..ff4e90c6b --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/AccountsCommandsService.java @@ -0,0 +1,12 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.service; + + +public interface AccountsCommandsService { + + public Object handleCommand(final Long accountId, final String command, final String jsonBody) ; +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountCommandsServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountCommandsServiceImpl.java new file mode 100644 index 000000000..d7109b8d2 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountCommandsServiceImpl.java @@ -0,0 +1,123 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.service; + +import java.util.Set; + +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.mifosplatform.portfolio.accounts.constants.ShareAccountApiConstants; +import org.mifosplatform.portfolio.accounts.domain.PurchasedShares; +import org.mifosplatform.portfolio.accounts.domain.ShareAccount; +import org.mifosplatform.portfolio.accounts.domain.ShareAccountTempRepository; +import org.mifosplatform.portfolio.accounts.serialization.ShareAccountDataSerializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.google.gson.JsonElement; + +@Service(value = "SHAREACCOUNT_COMMANDSERVICE") +public class ShareAccountCommandsServiceImpl implements AccountsCommandsService { + + private final FromJsonHelper fromApiJsonHelper; + + private final ShareAccountDataSerializer shareAccountDataSerializer ; + + @Autowired + public ShareAccountCommandsServiceImpl(final FromJsonHelper fromApiJsonHelper, + final ShareAccountDataSerializer shareAccountDataSerializer) { + this.fromApiJsonHelper = fromApiJsonHelper; + this.shareAccountDataSerializer = shareAccountDataSerializer ; + } + + @Override + public Object handleCommand(Long accountId, String command, String jsonBody) { + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(jsonBody); + final JsonCommand jsonCommand = JsonCommand.from(jsonBody, parsedCommand, this.fromApiJsonHelper, null, null, null, null, null, + null, null, null, null, null); + if(ShareAccountApiConstants.APPROVE_COMMAND.equals(command)){ + return approveShareAccount(accountId, jsonCommand) ; + }if(ShareAccountApiConstants.REJECT_COMMAND.equals(command)){ + return rejectShareAccount(accountId, jsonCommand) ; + }else if(ShareAccountApiConstants.APPLY_ADDITIONALSHARES_COMMAND.equals(command)) { + return applyAdditionalShares(accountId, jsonCommand) ; + }else if(ShareAccountApiConstants.APPROVE_ADDITIONSHARES_COMMAND.equals(command)) { + return approveAdditionalShares(accountId, jsonCommand) ; + }else if(ShareAccountApiConstants.REJECT_ADDITIONSHARES_COMMAND.equals(command)) { + return rejectAdditionalShares(accountId, jsonCommand) ; + } + + return CommandProcessingResult.empty(); + } + + public Object approveShareAccount(Long accountId, JsonCommand jsonCommand) { + //We need to add approval date also + ShareAccount account = ShareAccountTempRepository.getInstance().findOne(accountId); + account.setStatus("Approved"); + Set purchasedShares = account.getPurchasedShares() ; + for(PurchasedShares pur: purchasedShares) { + pur.setStatus("Approved") ; + } + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(account.getId()) // + .build(); + } + + public Object rejectShareAccount(Long accountId, JsonCommand jsonCommand) { + ShareAccount account = ShareAccountTempRepository.getInstance().findOne(accountId); + account.setStatus("Rejected"); + //rejection date we need to capture + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(account.getId()) // + .build(); + } + + public Object applyAdditionalShares(Long accountId, JsonCommand jsonCommand) { + ShareAccount account = ShareAccountTempRepository.getInstance().findOne(accountId); + Set additionalShares = this.shareAccountDataSerializer.asembleAdditionalShares(jsonCommand.parsedJson()) ; + account.addAddtionalShares(additionalShares) ; + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(account.getId()) // + .build(); + } + + public Object approveAdditionalShares(Long accountId, JsonCommand jsonCommand) { + //user might have requested for different dates. + //we need to capture either purchase date or ids [] + ShareAccount account = ShareAccountTempRepository.getInstance().findOne(accountId); + Set purchasedShares = account.getPurchasedShares() ; + for(PurchasedShares pur: purchasedShares) { + if(pur.getStatus().equals("Submitted") && !pur.getStatus().equals("Rejected")) { + pur.setStatus("Approved") ; + } + } + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(account.getId()) // + .build(); + } + + public Object rejectAdditionalShares(Long accountId, JsonCommand jsonCommand) { + //user might have requested for different dates. + //we need to capture either purchase date or ids [] + ShareAccount account = ShareAccountTempRepository.getInstance().findOne(accountId); + Set purchasedShares = account.getPurchasedShares() ; + for(PurchasedShares pur: purchasedShares) { + if(pur.getStatus().equals("Submitted")) { + pur.setStatus("Rejected") ; + } + } + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(account.getId()) // + .build(); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountReadPlatformServiceImpl.java new file mode 100644 index 000000000..abff1684d --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountReadPlatformServiceImpl.java @@ -0,0 +1,40 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.service; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.mifosplatform.portfolio.accounts.constants.AccountsApiConstants; +import org.mifosplatform.portfolio.accounts.data.AccountData; +import org.mifosplatform.portfolio.accounts.domain.ShareAccount; +import org.mifosplatform.portfolio.accounts.domain.ShareAccountTempRepository; +import org.springframework.stereotype.Service; + +@Service(value = "share"+AccountsApiConstants.READPLATFORM_NAME) +public class ShareAccountReadPlatformServiceImpl implements AccountReadPlatformService{ + + @Override + public AccountData retrieveOne(Long id) { + return ShareAccountTempRepository.getInstance().findOne(id).toData(); + } + + @Override + public Collection retrieveAll() { + Collection collection = ShareAccountTempRepository.getInstance().findAll() ; + Set set = new HashSet<>() ; + for(ShareAccount data: collection) { + set.add(data.toData()) ; + } + return set; + } + + @Override + public Set getResponseDataParams() { + return null; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountWritePlatformService.java new file mode 100644 index 000000000..4391416ab --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountWritePlatformService.java @@ -0,0 +1,17 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.service; + +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; + + +public interface ShareAccountWritePlatformService { + + public CommandProcessingResult createShareAccount(JsonCommand jsonCommand) ; + + public CommandProcessingResult updateShareAccount(Long accountId, JsonCommand jsonCommand) ; +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java new file mode 100644 index 000000000..8d176af64 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/accounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java @@ -0,0 +1,72 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.accounts.service; + +import java.util.Map; + +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; +import org.mifosplatform.portfolio.accounts.domain.ShareAccount; +import org.mifosplatform.portfolio.accounts.domain.ShareAccountTempRepository; +import org.mifosplatform.portfolio.accounts.exceptions.ShareAccountNotFoundException; +import org.mifosplatform.portfolio.accounts.serialization.ShareAccountDataSerializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.stereotype.Service; + +@Service +public class ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareAccountWritePlatformService { + + private final ShareAccountDataSerializer accountDataSerializer; + + @Autowired + public ShareAccountWritePlatformServiceJpaRepositoryImpl(final ShareAccountDataSerializer accountDataSerializer) { + this.accountDataSerializer = accountDataSerializer; + } + + @Override + public CommandProcessingResult createShareAccount(JsonCommand jsonCommand) { + try { + ShareAccount account = this.accountDataSerializer.validateAndCreate(jsonCommand); + ShareAccountTempRepository.getInstance().save(account); + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(account.getId()) // + .build(); + } catch (final DataIntegrityViolationException dve) { + handleDataIntegrityIssues(jsonCommand, dve); + return CommandProcessingResult.empty(); + } + } + + @Override + public CommandProcessingResult updateShareAccount(Long accountId, JsonCommand jsonCommand) { + try { + ShareAccount account = ShareAccountTempRepository.getInstance().findOne(accountId); + if (account == null) { + throw new ShareAccountNotFoundException(accountId) ; + } + Map changes = this.accountDataSerializer.validateAndUpdate(jsonCommand, account); + if (!changes.isEmpty()) { + // Save the data here + } + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(accountId) // + .with(changes) // + .build(); + } catch (DataIntegrityViolationException dve) { + handleDataIntegrityIssues(jsonCommand, dve); + return CommandProcessingResult.empty(); + } + } + + private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) { + + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/api/ProductsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/api/ProductsApiResource.java new file mode 100644 index 000000000..23af9360c --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/api/ProductsApiResource.java @@ -0,0 +1,144 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.products.api; + +import java.util.Collection; +import java.util.HashSet; + +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.UriInfo; + +import org.apache.commons.lang.StringUtils; +import org.mifosplatform.commands.domain.CommandWrapper; +import org.mifosplatform.commands.service.CommandWrapperBuilder; +import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; +import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; +import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer; +import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.mifosplatform.portfolio.products.constants.ProductsApiConstants; +import org.mifosplatform.portfolio.products.data.ProductData; +import org.mifosplatform.portfolio.products.service.ProductCommandsService; +import org.mifosplatform.portfolio.products.service.ProductReadPlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + + +@Path("/products/{type}") +@Component +@Scope("singleton") +public class ProductsApiResource { + + private final ApplicationContext applicationContext ; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final DefaultToApiJsonSerializer toApiJsonSerializer; + private final DefaultToApiJsonSerializer toApiObjectJsonSerializer ; + private final PlatformSecurityContext platformSecurityContext; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + + @Autowired + public ProductsApiResource(final ApplicationContext applicationContext, + final ApiRequestParameterHelper apiRequestParameterHelper, + final DefaultToApiJsonSerializer toApiJsonSerializer, + final PlatformSecurityContext platformSecurityContext, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, + final DefaultToApiJsonSerializer toApiDividendsJsonSerializer) { + this.applicationContext = applicationContext ; + this.apiRequestParameterHelper = apiRequestParameterHelper ; + this.toApiJsonSerializer = toApiJsonSerializer ; + this.platformSecurityContext = platformSecurityContext ; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService ; + this.toApiObjectJsonSerializer = toApiDividendsJsonSerializer ; + } + + @GET + @Path("template") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveTemplate(@PathParam("type") final String productType, @Context final UriInfo uriInfo) { + String serviceName = productType+ProductsApiConstants.READPLATFORM_NAME ; + ProductReadPlatformService service = (ProductReadPlatformService) this.applicationContext.getBean(serviceName) ; + ProductData data = service.retrieveTemplate() ; + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams()); + } + + @GET + @Path("{productId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveProduct(@PathParam("productId") final Long productId, @PathParam("type") final String productType, + @Context final UriInfo uriInfo) { + String serviceName = productType+ProductsApiConstants.READPLATFORM_NAME ; + ProductReadPlatformService service = (ProductReadPlatformService) this.applicationContext.getBean(serviceName) ; + ProductData data = service.retrieveOne(productId) ; + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams()); + } + + @GET + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String retrieveAllProducts(@PathParam("type") final String productType, @Context final UriInfo uriInfo) { + String serviceName = productType+ProductsApiConstants.READPLATFORM_NAME ; + ProductReadPlatformService service = (ProductReadPlatformService) this.applicationContext.getBean(serviceName) ; + Collection data = service.retrieveAllProducts() ; + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, data, service.getResponseDataParams()); + } + + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String createProduct(@PathParam("type") final String productType, final String apiRequestBodyAsJson) { + CommandWrapper commandWrapper = null; + this.platformSecurityContext.authenticatedUser(); + commandWrapper = new CommandWrapperBuilder().createProduct(productType).withJson(apiRequestBodyAsJson).build(); + final CommandProcessingResult commandProcessingResult = this.commandsSourceWritePlatformService.logCommandSource(commandWrapper); + return this.toApiJsonSerializer.serialize(commandProcessingResult); + } + + @POST + @Path("{productId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String handleCommands(@PathParam("type") final String productType, @PathParam("productId") final Long productId, @QueryParam("command") final String commandParam, + @Context final UriInfo uriInfo, final String apiRequestBodyAsJson) { + String serviceName = productType.toUpperCase()+ProductsApiConstants.PRODUCT_COMMANDSERVICE ; + ProductCommandsService service = (ProductCommandsService) this.applicationContext.getBean(serviceName) ; + final Object obj = service.handleCommand(productId, commandParam, apiRequestBodyAsJson) ; + final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiObjectJsonSerializer.serialize(settings, obj, new HashSet()); + } + + @PUT + @Path("{productId}") + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String updateProduct(@PathParam("type") final String productType, @PathParam("productId") final Long productId, final String apiRequestBodyAsJson) { + this.platformSecurityContext.authenticatedUser(); + final CommandWrapper commandRequest = new CommandWrapperBuilder().updateProduct(productType, productId) + .withJson(apiRequestBodyAsJson).build(); + final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest); + return this.toApiJsonSerializer.serialize(result); + } + + private boolean is(final String commandParam, final String commandValue) { + return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue); + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/constants/ProductsApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/constants/ProductsApiConstants.java new file mode 100644 index 000000000..410c6d48e --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/constants/ProductsApiConstants.java @@ -0,0 +1,14 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.products.constants; + + +public interface ProductsApiConstants { + + public final String READPLATFORM_NAME = "ReadPlatformService" ; + public final String PRODUCT_COMMANDSERVICE = "PRODUCT_COMMANDSERVICE" ; + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/data/ProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/data/ProductData.java new file mode 100644 index 000000000..2c8e0b642 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/data/ProductData.java @@ -0,0 +1,11 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.products.data; + + +public interface ProductData { + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/exception/ProductNotFoundException.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/exception/ProductNotFoundException.java new file mode 100644 index 000000000..a7fc2c224 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/exception/ProductNotFoundException.java @@ -0,0 +1,18 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.products.exception; + +import org.mifosplatform.infrastructure.core.exception.AbstractPlatformResourceNotFoundException; + +/** + * A {@link RuntimeException} thrown when loan product resources are not found. + */ +public class ProductNotFoundException extends AbstractPlatformResourceNotFoundException { + + public ProductNotFoundException(final Long id, String type) { + super("error.msg.product.id.invalid", type + " product with identifier " + id + " does not exist" , id); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/service/ProductCommandsService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/service/ProductCommandsService.java new file mode 100644 index 000000000..c4e38b336 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/service/ProductCommandsService.java @@ -0,0 +1,13 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.products.service; + + + +public interface ProductCommandsService { + + public Object handleCommand(final Long productId, final String command, final String jsonBody) ; +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/service/ProductReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/service/ProductReadPlatformService.java new file mode 100644 index 000000000..92a07c373 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/products/service/ProductReadPlatformService.java @@ -0,0 +1,22 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.products.service; + +import java.util.Collection; +import java.util.Set; + +import org.mifosplatform.portfolio.products.data.ProductData; + +public interface ProductReadPlatformService { + + public Collection retrieveAllProducts(); + + public ProductData retrieveOne(final Long productId); + + public ProductData retrieveTemplate(); + + public Set getResponseDataParams(); +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/constants/ShareProductApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/constants/ShareProductApiConstants.java new file mode 100644 index 000000000..8d80c3a74 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/constants/ShareProductApiConstants.java @@ -0,0 +1,39 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.constants; + +public interface ShareProductApiConstants { + + //Command Strings + public final String PREIEW_DIVIDENDS_COMMAND_STRING = "previewdividends" ; + public final String POST_DIVIDENdS_COMMAND_STRING = "postdividends" ; + + String id_paramname = "id"; + String name_paramname = "name"; + String shortname_paramname = "shortName"; + String description_paramname = "description"; + String externalid_paramname = "externalId"; + String totalshares_paramname = "totalShares"; + String currency_paramname = "currencyCode"; + String digitsafterdecimal_paramname = "digitsAfterDecimal"; + String inmultiplesof_paramname = "inMultiplesOf"; + String totalsharesissued_paramname = "totalSharesIssued"; + String unitprice_paramname = "unitPrice"; + String sharecapital_paramname = "shareCapital"; + String suspenseaccount_paramname = "suspenseAccount"; + String equityaccount_paramname = "equityAccount"; + String minimumshares_paramname = "minimumShares"; + String nominaltshares_paramname = "nominaltShares"; + String maximumshares_paramname = "maximumShares"; + String marketprice_paramname = "marketPrice"; + String charges_paramname = "charges"; + String allowdividendcalculationforinactiveclients_paramname = "allowDividendCalculationForInactiveClients"; + String lockperiod_paramname = "lockPeriod"; + String minimumactiveperiodfordividends_paramname = "minimumActivePeriodForDividends"; + + String startdate_paramname = "startDate"; + String sharevalue_paramname = "shareValue"; +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/DividendsData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/DividendsData.java new file mode 100644 index 000000000..315cf0d17 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/DividendsData.java @@ -0,0 +1,36 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.data; + +import java.math.BigDecimal; +import java.util.Date; + +public class DividendsData { + + private Long clientId; + + private String clientName; + + private String shareAccountNo; + + private String savingsAccountNo; + + private Long numberOfShares; + + private BigDecimal dividendAmount; + + private Date dividendIssuedDate; + + public DividendsData(final Long clientId, final String clientName, final String savingsAccountNo, final Long numberOfShares, + final BigDecimal dividendAmount, final Date dividendIssuedDate) { + this.clientId = clientId; + this.clientName = clientName; + this.savingsAccountNo = savingsAccountNo; + this.numberOfShares = numberOfShares; + this.dividendAmount = dividendAmount; + this.dividendIssuedDate = dividendIssuedDate; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/ProductDividendsData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/ProductDividendsData.java new file mode 100644 index 000000000..79adab93b --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/ProductDividendsData.java @@ -0,0 +1,52 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.data; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Date; + +import org.mifosplatform.organisation.monetary.data.CurrencyData; + + +public class ProductDividendsData { + + private Long id ; + + private Long productId ; + + private String productName ; + + private Date dividendsIssuedDate ; + + private BigDecimal dividendAmount ; + + private CurrencyData currency ; + + Collection dividendsData ; + + public ProductDividendsData(final Long productId, final String productName, final Date dividendsIssuedDate, + final BigDecimal dividendAmount, final CurrencyData currency, final Collection dividendsData) { + this.productId = productId ; + this.productName = productName ; + this.dividendsIssuedDate = dividendsIssuedDate ; + this.dividendAmount = dividendAmount ; + this.dividendsData = dividendsData ; + this.currency = currency ; + } + + public void setId(Long id) { + this.id = id ; + } + + public Long getId() { + return this.id ; + } + + public Long getProductId() { + return productId ; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/ShareMarketPriceData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/ShareMarketPriceData.java new file mode 100644 index 000000000..fd1233e6c --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/ShareMarketPriceData.java @@ -0,0 +1,29 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.data; + +import java.math.BigDecimal; +import java.util.Date; + +public class ShareMarketPriceData { + + private final Date startDate; + + private final BigDecimal shareValue; + + public ShareMarketPriceData(final Date startDate, final BigDecimal shareValue) { + this.startDate = startDate ; + this.shareValue = shareValue ; + } + + public Date getStartDate() { + return this.startDate; + } + + public BigDecimal getShareValue() { + return this.shareValue; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/ShareProductData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/ShareProductData.java new file mode 100644 index 000000000..5973b9de1 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/data/ShareProductData.java @@ -0,0 +1,147 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.data; + +import java.math.BigDecimal; +import java.util.List; + +import org.mifosplatform.accounting.glaccount.data.GLAccountData; +import org.mifosplatform.infrastructure.core.data.EnumOptionData; +import org.mifosplatform.organisation.monetary.data.CurrencyData; +import org.mifosplatform.portfolio.charge.data.ChargeData; +import org.mifosplatform.portfolio.products.data.ProductData; + +public class ShareProductData implements ProductData{ + + private final Long id; + private final String name; + private final String shortName; + private final String description; + private final String externalId; + private final CurrencyData currency; + private final Long totalShares; + private final Long totalSharesIssued; + private final BigDecimal unitPrice; + private final BigDecimal shareCapital; + private final GLAccountData suspenseAccount; + private final GLAccountData equityAccount; + private final Long minimumShares; + private final Long nominaltShares; + private final Long maximumShares; + private final List marketPrice; + private final List charges; + private Boolean allowDividendCalculationForInactiveClients; + private final EnumOptionData lockPeriod; + private final EnumOptionData minimumActivePeriodForDividends; + + public ShareProductData(final Long id, final String name, final String shortName, final String description, final String externalId, + final CurrencyData currency, final Long totalShares, final Long totalSharesIssued, final BigDecimal unitPrice, + final BigDecimal shareCapital, final GLAccountData suspenseAccount, final GLAccountData equityAccount, + final Long minimumShares, final Long nominaltShares, final Long maximumShares, List marketPrice, + final List charges, final Boolean allowDividendCalculationForInactiveClients, final EnumOptionData lockPeriod, + final EnumOptionData minimumActivePeriodForDividends) { + this.id = id; + this.name = name; + this.shortName = shortName; + this.description = description; + this.externalId = externalId; + this.currency = currency; + this.totalShares = totalShares; + this.totalSharesIssued = totalSharesIssued; + this.unitPrice = unitPrice; + this.shareCapital = shareCapital; + this.suspenseAccount = suspenseAccount; + this.equityAccount = equityAccount; + this.minimumShares = minimumShares; + this.nominaltShares = nominaltShares; + this.maximumShares = maximumShares; + this.marketPrice = marketPrice; + this.charges = charges; + this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients; + this.lockPeriod = lockPeriod; + this.minimumActivePeriodForDividends = minimumActivePeriodForDividends; + } + + public Long getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public String getShortName() { + return this.shortName; + } + + public String getDescription() { + return this.description; + } + + public String getExternalId() { + return this.externalId; + } + + public CurrencyData getCurrency() { + return this.currency; + } + + public Long getTotalShares() { + return this.totalShares; + } + + public Long getTotalSharesIssued() { + return this.totalSharesIssued; + } + + public BigDecimal getUnitPrice() { + return this.unitPrice; + } + + public BigDecimal getShareCapital() { + return this.shareCapital; + } + + public GLAccountData getSuspenseAccount() { + return this.suspenseAccount; + } + + public GLAccountData getEquityAccount() { + return this.equityAccount; + } + + public Long getMinimumShares() { + return this.minimumShares; + } + + public Long getNominaltShares() { + return this.nominaltShares; + } + + public Long getMaximumShares() { + return this.maximumShares; + } + + public List getMarketPrice() { + return this.marketPrice; + } + + public List getCharges() { + return this.charges; + } + + public Boolean getAllowDividendCalculationForInactiveClients() { + return this.allowDividendCalculationForInactiveClients; + } + + public EnumOptionData getLockPeriod() { + return this.lockPeriod; + } + + public EnumOptionData getMinimumActivePeriodForDividends() { + return this.minimumActivePeriodForDividends; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareMarketPrice.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareMarketPrice.java new file mode 100644 index 000000000..24f8d9ae3 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareMarketPrice.java @@ -0,0 +1,52 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.domain; + +import java.math.BigDecimal; +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.springframework.data.jpa.domain.AbstractPersistable; + +@Entity +@Table(name = "m_share_marketprice") +public class ShareMarketPrice extends AbstractPersistable { + + @ManyToOne(optional = false) + @JoinColumn(name = "product_id", referencedColumnName = "id", nullable = false) + private ShareProduct product; + + @Column(name = "start_date") + @Temporal(TemporalType.DATE) + private Date startDate; + + @Column(name = "share_value", nullable = false) + private BigDecimal shareValue ; + + public ShareMarketPrice(final Date startDate, final BigDecimal shareValue) { + this.startDate = startDate ; + this.shareValue = shareValue ; + } + + public void setShareProduct(final ShareProduct product) { + this.product = product ; + } + + public Date getStartDate() { + return this.startDate ; + } + + public BigDecimal getPrice() { + return this.shareValue ; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareProduct.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareProduct.java new file mode 100644 index 000000000..3d09ce6a3 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareProduct.java @@ -0,0 +1,350 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.domain; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import org.hibernate.annotations.LazyCollection; +import org.hibernate.annotations.LazyCollectionOption; +import org.joda.time.DateTime; +import org.mifosplatform.accounting.glaccount.data.GLAccountData; +import org.mifosplatform.accounting.glaccount.domain.GLAccount; +import org.mifosplatform.infrastructure.core.data.EnumOptionData; +import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom; +import org.mifosplatform.organisation.monetary.data.CurrencyData; +import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; +import org.mifosplatform.portfolio.charge.data.ChargeData; +import org.mifosplatform.portfolio.charge.domain.Charge; +import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType; +import org.mifosplatform.portfolio.shares.data.ShareMarketPriceData; +import org.mifosplatform.portfolio.shares.data.ShareProductData; +import org.mifosplatform.useradministration.domain.AppUser; + +@Entity +@Table(name = "m_shareproducts") +public class ShareProduct extends AbstractAuditableCustom { + + @Column(name = "name", nullable = false, unique = true) + private String name; + + @Column(name = "short_name", nullable = false, unique = true) + private String shortName; + + @Column(name = "description") + private String description; + + @Column(name = "start_date") + @Temporal(TemporalType.DATE) + private Date startDate; + + @Column(name = "end_date") + @Temporal(TemporalType.DATE) + private Date endDate; + + @Column(name = "external_id", length = 100, nullable = true, unique = true) + private String externalId; + + @Embedded + private MonetaryCurrency currency; + + @Column(name = "total_shares", nullable = false) + private Long totalShares; + + @Column(name = "total_shares_issued", nullable = false) + private Long totalSharesIssued; + + @Column(name = "unit_price", nullable = false) + private BigDecimal unitPrice; + + @Column(name = "share_capital", nullable = false) + private BigDecimal shareCapital; + + @ManyToOne + @JoinColumn(name = "suspence_account", nullable = false) + private GLAccount suspenseAccount; + + @ManyToOne + @JoinColumn(name = "equity_account", nullable = false) + private GLAccount equityAccount; + + @Column(name = "minimum_client_shares") + private Long minimumShares; + + @Column(name = "default_client_shares", nullable = false) + private Long nominalShares; + + @Column(name = "maximum_client_shares") + private Long maximumShares; + + @LazyCollection(LazyCollectionOption.FALSE) + @OneToMany(cascade = CascadeType.ALL, mappedBy = "product", orphanRemoval = true) + Set marketPrice = new HashSet<>(); + + @ManyToMany(fetch = FetchType.EAGER) + @JoinTable(name = "m_product_charges", joinColumns = @JoinColumn(name = "product_id"), inverseJoinColumns = @JoinColumn(name = "charge_id")) + private Set charges; + + @Column(name = "allow_dividends_inactive_clients") + private Boolean allowDividendCalculationForInactiveClients; + + @Enumerated(EnumType.ORDINAL) + @Column(name = "lock_period", nullable = true) + private PeriodFrequencyType lockPeriod; + + @Enumerated(EnumType.ORDINAL) + @Column(name = "dividend_active_period", nullable = true) + private PeriodFrequencyType minimumActivePeriodForDividends; + + protected ShareProduct() { + + } + // FIXME Remove this method + public void setTempId(Long id) { + super.setId(id); + } + + public ShareProduct(final String name, final String shortName, final String description, final String externalId, + final MonetaryCurrency currency, final Long totalShares, final Long totalSharesIssued, final BigDecimal unitPrice, + final BigDecimal shareCapital, final GLAccount suspenseAccount, final GLAccount equityAccount, final Long minimumShares, + final Long nominalShares, final Long maximumShares, Set marketPrice, Set charges, + final Boolean allowDividendCalculationForInactiveClients, final PeriodFrequencyType lockPeriod, + final PeriodFrequencyType minimumActivePeriodForDividends, + AppUser createdBy, DateTime createdDate, AppUser lastModifiedBy, DateTime lastModifiedDate) { + this.name = name; + this.shortName = shortName; + this.description = description; + this.externalId = externalId; + this.currency = currency; + this.totalShares = totalShares; + this.totalSharesIssued = totalSharesIssued; + this.unitPrice = unitPrice; + this.shareCapital = shareCapital; + this.suspenseAccount = suspenseAccount; + this.equityAccount = equityAccount; + this.minimumShares = minimumShares; + this.nominalShares = nominalShares; + this.maximumShares = maximumShares; + this.marketPrice = marketPrice; + this.charges = charges; + this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients; + this.lockPeriod = lockPeriod; + this.minimumActivePeriodForDividends = minimumActivePeriodForDividends; + setCreatedBy(createdBy) ; + setCreatedDate(createdDate) ; + setLastModifiedBy(lastModifiedBy) ; + setLastModifiedDate(lastModifiedDate) ; + } + + public ShareProductData toData() { + GLAccountData suspenseAccount1 = new GLAccountData(suspenseAccount.getId(), suspenseAccount.getName(), suspenseAccount.getGlCode()); + GLAccountData equityAccount1 = new GLAccountData(equityAccount.getId(), equityAccount.getName(), equityAccount.getGlCode()); + List chargeData = new ArrayList<>(); + for(Charge charge: this.charges) { + chargeData.add(ChargeData.lookup(charge.getId(), charge.getName(), charge.isPenalty())) ; + } + List marketData = new ArrayList<>() ; + for(ShareMarketPrice pri: marketPrice) { + marketData.add(new ShareMarketPriceData(pri.getStartDate(), pri.getPrice())) ; + } + EnumOptionData lock = new EnumOptionData(this.lockPeriod.getValue().longValue(), this.lockPeriod.getCode(), + this.lockPeriod.toString()); + EnumOptionData mini = new EnumOptionData(this.minimumActivePeriodForDividends.getValue().longValue(), this.minimumActivePeriodForDividends.getCode(), + this.minimumActivePeriodForDividends.toString());; + CurrencyData curr = new CurrencyData(currency.getCode(), "", currency.getDigitsAfterDecimal(), currency.getCurrencyInMultiplesOf(), + "", ""); + return new ShareProductData(getId(), name, shortName, description, externalId, curr, totalShares, totalSharesIssued, unitPrice, + shareCapital, suspenseAccount1, equityAccount1, minimumShares, nominalShares, maximumShares, marketData, chargeData, + allowDividendCalculationForInactiveClients, lock, mini); + } + + public boolean setProductName(String productName) { + boolean returnValue = false; + if (!this.name.equals(productName)) { + this.name = productName; + returnValue = true; + } + return returnValue; + } + + public String getProductName() { + return this.name ; + } + + public boolean setShortName(String shortName) { + boolean returnValue = false; + if (!this.shortName.equals(shortName)) { + this.shortName = shortName; + returnValue = true; + } + return returnValue; + } + + public boolean setDescription(String description) { + boolean returnValue = false; + if (!this.description.equals(description)) { + this.description = description; + returnValue = true; + } + return returnValue; + } + + public boolean setExternalId(String externalId) { + boolean returnValue = false; + if (!this.externalId.equals(externalId)) { + this.externalId = externalId; + returnValue = true; + } + return returnValue; + } + + public boolean setTotalShares(Long totalShares) { + boolean returnValue = false; + if (!this.totalShares.equals(totalShares)) { + this.totalShares = totalShares; + returnValue = true; + } + return returnValue; + + } + + public Long getTotalShares() { + return this.totalShares ; + } + + public boolean setTotalIssuedShares(Long totalSharesIssued) { + boolean returnValue = false; + if (!this.totalSharesIssued.equals(totalSharesIssued)) { + this.totalSharesIssued = totalSharesIssued; + returnValue = true; + } + return returnValue; + } + + public boolean setMonetaryCurrency(MonetaryCurrency currency) { + boolean returnValue = false; + if (!this.currency.equals(currency)) { + this.currency = currency; + returnValue = true; + } + return returnValue; + } + + public MonetaryCurrency getCurrency() { + return this.currency ; + } + + public boolean setUnitPrice(BigDecimal unitPrice) { + boolean returnValue = false; + if (!this.unitPrice.equals(unitPrice)) { + this.unitPrice = unitPrice; + returnValue = true; + } + return returnValue; + } + + public boolean setSuspenseAccount(GLAccount suspenseAccount) { + boolean returnValue = false; + if (!this.suspenseAccount.getId().equals(suspenseAccount.getId())) { + this.suspenseAccount = suspenseAccount; + returnValue = true; + } + return returnValue; + } + + public boolean setEquityAccount(GLAccount equityAccount) { + boolean returnValue = false; + if (!this.equityAccount.getId().equals(equityAccount.getId())) { + this.equityAccount = equityAccount; + returnValue = true; + } + return returnValue; + } + + public boolean setMinimumShares(final Long minimumShares) { + boolean returnValue = false; + if (!this.minimumShares.equals(minimumShares)) { + this.minimumShares = minimumShares; + returnValue = true; + } + return returnValue; + } + + public boolean setNominalShares(final Long nominalShares) { + boolean returnValue = false; + if (!this.nominalShares.equals(nominalShares)) { + this.nominalShares = nominalShares; + returnValue = true; + } + return returnValue; + } + + public boolean setMaximumShares(final Long maximumShares) { + boolean returnValue = false; + if (!this.maximumShares.equals(maximumShares)) { + this.maximumShares = maximumShares; + returnValue = true; + } + return returnValue; + } + + public boolean setMarketPrice(Set marketPrice) { + this.marketPrice = marketPrice; + return true; + } + + public boolean setCharges(Set charges) { + this.charges = charges; + return true; + } + + public boolean setAllowDividendCalculationForInactiveClients(Boolean allowDividendCalculationForInactiveClients) { + boolean returnValue = false; + if (!this.allowDividendCalculationForInactiveClients.equals(allowDividendCalculationForInactiveClients)) { + this.allowDividendCalculationForInactiveClients = allowDividendCalculationForInactiveClients; + returnValue = true; + } + return returnValue; + } + + public boolean setLockPeriod(final PeriodFrequencyType lockPeriod) { + boolean returnValue = false; + if (!this.lockPeriod.equals(lockPeriod)) { + this.lockPeriod = lockPeriod; + returnValue = true; + } + return returnValue; + } + + public boolean setminimumActivePeriodForDividends(final PeriodFrequencyType minimumActivePeriodForDividends) { + boolean returnValue = false; + if (!this.minimumActivePeriodForDividends.equals(minimumActivePeriodForDividends)) { + this.minimumActivePeriodForDividends = minimumActivePeriodForDividends; + returnValue = true; + } + return returnValue; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareProductRepository.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareProductRepository.java new file mode 100644 index 000000000..a1c988855 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareProductRepository.java @@ -0,0 +1,14 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.domain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + + +public interface ShareProductRepository extends JpaRepository, JpaSpecificationExecutor { + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareProductTempRepository.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareProductTempRepository.java new file mode 100644 index 000000000..ac9c1f589 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/domain/ShareProductTempRepository.java @@ -0,0 +1,66 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.domain; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.mifosplatform.portfolio.accounts.domain.ShareAccount; +import org.mifosplatform.portfolio.shares.data.ProductDividendsData; + + +public class ShareProductTempRepository { + + Map cache = new HashMap<>() ; + Map> accountsCache = new HashMap<>() ; + Map dividendsCahe = new HashMap<>() ; + + private final static ShareProductTempRepository instance = new ShareProductTempRepository() ; + + private ShareProductTempRepository() { + + } + + public final static ShareProductTempRepository getInstance() { + return instance ; + } + + public ShareProduct fineOne(Long productId) { + return this.cache.get(productId) ; + } + + public Collection findAll() { + return this.cache.values() ; + } + public void save(ShareProduct product) { + Long id = new Long(cache.size() + 1) ; + product.setTempId(id) ; + this.cache.put(id, product) ; + } + + public void addAccount(Long productId, ShareAccount account) { + if(accountsCache.containsKey(productId)) { + ArrayList list = accountsCache.get(productId) ; + list.add(account) ; + }else { + ArrayList list = new ArrayList<>() ; + list.add(account) ; + accountsCache.put(productId, list) ; + } + } + + public ArrayList getAllAccounts(Long productId) { + return accountsCache.get(productId) ; + } + + public void saveDividends(ProductDividendsData data) { + Long id = new Long(dividendsCahe.size()+1) ; + data.setId(id) ; + dividendsCahe.put(data.getProductId(), data) ; + } +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/handler/CreateShareProductCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/handler/CreateShareProductCommandHandler.java new file mode 100644 index 000000000..5510f527c --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/handler/CreateShareProductCommandHandler.java @@ -0,0 +1,34 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.handler; + +import org.mifosplatform.commands.annotation.CommandType; +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.portfolio.shares.service.ShareProductWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "SHAREPRODUCT", action = "CREATE") +public class CreateShareProductCommandHandler implements NewCommandSourceHandler { + + private final ShareProductWritePlatformService shareProductWritePlatformService ; + + @Autowired + public CreateShareProductCommandHandler(final ShareProductWritePlatformService shareProductWritePlatformService) { + this.shareProductWritePlatformService = shareProductWritePlatformService ; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(JsonCommand jsonCommand) { + return this.shareProductWritePlatformService.createShareProduct(jsonCommand); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/handler/UpdateShareProductCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/handler/UpdateShareProductCommandHandler.java new file mode 100644 index 000000000..8927de27e --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/handler/UpdateShareProductCommandHandler.java @@ -0,0 +1,34 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.handler; + +import org.mifosplatform.commands.annotation.CommandType; +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.portfolio.shares.service.ShareProductWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@CommandType(entity = "SHAREPRODUCT", action = "UPDATE") +public class UpdateShareProductCommandHandler implements NewCommandSourceHandler { + + private final ShareProductWritePlatformService shareProductWritePlatformService ; + + @Autowired + public UpdateShareProductCommandHandler(final ShareProductWritePlatformService shareProductWritePlatformService) { + this.shareProductWritePlatformService = shareProductWritePlatformService ; + } + + @Transactional + @Override + public CommandProcessingResult processCommand(JsonCommand jsonCommand) { + return this.shareProductWritePlatformService.updateProduct(jsonCommand.entityId(), jsonCommand); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/serialization/ShareProductDataSerializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/serialization/ShareProductDataSerializer.java new file mode 100644 index 000000000..8fe5ddec0 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/serialization/ShareProductDataSerializer.java @@ -0,0 +1,328 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.serialization; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.mifosplatform.accounting.glaccount.domain.GLAccount; +import org.mifosplatform.accounting.glaccount.domain.GLAccountRepositoryWrapper; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; +import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.mifosplatform.infrastructure.core.service.DateUtils; +import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; +import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; +import org.mifosplatform.portfolio.charge.domain.Charge; +import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper; +import org.mifosplatform.portfolio.common.domain.PeriodFrequencyType; +import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException; +import org.mifosplatform.portfolio.shares.constants.ShareProductApiConstants; +import org.mifosplatform.portfolio.shares.domain.ShareMarketPrice; +import org.mifosplatform.portfolio.shares.domain.ShareProduct; +import org.mifosplatform.useradministration.domain.AppUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; + +//This class responsibility is to validate data and serialize to entity and return object to the caller +@Service +public class ShareProductDataSerializer { + + private final Set supportedParameters = new HashSet<>(Arrays.asList("")); + + private final FromJsonHelper fromApiJsonHelper; + + private final ChargeRepositoryWrapper chargeRepository; + + private final GLAccountRepositoryWrapper glAccountRepository; + + private final PlatformSecurityContext platformSecurityContext ; + + @Autowired + public ShareProductDataSerializer(final FromJsonHelper fromApiJsonHelper, final ChargeRepositoryWrapper chargeRepository, + final GLAccountRepositoryWrapper glAccountRepository, + final PlatformSecurityContext platformSecurityContext) { + this.fromApiJsonHelper = fromApiJsonHelper; + this.chargeRepository = chargeRepository; + this.glAccountRepository = glAccountRepository; + this.platformSecurityContext = platformSecurityContext ; + } + + public ShareProduct validateAndCreate(JsonCommand jsonCommand) { + if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); } + final Type typeOfMap = new TypeToken>() {}.getType(); + //this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), supportedParameters); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesproduct"); + JsonElement element = jsonCommand.parsedJson(); + final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject()); + final String productName = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.name_paramname, element); + baseDataValidator.reset().parameter(ShareProductApiConstants.name_paramname).value(productName).notBlank() + .notExceedingLengthOf(200); + final String shortName = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.shortname_paramname, element); + baseDataValidator.reset().parameter(ShareProductApiConstants.shortname_paramname).value(shortName).notBlank() + .notExceedingLengthOf(10); + String description = null; + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.description_paramname, element)) { + description = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.description_paramname, element); + } + + String externalId = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.externalid_paramname, element); + Long totalNumberOfShares = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.totalshares_paramname, element); + final String currencyCode = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.currency_paramname, element); + final Integer digitsAfterDecimal = this.fromApiJsonHelper.extractIntegerWithLocaleNamed( + ShareProductApiConstants.digitsafterdecimal_paramname, element); + final Integer inMultiplesOf = this.fromApiJsonHelper.extractIntegerWithLocaleNamed( + ShareProductApiConstants.inmultiplesof_paramname, element); + final MonetaryCurrency currency = new MonetaryCurrency(currencyCode, digitsAfterDecimal, inMultiplesOf); + final Long sharesIssued = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.totalsharesissued_paramname, element); + final BigDecimal unitPrice = this.fromApiJsonHelper.extractBigDecimalNamed(ShareProductApiConstants.unitprice_paramname, element, + locale); + final BigDecimal shareCapitalValue = null; + Long suspenseAccountId = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.suspenseaccount_paramname, element); + Long equityAccountId = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.equityaccount_paramname, element); + Long minimumClientShares = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.minimumshares_paramname, element); + Long nominalClientShares = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.nominaltshares_paramname, element); + Long maximumClientShares = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.maximumshares_paramname, element); + Set marketPriceSet = asembleShareMarketPrice(element); + Set charges = assembleListOfProductCharges(element, currencyCode); + Boolean allowdividendsForInactiveClients = this.fromApiJsonHelper.extractBooleanNamed( + ShareProductApiConstants.allowdividendcalculationforinactiveclients_paramname, element); + PeriodFrequencyType lockPeriod = extractPeriodType(ShareProductApiConstants.lockperiod_paramname, element); + PeriodFrequencyType minimumActivePeriod = extractPeriodType(ShareProductApiConstants.minimumactiveperiodfordividends_paramname, + element); + GLAccount suspenseAccount = glAccountRepository.findOneWithNotFoundDetection(suspenseAccountId); + GLAccount equityAccount = glAccountRepository.findOneWithNotFoundDetection(equityAccountId); + AppUser modifiedBy = null; + DateTime modifiedOn = null; + AppUser createdBy = platformSecurityContext.authenticatedUser() ; + DateTime createdDate = DateUtils.getLocalDateTimeOfTenant().toDateTime() ; + ShareProduct product = new ShareProduct(productName, shortName, description, externalId, currency, totalNumberOfShares, + sharesIssued, unitPrice, shareCapitalValue, suspenseAccount, equityAccount, minimumClientShares, nominalClientShares, + maximumClientShares, marketPriceSet, charges, allowdividendsForInactiveClients, lockPeriod, minimumActivePeriod, + createdBy, createdDate, modifiedBy, modifiedOn); + return product; + } + + private PeriodFrequencyType extractPeriodType(String paramName, final JsonElement element) { + PeriodFrequencyType frequencyType = PeriodFrequencyType.INVALID; + frequencyType = PeriodFrequencyType.fromInt(this.fromApiJsonHelper.extractIntegerWithLocaleNamed(paramName, element)); + return frequencyType; + } + + private Set asembleShareMarketPrice(final JsonElement element) { + Set set = null; + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.marketprice_paramname, element)) { + set = new HashSet<>(); + JsonArray array = this.fromApiJsonHelper.extractJsonArrayNamed(ShareProductApiConstants.marketprice_paramname, element); + for (JsonElement arrayElement : array) { + LocalDate localDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareProductApiConstants.startdate_paramname, + arrayElement); + final BigDecimal shareValue = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed( + ShareProductApiConstants.sharevalue_paramname, arrayElement); + ShareMarketPrice obj = new ShareMarketPrice(localDate.toDate(), shareValue); + set.add(obj); + } + } + return set; + } + + private Set assembleListOfProductCharges(final JsonElement element, final String currencyCode) { + final Set charges = new HashSet<>(); + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.charges_paramname, element)) { + JsonArray chargesArray = this.fromApiJsonHelper.extractJsonArrayNamed(ShareProductApiConstants.charges_paramname, element); + if (chargesArray != null) { + for (int i = 0; i < chargesArray.size(); i++) { + final JsonObject jsonObject = chargesArray.get(i).getAsJsonObject(); + if (jsonObject.has("id")) { + final Long id = jsonObject.get("id").getAsLong(); + final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(id); + if (!currencyCode.equals(charge.getCurrencyCode())) { + final String errorMessage = "Charge and Loan Product must have the same currency."; + throw new InvalidCurrencyException("charge", "attach.to.loan.product", errorMessage); + } + charges.add(charge); + } + } + } + } + return charges; + } + + public Map validateAndUpdate(JsonCommand jsonCommand, ShareProduct product) { + Map actualChanges = new HashMap<>(); + + if (StringUtils.isBlank(jsonCommand.json())) { throw new InvalidJsonException(); } + final Type typeOfMap = new TypeToken>() {}.getType(); + //this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, jsonCommand.json(), supportedParameters); + + final List dataValidationErrors = new ArrayList<>(); + final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesproduct"); + + JsonElement element = jsonCommand.parsedJson(); + final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject()); + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.name_paramname, element)) { + final String productName = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.name_paramname, element); + if (product.setProductName(productName)) { + actualChanges.put(ShareProductApiConstants.name_paramname, productName); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.shortname_paramname, element)) { + final String shortName = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.shortname_paramname, element); + if (product.setShortName(shortName)) { + actualChanges.put(ShareProductApiConstants.shortname_paramname, shortName); + } + } + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.description_paramname, element)) { + String description = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.description_paramname, element); + if (product.setDescription(description)) { + actualChanges.put(ShareProductApiConstants.description_paramname, description); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.externalid_paramname, element)) { + String externalId = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.externalid_paramname, element); + if (product.setExternalId(externalId)) { + actualChanges.put(ShareProductApiConstants.externalid_paramname, externalId); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.totalshares_paramname, element)) { + Long totalShares = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.totalshares_paramname, element); + if (product.setTotalShares(totalShares)) { + actualChanges.put(ShareProductApiConstants.totalshares_paramname, totalShares); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.totalsharesissued_paramname, element)) { + final Long sharesIssued = this.fromApiJsonHelper + .extractLongNamed(ShareProductApiConstants.totalsharesissued_paramname, element); + if (product.setTotalIssuedShares(sharesIssued)) { + actualChanges.put(ShareProductApiConstants.totalsharesissued_paramname, sharesIssued); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.currency_paramname, element) + && this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.digitsafterdecimal_paramname, element) + && this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.inmultiplesof_paramname, element)) { + final String currencyCode = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.currency_paramname, element); + final Integer digitsAfterDecimal = this.fromApiJsonHelper.extractIntegerWithLocaleNamed( + ShareProductApiConstants.digitsafterdecimal_paramname, element); + final Integer inMultiplesOf = this.fromApiJsonHelper.extractIntegerWithLocaleNamed( + ShareProductApiConstants.inmultiplesof_paramname, element); + final MonetaryCurrency currency = new MonetaryCurrency(currencyCode, digitsAfterDecimal, inMultiplesOf); + if (product.setMonetaryCurrency(currency)) { + actualChanges.put(ShareProductApiConstants.currency_paramname, currency); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.unitprice_paramname, element)) { + final BigDecimal unitPrice = this.fromApiJsonHelper.extractBigDecimalNamed(ShareProductApiConstants.unitprice_paramname, + element, locale); + if (product.setUnitPrice(unitPrice)) { + actualChanges.put(ShareProductApiConstants.unitprice_paramname, unitPrice); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.suspenseaccount_paramname, element)) { + Long suspenseAccountId = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.suspenseaccount_paramname, element); + GLAccount suspenseAccount = glAccountRepository.findOneWithNotFoundDetection(suspenseAccountId); + if (product.setSuspenseAccount(suspenseAccount)) { + actualChanges.put(ShareProductApiConstants.suspenseaccount_paramname, suspenseAccount); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.equityaccount_paramname, element)) { + Long equityAccountId = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.equityaccount_paramname, element); + GLAccount equityAccount = glAccountRepository.findOneWithNotFoundDetection(equityAccountId); + if (product.setEquityAccount(equityAccount)) { + actualChanges.put(ShareProductApiConstants.equityaccount_paramname, equityAccount); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.minimumshares_paramname, element)) { + Long minimumClientShares = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.minimumshares_paramname, element); + if (product.setMinimumShares(minimumClientShares)) { + actualChanges.put(ShareProductApiConstants.minimumshares_paramname, minimumClientShares); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.nominaltshares_paramname, element)) { + Long nominalClientShares = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.nominaltshares_paramname, element); + if (product.setNominalShares(nominalClientShares)) { + actualChanges.put(ShareProductApiConstants.nominaltshares_paramname, nominalClientShares); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.maximumshares_paramname, element)) { + Long maximumClientShares = this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.maximumshares_paramname, element); + if (product.setMaximumShares(maximumClientShares)) { + actualChanges.put(ShareProductApiConstants.maximumshares_paramname, maximumClientShares); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.marketprice_paramname, element)) { + Set marketPrice = asembleShareMarketPrice(element); + if (product.setMarketPrice(marketPrice)) { + actualChanges.put(ShareProductApiConstants.marketprice_paramname, marketPrice); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.charges_paramname, element)) { + final String currencyCode = this.fromApiJsonHelper.extractStringNamed(ShareProductApiConstants.currency_paramname, element); + Set charges = assembleListOfProductCharges(element, currencyCode); + if (product.setCharges(charges)) { + actualChanges.put(ShareProductApiConstants.charges_paramname, charges); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.allowdividendcalculationforinactiveclients_paramname, element)) { + Boolean allowdividendsForInactiveClients = this.fromApiJsonHelper.extractBooleanNamed( + ShareProductApiConstants.allowdividendcalculationforinactiveclients_paramname, element); + if (product.setAllowDividendCalculationForInactiveClients(allowdividendsForInactiveClients)) { + actualChanges.put(ShareProductApiConstants.allowdividendcalculationforinactiveclients_paramname, + allowdividendsForInactiveClients); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.lockperiod_paramname, element)) { + PeriodFrequencyType lockPeriod = extractPeriodType(ShareProductApiConstants.lockperiod_paramname, element); + if (product.setLockPeriod(lockPeriod)) { + actualChanges.put(ShareProductApiConstants.lockperiod_paramname, lockPeriod); + } + } + + if (this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.minimumactiveperiodfordividends_paramname, element)) { + PeriodFrequencyType minimumActivePeriod = extractPeriodType(ShareProductApiConstants.minimumactiveperiodfordividends_paramname, + element); + if (product.setminimumActivePeriodForDividends(minimumActivePeriod)) { + actualChanges.put(ShareProductApiConstants.minimumactiveperiodfordividends_paramname, minimumActivePeriod); + } + } + return actualChanges; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductCommandsServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductCommandsServiceImpl.java new file mode 100644 index 000000000..a6f9de15a --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductCommandsServiceImpl.java @@ -0,0 +1,92 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.service; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; + +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.mifosplatform.organisation.monetary.data.CurrencyData; +import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; +import org.mifosplatform.portfolio.accounts.domain.ShareAccount; +import org.mifosplatform.portfolio.products.service.ProductCommandsService; +import org.mifosplatform.portfolio.shares.constants.ShareProductApiConstants; +import org.mifosplatform.portfolio.shares.data.DividendsData; +import org.mifosplatform.portfolio.shares.data.ProductDividendsData; +import org.mifosplatform.portfolio.shares.domain.ShareProduct; +import org.mifosplatform.portfolio.shares.domain.ShareProductTempRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.stereotype.Service; + +import com.google.gson.JsonElement; + +@Service(value = "SHAREPRODUCT_COMMANDSERVICE") +public class ShareProductCommandsServiceImpl implements ProductCommandsService { + + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public ShareProductCommandsServiceImpl(final FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } + + public ProductDividendsData previewDividends(Long productId, JsonCommand jsonCommand) { + ArrayList accounts = ShareProductTempRepository.getInstance().getAllAccounts(productId); + ShareProduct product = ShareProductTempRepository.getInstance().fineOne(productId); + Long total = product.getTotalShares(); + JsonElement element = jsonCommand.parsedJson(); + final BigDecimal totalDividendAmount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("dividendAmount", element); + BigDecimal perShareValue = totalDividendAmount.divide(new BigDecimal(total)); + Date date = new Date(); + ArrayList dividends = new ArrayList<>(); + for (ShareAccount account : accounts) { + if(account.getStatus().equals("Approved")) { + BigDecimal val = perShareValue.multiply(new BigDecimal(account.getTotalShares())); + DividendsData data = new DividendsData(account.getClientId(), account.getClientName(), account.getSavingsAccountNo(), + account.getTotalShares(), val, date); + dividends.add(data); + } + } + + MonetaryCurrency currency = product.getCurrency() ; + CurrencyData cur = new CurrencyData(currency.getCode(), "", currency.getDigitsAfterDecimal(), currency.getCurrencyInMultiplesOf(), + "", ""); + ProductDividendsData toReturn = new ProductDividendsData(productId, product.getProductName(), date, totalDividendAmount, cur, dividends); + return toReturn; + } + + public CommandProcessingResult postDividends(Long productId, JsonCommand jsonCommand) { + try { + ProductDividendsData data = previewDividends(productId, jsonCommand); + ShareProductTempRepository.getInstance().saveDividends(data); + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(data.getId()) // + .build(); + } catch (final DataIntegrityViolationException dve) { + return CommandProcessingResult.empty(); + } + } + + @Override + public Object handleCommand(Long productId, String command, String jsonBody) { + final JsonElement parsedCommand = this.fromApiJsonHelper.parse(jsonBody); + final JsonCommand jsonCommand = JsonCommand.from(jsonBody, parsedCommand, this.fromApiJsonHelper, null, null, null, null, null, + null, null, null, null, null); + if (ShareProductApiConstants.PREIEW_DIVIDENDS_COMMAND_STRING.equals(command)) { + return previewDividends(productId, jsonCommand); + } else if (ShareProductApiConstants.POST_DIVIDENdS_COMMAND_STRING.equals(command)) { return postDividends(productId, + jsonCommand); } + // throw unknow commandexception + return CommandProcessingResult.empty(); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductReadPlatformServiceImpl.java new file mode 100644 index 000000000..eae2a08bf --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductReadPlatformServiceImpl.java @@ -0,0 +1,51 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.service; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import org.mifosplatform.portfolio.products.data.ProductData; +import org.mifosplatform.portfolio.products.service.ProductReadPlatformService; +import org.mifosplatform.portfolio.shares.domain.ShareProduct; +import org.mifosplatform.portfolio.shares.domain.ShareProductTempRepository; +import org.springframework.stereotype.Service; + + +@Service(value = "shareReadPlatformService") +public class ShareProductReadPlatformServiceImpl implements ProductReadPlatformService{ + + ShareProductTempRepository repo = ShareProductTempRepository.getInstance() ; + + @Override + public Collection retrieveAllProducts() { + Collection entities = repo.findAll() ; + List toReturn = new ArrayList<>() ; + for(ShareProduct entity: entities) { + toReturn.add(entity.toData()) ; + } + return toReturn; + } + + @Override + public ProductData retrieveOne(Long productId) { + ShareProduct product = repo.fineOne(productId) ; + return product.toData() ; + } + + @Override + public ProductData retrieveTemplate() { + return null; + } + + @Override + public Set getResponseDataParams() { + return null; + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductWritePlatformService.java new file mode 100644 index 000000000..d6c3963bb --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductWritePlatformService.java @@ -0,0 +1,17 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.service; + +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; + + +public interface ShareProductWritePlatformService { + + CommandProcessingResult createShareProduct(JsonCommand jsonCommand) ; + + CommandProcessingResult updateProduct(Long productId, JsonCommand command); +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java new file mode 100644 index 000000000..e3a9b8c51 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/shares/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java @@ -0,0 +1,77 @@ +/** + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.mifosplatform.portfolio.shares.service; + +import java.util.Map; + +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder; +import org.mifosplatform.portfolio.products.exception.ProductNotFoundException; +import org.mifosplatform.portfolio.shares.domain.ShareProduct; +import org.mifosplatform.portfolio.shares.domain.ShareProductRepository; +import org.mifosplatform.portfolio.shares.domain.ShareProductTempRepository; +import org.mifosplatform.portfolio.shares.serialization.ShareProductDataSerializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.stereotype.Service; + +@Service +public class ShareProductWritePlatformServiceJpaRepositoryImpl implements ShareProductWritePlatformService { + + private final ShareProductRepository repository; + private final ShareProductDataSerializer serializer; + + @Autowired + public ShareProductWritePlatformServiceJpaRepositoryImpl(final ShareProductRepository repository, + final ShareProductDataSerializer serializer) { + this.repository = repository; + this.serializer = serializer; + } + + @Override + public CommandProcessingResult createShareProduct(JsonCommand jsonCommand) { + try { + ShareProduct product = this.serializer.validateAndCreate(jsonCommand); + //this.repository.save(product); + ShareProductTempRepository.getInstance().save(product) ; + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(product.getId()) // + .build(); + } catch (final DataIntegrityViolationException dve) { + handleDataIntegrityIssues(jsonCommand, dve); + return CommandProcessingResult.empty(); + } + + } + + @Override + public CommandProcessingResult updateProduct(Long productId, JsonCommand jsonCommand) { + try { + //ShareProduct product = this.repository.findOne(productId); + ShareProduct product = ShareProductTempRepository.getInstance().fineOne(productId) ; + if (product == null) { throw new ProductNotFoundException(productId, "share"); } + final Map changes = this.serializer.validateAndUpdate(jsonCommand, product); + if(!changes.isEmpty()) { + //this.repository.saveAndFlush(product) ; + } + return new CommandProcessingResultBuilder() // + .withCommandId(jsonCommand.commandId()) // + .withEntityId(productId) // + .with(changes) // + .build(); + } catch (DataIntegrityViolationException dve) { + handleDataIntegrityIssues(jsonCommand, dve); + return CommandProcessingResult.empty(); + } + } + + private void handleDataIntegrityIssues(final JsonCommand command, final DataIntegrityViolationException dve) { + + } + +} diff --git a/mifosng-provider/src/main/resources/sql/migrations/core_db/V290__shares_dividends_permissions_script.sql b/mifosng-provider/src/main/resources/sql/migrations/core_db/V290__shares_dividends_permissions_script.sql new file mode 100644 index 000000000..1bf56e999 --- /dev/null +++ b/mifosng-provider/src/main/resources/sql/migrations/core_db/V290__shares_dividends_permissions_script.sql @@ -0,0 +1,5 @@ +INSERT INTO `m_permission`(`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`) VALUES +('SHAREPRODUCT', 'CREATE_SHAREPRODUCT', 'SHAREPRODUCT', 'CREATE', 0), +('SHAREPRODUCT', 'UPDATE_SHAREPRODUCT', 'SHAREPRODUCT', 'CREATE', 0), +('SHAREACCOUNT', 'CREATE_SHAREACCOUNT', 'SHAREACCOUNT', 'CREATE', 0), +('SHAREACCOUNT', 'UPDATE_SHAREACCOUNT', 'SHAREACCOUNT', 'CREATE', 0); \ No newline at end of file