http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/serialization/ShareProductDataSerializer.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/serialization/ShareProductDataSerializer.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/serialization/ShareProductDataSerializer.java
new file mode 100644
index 0000000..345294b
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/serialization/ShareProductDataSerializer.java
@@ -0,0 +1,460 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.serialization;
+
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+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.apache.fineract.accounting.common.AccountingRuleType;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
+import 
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
+import 
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.portfolio.charge.domain.Charge;
+import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
+import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
+import 
org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
+import 
org.apache.fineract.portfolio.shareproducts.constants.ShareProductApiConstants;
+import 
org.apache.fineract.portfolio.shareproducts.data.ShareProductMarketPriceData;
+import org.apache.fineract.portfolio.shareproducts.domain.ShareProduct;
+import 
org.apache.fineract.portfolio.shareproducts.domain.ShareProductMarketPrice;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+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 ShareProductDataSerializer {
+
+    private final FromJsonHelper fromApiJsonHelper;
+
+    private final ChargeRepositoryWrapper chargeRepository;
+
+    private final PlatformSecurityContext platformSecurityContext;
+
+    @Autowired
+    public ShareProductDataSerializer(final FromJsonHelper fromApiJsonHelper, 
final ChargeRepositoryWrapper chargeRepository,
+            final PlatformSecurityContext platformSecurityContext) {
+        this.fromApiJsonHelper = fromApiJsonHelper;
+        this.chargeRepository = chargeRepository;
+        this.platformSecurityContext = platformSecurityContext;
+    }
+
+    public ShareProduct validateAndCreate(JsonCommand jsonCommand) {
+        if (StringUtils.isBlank(jsonCommand.json())) { throw new 
InvalidJsonException(); }
+        final Type typeOfMap = new TypeToken<Map<String, Object>>() 
{}.getType();
+        this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, 
jsonCommand.json(),
+                ShareProductApiConstants.supportedParametersForCreate);
+
+        final List<ApiParameterError> 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(4);
+        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);
+        // 
baseDataValidator.reset().parameter(ShareProductApiConstants.externalid_paramname).value(externalId).notBlank();
+
+        Long totalNumberOfShares = 
this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.totalshares_paramname,
 element);
+        
baseDataValidator.reset().parameter(ShareProductApiConstants.totalshares_paramname).value(totalNumberOfShares).notNull()
+                .longGreaterThanZero();
+
+        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);
+        
baseDataValidator.reset().parameter(ShareProductApiConstants.unitprice_paramname).value(unitPrice).notNull().positiveAmount();
+
+        BigDecimal shareCapitalValue = BigDecimal.ONE;
+        if (sharesIssued != null && unitPrice != null) {
+            shareCapitalValue = 
BigDecimal.valueOf(sharesIssued).multiply(unitPrice);
+        }
+
+        Integer accountingRule = 
this.fromApiJsonHelper.extractIntegerNamed(ShareProductApiConstants.accountingRuleParamName,
 element,
+                locale);
+        
baseDataValidator.reset().parameter(ShareProductApiConstants.accountingRuleParamName).value(accountingRule).notNull()
+                .integerGreaterThanZero();
+        AccountingRuleType accountingRuleType = null;
+        if (accountingRule != null) {
+            accountingRuleType = AccountingRuleType.fromInt(accountingRule);
+        }
+
+        Long minimumClientShares = 
this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.minimumshares_paramname,
 element);
+        Long nominalClientShares = 
this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.nominaltshares_paramname,
 element);
+        
baseDataValidator.reset().parameter(ShareProductApiConstants.nominaltshares_paramname).value(nominalClientShares).notNull()
+                .longGreaterThanZero();
+        if (minimumClientShares != null && nominalClientShares != null) {
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.nominaltshares_paramname).value(nominalClientShares)
+                    .longGreaterThanNumber(minimumClientShares);
+        }
+        Long maximumClientShares = 
this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.maximumshares_paramname,
 element);
+        if (maximumClientShares != null && nominalClientShares != null) {
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.maximumshares_paramname).value(maximumClientShares)
+                    .longGreaterThanNumber(nominalClientShares);
+        }
+
+        Set<ShareProductMarketPrice> marketPriceSet = 
asembleShareMarketPrice(element);
+        Set<Charge> charges = assembleListOfProductCharges(element, 
currencyCode);
+        Boolean allowdividendsForInactiveClients = 
this.fromApiJsonHelper.extractBooleanNamed(
+                
ShareProductApiConstants.allowdividendcalculationforinactiveclients_paramname, 
element);
+
+        Integer minimumActivePeriod = 
this.fromApiJsonHelper.extractIntegerNamed(
+                
ShareProductApiConstants.minimumactiveperiodfordividends_paramname, element, 
locale);
+        PeriodFrequencyType minimumActivePeriodType = extractPeriodType(
+                
ShareProductApiConstants.minimumactiveperiodfrequencytype_paramname, element);
+        if (minimumActivePeriod != null) {
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.minimumactiveperiodfrequencytype_paramname)
+                    
.value(minimumActivePeriodType.getValue()).integerSameAsNumber(PeriodFrequencyType.DAYS.getValue());
+        }
+
+        Integer lockinPeriod = 
this.fromApiJsonHelper.extractIntegerNamed(ShareProductApiConstants.lockperiod_paramname,
 element, locale);
+        PeriodFrequencyType lockPeriodType = 
extractPeriodType(ShareProductApiConstants.lockinperiodfrequencytype_paramname, 
element);
+
+        AppUser createdBy = platformSecurityContext.authenticatedUser();
+        AppUser modifiedBy = createdBy;
+        DateTime createdDate = 
DateUtils.getLocalDateTimeOfTenant().toDateTime();
+        DateTime modifiedOn = createdDate;
+        ShareProduct product = new ShareProduct(productName, shortName, 
description, externalId, currency, totalNumberOfShares,
+                sharesIssued, unitPrice, shareCapitalValue, 
minimumClientShares, nominalClientShares, maximumClientShares, marketPriceSet,
+                charges, allowdividendsForInactiveClients, lockinPeriod, 
lockPeriodType, minimumActivePeriod, minimumActivePeriodType,
+                createdBy, createdDate, modifiedBy, modifiedOn, 
accountingRuleType);
+        for (ShareProductMarketPrice data : marketPriceSet) {
+            data.setShareProduct(product);
+        }
+        if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
+        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<ShareProductMarketPriceData> 
asembleShareMarketPriceForUpdate(final JsonElement element) {
+        Set<ShareProductMarketPriceData> 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) {
+                Long id = 
this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.id_paramname, 
arrayElement);
+                LocalDate localDate = 
this.fromApiJsonHelper.extractLocalDateNamed(ShareProductApiConstants.startdate_paramname,
+                        arrayElement);
+                final BigDecimal shareValue = 
this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
+                        ShareProductApiConstants.sharevalue_paramname, 
arrayElement);
+                ShareProductMarketPriceData obj = new 
ShareProductMarketPriceData(id, localDate.toDate(), shareValue);
+                set.add(obj);
+            }
+        }
+        return set;
+    }
+
+    private Set<ShareProductMarketPrice> asembleShareMarketPrice(final 
JsonElement element) {
+        Set<ShareProductMarketPrice> 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);
+                ShareProductMarketPrice obj = new 
ShareProductMarketPrice(localDate.toDate(), shareValue);
+                set.add(obj);
+            }
+        }
+        return set;
+    }
+
+    private Set<Charge> assembleListOfProductCharges(final JsonElement 
element, final String currencyCode) {
+        final Set<Charge> 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 Share 
Product must have the same currency.";
+                            throw new InvalidCurrencyException("charge", 
"attach.to.share.product", errorMessage);
+                        }
+                        charges.add(charge);
+                    }
+                }
+            }
+        }
+        return charges;
+    }
+
+    public Map<String, Object> validateAndUpdate(JsonCommand jsonCommand, 
ShareProduct product) {
+        Map<String, Object> actualChanges = new HashMap<>();
+
+        if (StringUtils.isBlank(jsonCommand.json())) { throw new 
InvalidJsonException(); }
+        final Type typeOfMap = new TypeToken<Map<String, Object>>() 
{}.getType();
+        this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, 
jsonCommand.json(),
+                ShareProductApiConstants.supportedParametersForCreate);
+
+        final List<ApiParameterError> 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);
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.name_paramname).value(productName).notBlank();
+            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);
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.shortname_paramname).value(shortName).notBlank();
+            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);
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.externalid_paramname).value(externalId).notBlank();
+            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);
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.totalshares_paramname).value(totalShares).notNull()
+                    .longGreaterThanZero();
+            if (product.setTotalShares(totalShares)) {
+                
actualChanges.put(ShareProductApiConstants.totalshares_paramname, totalShares);
+            }
+        }
+        Long sharesIssued = null;
+        if 
(this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.totalsharesissued_paramname,
 element)) {
+            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);
+            }
+        }
+
+        BigDecimal unitPrice = null;
+        if 
(this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.unitprice_paramname,
 element)) {
+            unitPrice = 
this.fromApiJsonHelper.extractBigDecimalNamed(ShareProductApiConstants.unitprice_paramname,
 element, locale);
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.unitprice_paramname).value(unitPrice).notNull().positiveAmount();
+            if (product.setUnitPrice(unitPrice)) {
+                
actualChanges.put(ShareProductApiConstants.unitprice_paramname, unitPrice);
+            }
+        }
+
+        if 
(this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.accountingRuleParamName,
 element)) {
+            Integer accountingRule = 
this.fromApiJsonHelper.extractIntegerWithLocaleNamed(ShareProductApiConstants.accountingRuleParamName,
+                    element);
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.accountingRuleParamName).value(accountingRule).notNull()
+                    .integerGreaterThanZero();
+            if (product.setAccountingRule(accountingRule)) {
+                
actualChanges.put(ShareProductApiConstants.accountingRuleParamName, 
accountingRule);
+            }
+        }
+
+        if 
(this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.minimumshares_paramname,
 element)) {
+            Long minimumClientShares = 
this.fromApiJsonHelper.extractLongNamed(ShareProductApiConstants.minimumshares_paramname,
 element);
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.minimumshares_paramname).value(minimumClientShares).notNull()
+                    .longGreaterThanZero();
+            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);
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.nominaltshares_paramname).value(nominalClientShares).notNull()
+                    .longGreaterThanZero();
+            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);
+            
baseDataValidator.reset().parameter(ShareProductApiConstants.maximumshares_paramname).value(maximumClientShares).notNull()
+                    .longGreaterThanZero();
+            if (product.setMaximumShares(maximumClientShares)) {
+                
actualChanges.put(ShareProductApiConstants.maximumshares_paramname, 
maximumClientShares);
+            }
+        }
+
+        if 
(this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.marketprice_paramname,
 element)) {
+            Set<ShareProductMarketPriceData> marketPrice = 
asembleShareMarketPriceForUpdate(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<Charge> 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);
+            }
+        }
+
+        Integer minimumActivePeriod = null;
+
+        if 
(this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.minimumactiveperiodfordividends_paramname,
 element)) {
+            minimumActivePeriod = this.fromApiJsonHelper.extractIntegerNamed(
+                    
ShareProductApiConstants.minimumactiveperiodfordividends_paramname, element, 
locale);
+            if (product.setminimumActivePeriod(minimumActivePeriod)) {
+                
actualChanges.put(ShareProductApiConstants.minimumactiveperiodfordividends_paramname,
 minimumActivePeriod);
+            }
+        }
+
+        if 
(this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.minimumactiveperiodfrequencytype_paramname,
 element)) {
+            PeriodFrequencyType minimumActivePeriodType = extractPeriodType(
+                    
ShareProductApiConstants.minimumactiveperiodfrequencytype_paramname, element);
+            if (minimumActivePeriod != null) {
+                
baseDataValidator.reset().parameter(ShareProductApiConstants.minimumactiveperiodfrequencytype_paramname)
+                        
.value(minimumActivePeriodType.getValue()).integerSameAsNumber(PeriodFrequencyType.DAYS.getValue());
+            }
+            if 
(product.setminimumActivePeriodFrequencyType(minimumActivePeriodType)) {
+                
actualChanges.put(ShareProductApiConstants.minimumactiveperiodfrequencytype_paramname,
 minimumActivePeriodType);
+            }
+        }
+        final Integer lockinPeriod;
+        if 
(this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.lockperiod_paramname,
 element)) {
+            lockinPeriod = 
this.fromApiJsonHelper.extractIntegerNamed(ShareProductApiConstants.lockperiod_paramname,
 element, locale);
+            if (product.setLockinPeriod(lockinPeriod)) {
+                
actualChanges.put(ShareProductApiConstants.lockperiod_paramname, lockinPeriod);
+            }
+        }
+
+        if 
(this.fromApiJsonHelper.parameterExists(ShareProductApiConstants.lockinperiodfrequencytype_paramname,
 element)) {
+            PeriodFrequencyType lockPeriod = 
extractPeriodType(ShareProductApiConstants.lockinperiodfrequencytype_paramname, 
element);
+            if (product.setLockPeriodFrequencyType(lockPeriod)) {
+                
actualChanges.put(ShareProductApiConstants.lockinperiodfrequencytype_paramname, 
lockPeriod);
+            }
+        }
+
+        BigDecimal shareCapitalValue;
+        if (sharesIssued != null || unitPrice != null) {
+            if (sharesIssued == null) sharesIssued = product.getSharesIssued();
+            if (unitPrice == null) unitPrice = product.getUnitPrice();
+            shareCapitalValue = 
BigDecimal.valueOf(sharesIssued).multiply(unitPrice);
+            if (product.setshareCapitalValue(shareCapitalValue)) {
+                
actualChanges.put(ShareProductApiConstants.sharecapital_paramname, 
shareCapitalValue);
+            }
+        }
+
+        if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
+        return actualChanges;
+    }
+
+    public void validateDividendDetails(JsonCommand jsonCommand) {
+        if (StringUtils.isBlank(jsonCommand.json())) { throw new 
InvalidJsonException(); }
+        final Type typeOfMap = new TypeToken<Map<String, Object>>() 
{}.getType();
+        this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, 
jsonCommand.json(),
+                ShareProductApiConstants.supportedParametersForDivident);
+
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new 
DataValidatorBuilder(dataValidationErrors)
+                .resource("sharesproduct.dividend.processing");
+
+        JsonElement element = jsonCommand.parsedJson();
+
+        final LocalDate dividendPeriodStartDate = 
this.fromApiJsonHelper.extractLocalDateNamed(
+                ShareProductApiConstants.dividendPeriodStartDateParamName, 
element);
+        
baseDataValidator.reset().parameter(ShareProductApiConstants.dividendPeriodStartDateParamName).value(dividendPeriodStartDate)
+                .notBlank();
+
+        final LocalDate dividendPeriodEndDate = 
this.fromApiJsonHelper.extractLocalDateNamed(
+                ShareProductApiConstants.dividendPeriodEndDateParamName, 
element);
+        
baseDataValidator.reset().parameter(ShareProductApiConstants.dividendPeriodStartDateParamName).value(dividendPeriodEndDate)
+                .notBlank().validateDateAfter(dividendPeriodStartDate);
+        final BigDecimal dividendAmount = 
this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
+                ShareProductApiConstants.dividendAmountParamName, element);
+        
baseDataValidator.reset().parameter(ShareProductApiConstants.dividendAmountParamName).value(dividendAmount).notBlank()
+                .positiveAmount();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductCommandsServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductCommandsServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductCommandsServiceImpl.java
new file mode 100644
index 0000000..ee36863
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductCommandsServiceImpl.java
@@ -0,0 +1,59 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.service;
+
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.portfolio.products.service.ProductCommandsService;
+import 
org.apache.fineract.portfolio.shareproducts.constants.ShareProductApiConstants;
+import org.springframework.beans.factory.annotation.Autowired;
+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 CommandProcessingResult postDividends(Long productId, JsonCommand 
jsonCommand) {
+        return null ;
+    }
+
+    @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 null ;
+        } else if 
(ShareProductApiConstants.POST_DIVIDENdS_COMMAND_STRING.equals(command)) { 
return postDividends(productId,
+                jsonCommand); }
+        // throw unknow commandexception
+        return CommandProcessingResult.empty();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java
new file mode 100644
index 0000000..1ff71c7
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendAssembler.java
@@ -0,0 +1,131 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.service;
+
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
+import org.apache.fineract.organisation.monetary.domain.Money;
+import 
org.apache.fineract.portfolio.products.service.ProductReadPlatformService;
+import org.apache.fineract.portfolio.shareaccounts.data.PurchasedSharesData;
+import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountData;
+import 
org.apache.fineract.portfolio.shareaccounts.domain.PurchasedSharesStatusType;
+import 
org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountDividendDetails;
+import 
org.apache.fineract.portfolio.shareaccounts.service.ShareAccountReadPlatformService;
+import org.apache.fineract.portfolio.shareproducts.data.ShareProductData;
+import 
org.apache.fineract.portfolio.shareproducts.domain.ShareProductDividendPayOutDetails;
+import org.joda.time.Days;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ShareProductDividendAssembler {
+
+    private final ProductReadPlatformService shareProductReadPlatformService;
+    private final ShareAccountReadPlatformService 
ShareAccountReadPlatformService;
+
+    @Autowired
+    public ShareProductDividendAssembler(final 
ShareProductReadPlatformServiceImpl shareProductReadPlatformService,
+            final ShareAccountReadPlatformService 
ShareAccountReadPlatformService) {
+        this.shareProductReadPlatformService = shareProductReadPlatformService;
+        this.ShareAccountReadPlatformService = ShareAccountReadPlatformService;
+    }
+
+    public ShareProductDividendPayOutDetails calculateDividends(final Long 
productId, final BigDecimal amount,
+            final LocalDate dividendPeriodStartDate, final LocalDate 
dividendPeriodEndDate) {
+
+        ShareProductData product = (ShareProductData) 
this.shareProductReadPlatformService.retrieveOne(productId, false);
+        MonetaryCurrency currency = new 
MonetaryCurrency(product.getCurrency().code(), 
product.getCurrency().decimalPlaces(), product
+                .getCurrency().currencyInMultiplesOf());
+        Collection<ShareAccountData> shareAccountDatas = 
this.ShareAccountReadPlatformService.retrieveAllShareAccountDataForDividends(
+                productId, 
product.getAllowDividendCalculationForInactiveClients(), 
dividendPeriodStartDate);
+        ShareProductDividendPayOutDetails productDividendPayOutDetails = null;
+        final int minimumActivePeriod = product.getMinimumActivePeriod();
+        final Map<Long, Long> numberOfSharesdaysPerAccount = new HashMap<>();
+        long numberOfShareDays = 
calculateNumberOfShareDays(dividendPeriodEndDate, dividendPeriodStartDate, 
minimumActivePeriod,
+                shareAccountDatas, numberOfSharesdaysPerAccount);
+
+        if (numberOfShareDays > 0) {
+            double amountPerShareDay = amount.doubleValue() / 
numberOfShareDays;
+            productDividendPayOutDetails = new 
ShareProductDividendPayOutDetails(productId, Money.of(currency, 
amount).getAmount(),
+                    dividendPeriodStartDate.toDate(), 
dividendPeriodEndDate.toDate());
+            for (ShareAccountData accountData : shareAccountDatas) {
+                long numberOfShareDaysPerAccount = 
numberOfSharesdaysPerAccount.get(accountData.getId());
+                double amountForAccount = numberOfShareDaysPerAccount * 
amountPerShareDay;
+                final Money accountAmount = Money.of(currency, 
BigDecimal.valueOf(amountForAccount));
+                ShareAccountDividendDetails dividendDetails = new 
ShareAccountDividendDetails(accountData.getId(),
+                        accountAmount.getAmount());
+                
productDividendPayOutDetails.getAccountDividendDetails().add(dividendDetails);
+            }
+        }
+
+        return productDividendPayOutDetails;
+    }
+
+    private long calculateNumberOfShareDays(final LocalDate postingDate, final 
LocalDate lastDividendPostDate,
+            final int minimumActivePeriod, final Collection<ShareAccountData> 
shareAccountDatas,
+            final Map<Long, Long> numberOfSharesdaysPerAccount) {
+        long numberOfShareDays = 0;
+        for (ShareAccountData accountData : shareAccountDatas) {
+            long numberOfShareDaysPerAccount = 0;
+            Collection<PurchasedSharesData> purchasedShares = 
accountData.getPurchasedShares();
+            long numberOfShares = 0;
+            LocalDate lastDividendAppliedDate = null;
+            for (PurchasedSharesData purchasedSharesData : purchasedShares) {
+                final PurchasedSharesStatusType status = 
PurchasedSharesStatusType.fromInt(purchasedSharesData.getStatus().getId()
+                        .intValue());
+                final PurchasedSharesStatusType type = 
PurchasedSharesStatusType.fromInt(purchasedSharesData.getType().getId()
+                        .intValue());
+                if (status.isApproved() && !type.isChargePayment()) {
+                    
+                    LocalDate shareStartDate = 
purchasedSharesData.getPurchasedDate();
+                    if (shareStartDate.isBefore(lastDividendPostDate)) {
+                        shareStartDate = lastDividendPostDate;
+                    }
+                    int numberOfPurchseDays = Days.daysBetween(shareStartDate, 
postingDate).getDays();
+                    if (type.isPurchased() && numberOfPurchseDays < 
minimumActivePeriod) {
+                        continue;
+                    }
+
+                    if (lastDividendAppliedDate != null) {
+                        numberOfShareDaysPerAccount += 
(Days.daysBetween(lastDividendAppliedDate, shareStartDate).getDays() * 
numberOfShares);
+                    }
+                    lastDividendAppliedDate = shareStartDate;
+                    if (type.isPurchased()) {
+                        numberOfShares += 
purchasedSharesData.getNumberOfShares();
+                    } else {
+                        numberOfShares -= 
purchasedSharesData.getNumberOfShares();
+                    }
+
+                }
+            }
+            if (lastDividendAppliedDate != null) {
+                numberOfShareDaysPerAccount += 
(Days.daysBetween(lastDividendAppliedDate, postingDate).getDays() * 
numberOfShares);
+            }
+            numberOfShareDays += numberOfShareDaysPerAccount;
+            numberOfSharesdaysPerAccount.put(accountData.getId(), 
numberOfShareDaysPerAccount);
+        }
+        return numberOfShareDays;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendReadPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendReadPlatformService.java
new file mode 100644
index 0000000..18eba3a
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendReadPlatformService.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.service;
+
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import 
org.apache.fineract.portfolio.shareproducts.data.ShareProductDividendPayOutData;
+
+public interface ShareProductDividendReadPlatformService {
+
+    Page<ShareProductDividendPayOutData> retriveAll(Long productId, Integer 
status, SearchParameters searchParameters);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendReadPlatformServiceImpl.java
new file mode 100644
index 0000000..6760ef9
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDividendReadPlatformServiceImpl.java
@@ -0,0 +1,128 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.service;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.PaginationHelper;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import 
org.apache.fineract.portfolio.shareaccounts.data.ShareAccountDividendData;
+import org.apache.fineract.portfolio.shareaccounts.service.SharesEnumerations;
+import 
org.apache.fineract.portfolio.shareproducts.data.ShareProductDividendPayOutData;
+import org.apache.fineract.portfolio.shareproducts.data.ShareProductData;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ShareProductDividendReadPlatformServiceImpl implements 
ShareProductDividendReadPlatformService {
+
+    private final JdbcTemplate jdbcTemplate;
+    private final PaginationHelper<ShareProductDividendPayOutData> 
paginationHelper = new PaginationHelper<>();
+
+    @Autowired
+    public ShareProductDividendReadPlatformServiceImpl(final RoutingDataSource 
dataSource) {
+        this.jdbcTemplate = new JdbcTemplate(dataSource);
+    }
+
+    @Override
+    public Page<ShareProductDividendPayOutData> retriveAll(final Long 
productId, final Integer status,
+            final SearchParameters searchParameters) {
+        ShareProductDividendMapper shareProductDividendMapper = new 
ShareProductDividendMapper();
+        final StringBuilder sqlBuilder = new StringBuilder(200);
+        sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+        sqlBuilder.append(shareProductDividendMapper.schema());
+        sqlBuilder.append(" where sp.id = ? ");
+        List<Object> params = new ArrayList<>(2);
+        params.add(productId);
+        if (status != null) {
+            sqlBuilder.append(" and pod.status = ?");
+            params.add(status);
+        }
+        if (searchParameters.isOrderByRequested()) {
+            sqlBuilder.append(" order by 
").append(searchParameters.getOrderBy());
+
+            if (searchParameters.isSortOrderProvided()) {
+                sqlBuilder.append(' ').append(searchParameters.getSortOrder());
+            }
+        }
+
+        if (searchParameters.isLimited()) {
+            sqlBuilder.append(" limit ").append(searchParameters.getLimit());
+            if (searchParameters.isOffset()) {
+                sqlBuilder.append(" offset 
").append(searchParameters.getOffset());
+            }
+        }
+
+        final String sqlCountRows = "SELECT FOUND_ROWS()";
+        Object[] paramsObj = params.toArray();
+        return this.paginationHelper.fetchPage(this.jdbcTemplate, 
sqlCountRows, sqlBuilder.toString(), paramsObj,
+                shareProductDividendMapper);
+    }
+
+    private static final class ShareProductDividendMapper implements 
RowMapper<ShareProductDividendPayOutData> {
+
+        private final String sql;
+
+        public ShareProductDividendMapper() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(" pod.id as id, pod.amount as amount,");
+            sb.append(" pod.status as status, pod.dividend_period_start_date 
as startDate,");
+            sb.append(" pod.dividend_period_end_date as endDate,");
+            sb.append(" sp.id as productId,sp.name as productName ");
+            sb.append(" from m_share_product_dividend_pay_out pod");
+            sb.append(" inner join m_share_product sp on sp.id = 
pod.product_id ");
+            sql = sb.toString();
+        }
+
+        public String schema() {
+            return this.sql;
+        }
+
+        @Override
+        public ShareProductDividendPayOutData mapRow(ResultSet rs, 
@SuppressWarnings("unused") int rowNum) throws SQLException {
+            final Long id = rs.getLong("id");
+            final BigDecimal amount = rs.getBigDecimal("amount");
+            final Integer status = JdbcSupport.getInteger(rs, "status");
+            final EnumOptionData statusEnum = 
SharesEnumerations.ShareProductDividendStatusEnum(status);
+            final LocalDate startDate = JdbcSupport.getLocalDate(rs, 
"startDate");
+            final LocalDate endDate = JdbcSupport.getLocalDate(rs, "endDate");
+
+            final Long productId = rs.getLong("productId");
+            final String productName = rs.getString("productName");
+
+            final ShareProductData productData = 
ShareProductData.lookup(productId, productName);
+            final Collection<ShareAccountDividendData> accountDividendsData = 
null;
+            return new ShareProductDividendPayOutData(id, productData, amount, 
startDate, endDate, accountDividendsData, statusEnum);
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDropdownReadPlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDropdownReadPlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDropdownReadPlatformService.java
new file mode 100644
index 0000000..ae3f98f
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDropdownReadPlatformService.java
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.service;
+
+import java.util.Collection;
+
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+
+public interface ShareProductDropdownReadPlatformService {
+
+       Collection<EnumOptionData> retrieveLockinPeriodFrequencyTypeOptions();
+       
+       Collection<EnumOptionData> 
retrieveMinimumActivePeriodFrequencyTypeOptions() ;
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDropdownReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDropdownReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDropdownReadPlatformServiceImpl.java
new file mode 100644
index 0000000..c7c7b80
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductDropdownReadPlatformServiceImpl.java
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.service;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.portfolio.shareaccounts.service.SharesEnumerations;
+import org.apache.fineract.portfolio.shareproducts.SharePeriodFrequencyType;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ShareProductDropdownReadPlatformServiceImpl implements 
ShareProductDropdownReadPlatformService {
+
+    @Override
+    public Collection<EnumOptionData> 
retrieveLockinPeriodFrequencyTypeOptions() {
+        final List<EnumOptionData> allowedLockinPeriodFrequencyTypeOptions = 
Arrays.asList( //
+                
SharesEnumerations.lockinPeriodFrequencyType(SharePeriodFrequencyType.DAYS), //
+                
SharesEnumerations.lockinPeriodFrequencyType(SharePeriodFrequencyType.WEEKS), //
+                
SharesEnumerations.lockinPeriodFrequencyType(SharePeriodFrequencyType.MONTHS), 
//
+                
SharesEnumerations.lockinPeriodFrequencyType(SharePeriodFrequencyType.YEARS) //
+                );
+
+        return allowedLockinPeriodFrequencyTypeOptions;
+    }
+
+    @Override
+    public Collection<EnumOptionData> 
retrieveMinimumActivePeriodFrequencyTypeOptions() {
+        final List<EnumOptionData> minimumActivePeriodFrequencyTypeOptions = 
Arrays.asList( //
+                
SharesEnumerations.lockinPeriodFrequencyType(SharePeriodFrequencyType.DAYS) //
+                );
+
+        return minimumActivePeriodFrequencyTypeOptions;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductReadPlatformServiceImpl.java
new file mode 100644
index 0000000..cd3b42e
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductReadPlatformServiceImpl.java
@@ -0,0 +1,283 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.service;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import 
org.apache.fineract.accounting.common.AccountingDropdownReadPlatformService;
+import org.apache.fineract.accounting.common.AccountingEnumerations;
+import org.apache.fineract.accounting.glaccount.data.GLAccountData;
+import 
org.apache.fineract.accounting.producttoaccountmapping.data.ChargeToGLAccountMapper;
+import 
org.apache.fineract.accounting.producttoaccountmapping.data.PaymentTypeToGLAccountMapper;
+import 
org.apache.fineract.accounting.producttoaccountmapping.service.ProductToGLAccountMappingReadPlatformService;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.PaginationHelper;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import 
org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService;
+import org.apache.fineract.portfolio.charge.data.ChargeData;
+import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
+import org.apache.fineract.portfolio.products.data.ProductData;
+import 
org.apache.fineract.portfolio.products.exception.ProductNotFoundException;
+import 
org.apache.fineract.portfolio.products.service.ProductReadPlatformService;
+import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
+import 
org.apache.fineract.portfolio.shareproducts.data.ShareProductMarketPriceData;
+import org.apache.fineract.portfolio.shareproducts.data.ShareProductData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Service;
+
+@Service(value = "shareReadPlatformService")
+public class ShareProductReadPlatformServiceImpl implements 
ProductReadPlatformService {
+
+    private final JdbcTemplate jdbcTemplate;
+    private final CurrencyReadPlatformService currencyReadPlatformService;
+    private final ChargeReadPlatformService chargeReadPlatformService;
+    private final ShareProductDropdownReadPlatformService 
shareProductDropdownReadPlatformService;
+    private final AccountingDropdownReadPlatformService 
accountingDropdownReadPlatformService;
+    private final ProductToGLAccountMappingReadPlatformService 
accountMappingReadPlatformService;
+    private final PaginationHelper<ProductData> 
provisioningEntryDataPaginationHelper = new PaginationHelper<>();
+
+    @Autowired
+    public ShareProductReadPlatformServiceImpl(final RoutingDataSource 
dataSource,
+            final CurrencyReadPlatformService currencyReadPlatformService, 
final ChargeReadPlatformService chargeReadPlatformService,
+            final ShareProductDropdownReadPlatformService 
shareProductDropdownReadPlatformService,
+            final AccountingDropdownReadPlatformService 
accountingDropdownReadPlatformService,
+            final ProductToGLAccountMappingReadPlatformService 
accountMappingReadPlatformService) {
+        this.jdbcTemplate = new JdbcTemplate(dataSource);
+        this.currencyReadPlatformService = currencyReadPlatformService;
+        this.chargeReadPlatformService = chargeReadPlatformService;
+        this.shareProductDropdownReadPlatformService = 
shareProductDropdownReadPlatformService;
+        this.accountingDropdownReadPlatformService = 
accountingDropdownReadPlatformService;
+        this.accountMappingReadPlatformService = 
accountMappingReadPlatformService;
+    }
+
+    @Override
+    public Page<ProductData> retrieveAllProducts(Integer offSet, Integer 
limit) {
+        AllShareProductRowMapper mapper = new AllShareProductRowMapper();
+        StringBuilder sqlBuilder = new StringBuilder();
+        sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+        sqlBuilder.append(mapper.schema());
+        if (limit != null) {
+            sqlBuilder.append(" limit ").append(limit);
+        }
+        if (offSet != null) {
+            sqlBuilder.append(" offset ").append(offSet);
+        }
+
+        final String sqlCountRows = "SELECT FOUND_ROWS()";
+        Object[] whereClauseItemsitems = new Object[] {};
+        return 
this.provisioningEntryDataPaginationHelper.fetchPage(this.jdbcTemplate, 
sqlCountRows, sqlBuilder.toString(),
+                whereClauseItemsitems, mapper);
+    }
+
+    @Override
+    public ProductData retrieveOne(Long productId, boolean includeTemplate) {
+        MarketPriceRowMapper marketRowMapper = new MarketPriceRowMapper();
+
+        try {
+            final String sql1 = "select " + marketRowMapper.schema() + " where 
marketData.product_id = ?";
+            final Collection<ShareProductMarketPriceData> 
shareMarketCollection = this.jdbcTemplate.query(sql1, marketRowMapper,
+                    new Object[] { productId });
+            final Collection<ChargeData> charges = 
this.chargeReadPlatformService.retrieveShareProductCharges(productId);
+            ShareProductRowMapper mapper = new 
ShareProductRowMapper(shareMarketCollection, charges);
+            final String sql = "select " + mapper.schema() + " where 
shareproduct.id = ?";
+            ShareProductData data = (ShareProductData) 
this.jdbcTemplate.queryForObject(sql, mapper, new Object[] { productId });
+
+            if (data.hasAccountingEnabled()) {
+                final Map<String, Object> accountingMappings = 
this.accountMappingReadPlatformService
+                        .fetchAccountMappingDetailsForShareProduct(productId, 
data.accountingRuleTypeId());
+                final Collection<PaymentTypeToGLAccountMapper> 
paymentChannelToFundSourceMappings = this.accountMappingReadPlatformService
+                        
.fetchPaymentTypeToFundSourceMappingsForShareProduct(productId);
+                Collection<ChargeToGLAccountMapper> feeToGLAccountMappings = 
this.accountMappingReadPlatformService
+                        
.fetchFeeToIncomeAccountMappingsForShareProduct(productId);
+                data = ShareProductData.withAccountingDetails(data, 
accountingMappings, paymentChannelToFundSourceMappings,
+                        feeToGLAccountMappings);
+            }
+
+            if (includeTemplate) {
+                Collection<ChargeData> chargeOptions = 
this.chargeReadPlatformService.retrieveSharesApplicableCharges();
+                final Collection<CurrencyData> currencyOptions = 
this.currencyReadPlatformService.retrieveAllowedCurrencies();
+                final Collection<EnumOptionData> 
lockinPeriodFrequencyTypeOptions = this.shareProductDropdownReadPlatformService
+                        .retrieveLockinPeriodFrequencyTypeOptions();
+                final Collection<EnumOptionData> 
minimumActivePeriodFrequencyTypeOptions = 
this.shareProductDropdownReadPlatformService
+                        .retrieveMinimumActivePeriodFrequencyTypeOptions();
+                final Map<String, List<GLAccountData>> 
accountingMappingOptions = this.accountingDropdownReadPlatformService
+                        .retrieveAccountMappingOptionsForShareProducts();
+                data = ShareProductData.template(data, currencyOptions, 
chargeOptions, minimumActivePeriodFrequencyTypeOptions,
+                        lockinPeriodFrequencyTypeOptions, 
accountingMappingOptions);
+            }
+            return data;
+        } catch (final EmptyResultDataAccessException e) {
+            throw new ProductNotFoundException(productId, "share");
+        }
+    }
+
+    @Override
+    public ProductData retrieveTemplate() {
+        Collection<ChargeData> chargeOptions = 
this.chargeReadPlatformService.retrieveSharesApplicableCharges();
+        final Collection<CurrencyData> currencyOptions = 
this.currencyReadPlatformService.retrieveAllowedCurrencies();
+        final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = 
this.shareProductDropdownReadPlatformService
+                .retrieveLockinPeriodFrequencyTypeOptions();
+        final Collection<EnumOptionData> 
minimumActivePeriodFrequencyTypeOptions = 
this.shareProductDropdownReadPlatformService
+                .retrieveMinimumActivePeriodFrequencyTypeOptions();
+        final Map<String, List<GLAccountData>> accountingMappingOptions = 
this.accountingDropdownReadPlatformService
+                .retrieveAccountMappingOptionsForShareProducts();
+        return ShareProductData.template(currencyOptions, chargeOptions, 
minimumActivePeriodFrequencyTypeOptions,
+                lockinPeriodFrequencyTypeOptions, accountingMappingOptions);
+    }
+
+    @Override
+    public Collection<ProductData> retrieveAllForLookup() {
+        AllShareProductRowMapper mapper = new AllShareProductRowMapper();
+        String sql = "select " + mapper.schema();
+        return this.jdbcTemplate.query(sql, mapper, new Object[] {});
+    }
+
+    @Override
+    public Set<String> getResponseDataParams() {
+        return null;
+    }
+
+    private static final class AllShareProductRowMapper implements 
RowMapper<ProductData> {
+
+        @Override
+        public ShareProductData mapRow(ResultSet rs, int rowNum) throws 
SQLException {
+            final Long id = rs.getLong("id");
+            final String name = rs.getString("name");
+            final String shortName = rs.getString("short_name");
+            final Long totalShares = rs.getLong("total_shares");
+            return ShareProductData.generic(id, name, shortName, totalShares);
+        }
+
+        public String schema() {
+            return "shareproduct.id, shareproduct.name, 
shareproduct.short_name, shareproduct.total_shares from m_share_product 
shareproduct";
+        }
+    }
+
+    private static final class MarketPriceRowMapper implements 
RowMapper<ShareProductMarketPriceData> {
+
+        @Override
+        public ShareProductMarketPriceData mapRow(ResultSet rs, int rowNum) 
throws SQLException {
+            final Long id = rs.getLong("id");
+            final Date fromDate = rs.getDate("from_date");
+            final BigDecimal shareValue = rs.getBigDecimal("share_value");
+            return new ShareProductMarketPriceData(id, fromDate, shareValue);
+        }
+
+        public String schema() {
+            return "marketData.id, marketData.from_date, 
marketData.share_value from m_share_product_market_price marketData";
+        }
+    }
+
+    private final static class ShareProductRowMapper implements 
RowMapper<ProductData> {
+
+        Collection<ShareProductMarketPriceData> shareMarketCollection;
+        Collection<ChargeData> charges;
+        private StringBuffer buff = new StringBuffer();
+
+        ShareProductRowMapper(Collection<ShareProductMarketPriceData> 
shareMarketCollection, Collection<ChargeData> charges) {
+            this.shareMarketCollection = shareMarketCollection;
+            this.charges = charges;
+            buff.append("shareproduct.id, shareproduct.name, 
shareproduct.short_name, ")
+                    .append("shareproduct.external_id, 
shareproduct.description, shareproduct.start_date,")
+                    .append("shareproduct.end_date, 
shareproduct.currency_code, shareproduct.currency_digits, ")
+                    .append("shareproduct.currency_multiplesof, 
shareproduct.total_shares, shareproduct.issued_shares, ")
+                    .append("shareproduct.unit_price, 
shareproduct.capital_amount,  ")
+                    .append("shareproduct.accounting_type as accountingType, ")
+                    .append("shareproduct.minimum_client_shares, 
shareproduct.nominal_client_shares, ")
+                    .append("shareproduct.maximum_client_shares, 
shareproduct.minimum_active_period_frequency, ")
+                    
.append("shareproduct.minimum_active_period_frequency_enum, 
shareproduct.lockin_period_frequency, ")
+                    .append("shareproduct.lockin_period_frequency_enum, 
shareproduct.allow_dividends_inactive_clients, ")
+                    .append("shareproduct.createdby_id, created.username as 
createdName, modified.username as modifiedName, ")
+                    .append("shareproduct.created_date, 
shareproduct.lastmodifiedby_id, shareproduct.lastmodified_date, ")
+                    .append("curr.name as currencyName, 
curr.internationalized_name_code as currencyNameCode, ")
+                    .append("curr.display_symbol as currencyDisplaySymbol 
").append("from m_share_product shareproduct ")
+                    .append("LEFT JOIN m_currency curr on curr.code = 
shareproduct.currency_code ")
+                    .append("LEFT JOIN m_appuser created ON created.id = 
shareproduct.createdby_id ")
+                    .append("LEFT JOIN m_appuser modified ON modified.id = 
shareproduct.lastmodifiedby_id ");
+
+        }
+
+        @Override
+        public ShareProductData mapRow(ResultSet rs, int rowNum) throws 
SQLException {
+            final Long id = rs.getLong("id");
+            final String name = rs.getString("name");
+            final String shortName = rs.getString("short_name");
+            final String externalId = rs.getString("external_id");
+            final String description = rs.getString("description");
+            final String currencyCode = rs.getString("currency_code");
+            final Integer currencyDigits = rs.getInt("currency_digits");
+            final String currencyName = rs.getString("currencyName");
+            final String currencyNameCode = rs.getString("currencyNameCode");
+            final String currencyDisplaySymbol = 
rs.getString("currencyDisplaySymbol");
+            final Integer inMultiplesOf = JdbcSupport.getInteger(rs, 
"currency_multiplesof");
+            final CurrencyData currency = new CurrencyData(currencyCode, 
currencyName, currencyDigits, inMultiplesOf,
+                    currencyDisplaySymbol, currencyNameCode);
+
+            final Long totalShares = rs.getLong("total_shares");
+            final Long issuedShares = rs.getLong("issued_shares");
+            final BigDecimal unitPrice = rs.getBigDecimal("unit_price");
+            final BigDecimal capitalAmount = 
rs.getBigDecimal("capital_amount");
+            final Long minimumClientShares = JdbcSupport.getLong(rs, 
"minimum_client_shares");
+            final Long nominalClientShares = JdbcSupport.getLong(rs, 
"nominal_client_shares");
+            final Long maximumClientShares = JdbcSupport.getLong(rs, 
"maximum_client_shares");
+            final Boolean allowDividendsForInactiveClients = 
rs.getBoolean("allow_dividends_inactive_clients");
+            // final Long createdById = rs.getLong("createdby_id") ;
+            // final Date createdDate = rs.getDate("created_date") ;
+            // final Long modifiedById = rs.getLong("lastmodifiedby_id") ;
+            // final Date modifiedDate = rs.getDate("lastmodified_date") ;
+            final Integer minimumActivePeriod = JdbcSupport.getInteger(rs, 
"minimum_active_period_frequency");
+            final Integer minimumActviePeriodEnumValue = 
JdbcSupport.getInteger(rs, "minimum_active_period_frequency_enum");
+            EnumOptionData minimumActivePeriodType = null;
+            if (minimumActviePeriodEnumValue != null) {
+                minimumActivePeriodType = 
SavingsEnumerations.lockinPeriodFrequencyType(minimumActviePeriodEnumValue);
+            }
+
+            final Integer lockinPeriodFrequency = JdbcSupport.getInteger(rs, 
"lockin_period_frequency");
+            EnumOptionData lockinPeriodFrequencyType = null;
+            final Integer lockinPeriodFrequencyTypeValue = 
JdbcSupport.getInteger(rs, "lockin_period_frequency_enum");
+            if (lockinPeriodFrequencyTypeValue != null) {
+                lockinPeriodFrequencyType = 
SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodFrequencyTypeValue);
+            }
+            final Integer accountingRuleId = JdbcSupport.getInteger(rs, 
"accountingType");
+            final EnumOptionData accountingRuleType = 
AccountingEnumerations.accountingRuleType(accountingRuleId);
+
+            return ShareProductData.data(id, name, shortName, description, 
externalId, currency, totalShares, issuedShares, unitPrice,
+                    capitalAmount, minimumClientShares, nominalClientShares, 
maximumClientShares, shareMarketCollection, charges,
+                    allowDividendsForInactiveClients, lockinPeriodFrequency, 
lockinPeriodFrequencyType, minimumActivePeriod,
+                    minimumActivePeriodType, accountingRuleType);
+        }
+
+        public String schema() {
+            return this.buff.toString();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformService.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformService.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformService.java
new file mode 100644
index 0000000..7bb8111
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformService.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.service;
+
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+
+public interface ShareProductWritePlatformService {
+
+    CommandProcessingResult createShareProduct(JsonCommand jsonCommand);
+
+    CommandProcessingResult updateProduct(Long productId, JsonCommand command);
+
+    CommandProcessingResult createShareProductDividend(Long productId, 
JsonCommand jsonCommand);
+
+    CommandProcessingResult approveShareProductDividend(Long PayOutDetailId);
+
+    CommandProcessingResult deleteShareProductDividend(Long PayOutDetailId);
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java
new file mode 100644
index 0000000..e9aaac7
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/service/ShareProductWritePlatformServiceJpaRepositoryImpl.java
@@ -0,0 +1,190 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.shareproducts.service;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+import 
org.apache.fineract.accounting.producttoaccountmapping.service.ProductToGLAccountMappingWritePlatformService;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import 
org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
+import 
org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import 
org.apache.fineract.portfolio.shareproducts.constants.ShareProductApiConstants;
+import org.apache.fineract.portfolio.shareproducts.domain.ShareProduct;
+import 
org.apache.fineract.portfolio.shareproducts.domain.ShareProductDividendPayOutDetails;
+import 
org.apache.fineract.portfolio.shareproducts.domain.ShareProductDividentPayOutDetailsRepositoryWrapper;
+import 
org.apache.fineract.portfolio.shareproducts.domain.ShareProductRepositoryWrapper;
+import 
org.apache.fineract.portfolio.shareproducts.exception.DividentProcessingException;
+import 
org.apache.fineract.portfolio.shareproducts.serialization.ShareProductDataSerializer;
+import org.joda.time.LocalDate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.stereotype.Service;
+
+import com.google.gson.JsonElement;
+
+@Service
+public class ShareProductWritePlatformServiceJpaRepositoryImpl implements 
ShareProductWritePlatformService {
+
+    private final ShareProductRepositoryWrapper repository;
+    private final ShareProductDataSerializer serializer;
+    private final FromJsonHelper fromApiJsonHelper;
+    private final ShareProductDividentPayOutDetailsRepositoryWrapper 
shareProductDividentPayOutDetailsRepository;
+    private final ShareProductDividendAssembler shareProductDividendAssembler;
+    private final ProductToGLAccountMappingWritePlatformService 
accountMappingWritePlatformService;
+
+    @Autowired
+    public ShareProductWritePlatformServiceJpaRepositoryImpl(final 
ShareProductRepositoryWrapper repository,
+            final ShareProductDataSerializer serializer, final FromJsonHelper 
fromApiJsonHelper,
+            final ShareProductDividentPayOutDetailsRepositoryWrapper 
shareProductDividentPayOutDetailsRepositor,
+            final ShareProductDividendAssembler shareProductDividendAssembler,
+            final ProductToGLAccountMappingWritePlatformService 
accountMappingWritePlatformService) {
+        this.repository = repository;
+        this.serializer = serializer;
+        this.fromApiJsonHelper = fromApiJsonHelper;
+        this.shareProductDividentPayOutDetailsRepository = 
shareProductDividentPayOutDetailsRepositor;
+        this.shareProductDividendAssembler = shareProductDividendAssembler;
+        this.accountMappingWritePlatformService = 
accountMappingWritePlatformService;
+    }
+
+    @Override
+    public CommandProcessingResult createShareProduct(JsonCommand jsonCommand) 
{
+        try {
+            ShareProduct product = 
this.serializer.validateAndCreate(jsonCommand);
+            this.repository.save(product);
+
+            // save accounting mappings
+            
this.accountMappingWritePlatformService.createShareProductToGLAccountMapping(product.getId(),
 jsonCommand);
+
+            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.findOneWithNotFoundDetection(productId);
+            final Map<String, Object> changes = 
this.serializer.validateAndUpdate(jsonCommand, product);
+
+            // accounting related changes
+            final boolean accountingTypeChanged = 
changes.containsKey(ShareProductApiConstants.accountingRuleParamName);
+            final Map<String, Object> accountingMappingChanges = 
this.accountMappingWritePlatformService
+                    .updateShareProductToGLAccountMapping(product.getId(), 
jsonCommand, accountingTypeChanged, product.getAccountingType());
+            changes.putAll(accountingMappingChanges);
+
+            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();
+        }
+    }
+
+    @Override
+    public CommandProcessingResult createShareProductDividend(final Long 
productId, final JsonCommand jsonCommand) {
+        try {
+            this.serializer.validateDividendDetails(jsonCommand);
+            JsonElement element = jsonCommand.parsedJson();
+            final LocalDate dividendPeriodStartDate = 
this.fromApiJsonHelper.extractLocalDateNamed(
+                    ShareProductApiConstants.dividendPeriodStartDateParamName, 
element);
+            final LocalDate dividendPeriodEndDate = 
this.fromApiJsonHelper.extractLocalDateNamed(
+                    ShareProductApiConstants.dividendPeriodEndDateParamName, 
element);
+            final BigDecimal dividendAmount = 
this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(
+                    ShareProductApiConstants.dividendAmountParamName, element);
+
+            final ShareProductDividendPayOutDetails dividendPayOutDetails = 
this.shareProductDividendAssembler.calculateDividends(
+                    productId, dividendAmount, dividendPeriodStartDate, 
dividendPeriodEndDate);
+            if (dividendPayOutDetails == null) { throw new 
DividentProcessingException("eligible.shares.not.found",
+                    "No eligible shares for creating dividends"); }
+            
this.shareProductDividentPayOutDetailsRepository.save(dividendPayOutDetails);
+
+            return new CommandProcessingResultBuilder() //
+                    .withCommandId(jsonCommand.commandId()) //
+                    .withEntityId(productId) //
+                    .withSubEntityId(dividendPayOutDetails.getId())//
+                    .build();
+        } catch (DataIntegrityViolationException dve) {
+            handleDataIntegrityIssues(jsonCommand, dve);
+            return CommandProcessingResult.empty();
+        }
+    }
+
+    @Override
+    public CommandProcessingResult approveShareProductDividend(final Long 
PayOutDetailId) {
+        try {
+            ShareProductDividendPayOutDetails dividendPayOutDetails = 
this.shareProductDividentPayOutDetailsRepository
+                    .findOneWithNotFoundDetection(PayOutDetailId);
+            if (dividendPayOutDetails.getStatus().isApproved()) { throw new 
DividentProcessingException("alreay.approved",
+                    "Can't approve already appoved  dividends "); }
+            dividendPayOutDetails.approveDividendPayout();
+            
this.shareProductDividentPayOutDetailsRepository.save(dividendPayOutDetails);
+            return new CommandProcessingResultBuilder() //
+                    .withEntityId(PayOutDetailId) //
+                    .build();
+        } catch (DataIntegrityViolationException dve) {
+            handleDataIntegrityIssues(dve);
+            return CommandProcessingResult.empty();
+        }
+    }
+
+    @Override
+    public CommandProcessingResult deleteShareProductDividend(final Long 
PayOutDetailId) {
+        try {
+            ShareProductDividendPayOutDetails dividendPayOutDetails = 
this.shareProductDividentPayOutDetailsRepository
+                    .findOneWithNotFoundDetection(PayOutDetailId);
+            if (dividendPayOutDetails.getStatus().isApproved()) { throw new 
DividentProcessingException("alreay.approved",
+                    "Can't delete already appoved  dividends "); }
+            
this.shareProductDividentPayOutDetailsRepository.delete(dividendPayOutDetails);
+            return new CommandProcessingResultBuilder() //
+                    .withEntityId(PayOutDetailId) //
+                    .build();
+        } catch (DataIntegrityViolationException dve) {
+            handleDataIntegrityIssues(dve);
+            return CommandProcessingResult.empty();
+        }
+    }
+
+    private void handleDataIntegrityIssues(final 
DataIntegrityViolationException dve) {
+        final Throwable realCause = dve.getMostSpecificCause();
+        throw new 
PlatformDataIntegrityException("error.msg.glClosure.unknown.data.integrity.issue",
+                "Unknown data integrity issue with resource GL Closure: " + 
realCause.getMessage());
+    }
+
+    private void handleDataIntegrityIssues(@SuppressWarnings("unused") final 
JsonCommand command, final DataIntegrityViolationException dve) {
+        final Throwable realCause = dve.getMostSpecificCause();
+        throw new 
PlatformDataIntegrityException("error.msg.glClosure.unknown.data.integrity.issue",
+                "Unknown data integrity issue with resource GL Closure: " + 
realCause.getMessage());
+    }
+
+}

Reply via email to