http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/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
index 13c7b4d..1e63050 100644
--- 
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
@@ -49,7 +49,6 @@ 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;
@@ -87,9 +86,8 @@ public class ShareAccountDataSerializer {
 
     @Autowired
     public ShareAccountDataSerializer(final PlatformSecurityContext 
platformSecurityContext, final FromJsonHelper fromApiJsonHelper,
-            final ChargeRepositoryWrapper chargeRepository,
-            final SavingsAccountRepositoryWrapper 
savingsAccountRepositoryWrapper, final ClientRepositoryWrapper 
clientRepositoryWrapper,
-            final ShareProductRepositoryWrapper shareProductRepository) {
+            final ChargeRepositoryWrapper chargeRepository, final 
SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper,
+            final ClientRepositoryWrapper clientRepositoryWrapper, final 
ShareProductRepositoryWrapper shareProductRepository) {
         this.platformSecurityContext = platformSecurityContext;
         this.fromApiJsonHelper = fromApiJsonHelper;
         this.chargeRepository = chargeRepository;
@@ -117,7 +115,7 @@ public class ShareAccountDataSerializer {
         
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();
+        // 
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()
@@ -126,25 +124,16 @@ public class ShareAccountDataSerializer {
         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");;
+        if(requestedShares < shareProduct.getMinimumClientShares()) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares)
+            
.failWithCode("client.can.not.purchase.shares.lessthan.product.definition", 
"Client can not purchase shares less than product definition");
         }
         
-        /*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);*/
+        if(requestedShares > shareProduct.getMaximumClientShares()) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares)
+            
.failWithCode("client.can.not.purchase.shares.morethan.product.definition", 
"Client can not purchase shares more than product definition");
+        }
         
-        /*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();
 
@@ -185,7 +174,7 @@ public class ShareAccountDataSerializer {
         String accountNo = null;
         Long approvedShares = null;
         Long pendingShares = requestedShares;
-        BigDecimal unitPrice = 
shareProduct.deriveMarketPrice(applicationDate.toDate()) ;
+        BigDecimal unitPrice = 
shareProduct.deriveMarketPrice(applicationDate.toDate());
         ShareAccountTransaction transaction = new 
ShareAccountTransaction(applicationDate.toDate(), requestedShares, unitPrice);
         Set<ShareAccountTransaction> sharesPurchased = new HashSet<>();
         sharesPurchased.add(transaction);
@@ -204,28 +193,28 @@ public class ShareAccountDataSerializer {
                 charge.update(account);
             }
         }
-        createChargeTransaction(account, transaction);
+        createChargeTransaction(account);
         return account;
     }
 
-    private void createChargeTransaction(ShareAccount account, final 
ShareAccountTransaction transaction) {
+    private void createChargeTransaction(ShareAccount account) {
         BigDecimal totalChargeAmount = BigDecimal.ZERO;
         Set<ShareAccountCharge> charges = account.getCharges();
         Date currentDate = DateUtils.getLocalDateOfTenant().toDate();
         for (ShareAccountCharge charge : charges) {
-            if (charge.isShareAccountActivation()) {
-                charge.deriveChargeAmount(totalChargeAmount) ;
+            if (charge.isActive() && 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()) {
+                if (charge.isActive() && charge.isSharesPurchaseCharge()) {
                     BigDecimal amount = 
charge.deriveChargeAmount(pending.amount());
                     ShareAccountChargePaidBy paidBy = new 
ShareAccountChargePaidBy(pending, charge, amount);
                     pending.addShareAccountChargePaidBy(paidBy);
@@ -245,7 +234,7 @@ public class ShareAccountDataSerializer {
         final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
         final DataValidatorBuilder baseDataValidator = new 
DataValidatorBuilder(dataValidationErrors).resource("sharesaccount");
         JsonElement element = jsonCommand.parsedJson();
-        ShareProduct shareProduct = account.getShareProduct() ;
+        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);
@@ -266,7 +255,7 @@ public class ShareAccountDataSerializer {
 
         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();
+            // 
baseDataValidator.reset().parameter(ShareAccountApiConstants.externalid_paramname).value(externalId).notNull();
             if (account.setExternalId(externalId)) {
                 
actualChanges.put(ShareAccountApiConstants.externalid_paramname, externalId);
             }
@@ -274,25 +263,51 @@ public class ShareAccountDataSerializer {
 
         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);
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.savingsaccountid_paramname).value(savingsAccountId).notNull()
+            .longGreaterThanZero();
+            if(savingsAccountId != null) {
+                SavingsAccount savingsAccount = 
this.savingsAccountRepositoryWrapper.findOneWithNotFoundDetection(savingsAccountId);
+                if (account.setSavingsAccount(savingsAccount)) {
+                    
actualChanges.put(ShareAccountApiConstants.savingsaccountid_paramname, 
savingsAccount.getId());
+                }    
+            }
+        }
+
+        if 
(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.requestedshares_paramname,
 element)
+                || 
this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.charges_paramname,
 element)) {
+            Set<ShareAccountTransaction> transactions = 
account.getShareAccountTransactions();
+            List<Long> reveralIds = new ArrayList<>();
+            for (ShareAccountTransaction transaction : transactions) {
+                reveralIds.add(transaction.getId());
             }
+            actualChanges.put("reversalIds", reveralIds);
+            account.removeTransactions();
+            account.removeCharges();
         }
 
         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);*/
+            /*
+             * 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");;
+            BigDecimal unitPrice = 
shareProduct.deriveMarketPrice(applicationDate);
+            ShareAccountTransaction transaction = new 
ShareAccountTransaction(applicationDate, requestedShares, unitPrice);
+            account.addTransaction(transaction);
+            
actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, 
"Transaction");
+            
+            if(requestedShares < shareProduct.getMinimumClientShares()) {
+                
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares)
+                
.failWithCode("client.can.not.purchase.shares.lessthan.product.definition", 
"Client can not purchase shares less than product definition");
+            }
+            
+            if(requestedShares > shareProduct.getMaximumClientShares()) {
+                
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requestedShares)
+                
.failWithCode("client.can.not.purchase.shares.morethan.product.definition", 
"Client can not purchase shares more than product definition");
             }
         }
 
@@ -340,13 +355,19 @@ public class ShareAccountDataSerializer {
         }
         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>());
+            final MonetaryCurrency currency = shareProduct.getCurrency();
+            Set<ShareAccountCharge> charges = 
assembleListOfAccountCharges(element, currency.getCode());
+            if (charges != null) {
+                for (ShareAccountCharge charge : charges) {
+                    charge.update(account);
+                }
+                account.addCharges(charges);
+                if (!charges.isEmpty()) {
+                    
actualChanges.put(ShareAccountApiConstants.charges_paramname, new 
HashSet<ShareAccountCharge>());
+                }
             }
-
         }
+        createChargeTransaction(account);
         if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
         return actualChanges;
     }
@@ -366,30 +387,57 @@ public class ShareAccountDataSerializer {
             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");
+                    
.failWithCodeNoParameterAddedToErrorCode("approved.date.cannot.be.before.submitted.date");
+        }
+        
+        Set<ShareAccountTransaction> transactions = 
account.getShareAccountTransactions() ;
+        for(ShareAccountTransaction transaction: transactions) {
+            if(transaction.isActive() && 
transaction.isPendingForApprovalTransaction()) {
+                validateTotalSubsribedShares(account, transaction, 
baseDataValidator) ;
+            }
         }
+        
         if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
         
         AppUser approvedUser = 
this.platformSecurityContext.authenticatedUser();
-        account.approve(approvedDate.toDate(), approvedUser);    
+        account.approve(approvedDate.toDate(), approvedUser);
         actualChanges.put(ShareAccountApiConstants.id_paramname, 
account.getId());
         updateTotalChargeDerived(account);
         return actualChanges;
     }
 
+    private void validateTotalSubsribedShares(final ShareAccount account, 
final ShareAccountTransaction transaction, final  DataValidatorBuilder 
baseDataValidator) {
+        Long totalSubsribedShares = 
account.getShareProduct().getSubscribedShares() ;
+        Long requested = new Long(0) ;
+        if(transaction.isActive() && 
transaction.isPendingForApprovalTransaction()) {
+           requested +=transaction.getTotalShares() ;
+        }
+        Long totalSharesIssuable = account.getShareProduct().getSharesIssued() 
;
+        if(totalSharesIssuable == null) totalSharesIssuable = 
account.getShareProduct().getTotalShares() ;
+        if(totalSubsribedShares == null) totalSubsribedShares = new Long(0) ;
+        if((totalSubsribedShares+requested) > totalSharesIssuable) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(requested)
+            
.failWithCodeNoParameterAddedToErrorCode("shares.requested.can.not.be.approved.exceeding.totalshares.issuable");
+        }
+    }
     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);
+            if (transaction.isActive()) {
+                Set<ShareAccountChargePaidBy> paidBySet = 
transaction.getChargesPaidBy();
+                if (paidBySet != null && !paidBySet.isEmpty()) {
+                    for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
+                        ShareAccountCharge charge = chargePaidBy.getCharge();
+                        if (charge.isActive() && 
charge.isSharesPurchaseCharge()) {
+                            Money money = Money.of(shareAccount.getCurrency(), 
chargePaidBy.getAmount());
+                            charge.updatePaidAmountBy(money);
+                        }
                     }
                 }
+                if (!transaction.isChargeTransaction()) {
+                    transaction.addAmountPaid(transaction.chargeAmount());
+                }
             }
         }
     }
@@ -397,19 +445,54 @@ public class ShareAccountDataSerializer {
     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);
+        // 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();
+        // AppUser approvedUser =
+        // this.platformSecurityContext.authenticatedUser();
         account.undoApprove();
+        updateTotalChargeDerivedForUndoApproval(account) ;
         actualChanges.put(ShareAccountApiConstants.charges_paramname, 
Boolean.TRUE);
         return actualChanges;
     }
 
+    private void updateTotalChargeDerivedForUndoApproval(final ShareAccount 
shareAccount) {
+        Set<ShareAccountTransaction> purchaseTransactions = 
shareAccount.getPendingForApprovalSharePurchaseTransactions() ;
+        //we will have only 1 purchase transaction. Take that
+        ShareAccountTransaction purchaseTransaction = null ;
+        for (ShareAccountTransaction transaction : purchaseTransactions) {
+            purchaseTransaction = transaction ;
+        }
+        BigDecimal transactionAmount = BigDecimal.ZERO ;
+        if(purchaseTransaction != null) {
+            transactionAmount = 
purchaseTransaction.amount().subtract(purchaseTransaction.chargeAmount()) ;
+        }
+         Set<ShareAccountCharge> charges = shareAccount.getCharges() ;
+         for(ShareAccountCharge charge: charges) {
+             if(charge.isActive() && charge.isSharesPurchaseCharge()) {
+                 charge.update(transactionAmount, charge.percentageOrAmount()) 
;
+                 charge.deriveChargeAmount(transactionAmount);
+             }
+         }
+        Set<ShareAccountTransaction> transactions = 
shareAccount.getShareAccountTransactions();
+        for (ShareAccountTransaction transaction : transactions) {
+            if (transaction.isActive()) {
+                if (!transaction.isChargeTransaction()) {
+                    transaction.resetAmountPaid();
+                }
+            }
+        }
+    }
     @SuppressWarnings("unused")
     public Map<String, Object> validateAndReject(JsonCommand jsonCommand, 
ShareAccount account) {
         Map<String, Object> actualChanges = new HashMap<>();
@@ -449,10 +532,17 @@ public class ShareAccountDataSerializer {
     private void handlechargesOnActivation(final ShareAccount account) {
         Set<ShareAccountCharge> charges = account.getCharges();
         for (ShareAccountCharge charge : charges) {
-            if (charge.isShareAccountActivation()) {
+            if (charge.isActive() && charge.isShareAccountActivation()) {
                 charge.markAsFullyPaid();
             }
         }
+
+        Set<ShareAccountTransaction> transactions = 
account.getChargeTransactions();
+        for (ShareAccountTransaction transaction : transactions) {
+            if (transaction.isChargeTransaction()) {
+                transaction.updateAmountPaid(transaction.amount());
+            }
+        }
     }
 
     private Set<ShareAccountCharge> assembleListOfAccountCharges(final 
JsonElement element, final String currencyCode) {
@@ -484,49 +574,6 @@ public class ShareAccountDataSerializer {
         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));
@@ -546,15 +593,33 @@ public class ShareAccountDataSerializer {
         
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");;
-            }    
+        ShareProduct shareProduct = account.getShareProduct();
+        if (sharesRequested != null) {
+            Long totalSharesAfterapproval = account.getTotalApprovedShares() + 
sharesRequested;
+            if(totalSharesAfterapproval > 
shareProduct.getMaximumClientShares()) {
+                
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(sharesRequested)
+                
.failWithCode("exceeding.maximum.limit.defined.in.the.shareproduct", "Existing 
and requested shares count is more than product definition");
+            }
+        }
+        boolean isTransactionBeforeExistingTransactions = false ;
+        Set<ShareAccountTransaction> transactions = 
account.getShareAccountTransactions() ;
+        for(ShareAccountTransaction transaction: transactions) {
+            if(!transaction.isChargeTransaction()) {
+                LocalDate transactionDate = new 
LocalDate(transaction.getPurchasedDate()) ;
+                if(requestedDate.isBefore(transactionDate)) {
+                    isTransactionBeforeExistingTransactions = true ;
+                    break ;
+                }    
+            }
         }
+        if(isTransactionBeforeExistingTransactions) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.requesteddate_paramname)
+            .value(requestedDate)
+            
.failWithCodeNoParameterAddedToErrorCode("purchase.transaction.date.cannot.be.before.existing.transactions");
+        }
+        
         if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
-        final BigDecimal unitPrice = 
shareProduct.deriveMarketPrice(requestedDate.toDate()) ;
+        final BigDecimal unitPrice = 
shareProduct.deriveMarketPrice(requestedDate.toDate());
         ShareAccountTransaction purchaseTransaction = new 
ShareAccountTransaction(requestedDate.toDate(), sharesRequested, unitPrice);
         account.addAdditionalPurchasedShares(purchaseTransaction);
         handleAdditionalSharesChargeTransactions(account, purchaseTransaction);
@@ -566,7 +631,7 @@ public class ShareAccountDataSerializer {
         Set<ShareAccountCharge> charges = account.getCharges();
         BigDecimal totalChargeAmount = BigDecimal.ZERO;
         for (ShareAccountCharge charge : charges) {
-            if (charge.isSharesPurchaseCharge()) {
+            if (charge.isActive() && charge.isSharesPurchaseCharge()) {
                 BigDecimal amount = 
charge.updateChargeDetailsForAdditionalSharesRequest(purchaseTransaction.amount());
                 ShareAccountChargePaidBy paidBy = new 
ShareAccountChargePaidBy(purchaseTransaction, charge, amount);
                 purchaseTransaction.addShareAccountChargePaidBy(paidBy);
@@ -588,20 +653,21 @@ public class ShareAccountDataSerializer {
         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 ;
+            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()
 ;
+                
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname).value(purchasedSharesId).notBlank();
                 ShareAccountTransaction transaction = 
account.retrievePurchasedShares(purchasedSharesId);
                 if (transaction != null) {
-                    totalShares+=transaction.getTotalShares().longValue() ;
+                    validateTotalSubsribedShares(account, transaction, 
baseDataValidator) ;
+                    totalShares += transaction.getTotalShares().longValue();
                     transaction.approve();
                     updateTotalChargeDerivedForAdditonalShares(account, 
transaction);
                 }
                 purchasedShares.add(purchasedSharesId);
             }
-            if(totalShares > 0) {
-                account.updateApprovedShares(new Long(totalShares)) ;    
+            if (totalShares > 0) {
+                account.updateApprovedShares(new Long(totalShares));
             }
         }
         if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
@@ -614,11 +680,14 @@ public class ShareAccountDataSerializer {
         if (paidBySet != null && !paidBySet.isEmpty()) {
             for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
                 ShareAccountCharge charge = chargePaidBy.getCharge();
-                if (charge.isSharesPurchaseCharge()) {
+                if (charge.isActive() && charge.isSharesPurchaseCharge()) {
                     Money money = Money.of(shareAccount.getCurrency(), 
chargePaidBy.getAmount());
                     charge.updatePaidAmountBy(money);
                 }
             }
+            if (!transaction.isChargeTransaction()) {
+                transaction.addAmountPaid(transaction.chargeAmount());
+            }
         }
     }
 
@@ -631,20 +700,20 @@ public class ShareAccountDataSerializer {
         JsonElement element = jsonCommand.parsedJson();
         final ArrayList<Long> purchasedShares = new ArrayList<>();
         if 
(this.fromApiJsonHelper.parameterExists(ShareAccountApiConstants.requestedshares_paramname,
 element)) {
-            long totalShares = 0 ;
+            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() ;
+                    updateTotalChargeDerivedForAdditonalSharesReject(account, 
shares);
+                    totalShares += shares.getTotalShares().longValue();
                 }
                 purchasedShares.add(purchasedSharesId);
             }
-            if(totalShares > 0) {
-                account.removePendingShares(new Long(totalShares)) ;
+            if (totalShares > 0) {
+                account.removePendingShares(new Long(totalShares));
             }
         }
         actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, 
purchasedShares);
@@ -656,14 +725,17 @@ public class ShareAccountDataSerializer {
         if (paidBySet != null && !paidBySet.isEmpty()) {
             for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
                 ShareAccountCharge charge = chargePaidBy.getCharge();
-                if (charge.isSharesPurchaseCharge()) {
+                if (charge.isActive() && charge.isSharesPurchaseCharge()) {
                     Money money = Money.of(shareAccount.getCurrency(), 
chargePaidBy.getAmount());
                     charge.updatePaidAmountBy(money);
                 }
             }
+            if (!transaction.isChargeTransaction()) {
+                transaction.addAmountPaid(transaction.chargeAmount());
+            }
         }
     }
-    
+
     public Map<String, Object> validateAndRedeemShares(JsonCommand 
jsonCommand, ShareAccount account) {
         Map<String, Object> actualChanges = new HashMap<>();
         if (StringUtils.isBlank(jsonCommand.json())) { throw new 
InvalidJsonException(); }
@@ -683,19 +755,116 @@ public class ShareAccountDataSerializer {
         final BigDecimal unitPrice = 
this.fromApiJsonHelper.extractBigDecimalNamed(ShareAccountApiConstants.purchasedprice_paramname,
                 element, locale);
         
baseDataValidator.reset().parameter(ShareAccountApiConstants.purchasedprice_paramname).value(unitPrice).notNull().positiveAmount();
+        boolean isTransactionBeforeExistingTransactions = false ;
+        Set<ShareAccountTransaction> transactions = 
account.getShareAccountTransactions() ;
+        for(ShareAccountTransaction transaction: transactions) {
+            if(!transaction.isChargeTransaction()) {
+                LocalDate transactionDate = new 
LocalDate(transaction.getPurchasedDate()) ;
+                if(requestedDate.isBefore(transactionDate)) {
+                    isTransactionBeforeExistingTransactions = true ;
+                    break ;
+                }    
+            }
+        }
+        if(isTransactionBeforeExistingTransactions) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.requesteddate_paramname)
+            .value(requestedDate)
+            
.failWithCodeNoParameterAddedToErrorCode("redeem.transaction.date.cannot.be.before.existing.transactions");
+        }
+        if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
+        
         ShareAccountTransaction transaction = 
ShareAccountTransaction.createRedeemTransaction(requestedDate.toDate(), 
sharesRequested,
                 unitPrice);
         account.addAdditionalPurchasedShares(transaction);
         actualChanges.put(ShareAccountApiConstants.requestedshares_paramname, 
transaction);
+        validateRedeemRequest(account, transaction, baseDataValidator, 
dataValidationErrors) ;
         handleRedeemSharesChargeTransactions(account, transaction);
         return actualChanges;
     }
-
+    
+    private void validateRedeemRequest(final ShareAccount account, 
ShareAccountTransaction redeemTransaction,
+            final DataValidatorBuilder baseDataValidator,  final 
List<ApiParameterError> dataValidationErrors ) {
+        
+        if (account.getTotalApprovedShares() < 
redeemTransaction.getTotalShares()) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname)
+                    .value(redeemTransaction.getTotalShares())
+                    
.failWithCodeNoParameterAddedToErrorCode("cannot.be.redeemed.due.to.insufficient.shares");
+        }
+        if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
+        
+        LocalDate redeemDate = new 
LocalDate(redeemTransaction.getPurchasedDate());
+        final Integer lockinPeriod = account.getLockinPeriodFrequency();
+        final PeriodFrequencyType periodType = 
account.getLockinPeriodFrequencyType();
+        if (lockinPeriod == null && periodType == null) { return; }
+        Long totalSharesCanBeRedeemed = new Long(0);
+        Long totalSharesPurchasedBeforeRedeem = new Long(0) ;
+        boolean isPurchaseTransactionExist = false ;
+        
+        Set<ShareAccountTransaction> transactions = 
account.getShareAccountTransactions();
+        for (ShareAccountTransaction transaction : transactions) {
+            if (transaction.isActive() && !transaction.isChargeTransaction()) {
+                LocalDate purchaseDate = new 
LocalDate(transaction.getPurchasedDate());
+                LocalDate lockinDate = 
deriveLockinPeriodDuration(lockinPeriod, periodType, purchaseDate);
+                if (!lockinDate.isAfter(redeemDate)) {
+                    if (transaction.isPurchasTransaction()) {
+                        totalSharesCanBeRedeemed += 
transaction.getTotalShares();
+                    } else if (transaction.isRedeemTransaction()) {
+                        totalSharesCanBeRedeemed -= 
transaction.getTotalShares();
+                    }
+                }
+                
+                if(!purchaseDate.isAfter(redeemDate)) {
+                    isPurchaseTransactionExist = true ;
+                    if (transaction.isPurchasTransaction()) {
+                        totalSharesPurchasedBeforeRedeem += 
transaction.getTotalShares();
+                    } else if (transaction.isRedeemTransaction()) {
+                        totalSharesPurchasedBeforeRedeem -= 
transaction.getTotalShares();
+                    }
+                }
+            }
+        }
+        if(!isPurchaseTransactionExist) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.requesteddate_paramname)
+            .value(redeemDate)
+            
.failWithCodeNoParameterAddedToErrorCode("no.purchase.transaction.found.before.redeem.date");
+        }else if (totalSharesPurchasedBeforeRedeem < 
redeemTransaction.getTotalShares()) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname)
+            .value(redeemTransaction.getTotalShares())
+            
.failWithCodeNoParameterAddedToErrorCode("cannot.be.redeemed.due.to.insufficient.shares.for.this.redeem.date");
+        }else if (totalSharesCanBeRedeemed < 
redeemTransaction.getTotalShares()) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.requestedshares_paramname)
+                    .value(redeemTransaction.getTotalShares())
+                    
.failWithCodeNoParameterAddedToErrorCode("cannot.be.redeemed.due.to.lockinperiod");
+        }
+        if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
+    }
+    
+    private LocalDate deriveLockinPeriodDuration(final Integer lockinPeriod, 
final PeriodFrequencyType periodType, LocalDate purchaseDate) {
+        LocalDate lockinDate = null ;
+        switch(periodType) {
+            case INVALID: //It never comes in to this state.
+                break ;
+            case DAYS:
+                lockinDate = purchaseDate.plusDays(lockinPeriod) ;
+                break ;
+            case WEEKS:
+                lockinDate = purchaseDate.plusWeeks(lockinPeriod) ;
+                break ;
+            case MONTHS:
+                lockinDate = purchaseDate.plusMonths(lockinPeriod) ;
+                break ;
+            case YEARS:
+                lockinDate = purchaseDate.plusYears(lockinPeriod) ;
+                break ;
+        }
+        return lockinDate ;
+    }
+    
     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()) {
+            if (charge.isActive() && charge.isSharesRedeemCharge()) {
                 BigDecimal amount = 
charge.updateChargeDetailsForAdditionalSharesRequest(transaction.amount());
                 ShareAccountChargePaidBy paidBy = new 
ShareAccountChargePaidBy(transaction, charge, amount);
                 transaction.addShareAccountChargePaidBy(paidBy);
@@ -707,16 +876,15 @@ public class ShareAccountDataSerializer {
         if (paidBySet != null && !paidBySet.isEmpty()) {
             for (ShareAccountChargePaidBy chargePaidBy : paidBySet) {
                 ShareAccountCharge charge = chargePaidBy.getCharge();
-                if (charge.isSharesRedeemCharge()) {
+                if (charge.isActive() && charge.isSharesRedeemCharge()) {
                     Money money = Money.of(account.getCurrency(), 
chargePaidBy.getAmount());
                     charge.updatePaidAmountBy(money);
                 }
             }
         }
-        
-       // transaction.adjustRedeemAmount();
+        transaction.addAmountPaid(transaction.chargeAmount());
     }
-    
+
     public Map<String, Object> validateAndClose(JsonCommand jsonCommand, 
ShareAccount account) {
         Map<String, Object> actualChanges = new HashMap<>();
         if (StringUtils.isBlank(jsonCommand.json())) { throw new 
InvalidJsonException(); }
@@ -727,15 +895,35 @@ public class ShareAccountDataSerializer {
         JsonElement element = jsonCommand.parsedJson();
         LocalDate closedDate = 
this.fromApiJsonHelper.extractLocalDateNamed(ShareAccountApiConstants.closeddate_paramname,
 element);
         
baseDataValidator.reset().parameter(ShareAccountApiConstants.approveddate_paramname).value(closedDate).notNull();
+        boolean isTransactionBeforeExistingTransactions = false ;
+        Set<ShareAccountTransaction> transactions = 
account.getShareAccountTransactions() ;
+        for(ShareAccountTransaction transaction: transactions) {
+            if(!transaction.isChargeTransaction()) {
+                LocalDate transactionDate = new 
LocalDate(transaction.getPurchasedDate()) ;
+                if(closedDate.isBefore(transactionDate)) {
+                    isTransactionBeforeExistingTransactions = true ;
+                    break ;
+                }    
+            }
+        }
+        if(isTransactionBeforeExistingTransactions) {
+            
baseDataValidator.reset().parameter(ShareAccountApiConstants.closeddate_paramname)
+            .value(closedDate)
+            
.failWithCodeNoParameterAddedToErrorCode("share.account.cannot.be.closed.before.existing.transactions");
+        }
+        
+        if (!dataValidationErrors.isEmpty()) { throw new 
PlatformApiDataValidationException(dataValidationErrors); }
+        
         AppUser approvedUser = 
this.platformSecurityContext.authenticatedUser();
-        final BigDecimal unitPrice = 
account.getShareProduct().deriveMarketPrice(DateUtils.getDateOfTenant()) ;
-        ShareAccountTransaction transaction = 
ShareAccountTransaction.createRedeemTransaction(closedDate.toDate(), 
account.getTotalApprovedShares(), unitPrice) ;
+        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) ;
+        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/60588a78/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
index 4f3b401..1f608bf 100644
--- 
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
@@ -20,9 +20,9 @@ package org.apache.fineract.portfolio.shareaccounts.service;
 
 import java.util.Collection;
 
-import org.apache.fineract.portfolio.shareaccounts.data.PurchasedSharesData;
+import 
org.apache.fineract.portfolio.shareaccounts.data.ShareAccountTransactionData;
 
 public interface PurchasedSharesReadPlatformService {
 
-       public Collection<PurchasedSharesData> retrievePurchasedShares(final 
Long accountId) ;
+       public Collection<ShareAccountTransactionData> 
retrievePurchasedShares(final Long accountId) ;
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/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
index 5aa7f73..195e6d8 100644
--- 
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
@@ -26,7 +26,7 @@ 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.apache.fineract.portfolio.shareaccounts.data.ShareAccountTransactionData;
 import org.joda.time.LocalDate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -44,26 +44,27 @@ public class PurchasedSharesReadPlatformServiceImpl 
implements
                this.jdbcTemplate = new JdbcTemplate(dataSource) ;
        }
        @Override
-       public Collection<PurchasedSharesData> retrievePurchasedShares(
+       public Collection<ShareAccountTransactionData> retrievePurchasedShares(
                        Long accountId) {
                PurchasedSharesDataRowMapper mapper = new 
PurchasedSharesDataRowMapper() ;
-               final String sql = "select " + mapper.schema() + " where 
saps.account_id=?";
+               final String sql = "select " + mapper.schema() + " where 
saps.account_id=? and saps.is_active = 1";
                return this.jdbcTemplate.query(sql, mapper, new Object[] { 
accountId});
        }
 
-       private final static class PurchasedSharesDataRowMapper implements 
RowMapper<PurchasedSharesData> {
+       private final static class PurchasedSharesDataRowMapper implements 
RowMapper<ShareAccountTransactionData> {
 
                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("saps.status_enum, saps.type_enum, saps.amount, 
saps.charge_amount as chargeamount, ")
+                       .append("saps.amount_paid as amountPaid")
                        .append(" from m_share_account_transactions saps ");
                        schema = buff.toString() ;
                }
                @Override
-               public PurchasedSharesData mapRow(ResultSet rs, int rowNum)
+               public ShareAccountTransactionData mapRow(ResultSet rs, int 
rowNum)
                                throws SQLException {
                        final Long id = rs.getLong("id") ;
                        final Long accountId = rs.getLong("account_id") ;
@@ -76,7 +77,9 @@ public class PurchasedSharesReadPlatformServiceImpl implements
                        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);
+                       final BigDecimal amountPaid = 
JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountPaid") ;
+                       
+                       return new ShareAccountTransactionData(id,accountId, 
purchasedDate, numberOfShares, purchasedPrice, statusEnum, typeEnum, amount, 
chargeAmount, amountPaid);
                }
                
                public String schema() {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/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
index b4ddd96..66fb61e 100644
--- 
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
@@ -80,6 +80,7 @@ public class ShareAccountChargeReadPlatformServiceImpl 
implements
                                        .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("sc.charge_amount_or_percentage, ")
                                        .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 ");
@@ -132,13 +133,14 @@ public class ShareAccountChargeReadPlatformServiceImpl 
implements
                        final EnumOptionData chargeCalculationType = 
ChargeEnumerations
                                        
.chargeCalculationType(chargeCalculation);
                        final Boolean isActive = rs.getBoolean("isActive");
-
+                       final BigDecimal chargeamountorpercentage = 
rs.getBigDecimal("charge_amount_or_percentage") ;
+                       
                        final Collection<ChargeData> chargeOptions = null;
                        return new ShareAccountChargeData(id, chargeId, 
accountId, name,
                                        currency, amount, amountPaid, 
amountWaived,
                                        amountWrittenOff, amountOutstanding, 
chargeTimeType,
                                        chargeCalculationType, percentageOf,
-                                       amountPercentageAppliedTo, 
chargeOptions, isActive);
+                                       amountPercentageAppliedTo, 
chargeOptions, isActive, chargeamountorpercentage);
                }
 
                public String schema() {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformServiceImpl.java
index 3635aaa..90ab5b0 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountReadPlatformServiceImpl.java
@@ -42,9 +42,10 @@ import 
org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
 import org.apache.fineract.portfolio.products.constants.ProductsApiConstants;
 import org.apache.fineract.portfolio.products.data.ProductData;
 import 
org.apache.fineract.portfolio.products.service.ProductReadPlatformService;
+import org.apache.fineract.portfolio.savings.DepositAccountType;
 import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
 import 
org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
-import org.apache.fineract.portfolio.shareaccounts.data.PurchasedSharesData;
+import 
org.apache.fineract.portfolio.shareaccounts.data.ShareAccountTransactionData;
 import 
org.apache.fineract.portfolio.shareaccounts.data.ShareAccountApplicationTimelineData;
 import 
org.apache.fineract.portfolio.shareaccounts.data.ShareAccountDividendData;
 import 
org.apache.fineract.portfolio.shareaccounts.data.ShareAccountStatusEnumData;
@@ -114,7 +115,7 @@ public class ShareAccountReadPlatformServiceImpl implements 
ShareAccountReadPlat
             final Collection<EnumOptionData> 
minimumActivePeriodFrequencyTypeOptions = 
this.shareProductDropdownReadPlatformService
                     .retrieveMinimumActivePeriodFrequencyTypeOptions();
             final Collection<SavingsAccountData> clientSavingsAccounts = 
this.savingsAccountReadPlatformService
-                    .retrieveAllForLookup(clientId);
+                    .retrieveActiveForLookup(clientId, 
DepositAccountType.SAVINGS_DEPOSIT, productData.getCurrency().code());
             toReturn = new ShareAccountData(client.id(), client.displayName(), 
productData.getCurrency(), charges, marketPrice,
                     minimumActivePeriodFrequencyTypeOptions, 
lockinPeriodFrequencyTypeOptions, clientSavingsAccounts, 
productData.getNominaltShares());
         } else {
@@ -143,7 +144,7 @@ public class ShareAccountReadPlatformServiceImpl implements 
ShareAccountReadPlat
     @Override
     public ShareAccountData retrieveOne(final Long id, final boolean 
includeTemplate) {
         Collection<ShareAccountChargeData> charges = 
this.shareAccountChargeReadPlatformService.retrieveAccountCharges(id, "active");
-        Collection<PurchasedSharesData> purchasedShares = 
this.purchasedSharesReadPlatformService.retrievePurchasedShares(id);
+        Collection<ShareAccountTransactionData> purchasedShares = 
this.purchasedSharesReadPlatformService.retrievePurchasedShares(id);
         
         ShareAccountMapper mapper = new ShareAccountMapper(charges, 
purchasedShares);
         String query = "select " + mapper.schema() + "where sa.id=?";
@@ -161,8 +162,8 @@ public class ShareAccountReadPlatformServiceImpl implements 
ShareAccountReadPlat
             final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions 
= this.shareProductDropdownReadPlatformService
                     .retrieveLockinPeriodFrequencyTypeOptions();
             final Collection<EnumOptionData> 
minimumActivePeriodFrequencyTypeOptions = lockinPeriodFrequencyTypeOptions;
-            final Collection<SavingsAccountData> clientSavingsAccounts = 
this.savingsAccountReadPlatformService.retrieveAllForLookup(data
-                    .getClientId());
+            final Collection<SavingsAccountData> clientSavingsAccounts = 
this.savingsAccountReadPlatformService
+                    .retrieveActiveForLookup(data.getClientId(), 
DepositAccountType.SAVINGS_DEPOSIT, productData.getCurrency().code());
             Collection<ProductData> productOptions = 
service.retrieveAllForLookup();
             final Collection<ChargeData> chargeOptions = 
this.chargeReadPlatformService.retrieveSharesApplicableCharges();
             data = ShareAccountData.template(data, productOptions, 
chargeOptions, clientSavingsAccounts, lockinPeriodFrequencyTypeOptions,
@@ -224,11 +225,11 @@ public class ShareAccountReadPlatformServiceImpl 
implements ShareAccountReadPlat
     private final static class ShareAccountMapper implements 
RowMapper<ShareAccountData> {
 
         private final Collection<ShareAccountChargeData> charges;
-        private final Collection<PurchasedSharesData> purchasedShares;
+        private final Collection<ShareAccountTransactionData> purchasedShares;
 
         private final String schema;
 
-        public ShareAccountMapper(final Collection<ShareAccountChargeData> 
charges, final Collection<PurchasedSharesData> purchasedShares) {
+        public ShareAccountMapper(final Collection<ShareAccountChargeData> 
charges, final Collection<ShareAccountTransactionData> purchasedShares) {
             this.charges = charges;
             this.purchasedShares = purchasedShares;
             StringBuffer buff = new StringBuffer()
@@ -392,7 +393,7 @@ public class ShareAccountReadPlatformServiceImpl implements 
ShareAccountReadPlat
             final Boolean allowdividendsforinactiveclients = null;
 
             final Collection<ShareAccountChargeData> charges = null;
-            final Collection<PurchasedSharesData> purchasedSharesData = new 
ArrayList<>();
+            final Collection<ShareAccountTransactionData> purchasedSharesData 
= new ArrayList<>();
             final Integer lockinPeriod = null;
             final EnumOptionData lockPeriodTypeEnum = null;
             final Integer minimumActivePeriod = null;
@@ -418,19 +419,21 @@ public class ShareAccountReadPlatformServiceImpl 
implements ShareAccountReadPlat
         }
     }
 
-    private final static class PurchasedSharesDataRowMapper implements 
RowMapper<PurchasedSharesData> {
+    private final static class PurchasedSharesDataRowMapper implements 
RowMapper<ShareAccountTransactionData> {
 
         private final String schema;
 
         public PurchasedSharesDataRowMapper() {
             StringBuffer buff = new StringBuffer()
                     .append("saps.id as purchasedId, saps.account_id as 
accountId, saps.transaction_date as transactionDate, saps.total_shares as 
purchasedShares, saps.unit_price as unitPrice, ")
-                    .append("saps.status_enum as purchaseStatus, 
saps.type_enum as purchaseType, saps.amount as amount, saps.charge_amount as 
chargeamount ");
+                    .append("saps.status_enum as purchaseStatus, 
saps.type_enum as purchaseType, saps.amount as amount, saps.charge_amount as 
chargeamount, ")
+                    .append("saps.amount_paid as amountPaid ");
+            
             schema = buff.toString();
         }
 
         @Override
-        public PurchasedSharesData mapRow(ResultSet rs, 
@SuppressWarnings("unused") int rowNum) throws SQLException {
+        public ShareAccountTransactionData mapRow(ResultSet rs, 
@SuppressWarnings("unused") int rowNum) throws SQLException {
             final Long id = rs.getLong("purchasedId");
             final Long accountId = rs.getLong("accountId");
             final LocalDate transactionDate = new 
LocalDate(rs.getDate("transactionDate"));
@@ -442,8 +445,9 @@ public class ShareAccountReadPlatformServiceImpl implements 
ShareAccountReadPlat
             final EnumOptionData typeEnum = 
SharesEnumerations.purchasedSharesEnum(type);
             final BigDecimal amount = 
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "amount");
             final BigDecimal chargeAmount = 
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "chargeamount");
-            return new PurchasedSharesData(id, accountId, transactionDate, 
numberOfShares, purchasedPrice, statusEnum, typeEnum, amount,
-                    chargeAmount);
+            final BigDecimal amountPaid = 
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "amountPaid");
+            return new ShareAccountTransactionData(id, accountId, 
transactionDate, numberOfShares, purchasedPrice, statusEnum, typeEnum, amount,
+                    chargeAmount, amountPaid);
         }
 
         public String schema() {

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
index daad3be..e97f6e3 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareaccounts/service/ShareAccountWritePlatformServiceJpaRepositoryImpl.java
@@ -18,7 +18,9 @@
  */
 package org.apache.fineract.portfolio.shareaccounts.service;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -32,6 +34,7 @@ import 
org.apache.fineract.infrastructure.accountnumberformat.domain.EntityAccou
 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.service.DateUtils;
 import org.apache.fineract.organisation.monetary.data.CurrencyData;
 import org.apache.fineract.organisation.monetary.domain.MonetaryCurrency;
 import 
org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
@@ -42,6 +45,8 @@ import 
org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountChargePaid
 import 
org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountRepositoryWrapper;
 import 
org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountTransaction;
 import 
org.apache.fineract.portfolio.shareaccounts.serialization.ShareAccountDataSerializer;
+import org.apache.fineract.portfolio.shareproducts.domain.ShareProduct;
+import 
org.apache.fineract.portfolio.shareproducts.domain.ShareProductRepositoryWrapper;
 import org.joda.time.LocalDate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.DataIntegrityViolationException;
@@ -54,6 +59,8 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
 
     private final ShareAccountRepositoryWrapper shareAccountRepository;
 
+    private final ShareProductRepositoryWrapper shareProductRepository ;
+    
     private final AccountNumberGenerator accountNumberGenerator;
 
     private final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository;
@@ -62,12 +69,14 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
 
     @Autowired
     public ShareAccountWritePlatformServiceJpaRepositoryImpl(final 
ShareAccountDataSerializer accountDataSerializer,
-            final ShareAccountRepositoryWrapper shareAccountRepository,
+            final ShareAccountRepositoryWrapper shareAccountRepository, 
+            final ShareProductRepositoryWrapper shareProductRepository,
             final AccountNumberGenerator accountNumberGenerator,
             final AccountNumberFormatRepositoryWrapper 
accountNumberFormatRepository,
             final JournalEntryWritePlatformService 
journalEntryWritePlatformService) {
         this.accountDataSerializer = accountDataSerializer;
         this.shareAccountRepository = shareAccountRepository;
+        this.shareProductRepository = shareProductRepository ;
         this.accountNumberGenerator = accountNumberGenerator;
         this.accountNumberFormatRepository = accountNumberFormatRepository;
         this.journalEntryWritePlatformService = 
journalEntryWritePlatformService;
@@ -79,7 +88,6 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             ShareAccount account = 
this.accountDataSerializer.validateAndCreate(jsonCommand);
             this.shareAccountRepository.save(account);
             generateAccountNumber(account);
-            //this.shareProductRepository.save(account.getShareProduct()); 
//subscribed shares is increased
             
journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
                     account.getPendingForApprovalSharePurchaseTransactions()));
             return new CommandProcessingResultBuilder() //
@@ -126,7 +134,16 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             final ShareAccountTransactionEnumData typeEnum = new 
ShareAccountTransactionEnumData(type.longValue(), null, null);
             transactionDto.put("status", statusEnum);
             transactionDto.put("type", typeEnum);
-            transactionDto.put("amount", transaction.amount());
+            if(transaction.isPurchaseRejectedTransaction() || 
transaction.isRedeemTransaction()) {
+                BigDecimal amount = transaction.amount() ;
+                if(transaction.chargeAmount() != null) {
+                    amount = amount.add(transaction.chargeAmount()) ;
+                }
+                transactionDto.put("amount", amount);
+            }else {
+                transactionDto.put("amount", transaction.amount());    
+            }
+            
             transactionDto.put("chargeAmount", transaction.chargeAmount());
             transactionDto.put("paymentTypeId", null); // FIXME::make it cash
                                                        // payment
@@ -147,14 +164,24 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
         return accountingBridgeData;
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public CommandProcessingResult updateShareAccount(Long accountId, 
JsonCommand jsonCommand) {
         try {
+            Date transactionDate = DateUtils.getDateOfTenant();
             ShareAccount account = 
this.shareAccountRepository.findOneWithNotFoundDetection(accountId);
             Map<String, Object> changes = 
this.accountDataSerializer.validateAndUpdate(jsonCommand, account);
             if (!changes.isEmpty()) {
                 this.shareAccountRepository.save(account);
             }
+            // since we are reverting all journal entries we need to add 
journal
+            // entries for application request
+            if (changes.containsKey("reversalIds")) {
+                ArrayList<Long> reversalIds = (ArrayList<Long>) 
changes.get("reversalIds");
+                
this.journalEntryWritePlatformService.revertShareAccountJournalEntries(reversalIds,
 transactionDate);
+                
journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
+                        
account.getPendingForApprovalSharePurchaseTransactions()));
+            }
             return new CommandProcessingResultBuilder() //
                     .withCommandId(jsonCommand.commandId()) //
                     .withEntityId(accountId) //
@@ -205,8 +232,21 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             if (!changes.isEmpty()) {
                 this.shareAccountRepository.save(account);
             }
-            
this.journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
-                    account.getShareAccountTransactions()));
+            Set<ShareAccountTransaction> transactions = 
account.getShareAccountTransactions();
+            Set<ShareAccountTransaction> journalTransactions = new HashSet<>();
+            Long totalSubsribedShares = new Long(0) ;
+            
+            for (ShareAccountTransaction transaction : transactions) {
+                if (transaction.isActive() && 
transaction.isPurchasTransaction()) {
+                    journalTransactions.add(transaction);
+                    totalSubsribedShares += transaction.getTotalShares() ;
+                }
+            }
+            ShareProduct shareProduct = account.getShareProduct() ;
+            shareProduct.addSubscribedShares(totalSubsribedShares);
+            this.shareProductRepository.save(shareProduct);
+            
+            
this.journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
 journalTransactions));
             return new CommandProcessingResultBuilder() //
                     .withCommandId(jsonCommand.commandId()) //
                     .withEntityId(accountId) //
@@ -226,8 +266,14 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             if (!changes.isEmpty()) {
                 this.shareAccountRepository.save(account);
             }
-            
this.journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
-                    account.getShareAccountTransactions()));
+            Set<ShareAccountTransaction> transactions = 
account.getShareAccountTransactions();
+            Set<ShareAccountTransaction> journalTransactions = new HashSet<>();
+            for (ShareAccountTransaction transaction : transactions) {
+                if (transaction.isActive() && 
!transaction.isChargeTransaction()) {
+                    journalTransactions.add(transaction);
+                }
+            }
+            
this.journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
 journalTransactions));
             return new CommandProcessingResultBuilder() //
                     .withCommandId(jsonCommand.commandId()) //
                     .withEntityId(accountId) //
@@ -247,11 +293,18 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             if (!changes.isEmpty()) {
                 this.shareAccountRepository.save(account);
             }
-            /*
-             * 
this.journalEntryWritePlatformService.createJournalEntriesForShares
-             * (populateJournalEntries(account,
-             * account.getShareAccountTransactions()));
-             */
+            
+            Set<ShareAccountTransaction> transactions = 
account.getShareAccountTransactions() ;
+            ArrayList<Long> journalEntryTransactions = new ArrayList<>() ;
+            for(ShareAccountTransaction transaction: transactions) {
+                if(transaction.isActive() && 
!transaction.isChargeTransaction()){
+                    journalEntryTransactions.add(transaction.getId()) ;
+                }
+            }
+            Date transactionDate = DateUtils.getDateOfTenant();
+            
this.journalEntryWritePlatformService.revertShareAccountJournalEntries(journalEntryTransactions,
 transactionDate);
+            
journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
+                    account.getPendingForApprovalSharePurchaseTransactions()));
             return new CommandProcessingResultBuilder() //
                     .withCommandId(jsonCommand.commandId()) //
                     .withEntityId(accountId) //
@@ -285,6 +338,7 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
         }
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public CommandProcessingResult approveAdditionalShares(Long accountId, 
JsonCommand jsonCommand) {
 
@@ -294,14 +348,21 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             if (!changes.isEmpty()) {
                 this.shareAccountRepository.save(account);
                 ArrayList<Long> transactionIds = (ArrayList<Long>) 
changes.get(ShareAccountApiConstants.requestedshares_paramname);
+                Long totalSubscribedShares = new Long(0) ;
                 if (transactionIds != null) {
                     Set<ShareAccountTransaction> transactions = new 
HashSet<>();
                     for (Long id : transactionIds) {
                         ShareAccountTransaction transaction = 
account.retrievePurchasedShares(id);
                         transactions.add(transaction);
+                        totalSubscribedShares += transaction.getTotalShares() ;
                     }
                     
this.journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
 transactions));
                 }
+                if(!totalSubscribedShares.equals(new Long(0))) {
+                    ShareProduct shareProduct = account.getShareProduct() ;
+                    shareProduct.addSubscribedShares(totalSubscribedShares);
+                    this.shareProductRepository.save(shareProduct);
+                }
             }
             return new CommandProcessingResultBuilder() //
                     .withCommandId(jsonCommand.commandId()) //
@@ -314,9 +375,9 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
         }
     }
 
+    @SuppressWarnings("unchecked")
     @Override
     public CommandProcessingResult rejectAdditionalShares(Long accountId, 
JsonCommand jsonCommand) {
-
         try {
             ShareAccount account = 
this.shareAccountRepository.findOneWithNotFoundDetection(accountId);
             Map<String, Object> changes = 
this.accountDataSerializer.validateAndRejectAddtionalShares(jsonCommand, 
account);
@@ -352,7 +413,21 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
                 this.shareAccountRepository.save(account);
                 ShareAccountTransaction transaction = 
(ShareAccountTransaction) changes
                         
.get(ShareAccountApiConstants.requestedshares_paramname);
-                transaction = account.getShareAccountTransaction(transaction);
+                transaction = account.getShareAccountTransaction(transaction); 
// after
+                                                                               
// saving,
+                                                                               
// entity
+                                                                               
// will
+                                                                               
// have
+                                                                               
// different
+                                                                               
// object.
+                                                                               
// So
+                                                                               
// need
+                                                                               
// to
+                                                                               
// retrieve
+                                                                               
// to
+                                                                               
// get
+                                                                               
// the
+                                                                               
// id
                 Set<ShareAccountTransaction> transactions = new HashSet<>();
                 transactions.add(transaction);
                 
this.journalEntryWritePlatformService.createJournalEntriesForShares(populateJournalEntries(account,
 transactions));
@@ -398,6 +473,7 @@ public class 
ShareAccountWritePlatformServiceJpaRepositoryImpl implements ShareA
             return CommandProcessingResult.empty();
         }
     }
+
     private void handleDataIntegrityIssues(final JsonCommand command, final 
DataIntegrityViolationException dve) {
 
     }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProduct.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProduct.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProduct.java
index 4fee7ef..6cf301e 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProduct.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/domain/ShareProduct.java
@@ -226,7 +226,10 @@ public class ShareProduct extends 
AbstractAuditableCustom<AppUser, Long> {
 
     public boolean setTotalIssuedShares(Long totalSharesIssued) {
         boolean returnValue = false;
-        if (!this.totalSharesIssued.equals(totalSharesIssued)) {
+        if(this.totalSharesIssued == null) {
+            this.totalSharesIssued = totalSharesIssued ;
+            returnValue = true ;
+        }else if (!this.totalSharesIssued.equals(totalSharesIssued)) {
             this.totalSharesIssued = totalSharesIssued;
             returnValue = true;
         }
@@ -430,5 +433,16 @@ public class ShareProduct extends 
AbstractAuditableCustom<AppUser, Long> {
     public Long getSubscribedShares() {
         return this.totalSubscribedShares ;
     }
+ 
+    public Long getMinimumClientShares() {
+        return this.minimumShares ;
+    }
+    
+    public Long getMaximumClientShares() {
+        return this.maximumShares ;
+    }
     
+    public Long getDefaultClientShares() {
+        return this.nominalShares ;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-fineract/blob/60588a78/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/exception/ShareAccountsNotFoundException.java
----------------------------------------------------------------------
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/exception/ShareAccountsNotFoundException.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/exception/ShareAccountsNotFoundException.java
new file mode 100644
index 0000000..71b59bc
--- /dev/null
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/shareproducts/exception/ShareAccountsNotFoundException.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.exception;
+
+import 
org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+
+public class ShareAccountsNotFoundException extends 
AbstractPlatformResourceNotFoundException{
+
+    public ShareAccountsNotFoundException(final Long productId) {
+        super("error.msg.shareproduct.shareaccounts.not.defined", " No Share 
Accounts found for this prodct " + productId, productId);
+    }
+}

Reply via email to