fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From raj...@apache.org
Subject [06/12] incubator-fineract git commit: Shares And Dividends Implementation
Date Wed, 13 Apr 2016 14:35:18 GMT
http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/serialization/ShareAccountDataSerializer.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/serialization/ShareAccountDataSerializer.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/serialization/ShareAccountDataSerializer.java
new file mode 100644
index 0000000..13c7b4d
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/serialization/ShareAccountDataSerializer.java
@@ -0,0 +1,741 @@
+/**
+ * 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.shareaccounts.serialization;
+
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+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.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.organisation.monetary.domain.Money;
+import org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
+import org.apache.fineract.portfolio.charge.domain.Charge;
+import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
+import org.apache.fineract.portfolio.charge.domain.ChargeRepositoryWrapper;
+import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
+import org.apache.fineract.portfolio.client.domain.Client;
+import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
+import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
+import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException;
+import org.apache.fineract.portfolio.savings.SavingsApiConstants;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccount;
+import org.apache.fineract.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
+import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccount;
+import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountCharge;
+import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountChargePaidBy;
+import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountTransaction;
+import org.apache.fineract.portfolio.shareproducts.domain.ShareProduct;
+import org.apache.fineract.portfolio.shareproducts.domain.ShareProductRepositoryWrapper;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.joda.time.LocalDate;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+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 PlatformSecurityContext platformSecurityContext;
+
+    private final FromJsonHelper fromApiJsonHelper;
+
+    private final ChargeRepositoryWrapper chargeRepository;
+
+    private final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper;
+
+    private final ClientRepositoryWrapper clientRepositoryWrapper;
+
+    private final ShareProductRepositoryWrapper shareProductRepository;
+
+    @Autowired
+    public ShareAccountDataSerializer(final PlatformSecurityContext platformSecurityContext, final FromJsonHelper fromApiJsonHelper,
+            final ChargeRepositoryWrapper chargeRepository,
+            final SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper, final ClientRepositoryWrapper clientRepositoryWrapper,
+            final ShareProductRepositoryWrapper shareProductRepository) {
+        this.platformSecurityContext = platformSecurityContext;
+        this.fromApiJsonHelper = fromApiJsonHelper;
+        this.chargeRepository = chargeRepository;
+        this.savingsAccountRepositoryWrapper = savingsAccountRepositoryWrapper;
+        this.clientRepositoryWrapper = clientRepositoryWrapper;
+        this.shareProductRepository = shareProductRepository;
+    }
+
+    public ShareAccount 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(), ShareAccountApiConstants.supportedParameters);
+
+        final List<ApiParameterError> 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);
+        ShareProduct shareProduct = this.shareProductRepository.findOneWithNotFoundDetection(productId);
+        final LocalDate submittedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.submitteddate_paramname,
+                element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.submitteddate_paramname).value(submittedDate).notNull();
+
+        final String externalId = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.externalid_paramname, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.externalid_paramname).value(externalId).notNull();
+
+        Long savingsAccountId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.savingsaccountid_paramname, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.savingsaccountid_paramname).value(savingsAccountId).notNull()
+                .longGreaterThanZero();
+
+        final Long requestedShares = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.requestedshares_paramname, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares).notNull()
+                .longGreaterThanZero();
+        boolean allowed = shareProduct.isSharesAllowed(requestedShares) ;
+        if(!allowed) {
+            baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares).failWithCode("differ.from.productdefinition", "Out of range");;
+        }
+        
+        /*Long subscribedShares = shareProduct.getSubscribedShares() ;
+        if(subscribedShares == null) subscribedShares = new Long(0) ;
+        Long totalShares = shareProduct.getTotalShares() ;
+        Long issuedShares = shareProduct.getSharesIssued() ;
+        if(issuedShares == null) issuedShares = totalShares ;
+        if((subscribedShares+requestedShares) > issuedShares) {
+            throw new IssueableSharesExceededException() ;
+        }
+        shareProduct.addSubscribedShares(requestedShares);*/
+        
+        /*BigDecimal unitPrice = this.fromApiJsonHelper.extractBigDecimalNamed(ShareAccountApiConstants.purchasedprice_paramname, element,
+                locale);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.purchasedprice_paramname).value(unitPrice).notNull().positiveAmount();*/
+
+        LocalDate applicationDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.applicationdate_param, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.applicationdate_param).value(applicationDate).notNull();
+
+        Boolean allowdividendsForInactiveClients = this.fromApiJsonHelper.extractBooleanNamed(
+                ShareAccountApiConstants.allowdividendcalculationforinactiveclients_paramname, element);
+
+        Integer minimumActivePeriod = this.fromApiJsonHelper.extractIntegerNamed(ShareAccountApiConstants.minimumactiveperiod_paramname,
+                element, locale);
+        PeriodFrequencyType minimumActivePeriodEnum = extractPeriodType(
+                ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname, element);
+
+        if (minimumActivePeriod != null) {
+            baseDataValidator.reset().parameter(ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname)
+                    .value(minimumActivePeriodEnum.getValue()).integerSameAsNumber(PeriodFrequencyType.DAYS.getValue());
+        }
+
+        Integer lockinPeriod = this.fromApiJsonHelper.extractIntegerNamed(ShareAccountApiConstants.lockinperiod_paramname, element, locale);
+        PeriodFrequencyType lockPeriodEnum = extractPeriodType(ShareAccountApiConstants.lockperiodfrequencytype_paramname, element);
+
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+
+        Client client = this.clientRepositoryWrapper.findOneWithNotFoundDetection(clientId);
+        SavingsAccount savingsAccount = this.savingsAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsAccountId);
+        final MonetaryCurrency currency = shareProduct.getCurrency();
+        Set<ShareAccountCharge> charges = assembleListOfAccountCharges(element, currency.getCode());
+
+        AppUser submittedBy = platformSecurityContext.authenticatedUser();
+        AppUser approvedBy = null;
+        Date approvedDate = null;
+        AppUser rejectedBy = null;
+        Date rejectedDate = null;
+        AppUser activatedBy = null;
+        Date activatedDate = null;
+        AppUser closedBy = null;
+        Date closedDate = null;
+        AppUser modifiedBy = null;
+        Date modifiedDate = null;
+        String accountNo = null;
+        Long approvedShares = null;
+        Long pendingShares = requestedShares;
+        BigDecimal unitPrice = shareProduct.deriveMarketPrice(applicationDate.toDate()) ;
+        ShareAccountTransaction transaction = new ShareAccountTransaction(applicationDate.toDate(), requestedShares, unitPrice);
+        Set<ShareAccountTransaction> sharesPurchased = new HashSet<>();
+        sharesPurchased.add(transaction);
+
+        ShareAccount account = new ShareAccount(client, shareProduct, externalId, currency, savingsAccount, accountNo, approvedShares,
+                pendingShares, sharesPurchased, allowdividendsForInactiveClients, lockinPeriod, lockPeriodEnum, minimumActivePeriod,
+                minimumActivePeriodEnum, charges, submittedBy, submittedDate.toDate(), approvedBy, approvedDate, rejectedBy, rejectedDate,
+                activatedBy, activatedDate, closedBy, closedDate, modifiedBy, modifiedDate);
+
+        for (ShareAccountTransaction pur : sharesPurchased) {
+            pur.setShareAccount(account);
+        }
+
+        if (charges != null) {
+            for (ShareAccountCharge charge : charges) {
+                charge.update(account);
+            }
+        }
+        createChargeTransaction(account, transaction);
+        return account;
+    }
+
+    private void createChargeTransaction(ShareAccount account, final ShareAccountTransaction transaction) {
+        BigDecimal totalChargeAmount = BigDecimal.ZERO;
+        Set<ShareAccountCharge> charges = account.getCharges();
+        Date currentDate = DateUtils.getLocalDateOfTenant().toDate();
+        for (ShareAccountCharge charge : charges) {
+            if (charge.isShareAccountActivation()) {
+                charge.deriveChargeAmount(totalChargeAmount) ;
+                ShareAccountTransaction chargeTransaction = ShareAccountTransaction.createChargeTransaction(currentDate, charge);
+                ShareAccountChargePaidBy paidBy = new ShareAccountChargePaidBy(chargeTransaction, charge, charge.percentageOrAmount());
+                chargeTransaction.addShareAccountChargePaidBy(paidBy);
+                account.addChargeTransaction(chargeTransaction);
+            }
+        }
+       
+        Set<ShareAccountTransaction> pendingApprovalTransaction = account.getPendingForApprovalSharePurchaseTransactions();
+        for (ShareAccountTransaction pending : pendingApprovalTransaction) {
+            for (ShareAccountCharge charge : charges) {
+                if (charge.isSharesPurchaseCharge()) {
+                    BigDecimal amount = charge.deriveChargeAmount(pending.amount());
+                    ShareAccountChargePaidBy paidBy = new ShareAccountChargePaidBy(pending, charge, amount);
+                    pending.addShareAccountChargePaidBy(paidBy);
+                    totalChargeAmount = totalChargeAmount.add(amount);
+                }
+            }
+            pending.updateChargeAmount(totalChargeAmount);
+        }
+    }
+
+    public Map<String, Object> validateAndUpdate(JsonCommand jsonCommand, ShareAccount account) {
+        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(), ShareAccountApiConstants.supportedParameters);
+
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
+        JsonElement element = jsonCommand.parsedJson();
+        ShareProduct shareProduct = account.getShareProduct() ;
+        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 = this.shareProductRepository.findOneWithNotFoundDetection(productId);
+            if (account.setShareProduct(shareProduct)) {
+                actualChanges.put(ShareAccountApiConstants.productid_paramname, productId);
+            }
+        }
+
+        if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.submitteddate_paramname, element)) {
+            final Date submittedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.submitteddate_paramname,
+                    element).toDate();
+            baseDataValidator.reset().parameter(ShareAccountApiConstants.submitteddate_paramname).value(submittedDate).notNull();
+            if (account.setSubmittedDate(submittedDate)) {
+                actualChanges.put(ShareAccountApiConstants.submitteddate_paramname, submittedDate);
+            }
+        }
+
+        if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.externalid_paramname, element)) {
+            final String externalId = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.externalid_paramname, element);
+            baseDataValidator.reset().parameter(ShareAccountApiConstants.externalid_paramname).value(externalId).notNull();
+            if (account.setExternalId(externalId)) {
+                actualChanges.put(ShareAccountApiConstants.externalid_paramname, externalId);
+            }
+        }
+
+        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.requestedshares_paramname, element)) {
+            Long requestedShares = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.requestedshares_paramname, element);
+            /*BigDecimal unitPrice = this.fromApiJsonHelper.extractBigDecimalNamed(ShareAccountApiConstants.purchasedprice_paramname,
+                    element, locale);*/
+            Date applicationDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.applicationdate_param, element)
+                    .toDate();
+            BigDecimal unitPrice = shareProduct.deriveMarketPrice(applicationDate) ;
+            ShareAccountTransaction purchased = new ShareAccountTransaction(applicationDate, requestedShares, unitPrice);
+            account.updateRequestedShares(purchased);
+            actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, purchased);
+            boolean allowed = shareProduct.isSharesAllowed(requestedShares) ;
+            if(!allowed) {
+                baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares).failWithCode("differ.from.productdefinition", "Out of range");;
+            }
+        }
+
+        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.lockinperiod_paramname, element)) {
+            final Integer lockinperiod = this.fromApiJsonHelper.extractIntegerNamed(ShareAccountApiConstants.lockinperiod_paramname,
+                    element, locale);
+            baseDataValidator.reset().parameter(ShareAccountApiConstants.lockinperiod_paramname).value(lockinperiod).notNull();
+            if (account.setLockPeriod(lockinperiod)) {
+                actualChanges.put(ShareAccountApiConstants.lockinperiod_paramname, lockinperiod);
+            }
+        }
+
+        if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.lockperiodfrequencytype_paramname, element)) {
+            PeriodFrequencyType lockPeriod = extractPeriodType(ShareAccountApiConstants.lockperiodfrequencytype_paramname, element);
+            if (account.setLockPeriodFrequencyEnum(lockPeriod)) {
+                actualChanges.put(ShareAccountApiConstants.lockperiodfrequencytype_paramname, lockPeriod);
+            }
+        }
+
+        if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.minimumactiveperiod_paramname, element)) {
+            final Integer minimumActivePeriod = this.fromApiJsonHelper.extractIntegerNamed(
+                    ShareAccountApiConstants.minimumactiveperiod_paramname, element, locale);
+            baseDataValidator.reset().parameter(ShareAccountApiConstants.minimumactiveperiod_paramname).value(minimumActivePeriod)
+                    .notNull();
+            if (account.setminimumActivePeriod(minimumActivePeriod)) {
+                actualChanges.put(ShareAccountApiConstants.minimumactiveperiod_paramname, minimumActivePeriod);
+            }
+        }
+
+        if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname, element)) {
+            PeriodFrequencyType minimumActivePeriod = extractPeriodType(
+                    ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname, element);
+            if (account.setminimumActivePeriodTypeEnum(minimumActivePeriod)) {
+                actualChanges.put(ShareAccountApiConstants.minimumactiveperiodfrequencytype_paramname, minimumActivePeriod);
+            }
+        }
+        if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.charges_paramname, element)) {
+            shareProduct = account.getShareProduct();
+            Set<ShareAccountCharge> updatedCharges = assembleListOfAccountChargesforUpdate(account, element, shareProduct.getCurrency()
+                    .getCode());
+            if (!updatedCharges.isEmpty()) {
+                actualChanges.put(ShareAccountApiConstants.charges_paramname, new HashSet<ShareAccountCharge>());
+            }
+
+        }
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+        return actualChanges;
+    }
+
+    @SuppressWarnings("null")
+    public Map<String, Object> validateAndApprove(JsonCommand jsonCommand, ShareAccount account) {
+        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(), ShareAccountApiConstants.approvalParameters);
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
+        JsonElement element = jsonCommand.parsedJson();
+        LocalDate approvedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.approveddate_paramname, element);
+        final LocalDate submittalDate = new LocalDate(account.getSubmittedDate());
+        if (approvedDate != null && approvedDate.isBefore(submittalDate)) {
+            final DateTimeFormatter formatter = DateTimeFormat.forPattern(jsonCommand.dateFormat()).withLocale(jsonCommand.extractLocale());
+            final String submittalDateAsString = formatter.print(submittalDate);
+            baseDataValidator.reset().parameter(ShareAccountApiConstants.approveddate_paramname).value(submittalDateAsString)
+                    .failWithCodeNoParameterAddedToErrorCode("cannot.be.before.submittal.date");
+        }
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+        
+        AppUser approvedUser = this.platformSecurityContext.authenticatedUser();
+        account.approve(approvedDate.toDate(), approvedUser);    
+        actualChanges.put(ShareAccountApiConstants.id_paramname, account.getId());
+        updateTotalChargeDerived(account);
+        return actualChanges;
+    }
+
+    private void updateTotalChargeDerived(final ShareAccount shareAccount) {
+        // Set<ShareAccountCharge> charges = shareAccount.getCharges() ;
+        Set<ShareAccountTransaction> transactions = shareAccount.getShareAccountTransactions();
+        for (ShareAccountTransaction transaction : transactions) {
+            Set<ShareAccountChargePaidBy> paidBySet = transaction.getChargesPaidBy();
+            if (paidBySet != null && !paidBySet.isEmpty()) {
+                for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
+                    ShareAccountCharge charge = chargePaidBy.getCharge();
+                    if (charge.isSharesPurchaseCharge()) {
+                        Money money = Money.of(shareAccount.getCurrency(), chargePaidBy.getAmount());
+                        charge.updatePaidAmountBy(money);
+                    }
+                }
+            }
+        }
+    }
+
+    public Map<String, Object> validateAndUndoApprove(JsonCommand jsonCommand, ShareAccount account) {
+        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(), ShareAccountApiConstants.activateParameters);
+        //final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        //final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
+        //JsonElement element = jsonCommand.parsedJson();
+        //String notes = this.fromApiJsonHelper.extractStringNamed(ShareAccountApiConstants.note_paramname, element);
+        // baseDataValidator.reset().parameter(ShareAccountApiConstants.approveddate_paramname).validateDateAfter(account.get)
+        //AppUser approvedUser = this.platformSecurityContext.authenticatedUser();
+        account.undoApprove();
+        actualChanges.put(ShareAccountApiConstants.charges_paramname, Boolean.TRUE);
+        return actualChanges;
+    }
+
+    @SuppressWarnings("unused")
+    public Map<String, Object> validateAndReject(JsonCommand jsonCommand, ShareAccount account) {
+        Map<String, Object> actualChanges = new HashMap<>();
+        AppUser rejectedUser = this.platformSecurityContext.authenticatedUser();
+        Date rejectedDate = DateUtils.getDateOfTenant();
+        account.reject(rejectedDate, rejectedUser);
+        actualChanges.put(ShareAccountApiConstants.charges_paramname, Boolean.TRUE);
+        return actualChanges;
+    }
+
+    @SuppressWarnings("null")
+    public Map<String, Object> validateAndActivate(JsonCommand jsonCommand, ShareAccount account) {
+        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(), ShareAccountApiConstants.activateParameters);
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
+        JsonElement element = jsonCommand.parsedJson();
+        LocalDate activatedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.activatedate_paramname, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.activatedate_paramname).value(activatedDate).notNull();
+        final LocalDate approvedDate = new LocalDate(account.getApprovedDate());
+        if (activatedDate != null && activatedDate.isBefore(approvedDate)) {
+            final DateTimeFormatter formatter = DateTimeFormat.forPattern(jsonCommand.dateFormat()).withLocale(jsonCommand.extractLocale());
+            final String submittalDateAsString = formatter.print(approvedDate);
+            baseDataValidator.reset().parameter(ShareAccountApiConstants.activatedate_paramname).value(submittalDateAsString)
+                    .failWithCodeNoParameterAddedToErrorCode("cannot.be.before.approved.date");
+        }
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+        AppUser approvedUser = this.platformSecurityContext.authenticatedUser();
+        account.activate(activatedDate.toDate(), approvedUser);
+        handlechargesOnActivation(account);
+        actualChanges.put(ShareAccountApiConstants.charges_paramname, activatedDate.toDate());
+        return actualChanges;
+    }
+
+    private void handlechargesOnActivation(final ShareAccount account) {
+        Set<ShareAccountCharge> charges = account.getCharges();
+        for (ShareAccountCharge charge : charges) {
+            if (charge.isShareAccountActivation()) {
+                charge.markAsFullyPaid();
+            }
+        }
+    }
+
+    private Set<ShareAccountCharge> assembleListOfAccountCharges(final JsonElement element, final String currencyCode) {
+        final Set<ShareAccountCharge> 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("chargeId")) {
+                        final Long id = jsonObject.get("chargeId").getAsLong();
+                        BigDecimal amount = jsonObject.get("amount").getAsBigDecimal();
+                        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);
+                        }
+
+                        ChargeTimeType chargeTime = null;
+                        ChargeCalculationType chargeCalculation = null;
+                        Boolean status = Boolean.TRUE;
+                        ShareAccountCharge accountCharge = ShareAccountCharge.createNewWithoutShareAccount(charge, amount, chargeTime,
+                                chargeCalculation, status);
+                        charges.add(accountCharge);
+                    }
+                }
+            }
+        }
+        return charges;
+    }
+
+    private Set<ShareAccountCharge> assembleListOfAccountChargesforUpdate(final ShareAccount account, final JsonElement element,
+            final String currencyCode) {
+        Set<ShareAccountCharge> updated = 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 Long chargeId = jsonObject.get("chargeId").getAsLong();
+                        BigDecimal amount = jsonObject.get("amount").getAsBigDecimal();
+                        final Charge charge = this.chargeRepository.findOneWithNotFoundDetection(chargeId);
+                        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 updatedCharge = account.updateShareCharge(id, chargeId, amount);
+                        updated.add(updatedCharge);
+                    } else {
+                        if (jsonObject.has("chargeId")) {
+                            final Long id = jsonObject.get("chargeId").getAsLong();
+                            BigDecimal amount = jsonObject.get("amount").getAsBigDecimal();
+                            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);
+                            }
+                            ChargeTimeType chargeTime = ChargeTimeType.fromInt(charge.getChargeTimeType());
+                            ChargeCalculationType chargeCalculation = ChargeCalculationType.fromInt(charge.getChargeCalculation());
+                            Boolean status = Boolean.TRUE;
+                            ShareAccountCharge accountCharge = ShareAccountCharge.createNewWithoutShareAccount(charge, amount, chargeTime,
+                                    chargeCalculation, status);
+                            account.addShareAccountCharge(accountCharge);
+                            updated.add(accountCharge);
+                        }
+                    }
+                }
+            }
+        }
+        return updated;
+    }
+
+    private PeriodFrequencyType extractPeriodType(String paramName, final JsonElement element) {
+        PeriodFrequencyType frequencyType = PeriodFrequencyType.INVALID;
+        frequencyType = PeriodFrequencyType.fromInt(this.fromApiJsonHelper.extractIntegerWithLocaleNamed(paramName, element));
+        return frequencyType;
+    }
+
+    public Map<String, Object> validateAndApplyAddtionalShares(JsonCommand jsonCommand, ShareAccount account) {
+        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(),
+                ShareAccountApiConstants.addtionalSharesParameters);
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
+        JsonElement element = jsonCommand.parsedJson();
+        LocalDate requestedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.requesteddate_paramname, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.requesteddate_paramname).value(requestedDate).notNull();
+        final Long sharesRequested = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.requestedshares_paramname, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(sharesRequested).notNull();
+        ShareProduct shareProduct = account.getShareProduct() ;
+        if(sharesRequested != null) {
+            boolean allowed = shareProduct.isSharesAllowed(sharesRequested) ;
+            if(!allowed) {
+                baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(sharesRequested).failWithCode("differ.from.productdefinition", "Out of range");;
+            }    
+        }
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+        final BigDecimal unitPrice = shareProduct.deriveMarketPrice(requestedDate.toDate()) ;
+        ShareAccountTransaction purchaseTransaction = new ShareAccountTransaction(requestedDate.toDate(), sharesRequested, unitPrice);
+        account.addAdditionalPurchasedShares(purchaseTransaction);
+        handleAdditionalSharesChargeTransactions(account, purchaseTransaction);
+        actualChanges.put(ShareAccountApiConstants.additionalshares_paramname, purchaseTransaction);
+        return actualChanges;
+    }
+
+    private void handleAdditionalSharesChargeTransactions(final ShareAccount account, final ShareAccountTransaction purchaseTransaction) {
+        Set<ShareAccountCharge> charges = account.getCharges();
+        BigDecimal totalChargeAmount = BigDecimal.ZERO;
+        for (ShareAccountCharge charge : charges) {
+            if (charge.isSharesPurchaseCharge()) {
+                BigDecimal amount = charge.updateChargeDetailsForAdditionalSharesRequest(purchaseTransaction.amount());
+                ShareAccountChargePaidBy paidBy = new ShareAccountChargePaidBy(purchaseTransaction, charge, amount);
+                purchaseTransaction.addShareAccountChargePaidBy(paidBy);
+                totalChargeAmount = totalChargeAmount.add(amount);
+            }
+        }
+        purchaseTransaction.updateChargeAmount(totalChargeAmount);
+    }
+
+    public Map<String, Object> validateAndApproveAddtionalShares(JsonCommand jsonCommand, ShareAccount account) {
+        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(),
+                ShareAccountApiConstants.addtionalSharesParameters);
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
+        JsonElement element = jsonCommand.parsedJson();
+        final ArrayList<Long> purchasedShares = new ArrayList<>();
+        if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.requestedshares_paramname, element)) {
+            JsonArray array = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.requestedshares_paramname, element);
+            long totalShares = 0 ;
+            for (JsonElement arrayElement : array) {
+                final Long purchasedSharesId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.id_paramname, arrayElement);
+                baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(purchasedSharesId).notBlank() ;
+                ShareAccountTransaction transaction = account.retrievePurchasedShares(purchasedSharesId);
+                if (transaction != null) {
+                    totalShares+=transaction.getTotalShares().longValue() ;
+                    transaction.approve();
+                    updateTotalChargeDerivedForAdditonalShares(account, transaction);
+                }
+                purchasedShares.add(purchasedSharesId);
+            }
+            if(totalShares > 0) {
+                account.updateApprovedShares(new Long(totalShares)) ;    
+            }
+        }
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+        actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, purchasedShares);
+        return actualChanges;
+    }
+
+    private void updateTotalChargeDerivedForAdditonalShares(final ShareAccount shareAccount, final ShareAccountTransaction transaction) {
+        Set<ShareAccountChargePaidBy> paidBySet = transaction.getChargesPaidBy();
+        if (paidBySet != null && !paidBySet.isEmpty()) {
+            for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
+                ShareAccountCharge charge = chargePaidBy.getCharge();
+                if (charge.isSharesPurchaseCharge()) {
+                    Money money = Money.of(shareAccount.getCurrency(), chargePaidBy.getAmount());
+                    charge.updatePaidAmountBy(money);
+                }
+            }
+        }
+    }
+
+    public Map<String, Object> validateAndRejectAddtionalShares(JsonCommand jsonCommand, ShareAccount account) {
+        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(),
+                ShareAccountApiConstants.addtionalSharesParameters);
+        JsonElement element = jsonCommand.parsedJson();
+        final ArrayList<Long> purchasedShares = new ArrayList<>();
+        if (this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.requestedshares_paramname, element)) {
+            long totalShares = 0 ;
+            JsonArray array = this.fromApiJsonHelper.extractJsonArrayNamed(ShareAccountApiConstants.requestedshares_paramname, element);
+            for (JsonElement arrayElement : array) {
+                final Long purchasedSharesId = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.id_paramname, arrayElement);
+                ShareAccountTransaction shares = account.retrievePurchasedShares(purchasedSharesId);
+                if (shares != null) {
+                    shares.reject();
+                    updateTotalChargeDerivedForAdditonalSharesReject(account, shares) ;
+                    totalShares +=shares.getTotalShares().longValue() ;
+                }
+                purchasedShares.add(purchasedSharesId);
+            }
+            if(totalShares > 0) {
+                account.removePendingShares(new Long(totalShares)) ;
+            }
+        }
+        actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, purchasedShares);
+        return actualChanges;
+    }
+
+    private void updateTotalChargeDerivedForAdditonalSharesReject(final ShareAccount shareAccount, final ShareAccountTransaction transaction) {
+        Set<ShareAccountChargePaidBy> paidBySet = transaction.getChargesPaidBy();
+        if (paidBySet != null && !paidBySet.isEmpty()) {
+            for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
+                ShareAccountCharge charge = chargePaidBy.getCharge();
+                if (charge.isSharesPurchaseCharge()) {
+                    Money money = Money.of(shareAccount.getCurrency(), chargePaidBy.getAmount());
+                    charge.updatePaidAmountBy(money);
+                }
+            }
+        }
+    }
+    
+    public Map<String, Object> validateAndRedeemShares(JsonCommand jsonCommand, ShareAccount account) {
+        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(),
+                ShareAccountApiConstants.addtionalSharesParameters);
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
+        JsonElement element = jsonCommand.parsedJson();
+        LocalDate requestedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.requesteddate_paramname, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.requesteddate_paramname).value(requestedDate).notNull();
+        final Long sharesRequested = this.fromApiJsonHelper.extractLongNamed(ShareAccountApiConstants.requestedshares_paramname, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(sharesRequested).notNull()
+                .longGreaterThanZero();
+
+        final Locale locale = this.fromApiJsonHelper.extractLocaleParameter(element.getAsJsonObject());
+        final BigDecimal unitPrice = this.fromApiJsonHelper.extractBigDecimalNamed(ShareAccountApiConstants.purchasedprice_paramname,
+                element, locale);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.purchasedprice_paramname).value(unitPrice).notNull().positiveAmount();
+        ShareAccountTransaction transaction = ShareAccountTransaction.createRedeemTransaction(requestedDate.toDate(), sharesRequested,
+                unitPrice);
+        account.addAdditionalPurchasedShares(transaction);
+        actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, transaction);
+        handleRedeemSharesChargeTransactions(account, transaction);
+        return actualChanges;
+    }
+
+    private void handleRedeemSharesChargeTransactions(final ShareAccount account, final ShareAccountTransaction transaction) {
+        Set<ShareAccountCharge> charges = account.getCharges();
+        BigDecimal totalChargeAmount = BigDecimal.ZERO;
+        for (ShareAccountCharge charge : charges) {
+            if (charge.isSharesRedeemCharge()) {
+                BigDecimal amount = charge.updateChargeDetailsForAdditionalSharesRequest(transaction.amount());
+                ShareAccountChargePaidBy paidBy = new ShareAccountChargePaidBy(transaction, charge, amount);
+                transaction.addShareAccountChargePaidBy(paidBy);
+                totalChargeAmount = totalChargeAmount.add(amount);
+            }
+        }
+        transaction.deductChargesFromTotalAmount(totalChargeAmount);
+        Set<ShareAccountChargePaidBy> paidBySet = transaction.getChargesPaidBy();
+        if (paidBySet != null && !paidBySet.isEmpty()) {
+            for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
+                ShareAccountCharge charge = chargePaidBy.getCharge();
+                if (charge.isSharesRedeemCharge()) {
+                    Money money = Money.of(account.getCurrency(), chargePaidBy.getAmount());
+                    charge.updatePaidAmountBy(money);
+                }
+            }
+        }
+        
+       // transaction.adjustRedeemAmount();
+    }
+    
+    public Map<String, Object> validateAndClose(JsonCommand jsonCommand, ShareAccount account) {
+        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(), ShareAccountApiConstants.closeParameters);
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
+        JsonElement element = jsonCommand.parsedJson();
+        LocalDate closedDate = this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.closeddate_paramname, element);
+        baseDataValidator.reset().parameter(ShareAccountApiConstants.approveddate_paramname).value(closedDate).notNull();
+        AppUser approvedUser = this.platformSecurityContext.authenticatedUser();
+        final BigDecimal unitPrice = account.getShareProduct().deriveMarketPrice(DateUtils.getDateOfTenant()) ;
+        ShareAccountTransaction transaction = ShareAccountTransaction.createRedeemTransaction(closedDate.toDate(), account.getTotalApprovedShares(), unitPrice) ;
+        account.addAdditionalPurchasedShares(transaction);
+        account.close(closedDate.toDate(), approvedUser);
+        handleRedeemSharesChargeTransactions(account, transaction) ;
+        actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, transaction);
+        updateTotalChargeDerived(account);
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+        return actualChanges;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/PurchasedSharesReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/PurchasedSharesReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/PurchasedSharesReadPlatformService.java
new file mode 100644
index 0000000..4f3b401
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/PurchasedSharesReadPlatformService.java
@@ -0,0 +1,28 @@
+/**
+ * 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.shareaccounts.service;
+
+import java.util.Collection;
+
+import org.apache.fineract.portfolio.shareaccounts.data.PurchasedSharesData;
+
+public interface PurchasedSharesReadPlatformService {
+
+	public Collection<PurchasedSharesData> retrievePurchasedShares(final Long accountId) ;
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/PurchasedSharesReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/PurchasedSharesReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/PurchasedSharesReadPlatformServiceImpl.java
new file mode 100644
index 0000000..5aa7f73
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/PurchasedSharesReadPlatformServiceImpl.java
@@ -0,0 +1,86 @@
+/**
+ * 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.shareaccounts.service;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.portfolio.shareaccounts.data.PurchasedSharesData;
+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 PurchasedSharesReadPlatformServiceImpl implements
+		PurchasedSharesReadPlatformService {
+
+	private final JdbcTemplate jdbcTemplate;
+	
+	@Autowired
+	public PurchasedSharesReadPlatformServiceImpl(final RoutingDataSource dataSource) {
+		this.jdbcTemplate = new JdbcTemplate(dataSource) ;
+	}
+	@Override
+	public Collection<PurchasedSharesData> retrievePurchasedShares(
+			Long accountId) {
+		PurchasedSharesDataRowMapper mapper = new PurchasedSharesDataRowMapper() ;
+		final String sql = "select " + mapper.schema() + " where saps.account_id=?";
+		return this.jdbcTemplate.query(sql, mapper, new Object[] { accountId});
+	}
+
+	private final static class PurchasedSharesDataRowMapper implements RowMapper<PurchasedSharesData> {
+
+		private final String schema ;
+		
+		public PurchasedSharesDataRowMapper() {
+			StringBuffer buff = new StringBuffer()
+			.append("saps.id, saps.account_id, saps.transaction_date, saps.total_shares, saps.unit_price, ")
+			.append("saps.status_enum, saps.type_enum, saps.amount, saps.charge_amount as chargeamount ")
+			.append(" from m_share_account_transactions saps ");
+			schema = buff.toString() ;
+		}
+		@Override
+		public PurchasedSharesData mapRow(ResultSet rs, int rowNum)
+				throws SQLException {
+			final Long id = rs.getLong("id") ;
+			final Long accountId = rs.getLong("account_id") ;
+			final LocalDate purchasedDate = new LocalDate(rs.getDate("transaction_date")) ;
+			final Long numberOfShares = JdbcSupport.getLong(rs, "total_shares") ;
+			final BigDecimal purchasedPrice = rs.getBigDecimal("unit_price") ;
+			final Integer status = rs.getInt("status_enum") ;
+			final EnumOptionData statusEnum = SharesEnumerations.purchasedSharesEnum(status) ;
+			final Integer type = rs.getInt("type_enum") ;
+			final EnumOptionData typeEnum = SharesEnumerations.purchasedSharesEnum(type) ;
+			final BigDecimal amount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amount") ;
+			final BigDecimal chargeAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "chargeamount") ;
+			return new PurchasedSharesData(id,accountId, purchasedDate, numberOfShares, purchasedPrice, statusEnum, typeEnum, amount, chargeAmount);
+		}
+		
+		public String schema() {
+			return this.schema ;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountChargeReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountChargeReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountChargeReadPlatformService.java
new file mode 100644
index 0000000..af23abe
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountChargeReadPlatformService.java
@@ -0,0 +1,28 @@
+/**
+ * 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.shareaccounts.service;
+
+import java.util.Collection;
+
+import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountChargeData;
+
+public interface ShareAccountChargeReadPlatformService {
+
+	Collection<ShareAccountChargeData> retrieveAccountCharges(final Long accountId, final String status) ;
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountChargeReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountChargeReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountChargeReadPlatformServiceImpl.java
new file mode 100644
index 0000000..b4ddd96
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountChargeReadPlatformServiceImpl.java
@@ -0,0 +1,148 @@
+/**
+ * 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.shareaccounts.service;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import org.apache.fineract.portfolio.charge.data.ChargeData;
+import org.apache.fineract.portfolio.charge.service.ChargeEnumerations;
+import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountChargeData;
+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 ShareAccountChargeReadPlatformServiceImpl implements
+		ShareAccountChargeReadPlatformService {
+
+	private final JdbcTemplate jdbcTemplate;
+
+	@Autowired
+	public ShareAccountChargeReadPlatformServiceImpl(
+			final RoutingDataSource dataSource) {
+		this.jdbcTemplate = new JdbcTemplate(dataSource);
+	}
+
+	@Override
+	public Collection<ShareAccountChargeData> retrieveAccountCharges(
+			Long accountId, String status) {
+		final ShareAccountChargeMapper rm = new ShareAccountChargeMapper();
+		final StringBuilder sqlBuilder = new StringBuilder();
+		sqlBuilder.append("select ").append(rm.schema())
+				.append(" where sc.account_id=? ");
+		if (status.equalsIgnoreCase("active")) {
+			sqlBuilder.append(" and sc.is_active = 1 ");
+		} else if (status.equalsIgnoreCase("inactive")) {
+			sqlBuilder.append(" and sc.is_active = 0 ");
+		}
+		sqlBuilder.append(" order by sc.charge_time_enum ASC");
+
+		return this.jdbcTemplate.query(sqlBuilder.toString(), rm,
+				new Object[] { accountId });
+	}
+
+	private final static class ShareAccountChargeMapper implements
+			RowMapper<ShareAccountChargeData> {
+
+		private final String schema;
+
+		public ShareAccountChargeMapper() {
+			StringBuffer buff = new StringBuffer()
+					.append("sc.id as id, c.id as chargeId, sc.account_id as accountId, c.name as name, ")
+					.append("sc.amount as amountDue, sc.amount_paid_derived as amountPaid, ")
+					.append("sc.amount_waived_derived as amountWaived, sc.amount_writtenoff_derived as amountWrittenOff, ")
+					.append("sc.amount_outstanding_derived as amountOutstanding, sc.calculation_percentage as percentageOf, ")
+					.append("sc.calculation_on_amount as amountPercentageAppliedTo, sc.charge_time_enum as chargeTime, ")
+					.append("sc.charge_calculation_enum as chargeCalculation, c.is_active as isActive, ")
+					.append("c.currency_code as currencyCode, oc.name as currencyName, ")
+					.append("oc.decimal_places as currencyDecimalPlaces, oc.currency_multiplesof as inMultiplesOf, oc.display_symbol as currencyDisplaySymbol, ")
+					.append("oc.internationalized_name_code as currencyNameCode from m_charge c ")
+					.append("join m_organisation_currency oc on c.currency_code = oc.code ")
+					.append("join m_share_account_charge sc on sc.charge_id = c.id ");
+
+			schema = buff.toString();
+		}
+
+		@Override
+		public ShareAccountChargeData mapRow(ResultSet rs, int rowNum)
+				throws SQLException {
+			final Long id = rs.getLong("id");
+			final Long chargeId = rs.getLong("chargeId");
+			final Long accountId = rs.getLong("accountId");
+			final String name = rs.getString("name");
+			final BigDecimal amount = rs.getBigDecimal("amountDue");
+			final BigDecimal amountPaid = JdbcSupport
+					.getBigDecimalDefaultToZeroIfNull(rs, "amountPaid");
+			final BigDecimal amountWaived = JdbcSupport
+					.getBigDecimalDefaultToZeroIfNull(rs, "amountWaived");
+			final BigDecimal amountWrittenOff = JdbcSupport
+					.getBigDecimalDefaultToZeroIfNull(rs, "amountWrittenOff");
+			final BigDecimal amountOutstanding = rs
+					.getBigDecimal("amountOutstanding");
+
+			final BigDecimal percentageOf = JdbcSupport
+					.getBigDecimalDefaultToZeroIfNull(rs, "percentageOf");
+			final BigDecimal amountPercentageAppliedTo = JdbcSupport
+					.getBigDecimalDefaultToZeroIfNull(rs,
+							"amountPercentageAppliedTo");
+
+			final String currencyCode = rs.getString("currencyCode");
+			final String currencyName = rs.getString("currencyName");
+			final String currencyNameCode = rs.getString("currencyNameCode");
+			final String currencyDisplaySymbol = rs
+					.getString("currencyDisplaySymbol");
+			final Integer currencyDecimalPlaces = JdbcSupport.getInteger(rs,
+					"currencyDecimalPlaces");
+			final Integer inMultiplesOf = JdbcSupport.getInteger(rs,
+					"inMultiplesOf");
+
+			final CurrencyData currency = new CurrencyData(currencyCode,
+					currencyName, currencyDecimalPlaces, inMultiplesOf,
+					currencyDisplaySymbol, currencyNameCode);
+
+			final int chargeTime = rs.getInt("chargeTime");
+			final EnumOptionData chargeTimeType = ChargeEnumerations
+					.chargeTimeType(chargeTime);
+
+			final int chargeCalculation = rs.getInt("chargeCalculation");
+			final EnumOptionData chargeCalculationType = ChargeEnumerations
+					.chargeCalculationType(chargeCalculation);
+			final Boolean isActive = rs.getBoolean("isActive");
+
+			final Collection<ChargeData> chargeOptions = null;
+			return new ShareAccountChargeData(id, chargeId, accountId, name,
+					currency, amount, amountPaid, amountWaived,
+					amountWrittenOff, amountOutstanding, chargeTimeType,
+					chargeCalculationType, percentageOf,
+					amountPercentageAppliedTo, chargeOptions, isActive);
+		}
+
+		public String schema() {
+			return this.schema;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountCommandsServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountCommandsServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountCommandsServiceImpl.java
new file mode 100644
index 0000000..6f56afa
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountCommandsServiceImpl.java
@@ -0,0 +1,85 @@
+/**
+ * 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.shareaccounts.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.accounts.constants.ShareAccountApiConstants;
+import org.apache.fineract.portfolio.accounts.service.AccountsCommandsService;
+import org.apache.fineract.portfolio.shareaccounts.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) {
+    	return null ;
+    }
+
+    public Object rejectShareAccount(Long accountId, JsonCommand jsonCommand) {
+        return null ;
+    }
+
+    public Object applyAdditionalShares(Long accountId, JsonCommand jsonCommand) {
+        return null ;
+    }
+
+    public Object approveAdditionalShares(Long accountId, JsonCommand jsonCommand) {
+        return null ;
+    }
+
+    public Object rejectAdditionalShares(Long accountId, JsonCommand jsonCommand) {
+        return null ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountDividendReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountDividendReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountDividendReadPlatformService.java
new file mode 100644
index 0000000..bacf6db
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountDividendReadPlatformService.java
@@ -0,0 +1,34 @@
+/**
+ * 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.shareaccounts.service;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.fineract.infrastructure.core.service.Page;
+import org.apache.fineract.infrastructure.core.service.SearchParameters;
+import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountDividendData;
+
+public interface ShareAccountDividendReadPlatformService {
+
+    List<Map<String, Object>> retriveDividendDetailsForPostDividents();
+
+    Page<ShareAccountDividendData> retriveAll(Long payoutDetailId, SearchParameters searchParameters);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountDividendReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountDividendReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountDividendReadPlatformServiceImpl.java
new file mode 100644
index 0000000..1be1eac
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountDividendReadPlatformServiceImpl.java
@@ -0,0 +1,140 @@
+/**
+ * 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.shareaccounts.service;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+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.data.ShareAccountData;
+import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountDividendStatusType;
+import org.apache.fineract.portfolio.shareproducts.domain.ShareProductDividendStatusType;
+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 ShareAccountDividendReadPlatformServiceImpl implements ShareAccountDividendReadPlatformService {
+
+    private final JdbcTemplate jdbcTemplate;
+    private final PaginationHelper<ShareAccountDividendData> paginationHelper = new PaginationHelper<>();
+
+    @Autowired
+    public ShareAccountDividendReadPlatformServiceImpl(final RoutingDataSource dataSource) {
+        this.jdbcTemplate = new JdbcTemplate(dataSource);
+    }
+
+    @Override
+    public List<Map<String, Object>> retriveDividendDetailsForPostDividents() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("select ");
+        sb.append(" sadd.id as id, ");
+        sb.append(" sa.savings_account_id as savingsAccountId ");
+        sb.append(" from m_share_account_dividend_details sadd");
+        sb.append(" inner join m_share_product_dividend_pay_out spdpo on spdpo.id = sadd.dividend_pay_out_id ");
+        sb.append(" inner join m_share_account sa on sa.id = sadd.account_id ");
+        sb.append(" where spdpo.status = ? and sadd.status = ?");
+        return this.jdbcTemplate.queryForList(sb.toString(), ShareProductDividendStatusType.APPROVED.getValue(),
+                ShareAccountDividendStatusType.INITIATED.getValue());
+    }
+
+    @Override
+    public Page<ShareAccountDividendData> retriveAll(final Long payoutDetailId, final SearchParameters searchParameters) {
+        ShareAccountDividendMapper shareAccountDividendMapper = new ShareAccountDividendMapper();
+        final StringBuilder sqlBuilder = new StringBuilder(200);
+        sqlBuilder.append("select SQL_CALC_FOUND_ROWS ");
+        sqlBuilder.append(shareAccountDividendMapper.schema());
+        sqlBuilder.append(" where sadd.dividend_pay_out_id = ? ");
+        List<Object> params = new ArrayList<>(2);
+        params.add(payoutDetailId);
+        if (searchParameters.getAccountNo() != null) {
+            sqlBuilder.append(" and sa.account_no = ? ");
+            params.add(searchParameters.getAccountNo());
+        }
+        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,
+                shareAccountDividendMapper);
+    }
+
+    private static final class ShareAccountDividendMapper implements RowMapper<ShareAccountDividendData> {
+
+        private final String sql;
+
+        public ShareAccountDividendMapper() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(" sadd.id as id, sadd.amount as amount,");
+            sb.append(" sadd.status as status, sadd.savings_transaction_id as savingsTransactionId,");
+            sb.append(" sa.id as accountId,sa.account_no as accountNumber, ");
+            sb.append(" mc.id as clientId,mc.display_name as clientName ");
+            sb.append(" from m_share_account_dividend_details sadd");
+            sb.append(" inner join m_share_account sa on sa.id = sadd.account_id ");
+            sb.append(" inner join m_client mc on mc.id=sa.client_id ");
+            sql = sb.toString();
+        }
+
+        public String schema() {
+            return this.sql;
+        }
+
+        @Override
+        public ShareAccountDividendData 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.ShareAccountDividendStatusEnum(status);
+            final Long savingsTransactionId = JdbcSupport.getLong(rs, "savingsTransactionId");
+
+            final Long accounId = rs.getLong("accountId");
+            final String accountNumber = rs.getString("accountNumber");
+            final String clientName = rs.getString("clientName");
+            final Long clientId = rs.getLong("clientId");
+            final ShareAccountData accountData = ShareAccountData.lookup(accounId, accountNumber, clientId, clientName);
+            return new ShareAccountDividendData(id, accountData, amount, statusEnum, savingsTransactionId);
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/08c553f9/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformService.java
new file mode 100644
index 0000000..06cdf62
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformService.java
@@ -0,0 +1,41 @@
+/**
+ * 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.shareaccounts.service;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.apache.fineract.portfolio.accounts.service.AccountReadPlatformService;
+import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountData;
+import org.joda.time.LocalDate;
+
+public interface ShareAccountReadPlatformService extends AccountReadPlatformService {
+
+    @Override
+    public ShareAccountData retrieveTemplate(final Long clientId, final Long productId);
+
+    @Override
+    public ShareAccountData retrieveOne(Long id, boolean includeTemplate);
+
+    @Override
+    public Set<String> getResponseDataParams();
+
+    Collection<ShareAccountData> retrieveAllShareAccountDataForDividends(Long productId, boolean fetchInActiveAccounts, LocalDate startDate);
+
+}


Mime
View raw message